mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
UDP source: adaptation to 24 bit DSP
This commit is contained in:
parent
ba4d9ec0ca
commit
b57793607c
17
Readme.md
17
Readme.md
@ -81,6 +81,8 @@ If you use your own location for libairspyhf install directory you need to speci
|
|||||||
|
|
||||||
`-DLIBAIRSPYHF_LIBRARIES=/opt/install/libairspyhf/lib/libairspyhf.so -DLIBAIRSPYHF_INCLUDE_DIR=/opt/install/libairspyhf/include`
|
`-DLIBAIRSPYHF_LIBRARIES=/opt/install/libairspyhf/lib/libairspyhf.so -DLIBAIRSPYHF_INCLUDE_DIR=/opt/install/libairspyhf/include`
|
||||||
|
|
||||||
|
It is recommended to add `-DRX_SAMPLE_24BIT` on the cmake command line to activate the Rx 24 bit DSP build and take advantage of improved dynamic range when using decimation.
|
||||||
|
|
||||||
<h2>BladeRF</h2>
|
<h2>BladeRF</h2>
|
||||||
|
|
||||||
[BladeRF](https://www.nuand.com/) is supported through the libbladerf library that should be installed in your system for proper build of the software and operation support. Add `libbladerf-dev` to the list of dependencies to install.
|
[BladeRF](https://www.nuand.com/) is supported through the libbladerf library that should be installed in your system for proper build of the software and operation support. Add `libbladerf-dev` to the list of dependencies to install.
|
||||||
@ -160,7 +162,7 @@ If you use your own location for libmirisdr-4 install directory you need to spec
|
|||||||
|
|
||||||
<h1>Plugins for special devices</h1>
|
<h1>Plugins for special devices</h1>
|
||||||
|
|
||||||
These plugins do not use any hardware device connected to your system. They support "virtual" devices related to the file system or the network.
|
These plugins do not use any hardware device connected to your system.
|
||||||
|
|
||||||
<h2>File input</h2>
|
<h2>File input</h2>
|
||||||
|
|
||||||
@ -176,6 +178,10 @@ The [File sink plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/sample
|
|||||||
|
|
||||||
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is always available in the list of devices as `FileSink[0]` even if no physical device is connected.
|
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is always available in the list of devices as `FileSink[0]` even if no physical device is connected.
|
||||||
|
|
||||||
|
<h2>Test source</h2>
|
||||||
|
|
||||||
|
The [Test source plugin](https://github.com/f4exb/sdrangel/tree/master/plugins/samplesource/testsource) is an internal continuous wave generator that can be used to carry out test of software internals.
|
||||||
|
|
||||||
<h2>SDRdaemon receiver input</h2>
|
<h2>SDRdaemon receiver input</h2>
|
||||||
|
|
||||||
Linux only.
|
Linux only.
|
||||||
@ -290,6 +296,15 @@ To be sure you will need at least Qt version 5.5. It definitely does not work wi
|
|||||||
- Windows 32 build is made with 5.9.1 and has Qt ANGLE support (OpenGL emulation with DirectX)
|
- Windows 32 build is made with 5.9.1 and has Qt ANGLE support (OpenGL emulation with DirectX)
|
||||||
- Windows 64 build is made with 5.9.1 and has no Qt ANGLE support (native OpenGL)
|
- Windows 64 build is made with 5.9.1 and has no Qt ANGLE support (native OpenGL)
|
||||||
|
|
||||||
|
<h2>24 bit DSP</h2>
|
||||||
|
|
||||||
|
By default all Rx DSP processes use 16 bit samples coded on int16 fields. In order to use 24 bit samples coded on int32 fields you can specify `-DRX_SAMPLE_24BIT` on the cmake command line. This will give more dynamic range when the number of bits with decimation exceeds 16 bits:
|
||||||
|
|
||||||
|
- RTL-SDR, HackRF: (8 bit native) no advantage
|
||||||
|
- Funcube Pro and Pro+: (16 bit native) no decimation hence no advantage
|
||||||
|
- Airspy, BladeRF, LimeSDR, PlutoSDR, SDRPlay: (12 bit native) advantage for decimation by 32 or 64
|
||||||
|
- AirspyHF: (16 bit native) advantage for any decimation
|
||||||
|
|
||||||
<h2>Ubuntu</h2>
|
<h2>Ubuntu</h2>
|
||||||
|
|
||||||
<h3>Prerequisites for 14.04 LTS</h3>
|
<h3>Prerequisites for 14.04 LTS</h3>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
Binary file not shown.
@ -36,20 +36,25 @@ The display is in the format `address:audio port/data port`
|
|||||||
|
|
||||||
Sample rate in samples per second of the signal that is sent over UDP. The actual byte rate depends on the type of sample which corresponds to a number of bytes per sample.
|
Sample rate in samples per second of the signal that is sent over UDP. The actual byte rate depends on the type of sample which corresponds to a number of bytes per sample.
|
||||||
|
|
||||||
<h3>6: Type of samples</h3>
|
<h3>6: Type and size of samples</h3>
|
||||||
|
|
||||||
Combo box to specify the type of samples that are sent over UDP.
|
Left: combo box to specify the type of samples that are sent over UDP:
|
||||||
|
|
||||||
- `S16LE I/Q`: Raw I/Q samples on signed 16 bits integers with Little Endian layout. Use it with software that accepts I/Q data as input like GNUradio with the `UDP source` block. The output is interleaved I and Q samples
|
- `I/Q`: Raw I/Q samples. Use it with software that accepts I/Q data as input like GNUradio with the `UDP source` block. The output is interleaved I and Q samples
|
||||||
- `S16LE NFM`: AF of FM demodulated signal as 16 bits signed integers with Little Endian layout. Use it with software that takes the FM demodulated audio or the discriminator output of a radio as input. Make sure you specify the appropriate signal bandwidth (see 7) according to the AF bandwidth needs. The output is a repetition of NFM samples on real part and on imaginary part this facilitates integration wtih software expecting a stereo type of input with the same samples on L and R channels. With GNURadio just use a complex to real block.
|
- `NFM`: AF of FM demodulated signal. Use it with software that takes the FM demodulated audio or the discriminator output of a radio as input. Make sure you specify the appropriate signal bandwidth (see 7) according to the AF bandwidth needs. The output is a repetition of NFM samples on real part and on imaginary part this facilitates integration wtih software expecting a stereo type of input with the same samples on L and R channels. With GNURadio just use a complex to real block.
|
||||||
- `S16LE NFM Mono`: This is the same as above but only one sample is output for one NFM sample. This can be used with software that accept a mono type of input like `dsd` or `multimon`.
|
- `NFM Mono`: This is the same as above but only one sample is output for one NFM sample. This can be used with software that accept a mono type of input like `dsd` or `multimon`.
|
||||||
- `S16LE USB`: AF of USB demodulated signal as 16 bits signed integers with Little Endian layout. Use it with software that uses a SSB demodulated signal as input i.e. software that is based on the audio output of a SSB radio. The output is the I/Q binaural output of the demodulator.
|
- `USB`: AF of USB demodulated signal. Use it with software that uses a SSB demodulated signal as input i.e. software that is based on the audio output of a SSB radio. The output is the I/Q binaural output of the demodulator.
|
||||||
- `S16LE LSB`: AF of LSB demodulated signal as 16 bits signed integers with Little Endian layout. Use it with software that uses a SSB demodulated signal as input i.e. software that is based on the audio output of a SSB radio. The output is the I/Q binaural output of the demodulator.
|
- `LSB`: AF of LSB demodulated signal. Use it with software that uses a SSB demodulated signal as input i.e. software that is based on the audio output of a SSB radio. The output is the I/Q binaural output of the demodulator.
|
||||||
- `S16LE LSB Mono`: AF of the LSB part of a SSB demodulated signal as "mono" (I+Q)*0.7 samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
- `LSB Mono`: AF of the LSB part of a SSB demodulated signal as "mono" (I+Q)*0.7 samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
||||||
- `S16LE USB Mono`: AF of the USB part of a SSB demodulated signal as "mono" (I+Q)*0.7 samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
- `USB Mono`: AF of the USB part of a SSB demodulated signal as "mono" (I+Q)*0.7 samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
||||||
- `S16LE AM Mono`: AF of the enveloppe demodulated signal i.e. channel magnitude or sqrt(I² + Q²) as "mono" samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
- `AM Mono`: AF of the enveloppe demodulated signal i.e. channel magnitude or sqrt(I² + Q²) as "mono" samples that is one sample per demodulator output sample. This can be used with software that accepts mono type of input.
|
||||||
- `S16LE AM !DC Mono`: Same as above but with a DC block based on magnitude average over a 5 ms period
|
- `AM !DC Mono`: Same as above but with a DC block based on magnitude average over a 5 ms period
|
||||||
- `S16LE AM BPF Mono`: Same as AM Mono but raw magnitude signal is passed through a bandpass filter with lower cutoff at 300 Hz and higher cutoff at RF bandwidth frequency
|
- `AM BPF Mono`: Same as AM Mono but raw magnitude signal is passed through a bandpass filter with lower cutoff at 300 Hz and higher cutoff at RF bandwidth frequency
|
||||||
|
|
||||||
|
Right: Sample size in bits:
|
||||||
|
|
||||||
|
- `16 bits`: samples are 16 bit signed with little endian layout (S16LE)
|
||||||
|
- `24 bits`: samples are 32 bit signed with little endian layout (S32LE) using only the 3 less significant bytes. This means that the range is -2²³ to 2²³ - 1
|
||||||
|
|
||||||
<h3>7: Signal bandwidth</h3>
|
<h3>7: Signal bandwidth</h3>
|
||||||
|
|
||||||
|
@ -57,8 +57,10 @@ UDPSrc::UDPSrc(DeviceSourceAPI *deviceAPI) :
|
|||||||
{
|
{
|
||||||
setObjectName(m_channelId);
|
setObjectName(m_channelId);
|
||||||
|
|
||||||
m_udpBuffer = new UDPSink<Sample>(this, udpBlockSize, m_settings.m_udpPort);
|
m_udpBuffer16 = new UDPSink<Sample16>(this, udpBlockSize, m_settings.m_udpPort);
|
||||||
m_udpBufferMono = new UDPSink<FixReal>(this, udpBlockSize, m_settings.m_udpPort);
|
m_udpBufferMono16 = new UDPSink<int16_t>(this, udpBlockSize, m_settings.m_udpPort);
|
||||||
|
m_udpBuffer24 = new UDPSink<Sample24>(this, udpBlockSize, m_settings.m_udpPort);
|
||||||
|
m_udpBufferMono24 = new UDPSink<int32_t>(this, udpBlockSize, m_settings.m_udpPort);
|
||||||
m_audioSocket = new QUdpSocket(this);
|
m_audioSocket = new QUdpSocket(this);
|
||||||
m_udpAudioBuf = new char[m_udpAudioPayloadSize];
|
m_udpAudioBuf = new char[m_udpAudioPayloadSize];
|
||||||
|
|
||||||
@ -109,8 +111,10 @@ UDPSrc::UDPSrc(DeviceSourceAPI *deviceAPI) :
|
|||||||
UDPSrc::~UDPSrc()
|
UDPSrc::~UDPSrc()
|
||||||
{
|
{
|
||||||
delete m_audioSocket;
|
delete m_audioSocket;
|
||||||
delete m_udpBuffer;
|
delete m_udpBuffer24;
|
||||||
delete m_udpBufferMono;
|
delete m_udpBufferMono24;
|
||||||
|
delete m_udpBuffer16;
|
||||||
|
delete m_udpBufferMono16;
|
||||||
delete[] m_udpAudioBuf;
|
delete[] m_udpAudioBuf;
|
||||||
if (UDPFilter) delete UDPFilter;
|
if (UDPFilter) delete UDPFilter;
|
||||||
if (m_settings.m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
if (m_settings.m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo);
|
||||||
@ -148,7 +152,7 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
if ((m_settings.m_agc) &&
|
if ((m_settings.m_agc) &&
|
||||||
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFM) &&
|
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFM) &&
|
||||||
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFMMono) &&
|
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFMMono) &&
|
||||||
(m_settings.m_sampleFormat != UDPSrcSettings::FormatS16LE))
|
(m_settings.m_sampleFormat != UDPSrcSettings::FormatIQ))
|
||||||
{
|
{
|
||||||
agcFactor = m_agc.feedAndGetValue(ci);
|
agcFactor = m_agc.feedAndGetValue(ci);
|
||||||
inMagSq = m_agc.getMagSq();
|
inMagSq = m_agc.getMagSq();
|
||||||
@ -179,7 +183,7 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
{
|
{
|
||||||
l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0;
|
l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0;
|
||||||
r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0;
|
r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0;
|
||||||
m_udpBuffer->write(Sample(l, r));
|
udpWrite(l, r);
|
||||||
m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,22 +199,24 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
{
|
{
|
||||||
l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0;
|
l = m_squelchOpen ? sideband[i].real() * m_settings.m_gain : 0;
|
||||||
r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0;
|
r = m_squelchOpen ? sideband[i].imag() * m_settings.m_gain : 0;
|
||||||
m_udpBuffer->write(Sample(l, r));
|
udpWrite(l, r);
|
||||||
m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
m_outMovingAverage.feed((l*l + r*r) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatNFM)
|
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatNFM)
|
||||||
{
|
{
|
||||||
double demod = m_squelchOpen ? SDR_RX_SCALED * m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
|
Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
|
||||||
m_udpBuffer->write(Sample(demod, demod));
|
FixReal demod = (FixReal) (SDR_RX_SCALEF * discri);
|
||||||
m_outMovingAverage.feed((demod * demod) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
udpWrite(demod, demod);
|
||||||
|
m_outMovingAverage.feed(discri*discri);
|
||||||
}
|
}
|
||||||
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatNFMMono)
|
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatNFMMono)
|
||||||
{
|
{
|
||||||
FixReal demod = m_squelchOpen ? (FixReal) (SDR_RX_SCALEF * m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain) : 0;
|
Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
|
||||||
m_udpBufferMono->write(demod);
|
FixReal demod = (FixReal) (SDR_RX_SCALEF * discri);
|
||||||
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
|
udpWriteMono(demod);
|
||||||
|
m_outMovingAverage.feed(discri*discri);
|
||||||
}
|
}
|
||||||
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatLSBMono) // Monaural LSB
|
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatLSBMono) // Monaural LSB
|
||||||
{
|
{
|
||||||
@ -222,7 +228,7 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
for (int i = 0; i < n_out; i++)
|
for (int i = 0; i < n_out; i++)
|
||||||
{
|
{
|
||||||
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0;
|
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0;
|
||||||
m_udpBufferMono->write(l);
|
udpWriteMono(l);
|
||||||
m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,16 +243,17 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
for (int i = 0; i < n_out; i++)
|
for (int i = 0; i < n_out; i++)
|
||||||
{
|
{
|
||||||
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0;
|
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_settings.m_gain : 0;
|
||||||
m_udpBufferMono->write(l);
|
udpWriteMono(l);
|
||||||
m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
m_outMovingAverage.feed((l * l) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatAMMono)
|
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatAMMono)
|
||||||
{
|
{
|
||||||
FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * agcFactor * m_settings.m_gain) : 0;
|
Real amplitude = m_squelchOpen ? sqrt(inMagSq) * agcFactor * m_settings.m_gain : 0;
|
||||||
m_udpBufferMono->write(demod);
|
FixReal demod = (FixReal) amplitude;
|
||||||
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
|
udpWriteMono(demod);
|
||||||
|
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
|
||||||
}
|
}
|
||||||
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatAMNoDCMono)
|
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatAMNoDCMono)
|
||||||
{
|
{
|
||||||
@ -254,13 +261,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
{
|
{
|
||||||
double demodf = sqrt(inMagSq);
|
double demodf = sqrt(inMagSq);
|
||||||
m_amMovingAverage.feed(demodf);
|
m_amMovingAverage.feed(demodf);
|
||||||
FixReal demod = (FixReal) ((demodf - m_amMovingAverage.average()) * agcFactor * m_settings.m_gain);
|
Real amplitude = (demodf - m_amMovingAverage.average()) * agcFactor * m_settings.m_gain;
|
||||||
m_udpBufferMono->write(demod);
|
FixReal demod = (FixReal) amplitude;
|
||||||
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
|
udpWriteMono(demod);
|
||||||
|
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_udpBufferMono->write(0);
|
udpWriteMono(0);
|
||||||
m_outMovingAverage.feed(0);
|
m_outMovingAverage.feed(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,13 +279,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
double demodf = sqrt(inMagSq);
|
double demodf = sqrt(inMagSq);
|
||||||
demodf = m_bandpass.filter(demodf);
|
demodf = m_bandpass.filter(demodf);
|
||||||
demodf /= 301.0;
|
demodf /= 301.0;
|
||||||
FixReal demod = (FixReal) (demodf * agcFactor * m_settings.m_gain);
|
Real amplitude = demodf * agcFactor * m_settings.m_gain;
|
||||||
m_udpBufferMono->write(demod);
|
FixReal demod = (FixReal) amplitude;
|
||||||
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
|
udpWriteMono(demod);
|
||||||
|
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_udpBufferMono->write(0);
|
udpWriteMono(0);
|
||||||
m_outMovingAverage.feed(0);
|
m_outMovingAverage.feed(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,14 +294,12 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
|||||||
{
|
{
|
||||||
if (m_squelchOpen)
|
if (m_squelchOpen)
|
||||||
{
|
{
|
||||||
Sample s(ci.real() * m_settings.m_gain, ci.imag() * m_settings.m_gain);
|
udpWrite(ci.real() * m_settings.m_gain, ci.imag() * m_settings.m_gain);
|
||||||
m_udpBuffer->write(s);
|
|
||||||
m_outMovingAverage.feed((inMagSq*m_settings.m_gain*m_settings.m_gain) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
m_outMovingAverage.feed((inMagSq*m_settings.m_gain*m_settings.m_gain) / (SDR_RX_SCALED*SDR_RX_SCALED));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sample s(0, 0);
|
udpWrite(0, 0);
|
||||||
m_udpBuffer->write(s);
|
|
||||||
m_outMovingAverage.feed(0);
|
m_outMovingAverage.feed(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,6 +491,7 @@ void UDPSrc::applySettings(const UDPSrcSettings& settings, bool force)
|
|||||||
<< " m_squelchGate" << settings.m_squelchGate
|
<< " m_squelchGate" << settings.m_squelchGate
|
||||||
<< " m_agc" << settings.m_agc
|
<< " m_agc" << settings.m_agc
|
||||||
<< " m_sampleFormat: " << settings.m_sampleFormat
|
<< " m_sampleFormat: " << settings.m_sampleFormat
|
||||||
|
<< " m_sampleSize: " << 16 + settings.m_sampleSize*8
|
||||||
<< " m_outputSampleRate: " << settings.m_outputSampleRate
|
<< " m_outputSampleRate: " << settings.m_outputSampleRate
|
||||||
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||||
<< " m_fmDeviation: " << settings.m_fmDeviation
|
<< " m_fmDeviation: " << settings.m_fmDeviation
|
||||||
@ -568,14 +576,18 @@ void UDPSrc::applySettings(const UDPSrcSettings& settings, bool force)
|
|||||||
|
|
||||||
if ((settings.m_udpAddress != m_settings.m_udpAddress) || force)
|
if ((settings.m_udpAddress != m_settings.m_udpAddress) || force)
|
||||||
{
|
{
|
||||||
m_udpBuffer->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
m_udpBuffer16->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||||
m_udpBufferMono->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
m_udpBufferMono16->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||||
|
m_udpBuffer24->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||||
|
m_udpBufferMono24->setAddress(const_cast<QString&>(settings.m_udpAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_udpPort != m_settings.m_udpPort) || force)
|
if ((settings.m_udpPort != m_settings.m_udpPort) || force)
|
||||||
{
|
{
|
||||||
m_udpBuffer->setPort(settings.m_udpPort);
|
m_udpBuffer16->setPort(settings.m_udpPort);
|
||||||
m_udpBufferMono->setPort(settings.m_udpPort);
|
m_udpBufferMono16->setPort(settings.m_udpPort);
|
||||||
|
m_udpBuffer24->setPort(settings.m_udpPort);
|
||||||
|
m_udpBufferMono24->setPort(settings.m_udpPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_audioPort != m_settings.m_audioPort) || force)
|
if ((settings.m_audioPort != m_settings.m_audioPort) || force)
|
||||||
|
@ -142,6 +142,22 @@ protected:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Sample16
|
||||||
|
{
|
||||||
|
Sample16() : m_r(0), m_i(0) {}
|
||||||
|
Sample16(int16_t r, int16_t i) : m_r(r), m_i(i) {}
|
||||||
|
int16_t m_r;
|
||||||
|
int16_t m_i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sample24
|
||||||
|
{
|
||||||
|
Sample24() : m_r(0), m_i(0) {}
|
||||||
|
Sample24(int32_t r, int32_t i) : m_r(r), m_i(i) {}
|
||||||
|
int32_t m_r;
|
||||||
|
int32_t m_i;
|
||||||
|
};
|
||||||
|
|
||||||
DeviceSourceAPI *m_deviceAPI;
|
DeviceSourceAPI *m_deviceAPI;
|
||||||
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
ThreadedBasebandSampleSink* m_threadedChannelizer;
|
||||||
DownChannelizer* m_channelizer;
|
DownChannelizer* m_channelizer;
|
||||||
@ -167,8 +183,10 @@ protected:
|
|||||||
fftfilt* UDPFilter;
|
fftfilt* UDPFilter;
|
||||||
|
|
||||||
SampleVector m_sampleBuffer;
|
SampleVector m_sampleBuffer;
|
||||||
UDPSink<Sample> *m_udpBuffer;
|
UDPSink<Sample16> *m_udpBuffer16;
|
||||||
UDPSink<FixReal> *m_udpBufferMono;
|
UDPSink<int16_t> *m_udpBufferMono16;
|
||||||
|
UDPSink<Sample24> *m_udpBuffer24;
|
||||||
|
UDPSink<int32_t> *m_udpBufferMono24;
|
||||||
|
|
||||||
AudioVector m_audioBuffer;
|
AudioVector m_audioBuffer;
|
||||||
uint m_audioBufferFill;
|
uint m_audioBufferFill;
|
||||||
@ -259,6 +277,46 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void udpWrite(FixReal real, FixReal imag)
|
||||||
|
{
|
||||||
|
if (SDR_RX_SAMP_SZ == 16)
|
||||||
|
{
|
||||||
|
if (m_settings.m_sampleSize == UDPSrcSettings::Size16bits) {
|
||||||
|
m_udpBuffer16->write(Sample16(real, imag));
|
||||||
|
} else if (m_settings.m_sampleSize == UDPSrcSettings::Size24bits) {
|
||||||
|
m_udpBuffer24->write(Sample24(real<<8, imag<<8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (SDR_RX_SAMP_SZ == 24)
|
||||||
|
{
|
||||||
|
if (m_settings.m_sampleSize == UDPSrcSettings::Size16bits) {
|
||||||
|
m_udpBuffer16->write(Sample16(real>>8, imag>>8));
|
||||||
|
} else if (m_settings.m_sampleSize == UDPSrcSettings::Size24bits) {
|
||||||
|
m_udpBuffer24->write(Sample24(real, imag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void udpWriteMono(FixReal sample)
|
||||||
|
{
|
||||||
|
if (SDR_RX_SAMP_SZ == 16)
|
||||||
|
{
|
||||||
|
if (m_settings.m_sampleSize == UDPSrcSettings::Size16bits) {
|
||||||
|
m_udpBufferMono16->write(sample);
|
||||||
|
} else if (m_settings.m_sampleSize == UDPSrcSettings::Size24bits) {
|
||||||
|
m_udpBufferMono24->write(sample<<8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (SDR_RX_SAMP_SZ == 24)
|
||||||
|
{
|
||||||
|
if (m_settings.m_sampleSize == UDPSrcSettings::Size16bits) {
|
||||||
|
m_udpBufferMono16->write(sample>>8);
|
||||||
|
} else if (m_settings.m_sampleSize == UDPSrcSettings::Size24bits) {
|
||||||
|
m_udpBufferMono24->write(sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_UDPSRC_H
|
#endif // INCLUDE_UDPSRC_H
|
||||||
|
@ -262,7 +262,7 @@ void UDPSrcGUI::setSampleFormatIndex(const UDPSrcSettings::SampleFormat& sampleF
|
|||||||
{
|
{
|
||||||
switch(sampleFormat)
|
switch(sampleFormat)
|
||||||
{
|
{
|
||||||
case UDPSrcSettings::FormatS16LE:
|
case UDPSrcSettings::FormatIQ:
|
||||||
ui->sampleFormat->setCurrentIndex(0);
|
ui->sampleFormat->setCurrentIndex(0);
|
||||||
break;
|
break;
|
||||||
case UDPSrcSettings::FormatNFM:
|
case UDPSrcSettings::FormatNFM:
|
||||||
@ -303,7 +303,7 @@ void UDPSrcGUI::setSampleFormat(int index)
|
|||||||
switch(index)
|
switch(index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
m_settings.m_sampleFormat = UDPSrcSettings::FormatS16LE;
|
m_settings.m_sampleFormat = UDPSrcSettings::FormatIQ;
|
||||||
ui->fmDeviation->setEnabled(false);
|
ui->fmDeviation->setEnabled(false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
@ -343,7 +343,7 @@ void UDPSrcGUI::setSampleFormat(int index)
|
|||||||
ui->fmDeviation->setEnabled(false);
|
ui->fmDeviation->setEnabled(false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_settings.m_sampleFormat = UDPSrcSettings::FormatS16LE;
|
m_settings.m_sampleFormat = UDPSrcSettings::FormatIQ;
|
||||||
ui->fmDeviation->setEnabled(false);
|
ui->fmDeviation->setEnabled(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -395,6 +395,18 @@ void UDPSrcGUI::on_sampleFormat_currentIndexChanged(int index)
|
|||||||
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UDPSrcGUI::on_sampleSize_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
if ((index < 0) || (index >= UDPSrcSettings::SizeNone)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_settings.m_sampleSize = (UDPSrcSettings::SampleSize) index;
|
||||||
|
|
||||||
|
ui->applyBtn->setEnabled(true);
|
||||||
|
ui->applyBtn->setStyleSheet("QPushButton { background-color : green; }");
|
||||||
|
}
|
||||||
|
|
||||||
void UDPSrcGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unused)))
|
void UDPSrcGUI::on_sampleRate_textEdited(const QString& arg1 __attribute__((unused)))
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
@ -95,6 +95,7 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
void on_deltaFrequency_changed(qint64 value);
|
void on_deltaFrequency_changed(qint64 value);
|
||||||
void on_sampleFormat_currentIndexChanged(int index);
|
void on_sampleFormat_currentIndexChanged(int index);
|
||||||
|
void on_sampleSize_currentIndexChanged(int index);
|
||||||
void on_sampleRate_textEdited(const QString& arg1);
|
void on_sampleRate_textEdited(const QString& arg1);
|
||||||
void on_rfBandwidth_textEdited(const QString& arg1);
|
void on_rfBandwidth_textEdited(const QString& arg1);
|
||||||
void on_fmDeviation_textEdited(const QString& arg1);
|
void on_fmDeviation_textEdited(const QString& arg1);
|
||||||
|
@ -364,7 +364,7 @@
|
|||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<layout class="QHBoxLayout" name="FormatLayout">
|
<layout class="QHBoxLayout" name="FormatLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="formatLabel">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>30</width>
|
<width>30</width>
|
||||||
@ -386,52 +386,69 @@
|
|||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE I/Q</string>
|
<string>I/Q</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE NFM</string>
|
<string>NFM</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE NFM Mono</string>
|
<string>NFM Mono</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE LSB</string>
|
<string>LSB</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE USB</string>
|
<string>USB</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE LSB Mono</string>
|
<string>LSB Mono</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE USB Mono</string>
|
<string>USB Mono</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE AM Mono</string>
|
<string>AM Mono</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE AM !DC Mono</string>
|
<string>AM !DC Mono</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>S16LE AM BPF Mono</string>
|
<string>AM BPF Mono</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="sampleSize">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Samples size</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>16 bits</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>24 bits</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
const PluginDescriptor UDPSrcPlugin::m_pluginDescriptor = {
|
const PluginDescriptor UDPSrcPlugin::m_pluginDescriptor = {
|
||||||
QString("UDP Channel Source"),
|
QString("UDP Channel Source"),
|
||||||
QString("3.10.1"),
|
QString("3.11.1"),
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -31,7 +31,8 @@ UDPSrcSettings::UDPSrcSettings() :
|
|||||||
void UDPSrcSettings::resetToDefaults()
|
void UDPSrcSettings::resetToDefaults()
|
||||||
{
|
{
|
||||||
m_outputSampleRate = 48000;
|
m_outputSampleRate = 48000;
|
||||||
m_sampleFormat = FormatS16LE;
|
m_sampleFormat = FormatIQ;
|
||||||
|
m_sampleSize = Size16bits;
|
||||||
m_inputFrequencyOffset = 0;
|
m_inputFrequencyOffset = 0;
|
||||||
m_rfBandwidth = 12500;
|
m_rfBandwidth = 12500;
|
||||||
m_fmDeviation = 2500;
|
m_fmDeviation = 2500;
|
||||||
@ -77,6 +78,7 @@ QByteArray UDPSrcSettings::serialize() const
|
|||||||
s.writeS32(17, m_squelchGate);
|
s.writeS32(17, m_squelchGate);
|
||||||
s.writeBool(18, m_agc);
|
s.writeBool(18, m_agc);
|
||||||
s.writeString(19, m_title);
|
s.writeString(19, m_title);
|
||||||
|
s.writeS32(20, (int) m_sampleFormat);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
|
|
||||||
@ -106,12 +108,12 @@ bool UDPSrcSettings::deserialize(const QByteArray& data)
|
|||||||
d.readS32(2, &s32tmp, 0);
|
d.readS32(2, &s32tmp, 0);
|
||||||
m_inputFrequencyOffset = s32tmp;
|
m_inputFrequencyOffset = s32tmp;
|
||||||
|
|
||||||
d.readS32(3, &s32tmp, FormatS16LE);
|
d.readS32(3, &s32tmp, FormatIQ);
|
||||||
|
|
||||||
if ((s32tmp >= 0) && (s32tmp < (int) FormatNone)) {
|
if ((s32tmp >= 0) && (s32tmp < (int) FormatNone)) {
|
||||||
m_sampleFormat = (SampleFormat) s32tmp;
|
m_sampleFormat = (SampleFormat) s32tmp;
|
||||||
} else {
|
} else {
|
||||||
m_sampleFormat = FormatS16LE;
|
m_sampleFormat = FormatIQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
d.readReal(4, &m_outputSampleRate, 48000.0);
|
d.readReal(4, &m_outputSampleRate, 48000.0);
|
||||||
@ -134,6 +136,14 @@ bool UDPSrcSettings::deserialize(const QByteArray& data)
|
|||||||
d.readBool(18, &m_agc, false);
|
d.readBool(18, &m_agc, false);
|
||||||
d.readString(19, &m_title, "UDP Sample Source");
|
d.readString(19, &m_title, "UDP Sample Source");
|
||||||
|
|
||||||
|
d.readS32(20, &s32tmp, Size16bits);
|
||||||
|
|
||||||
|
if ((s32tmp >= 0) && (s32tmp < (int) SizeNone)) {
|
||||||
|
m_sampleSize = (SampleSize) s32tmp;
|
||||||
|
} else {
|
||||||
|
m_sampleSize = Size16bits;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -26,7 +26,7 @@ struct Serializable;
|
|||||||
struct UDPSrcSettings
|
struct UDPSrcSettings
|
||||||
{
|
{
|
||||||
enum SampleFormat {
|
enum SampleFormat {
|
||||||
FormatS16LE,
|
FormatIQ,
|
||||||
FormatNFM,
|
FormatNFM,
|
||||||
FormatNFMMono,
|
FormatNFMMono,
|
||||||
FormatLSB,
|
FormatLSB,
|
||||||
@ -39,8 +39,15 @@ struct UDPSrcSettings
|
|||||||
FormatNone
|
FormatNone
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SampleSize {
|
||||||
|
Size16bits,
|
||||||
|
Size24bits,
|
||||||
|
SizeNone
|
||||||
|
};
|
||||||
|
|
||||||
float m_outputSampleRate;
|
float m_outputSampleRate;
|
||||||
SampleFormat m_sampleFormat;
|
SampleFormat m_sampleFormat;
|
||||||
|
SampleSize m_sampleSize;
|
||||||
int64_t m_inputFrequencyOffset;
|
int64_t m_inputFrequencyOffset;
|
||||||
float m_rfBandwidth;
|
float m_rfBandwidth;
|
||||||
int m_fmDeviation;
|
int m_fmDeviation;
|
||||||
|
Loading…
Reference in New Issue
Block a user