1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

UDP source plugin: new formats with mono output in particular NFM for mono discriminator type output

This commit is contained in:
f4exb 2016-04-05 17:02:24 +02:00
parent 98f325d60e
commit 9cb1a41471
5 changed files with 146 additions and 29 deletions

View File

@ -23,8 +23,13 @@ Total power in dB relative to a +/- 1.0 amplitude signal received in the pass ba
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 SSB`: AF of SSB 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 interleaved samples of the USB (on real part) and LSB signals (on imaginary part).
- `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 mono from stereo like input. With GNURadio just use a complex to real block.
- `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`. With GNURadio you can use a short to float block but remember that the UDP payload size is now 1024 bytes so you have to change it in the UDP source block.
- `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. Remember that as these are single 16 bits samples the UDP payload size is 1024 bytes (not 2048).
- `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. Remember that as these are single 16 bits samples the UDP payload size is 1024 bytes (not 2048).
- `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. Remember that as these are single 16 bits samples the UDP payload size is 1024 bytes (not 2048)
<h3>4: Signal sample rate</h3>

View File

@ -40,13 +40,14 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, SampleSink* s
setObjectName("UDPSrc");
m_udpBuffer = new UDPSink<Sample>(this, udpBLockSampleSize, m_udpPort);
m_udpBufferMono = new UDPSink<FixReal>(this, udpBLockSampleSize, m_udpPort);
m_audioSocket = new QUdpSocket(this);
m_audioBuffer.resize(1<<9);
m_audioBufferFill = 0;
m_inputSampleRate = 96000;
m_sampleFormat = FormatSSB;
m_sampleFormat = FormatS16LE;
m_outputSampleRate = 48000;
m_rfBandwidth = 32000;
m_audioPort = m_udpPort - 1;
@ -65,7 +66,7 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, SampleSink* s
m_scale = 0;
m_boost = 0;
m_magsq = 0;
UDPFilter = new fftfilt(0.3 / 48.0, 16.0 / 48.0, udpBLockSampleSize * sizeof(Sample));
UDPFilter = new fftfilt(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate, udpBLockSampleSize * sizeof(Sample));
m_phaseDiscri.setFMScaling((float) m_outputSampleRate / (2.0f * m_fmDeviation));
@ -86,6 +87,7 @@ UDPSrc::~UDPSrc()
{
delete m_audioSocket;
delete m_udpBuffer;
delete m_udpBufferMono;
if (UDPFilter) delete UDPFilter;
if (m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo);
}
@ -151,16 +153,30 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
m_sampleBuffer.push_back(s);
m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate;
if (m_sampleFormat == FormatSSB)
if (m_sampleFormat == FormatLSB)
{
int n_out = UDPFilter->runSSB(ci, &sideband, false);
if (n_out)
{
for (int i = 0; i < n_out; i++)
{
l = sideband[i].real();
r = sideband[i].imag();
m_udpBuffer->write(Sample(l, r));
}
}
}
if (m_sampleFormat == FormatUSB)
{
int n_out = UDPFilter->runSSB(ci, &sideband, true);
if (n_out)
{
for (int i = 0; i < n_out; i+=2)
for (int i = 0; i < n_out; i++)
{
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
r = (sideband[i+1].real() + sideband[i+1].imag()) * 0.7;
l = sideband[i].real();
r = sideband[i].imag();
m_udpBuffer->write(Sample(l, r));
}
}
@ -170,6 +186,42 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci);
m_udpBuffer->write(Sample(demod, demod));
}
else if (m_sampleFormat == FormatNFMMono)
{
FixReal demod = (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci));
m_udpBufferMono->write(demod);
}
else if (m_sampleFormat == FormatLSBMono)
{
int n_out = UDPFilter->runSSB(ci, &sideband, false);
if (n_out)
{
for (int i = 0; i < n_out; i++)
{
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
m_udpBufferMono->write(l);
}
}
}
else if (m_sampleFormat == FormatUSBMono)
{
int n_out = UDPFilter->runSSB(ci, &sideband, true);
if (n_out)
{
for (int i = 0; i < n_out; i++)
{
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
m_udpBufferMono->write(l);
}
}
}
else if (m_sampleFormat == FormatAMMono)
{
FixReal demod = (FixReal) (32768.0f * sqrt(m_magsq));
m_udpBufferMono->write(demod);
}
else // Raw I/Q samples
{
m_udpBuffer->write(s);
@ -279,12 +331,14 @@ bool UDPSrc::handleMessage(const Message& cmd)
{
m_udpAddressStr = cfg.getUDPAddress();
m_udpBuffer->setAddress(m_udpAddressStr);
m_udpBufferMono->setAddress(m_udpAddressStr);
}
if (cfg.getUDPPort() != m_udpPort)
{
m_udpPort = cfg.getUDPPort();
m_udpBuffer->setPort(m_udpPort);
m_udpBufferMono->setPort(m_udpPort);
}
if (cfg.getAudioPort() != m_audioPort)
@ -313,15 +367,7 @@ bool UDPSrc::handleMessage(const Message& cmd)
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
if (m_sampleFormat == FormatSSB)
{
UDPFilter->create_filter(0.3 / 48.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
}
else
{
UDPFilter->create_filter(0.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
}
UDPFilter->create_filter(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate);
m_settingsMutex.unlock();

View File

@ -38,9 +38,14 @@ class UDPSrc : public SampleSink {
public:
enum SampleFormat {
FormatSSB,
FormatNFM,
FormatS16LE,
FormatNFM,
FormatNFMMono,
FormatLSB,
FormatUSB,
FormatLSBMono,
FormatUSBMono,
FormatAMMono,
FormatNone
};
@ -228,6 +233,7 @@ protected:
SampleVector m_sampleBuffer;
UDPSink<Sample> *m_udpBuffer;
UDPSink<FixReal> *m_udpBufferMono;
AudioVector m_audioBuffer;
uint m_audioBufferFill;

View File

@ -129,17 +129,32 @@ bool UDPSrcGUI::deserialize(const QByteArray& data)
restoreState(bytetmp);
d.readS32(2, &s32tmp, 0);
m_channelMarker.setCenterFrequency(s32tmp);
d.readS32(3, &s32tmp, UDPSrc::FormatSSB);
d.readS32(3, &s32tmp, UDPSrc::FormatS16LE);
switch(s32tmp) {
case UDPSrc::FormatSSB:
case UDPSrc::FormatS16LE:
ui->sampleFormat->setCurrentIndex(0);
break;
case UDPSrc::FormatNFM:
ui->sampleFormat->setCurrentIndex(1);
break;
case UDPSrc::FormatS16LE:
case UDPSrc::FormatNFMMono:
ui->sampleFormat->setCurrentIndex(2);
break;
case UDPSrc::FormatLSB:
ui->sampleFormat->setCurrentIndex(3);
break;
case UDPSrc::FormatUSB:
ui->sampleFormat->setCurrentIndex(4);
break;
case UDPSrc::FormatLSBMono:
ui->sampleFormat->setCurrentIndex(5);
break;
case UDPSrc::FormatUSBMono:
ui->sampleFormat->setCurrentIndex(6);
break;
case UDPSrc::FormatAMMono:
ui->sampleFormat->setCurrentIndex(7);
break;
default:
ui->sampleFormat->setCurrentIndex(0);
break;
@ -356,7 +371,7 @@ void UDPSrcGUI::applySettings()
switch(ui->sampleFormat->currentIndex())
{
case 0:
sampleFormat = UDPSrc::FormatSSB;
sampleFormat = UDPSrc::FormatS16LE;
ui->fmDeviation->setEnabled(false);
break;
case 1:
@ -364,11 +379,31 @@ void UDPSrcGUI::applySettings()
ui->fmDeviation->setEnabled(true);
break;
case 2:
sampleFormat = UDPSrc::FormatS16LE;
sampleFormat = UDPSrc::FormatNFMMono;
ui->fmDeviation->setEnabled(true);
break;
case 3:
sampleFormat = UDPSrc::FormatLSB;
ui->fmDeviation->setEnabled(false);
break;
case 4:
sampleFormat = UDPSrc::FormatUSB;
ui->fmDeviation->setEnabled(false);
break;
case 5:
sampleFormat = UDPSrc::FormatLSBMono;
ui->fmDeviation->setEnabled(false);
break;
case 6:
sampleFormat = UDPSrc::FormatUSBMono;
ui->fmDeviation->setEnabled(false);
break;
case 7:
sampleFormat = UDPSrc::FormatAMMono;
ui->fmDeviation->setEnabled(false);
break;
default:
sampleFormat = UDPSrc::FormatSSB;
sampleFormat = UDPSrc::FormatS16LE;
ui->fmDeviation->setEnabled(false);
break;
}
@ -416,7 +451,7 @@ void UDPSrcGUI::on_deltaFrequency_changed(quint64 value)
void UDPSrcGUI::on_sampleFormat_currentIndexChanged(int index)
{
if (index == 1) {
if ((index == 1) || (index == 2)) {
ui->fmDeviation->setEnabled(true);
} else {
ui->fmDeviation->setEnabled(false);

View File

@ -440,11 +440,11 @@
<string>Samples format</string>
</property>
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<item>
<property name="text">
<string>S16LE SSB</string>
<string>S16LE I/Q</string>
</property>
</item>
<item>
@ -454,7 +454,32 @@
</item>
<item>
<property name="text">
<string>S16LE I/Q</string>
<string>S16LE NFM Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE LSB</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE USB</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE LSB Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE USB Mono</string>
</property>
</item>
<item>
<property name="text">
<string>S16LE AM Mono</string>
</property>
</item>
</widget>