diff --git a/plugins/samplesource/audioinput/audioinput.cpp b/plugins/samplesource/audioinput/audioinput.cpp index 4234cdd51..2a1dc2bf9 100644 --- a/plugins/samplesource/audioinput/audioinput.cpp +++ b/plugins/samplesource/audioinput/audioinput.cpp @@ -287,6 +287,7 @@ void AudioInput::applySettings(const AudioInputSettings& settings, bool force, b if ((m_settings.m_iqMapping != settings.m_iqMapping) || force) { reverseAPIKeys.append("iqMapping"); + forwardChange = true; if (m_worker) { m_worker->setIQMapping(settings.m_iqMapping); @@ -306,7 +307,11 @@ void AudioInput::applySettings(const AudioInputSettings& settings, bool force, b if (forwardChange) { - DSPSignalNotification *notif = new DSPSignalNotification(m_settings.m_sampleRate/(1<getDeviceEngineInputMessageQueue()->push(notif); } } diff --git a/plugins/samplesource/audioinput/audioinputgui.cpp b/plugins/samplesource/audioinput/audioinputgui.cpp index 6c2ae9922..a4deece7b 100644 --- a/plugins/samplesource/audioinput/audioinputgui.cpp +++ b/plugins/samplesource/audioinput/audioinputgui.cpp @@ -37,7 +37,8 @@ AudioInputGui::AudioInputGui(DeviceUISet *deviceUISet, QWidget* parent) : m_deviceUISet(deviceUISet), m_forceSettings(true), m_settings(), - m_sampleSource(NULL) + m_sampleSource(nullptr), + m_centerFrequency(0) { m_sampleSource = (AudioInput*) m_deviceUISet->m_deviceAPI->getSampleSource(); @@ -130,6 +131,7 @@ void AudioInputGui::handleInputMessages() { DSPSignalNotification* notif = (DSPSignalNotification*) message; m_sampleRate = notif->getSampleRate(); + m_centerFrequency = notif->getCenterFrequency(); qDebug("AudioInputGui::handleInputMessages: DSPSignalNotification: SampleRate: %d", notif->getSampleRate()); updateSampleRateAndFrequency(); @@ -160,7 +162,7 @@ void AudioInputGui::updateSampleRateAndFrequency() */ { m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate); - m_deviceUISet->getSpectrum()->setCenterFrequency(0); + m_deviceUISet->getSpectrum()->setCenterFrequency(m_centerFrequency); m_deviceUISet->getSpectrum()->setSsbSpectrum(false); m_deviceUISet->getSpectrum()->setLsbDisplay(false); } diff --git a/plugins/samplesource/audioinput/audioinputgui.h b/plugins/samplesource/audioinput/audioinputgui.h index 8c8507f77..1976091d4 100644 --- a/plugins/samplesource/audioinput/audioinputgui.h +++ b/plugins/samplesource/audioinput/audioinputgui.h @@ -57,6 +57,7 @@ private: QTimer m_updateTimer; DeviceSampleSource* m_sampleSource; int m_sampleRate; + qint64 m_centerFrequency; MessageQueue m_inputMessageQueue; diff --git a/plugins/samplesource/audioinput/audioinputgui.ui b/plugins/samplesource/audioinput/audioinputgui.ui index 5c3511e66..f2081a25e 100644 --- a/plugins/samplesource/audioinput/audioinputgui.ui +++ b/plugins/samplesource/audioinput/audioinputgui.ui @@ -210,6 +210,13 @@ + + + + Dec + + + @@ -243,13 +250,6 @@ - - - - Dec - - - @@ -336,12 +336,12 @@ - I=L, Q=0 + Mono L - I=R, Q=0 + Mono R diff --git a/plugins/samplesource/audioinput/audioinputworker.cpp b/plugins/samplesource/audioinput/audioinputworker.cpp index f72de8f1c..7de170adf 100644 --- a/plugins/samplesource/audioinput/audioinputworker.cpp +++ b/plugins/samplesource/audioinput/audioinputworker.cpp @@ -33,7 +33,8 @@ AudioInputWorker::AudioInputWorker(SampleSinkFifo* sampleFifo, AudioFifo *fifo, m_log2Decim(0), m_iqMapping(AudioInputSettings::IQMapping::L), m_convertBuffer(m_convBufSamples), - m_sampleFifo(sampleFifo) + m_sampleFifo(sampleFifo), + m_quNCOPhase(0) { } @@ -56,20 +57,40 @@ void AudioInputWorker::stopWork() void AudioInputWorker::workIQ(unsigned int nbRead) { // Map between left and right audio channels and IQ channels - if (m_iqMapping == AudioInputSettings::IQMapping::L) - { - for (uint32_t i = 0; i < nbRead; i++) - m_buf[i*2+1] = 0; - } - else if (m_iqMapping == AudioInputSettings::IQMapping::R) + if ((m_iqMapping == AudioInputSettings::IQMapping::L) || // mono + (m_iqMapping == AudioInputSettings::IQMapping::R)) { for (uint32_t i = 0; i < nbRead; i++) { - m_buf[i*2] = m_buf[i*2+1]; - m_buf[i*2+1] = 0; + qint16 r = m_buf[i*2 + (m_iqMapping == AudioInputSettings::IQMapping::R ? 1 : 0)]; // real sample + + if (m_quNCOPhase == 0) // 0 + { + m_buf[i*2] = r; // 1 + m_buf[i*2+1] = 0; // 0 + m_quNCOPhase = 1; // next phase + } + else if (m_quNCOPhase == 1) // -pi/2 + { + m_buf[i*2] = 0; // 0 + m_buf[i*2+1] = -r; // -1 + m_quNCOPhase = 2; // next phase + } + else if (m_quNCOPhase == 2) // pi or -pi + { + m_buf[i*2] = -r; // -1 + m_buf[i*2+1] = 0; // 0 + m_quNCOPhase = 3; // next phase + } + else if (m_quNCOPhase == 3) // pi/2 + { + m_buf[i*2] = 0; // 0 + m_buf[i*2+1] = r; // 1 + m_quNCOPhase = 0; // next phase + } } } - else if (m_iqMapping == AudioInputSettings::IQMapping::LR) + else if (m_iqMapping == AudioInputSettings::IQMapping::LR) // stereo - reverse { for (uint32_t i = 0; i < nbRead; i++) { @@ -79,30 +100,35 @@ void AudioInputWorker::workIQ(unsigned int nbRead) } } + decimate(m_buf, nbRead); +} + +void AudioInputWorker::decimate(qint16 *buf, unsigned int nbRead) +{ SampleVector::iterator it = m_convertBuffer.begin(); switch (m_log2Decim) { case 0: - m_decimatorsIQ.decimate1(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate1(&it, buf, 2*nbRead); break; case 1: - m_decimatorsIQ.decimate2_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate2_cen(&it, buf, 2*nbRead); break; case 2: - m_decimatorsIQ.decimate4_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate4_cen(&it, buf, 2*nbRead); break; case 3: - m_decimatorsIQ.decimate8_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate8_cen(&it, buf, 2*nbRead); break; case 4: - m_decimatorsIQ.decimate16_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate16_cen(&it, buf, 2*nbRead); break; case 5: - m_decimatorsIQ.decimate32_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate32_cen(&it, buf, 2*nbRead); break; case 6: - m_decimatorsIQ.decimate64_cen(&it, m_buf, 2*nbRead); + m_decimatorsIQ.decimate64_cen(&it, buf, 2*nbRead); break; default: break; diff --git a/plugins/samplesource/audioinput/audioinputworker.h b/plugins/samplesource/audioinput/audioinputworker.h index 693e52177..f0c4e62ef 100644 --- a/plugins/samplesource/audioinput/audioinputworker.h +++ b/plugins/samplesource/audioinput/audioinputworker.h @@ -51,8 +51,10 @@ private: SampleVector m_convertBuffer; SampleSinkFifo* m_sampleFifo; Decimators m_decimatorsIQ; + int m_quNCOPhase; //!< Quarter sample rate pseudo NCO phase index (0, 90, 180, 270) void workIQ(unsigned int nbRead); + void decimate(qint16 *buf, unsigned int nbRead); private slots: void handleAudio(); diff --git a/plugins/samplesource/audioinput/readme.md b/plugins/samplesource/audioinput/readme.md index c60ba3831..9767705b4 100644 --- a/plugins/samplesource/audioinput/readme.md +++ b/plugins/samplesource/audioinput/readme.md @@ -38,9 +38,9 @@ A control to set the input volume. This is not supported by all input audio devi

7: Channel Map

-This controls how the left and right stereo audio channels map on to the IQ channels. +This controls how the left and right audio channels map on to the IQ channels. -* I=L, Q=0 - The left audio channel is driven to the I channel. The Q channel is set to 0. -* I=R, Q=0 - The right audio channel is driven to the I channel. The Q channel is set to 0. -* I=L, Q=R - The left audio channel is driven to the I channel. The right audio channel is driven to the Q channel. -* I=R, Q=L - The right audio channel is driven to the I channel. The left audio channel is driven to the Q channel. +* Mono L - Real samples are taken from the left audio channel and are heterodyned by the fourth of the sample rate (fs/4) to obtain complex samples. Therefore the spectrum of the complex baseband is centered at the fourth of the sample rate (fs/4). As per Nyquist rule only a bandwidth of half of the sample rate (fs/2) is available for real signals. Frequencies outside the [0, fs/2] interval are artefacts and can be eliminated by decimating by a factor of 2. +* Mono R - Same as above but takes the right audio channel for the real signal. +* I=L, Q=R - The left audio channel is driven to the I channel. The right audio channel is driven to the Q channel for a complex (analytic signal)input. +* I=R, Q=L - The right audio channel is driven to the I channel. The left audio channel is driven to the Q channel for a complex (analytic signal)input.