mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-10 10:33:29 -05:00
Copy audio to UDP/RTP: adapt decimation filter to codec also
This commit is contained in:
parent
010f6b7ec6
commit
d98c4cd3ac
@ -37,14 +37,13 @@ AudioFilter::~AudioFilter()
|
||||
{}
|
||||
|
||||
|
||||
void AudioFilter::setDecimFilters(int sr, uint32_t decim)
|
||||
void AudioFilter::setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow)
|
||||
{
|
||||
int downSR = sr / (decim == 0 ? 1 : decim);
|
||||
double fcH = (0.45 * downSR) / (sr <= 0 ? 1 : sr); // high cut frequency normalized to SR
|
||||
double fcL = 300.0 / downSR; // low cut frequency normalized to downsampled SR
|
||||
double fcNormHigh = fcHigh / srHigh;
|
||||
double fcNormLow = fcLow / srLow;
|
||||
|
||||
calculate2(false, fcH, m_lpva, m_lpvb);
|
||||
calculate2(true, fcL, m_hpva, m_hpvb);
|
||||
calculate2(false, fcNormHigh, m_lpva, m_lpvb);
|
||||
calculate2(true, fcNormLow, m_hpva, m_hpvb);
|
||||
|
||||
m_filterLP.setCoeffs(m_lpva, m_lpvb);
|
||||
m_filterHP.setCoeffs(m_hpva, m_hpvb);
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
|
||||
void useHP(bool useHP) { m_useHP = useHP; }
|
||||
bool usesHP() const { return m_useHP; }
|
||||
void setDecimFilters(int sr, uint32_t decim);
|
||||
void setDecimFilters(int srHigh, int srLow, float fcHigh, float fcLow);
|
||||
float run(const float& sample);
|
||||
float runHP(const float& sample);
|
||||
float runLP(const float& sample);
|
||||
|
@ -93,6 +93,9 @@ void AudioG722::g722_encode_state::init(int rate, int options)
|
||||
out_buffer = 0;
|
||||
out_bits = 0;
|
||||
|
||||
char *pBand = (char *) band;
|
||||
std::fill(pBand, pBand + sizeof(band), 0);
|
||||
|
||||
if (rate == 48000) {
|
||||
bits_per_sample = 6;
|
||||
} else if (rate == 56000) {
|
||||
@ -263,8 +266,8 @@ int AudioG722::encode(uint8_t g722_data[], const int16_t amp[], int len)
|
||||
{
|
||||
if (state.itu_test_mode)
|
||||
{
|
||||
xlow =
|
||||
xhigh = amp[j++] >> 1;
|
||||
xlow = xhigh;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -115,7 +115,8 @@ void AudioNetSink::setParameters(Codec codec, bool stereo, int sampleRate)
|
||||
|
||||
m_codec = codec;
|
||||
m_sampleRate = sampleRate;
|
||||
m_audioFilter.setDecimFilters(m_sampleRate, m_decimation);
|
||||
|
||||
setDecimationFilters();
|
||||
|
||||
if (m_rtpBufferAudio)
|
||||
{
|
||||
@ -147,17 +148,38 @@ void AudioNetSink::setDecimation(uint32_t decimation)
|
||||
{
|
||||
m_decimation = decimation < 1 ? 1 : decimation > 6 ? 6 : decimation;
|
||||
qDebug() << "AudioNetSink::setDecimation: " << m_decimation << " from: " << decimation;
|
||||
m_audioFilter.setDecimFilters(m_sampleRate, m_decimation);
|
||||
setDecimationFilters();
|
||||
m_decimationCount = 0;
|
||||
}
|
||||
|
||||
void AudioNetSink::setDecimationFilters()
|
||||
{
|
||||
int decimatedSampleRate = m_sampleRate / m_decimation;
|
||||
|
||||
switch (m_codec)
|
||||
{
|
||||
case CodecPCMA:
|
||||
case CodecPCMU:
|
||||
m_audioFilter.setDecimFilters(m_sampleRate, decimatedSampleRate, 3300.0, 300.0);
|
||||
break;
|
||||
case CodecG722:
|
||||
m_audioFilter.setDecimFilters(m_sampleRate, decimatedSampleRate, 7000.0, 50.0);
|
||||
break;
|
||||
case CodecL8:
|
||||
case CodecL16:
|
||||
default:
|
||||
m_audioFilter.setDecimFilters(m_sampleRate, decimatedSampleRate, 0.45*decimatedSampleRate, 50.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioNetSink::write(qint16 isample)
|
||||
{
|
||||
qint16& sample = isample;
|
||||
|
||||
if (m_decimation > 1)
|
||||
{
|
||||
float lpSample = m_audioFilter.runLP(sample / 32768.0f);
|
||||
float lpSample = m_audioFilter.run(sample / 32768.0f);
|
||||
|
||||
if (m_decimationCount >= m_decimation - 1)
|
||||
{
|
||||
|
@ -68,10 +68,12 @@ public:
|
||||
void moveToThread(QThread *thread);
|
||||
|
||||
static const int m_udpBlockSize;
|
||||
static const int m_dataBlockSize = 16384*5; // room for G722 conversion (largest to date)
|
||||
static const int m_g722BlockSize = 16384; // number of resulting G722 bytes
|
||||
static const int m_dataBlockSize = 65536; // room for G722 conversion (64000 = 12800*5 largest to date)
|
||||
static const int m_g722BlockSize = 12800; // number of resulting G722 bytes (80*20ms frames)
|
||||
|
||||
protected:
|
||||
void setDecimationFilters();
|
||||
|
||||
SinkType m_type;
|
||||
Codec m_codec;
|
||||
QUdpSocket *m_udpSocket;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<h1>Audio management</h1>
|
||||
|
||||
Audio devices can be controlled with two dialogs:
|
||||
- The Audio preferences dialog: set audio device parameters. The dialog shows one tab for output and another tab for input devices
|
||||
- The Audio selection dialog: each channel plugin having audio output or input can show this dialog to select which device to use to direct output or input streams. This dialog opens by right clicking on a button that depends on the plugin (see plugin documentation).
|
||||
- The Audio preferences dialog: set audio device parameters. The dialog shows one tab for output and another tab for input devices. Detailed in sections 1 and 2.
|
||||
- The Audio selection dialog: each channel plugin having audio output or input can show this dialog to select which device to use to direct output or input streams. This dialog opens by right clicking on a button that depends on the plugin (see plugin documentation). Detailed in section 3.
|
||||
|
||||
<h2>1. Audio output preferences</h2>
|
||||
|
||||
@ -64,8 +64,8 @@ This is the codec applied before sending the stream via UDP. The following are a
|
||||
|
||||
- `L16`: Linear 16 bit signed integers (native)
|
||||
- `L8`: Linear 8 bit signed integers
|
||||
- `PCMA`: A-law compressed 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||
- `PCMU`: Mu-law compressed 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||
- `PCMA`: A-law 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||
- `PCMU`: Mu-law 8 bit PCM (requires 8000 Hz sample rate mono)
|
||||
- `G722`: G722 64 kbit/s (requires 16000 Hz sample rate mono)
|
||||
|
||||
<h3>1.10 SDP string</h3>
|
||||
@ -92,10 +92,14 @@ Check this box to activate the RTP protocol over UDP. RTP parameters are as foll
|
||||
- codec `L16`, `L8`: 96
|
||||
- codec `PCMA`: 8
|
||||
- codec `PCMU`: 0
|
||||
- Sample rate: the sample rate of the corresponding audio device
|
||||
- codec `G722`: 9
|
||||
- Sample rate: the resulting stream sample rate after decimation and possible compression:
|
||||
- codec `PCMA`, `PCMU`: must be 8000 S/s
|
||||
- codec `G722`: must be 8000 S/s (16000 S/s input before compression)
|
||||
- Sample format:
|
||||
- codec `L16`: 16 bit integer signed (S16LE)
|
||||
- codec `L8`, `PCMA`, `PCMU`: 8 bit integer signed (S8)
|
||||
- codec `G722`: 8 bit unsigned integer. Note that this is the stream compressed to 64 kbits/s.
|
||||
- Channels: 1 for mono (Left, Right and Mixed copy channels mode); 2 for stereo (Stereo copy channels mode)
|
||||
- Address and port: destination address and port (local on the client machine)
|
||||
|
||||
@ -107,7 +111,7 @@ m=audio 9998 RTP/AVP 96
|
||||
a=rtpmap:96 L16/48000/1
|
||||
```
|
||||
|
||||
For PCMA at 8k sample rate which is a popular format the contents of the file would be as follows:
|
||||
For PCMA or PCMU (here PCMA):
|
||||
|
||||
```
|
||||
c=IN IP4 192.168.0.34
|
||||
@ -115,9 +119,17 @@ m=audio 9998 RTP/AVP 8
|
||||
a=rtpmap:8 PCMA/8000/1
|
||||
```
|
||||
|
||||
For G722:
|
||||
|
||||
```
|
||||
c=IN IP4 192.168.0.34
|
||||
m=audio 9998 RTP/AVP 9
|
||||
a=rtpmap:9 G722/8000/1
|
||||
```
|
||||
|
||||
☞ Note that on Android clients VLC has trouble working with the RTP stream (choppy audio, hanging unexpectedly...) therefore [MX player](https://play.google.com/store/apps/details?id=com.mxtech.videoplayer.ad&hl=en) is recommended.
|
||||
|
||||
☞ With PCMA and PCMU codecs it is possible to listen to the RTP stream directly in the browser using a [Janus WebRTC server](https://janus.conf.meetecho.com/). Please refer to the Wiki for more instructions.
|
||||
☞ With PCMA and PCMU and more recently G722 codecs it is possible to listen to the RTP stream directly in the browser using a [Janus WebRTC server](https://janus.conf.meetecho.com/). Please refer to the Wiki page "Networking audio" for detailed instructions.
|
||||
|
||||
<h3>1.15 Cleanup registrations not in the list</h3>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user