1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-22 17:45:48 -05:00

UDP source: adaptation to 24 bit DSP

This commit is contained in:
f4exb 2018-01-28 02:30:15 +01:00
parent ba4d9ec0ca
commit b57793607c
12 changed files with 205 additions and 68 deletions

View File

@ -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`
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>
[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>
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>
@ -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.
<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>
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 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>
<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.

View File

@ -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.
<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
- `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.
- `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`.
- `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.
- `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.
- `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.
- `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.
- `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.
- `S16LE 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
- `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
- `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.
- `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`.
- `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.
- `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.
- `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.
- `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.
- `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 !DC Mono`: Same as above but with a DC block based on magnitude average over a 5 ms period
- `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>

View File

@ -57,8 +57,10 @@ UDPSrc::UDPSrc(DeviceSourceAPI *deviceAPI) :
{
setObjectName(m_channelId);
m_udpBuffer = new UDPSink<Sample>(this, udpBlockSize, m_settings.m_udpPort);
m_udpBufferMono = new UDPSink<FixReal>(this, udpBlockSize, m_settings.m_udpPort);
m_udpBuffer16 = new UDPSink<Sample16>(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_udpAudioBuf = new char[m_udpAudioPayloadSize];
@ -109,8 +111,10 @@ UDPSrc::UDPSrc(DeviceSourceAPI *deviceAPI) :
UDPSrc::~UDPSrc()
{
delete m_audioSocket;
delete m_udpBuffer;
delete m_udpBufferMono;
delete m_udpBuffer24;
delete m_udpBufferMono24;
delete m_udpBuffer16;
delete m_udpBufferMono16;
delete[] m_udpAudioBuf;
if (UDPFilter) delete UDPFilter;
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) &&
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFM) &&
(m_settings.m_sampleFormat != UDPSrcSettings::FormatNFMMono) &&
(m_settings.m_sampleFormat != UDPSrcSettings::FormatS16LE))
(m_settings.m_sampleFormat != UDPSrcSettings::FormatIQ))
{
agcFactor = m_agc.feedAndGetValue(ci);
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;
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));
}
}
@ -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;
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));
}
}
}
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatNFM)
{
double demod = m_squelchOpen ? SDR_RX_SCALED * m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
m_udpBuffer->write(Sample(demod, demod));
m_outMovingAverage.feed((demod * demod) / (SDR_RX_SCALED*SDR_RX_SCALED));
Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
FixReal demod = (FixReal) (SDR_RX_SCALEF * discri);
udpWrite(demod, demod);
m_outMovingAverage.feed(discri*discri);
}
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;
m_udpBufferMono->write(demod);
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
Real discri = m_squelchOpen ? m_phaseDiscri.phaseDiscriminator(ci) * m_settings.m_gain : 0;
FixReal demod = (FixReal) (SDR_RX_SCALEF * discri);
udpWriteMono(demod);
m_outMovingAverage.feed(discri*discri);
}
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++)
{
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));
}
}
@ -237,16 +243,17 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
for (int i = 0; i < n_out; i++)
{
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));
}
}
}
else if (m_settings.m_sampleFormat == UDPSrcSettings::FormatAMMono)
{
FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * agcFactor * m_settings.m_gain) : 0;
m_udpBufferMono->write(demod);
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
Real amplitude = m_squelchOpen ? sqrt(inMagSq) * agcFactor * m_settings.m_gain : 0;
FixReal demod = (FixReal) amplitude;
udpWriteMono(demod);
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
}
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);
m_amMovingAverage.feed(demodf);
FixReal demod = (FixReal) ((demodf - m_amMovingAverage.average()) * agcFactor * m_settings.m_gain);
m_udpBufferMono->write(demod);
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
Real amplitude = (demodf - m_amMovingAverage.average()) * agcFactor * m_settings.m_gain;
FixReal demod = (FixReal) amplitude;
udpWriteMono(demod);
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
}
else
{
m_udpBufferMono->write(0);
udpWriteMono(0);
m_outMovingAverage.feed(0);
}
}
@ -271,13 +279,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
double demodf = sqrt(inMagSq);
demodf = m_bandpass.filter(demodf);
demodf /= 301.0;
FixReal demod = (FixReal) (demodf * agcFactor * m_settings.m_gain);
m_udpBufferMono->write(demod);
m_outMovingAverage.feed((demod * demod) / SDR_RX_SCALED*SDR_RX_SCALED);
Real amplitude = demodf * agcFactor * m_settings.m_gain;
FixReal demod = (FixReal) amplitude;
udpWriteMono(demod);
m_outMovingAverage.feed((amplitude/SDR_RX_SCALEF)*(amplitude/SDR_RX_SCALEF));
}
else
{
m_udpBufferMono->write(0);
udpWriteMono(0);
m_outMovingAverage.feed(0);
}
}
@ -285,14 +294,12 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
{
if (m_squelchOpen)
{
Sample s(ci.real() * m_settings.m_gain, ci.imag() * m_settings.m_gain);
m_udpBuffer->write(s);
udpWrite(ci.real() * m_settings.m_gain, ci.imag() * m_settings.m_gain);
m_outMovingAverage.feed((inMagSq*m_settings.m_gain*m_settings.m_gain) / (SDR_RX_SCALED*SDR_RX_SCALED));
}
else
{
Sample s(0, 0);
m_udpBuffer->write(s);
udpWrite(0, 0);
m_outMovingAverage.feed(0);
}
}
@ -484,6 +491,7 @@ void UDPSrc::applySettings(const UDPSrcSettings& settings, bool force)
<< " m_squelchGate" << settings.m_squelchGate
<< " m_agc" << settings.m_agc
<< " m_sampleFormat: " << settings.m_sampleFormat
<< " m_sampleSize: " << 16 + settings.m_sampleSize*8
<< " m_outputSampleRate: " << settings.m_outputSampleRate
<< " m_rfBandwidth: " << settings.m_rfBandwidth
<< " 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)
{
m_udpBuffer->setAddress(const_cast<QString&>(settings.m_udpAddress));
m_udpBufferMono->setAddress(const_cast<QString&>(settings.m_udpAddress));
m_udpBuffer16->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)
{
m_udpBuffer->setPort(settings.m_udpPort);
m_udpBufferMono->setPort(settings.m_udpPort);
m_udpBuffer16->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)

View File

@ -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;
ThreadedBasebandSampleSink* m_threadedChannelizer;
DownChannelizer* m_channelizer;
@ -167,8 +183,10 @@ protected:
fftfilt* UDPFilter;
SampleVector m_sampleBuffer;
UDPSink<Sample> *m_udpBuffer;
UDPSink<FixReal> *m_udpBufferMono;
UDPSink<Sample16> *m_udpBuffer16;
UDPSink<int16_t> *m_udpBufferMono16;
UDPSink<Sample24> *m_udpBuffer24;
UDPSink<int32_t> *m_udpBufferMono24;
AudioVector m_audioBuffer;
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

View File

@ -262,7 +262,7 @@ void UDPSrcGUI::setSampleFormatIndex(const UDPSrcSettings::SampleFormat& sampleF
{
switch(sampleFormat)
{
case UDPSrcSettings::FormatS16LE:
case UDPSrcSettings::FormatIQ:
ui->sampleFormat->setCurrentIndex(0);
break;
case UDPSrcSettings::FormatNFM:
@ -303,7 +303,7 @@ void UDPSrcGUI::setSampleFormat(int index)
switch(index)
{
case 0:
m_settings.m_sampleFormat = UDPSrcSettings::FormatS16LE;
m_settings.m_sampleFormat = UDPSrcSettings::FormatIQ;
ui->fmDeviation->setEnabled(false);
break;
case 1:
@ -343,7 +343,7 @@ void UDPSrcGUI::setSampleFormat(int index)
ui->fmDeviation->setEnabled(false);
break;
default:
m_settings.m_sampleFormat = UDPSrcSettings::FormatS16LE;
m_settings.m_sampleFormat = UDPSrcSettings::FormatIQ;
ui->fmDeviation->setEnabled(false);
break;
}
@ -395,6 +395,18 @@ void UDPSrcGUI::on_sampleFormat_currentIndexChanged(int index)
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)))
{
bool ok;

View File

@ -95,6 +95,7 @@ private:
private slots:
void on_deltaFrequency_changed(qint64 value);
void on_sampleFormat_currentIndexChanged(int index);
void on_sampleSize_currentIndexChanged(int index);
void on_sampleRate_textEdited(const QString& arg1);
void on_rfBandwidth_textEdited(const QString& arg1);
void on_fmDeviation_textEdited(const QString& arg1);

View File

@ -364,7 +364,7 @@
<item row="4" column="0">
<layout class="QHBoxLayout" name="FormatLayout">
<item>
<widget class="QLabel" name="label">
<widget class="QLabel" name="formatLabel">
<property name="maximumSize">
<size>
<width>30</width>
@ -386,52 +386,69 @@
</property>
<item>
<property name="text">
<string>S16LE I/Q</string>
<string>I/Q</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE NFM</string>
<string>NFM</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE NFM Mono</string>
<string>NFM Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE LSB</string>
<string>LSB</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE USB</string>
<string>USB</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE LSB Mono</string>
<string>LSB Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE USB Mono</string>
<string>USB Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE AM Mono</string>
<string>AM Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE AM !DC Mono</string>
<string>AM !DC Mono</string>
</property>
</item>
<item>
<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>
</item>
</widget>

View File

@ -25,7 +25,7 @@
const PluginDescriptor UDPSrcPlugin::m_pluginDescriptor = {
QString("UDP Channel Source"),
QString("3.10.1"),
QString("3.11.1"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,

View File

@ -31,7 +31,8 @@ UDPSrcSettings::UDPSrcSettings() :
void UDPSrcSettings::resetToDefaults()
{
m_outputSampleRate = 48000;
m_sampleFormat = FormatS16LE;
m_sampleFormat = FormatIQ;
m_sampleSize = Size16bits;
m_inputFrequencyOffset = 0;
m_rfBandwidth = 12500;
m_fmDeviation = 2500;
@ -77,6 +78,7 @@ QByteArray UDPSrcSettings::serialize() const
s.writeS32(17, m_squelchGate);
s.writeBool(18, m_agc);
s.writeString(19, m_title);
s.writeS32(20, (int) m_sampleFormat);
return s.final();
@ -106,12 +108,12 @@ bool UDPSrcSettings::deserialize(const QByteArray& data)
d.readS32(2, &s32tmp, 0);
m_inputFrequencyOffset = s32tmp;
d.readS32(3, &s32tmp, FormatS16LE);
d.readS32(3, &s32tmp, FormatIQ);
if ((s32tmp >= 0) && (s32tmp < (int) FormatNone)) {
m_sampleFormat = (SampleFormat) s32tmp;
} else {
m_sampleFormat = FormatS16LE;
m_sampleFormat = FormatIQ;
}
d.readReal(4, &m_outputSampleRate, 48000.0);
@ -134,6 +136,14 @@ bool UDPSrcSettings::deserialize(const QByteArray& data)
d.readBool(18, &m_agc, false);
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;
}
else

View File

@ -26,7 +26,7 @@ struct Serializable;
struct UDPSrcSettings
{
enum SampleFormat {
FormatS16LE,
FormatIQ,
FormatNFM,
FormatNFMMono,
FormatLSB,
@ -39,8 +39,15 @@ struct UDPSrcSettings
FormatNone
};
enum SampleSize {
Size16bits,
Size24bits,
SizeNone
};
float m_outputSampleRate;
SampleFormat m_sampleFormat;
SampleSize m_sampleSize;
int64_t m_inputFrequencyOffset;
float m_rfBandwidth;
int m_fmDeviation;