From 6d3ab1a7301ead68a58ff42788eae718fae00c43 Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 31 Jul 2019 02:38:50 +0200 Subject: [PATCH] Audio modulators audio feedback: AM, NFM, SSB. Removed existing changes for FreeDV and WFM --- plugins/channeltx/modam/ammod.cpp | 101 ++++++++++++++++- plugins/channeltx/modam/ammod.h | 9 ++ plugins/channeltx/modam/ammodgui.cpp | 17 +++ plugins/channeltx/modam/ammodgui.h | 3 + plugins/channeltx/modam/ammodgui.ui | 89 +++++++++++++-- plugins/channeltx/modam/ammodsettings.cpp | 2 +- plugins/channeltx/modfreedv/freedvmod.cpp | 8 -- plugins/channeltx/modfreedv/freedvmod.h | 5 - .../channeltx/modfreedv/freedvmodsettings.cpp | 9 -- .../channeltx/modfreedv/freedvmodsettings.h | 3 - plugins/channeltx/modnfm/nfmmod.cpp | 101 ++++++++++++++++- plugins/channeltx/modnfm/nfmmod.h | 10 ++ plugins/channeltx/modnfm/nfmmodgui.cpp | 17 +++ plugins/channeltx/modnfm/nfmmodgui.h | 3 + plugins/channeltx/modnfm/nfmmodgui.ui | 104 ++++++++++++++++-- plugins/channeltx/modnfm/nfmmodsettings.cpp | 2 +- plugins/channeltx/modssb/ssbmod.cpp | 101 ++++++++++++++++- plugins/channeltx/modssb/ssbmod.h | 12 +- plugins/channeltx/modssb/ssbmodgui.cpp | 17 +++ plugins/channeltx/modssb/ssbmodgui.h | 3 + plugins/channeltx/modssb/ssbmodgui.ui | 76 +++++++++++-- plugins/channeltx/modssb/ssbmodsettings.cpp | 2 +- plugins/channeltx/modwfm/wfmmod.cpp | 8 -- plugins/channeltx/modwfm/wfmmod.h | 5 - plugins/channeltx/modwfm/wfmmodsettings.cpp | 9 -- plugins/channeltx/modwfm/wfmmodsettings.h | 3 - sdrbase/dsp/dspcommands.h | 2 +- 27 files changed, 630 insertions(+), 91 deletions(-) diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index ed75857a1..eb0108493 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -57,7 +57,7 @@ AMMod::AMMod(DeviceAPI *deviceAPI) : m_outputSampleRate(48000), m_inputFrequencyOffset(0), m_audioFifo(4800), - m_feedbackAudioFifo(4800), + m_feedbackAudioFifo(48000), m_settingsMutex(QMutex::Recursive), m_fileSize(0), m_recordLength(0), @@ -81,6 +81,7 @@ AMMod::AMMod(DeviceAPI *deviceAPI) : DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue()); m_feedbackAudioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); m_toneNco.setFreq(1000.0, m_audioSampleRate); m_cwKeyer.setSampleRate(m_audioSampleRate); @@ -174,6 +175,11 @@ void AMMod::modulateSample() Real t; pullAF(t); + + if (m_settings.m_feedbackAudioEnable) { + pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f); + } + calculateLevel(t); m_audioBufferFill++; @@ -248,6 +254,50 @@ void AMMod::pullAF(Real& sample) } } +void AMMod::pushFeedback(Real sample) +{ + Complex c(sample, sample); + Complex ci; + + if (m_feedbackInterpolatorDistance < 1.0f) // interpolate + { + while (!m_feedbackInterpolator.interpolate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } + else // decimate + { + if (m_feedbackInterpolator.decimate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } +} + +void AMMod::processOneSample(Complex& ci) +{ + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real(); + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag(); + ++m_feedbackAudioBufferFill; + + if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size()) + { + uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill); + + if (res != m_feedbackAudioBufferFill) + { + qDebug("AMDemod::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f", + res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance); + m_feedbackAudioFifo.clear(); + } + + m_feedbackAudioBufferFill = 0; + } +} + void AMMod::calculateLevel(Real& sample) { if (m_levelCalcCount < m_levelNbSamples) @@ -361,12 +411,23 @@ bool AMMod::handleMessage(const Message& cmd) { DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd; uint32_t sampleRate = cfg.getSampleRate(); + DSPConfigureAudio::AudioType audioType = cfg.getAudioType(); qDebug() << "AMMod::handleMessage: DSPConfigureAudio:" - << " sampleRate: " << sampleRate; + << " sampleRate: " << sampleRate + << " audioType: " << audioType; - if (sampleRate != m_audioSampleRate) { - applyAudioSampleRate(sampleRate); + if (audioType == DSPConfigureAudio::AudioInput) + { + if (sampleRate != m_audioSampleRate) { + applyAudioSampleRate(sampleRate); + } + } + else if (audioType == DSPConfigureAudio::AudioOutput) + { + if (sampleRate != m_audioSampleRate) { + applyFeedbackAudioSampleRate(sampleRate); + } } return true; @@ -436,6 +497,24 @@ void AMMod::applyAudioSampleRate(int sampleRate) m_settingsMutex.unlock(); m_audioSampleRate = sampleRate; + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); +} + +void AMMod::applyFeedbackAudioSampleRate(unsigned int sampleRate) +{ + qDebug("AMMod::applyFeedbackAudioSampleRate: %u", sampleRate); + + m_settingsMutex.lock(); + + m_feedbackInterpolatorDistanceRemain = 0; + m_feedbackInterpolatorConsumed = false; + m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate; + Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f; + m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0); + + m_settingsMutex.unlock(); + + m_feedbackAudioSampleRate = sampleRate; } void AMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force) @@ -546,6 +625,20 @@ void AMMod::applySettings(const AMModSettings& settings, bool force) } } + if ((settings.m_feedbackAudioDeviceName != m_settings.m_feedbackAudioDeviceName) || force) + { + reverseAPIKeys.append("feedbackAudioDeviceName"); + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName); + audioDeviceManager->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue(), audioDeviceIndex); + uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex); + + if (m_feedbackAudioSampleRate != audioSampleRate) { + reverseAPIKeys.append("feedbackAudioSampleRate"); + applyFeedbackAudioSampleRate(audioSampleRate); + } + } + if (settings.m_useReverseAPI) { bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || diff --git a/plugins/channeltx/modam/ammod.h b/plugins/channeltx/modam/ammod.h index d89b1134d..9048ec7e7 100644 --- a/plugins/channeltx/modam/ammod.h +++ b/plugins/channeltx/modam/ammod.h @@ -277,11 +277,17 @@ private: NCO m_carrierNco; NCOF m_toneNco; Complex m_modSample; + Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; bool m_interpolatorConsumed; + Interpolator m_feedbackInterpolator; + Real m_feedbackInterpolatorDistance; + Real m_feedbackInterpolatorDistanceRemain; + bool m_feedbackInterpolatorConsumed; + double m_magsq; MovingAverageUtil m_movingAverage; @@ -315,9 +321,12 @@ private: QNetworkRequest m_networkRequest; void applyAudioSampleRate(int sampleRate); + void applyFeedbackAudioSampleRate(unsigned int sampleRate); + void processOneSample(Complex& ci); void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false); void applySettings(const AMModSettings& settings, bool force = false); void pullAF(Real& sample); + void pushFeedback(Real sample); void calculateLevel(Real& sample); void modulateSample(); void openFileStream(); diff --git a/plugins/channeltx/modam/ammodgui.cpp b/plugins/channeltx/modam/ammodgui.cpp index b08a3c10d..7e97166e0 100644 --- a/plugins/channeltx/modam/ammodgui.cpp +++ b/plugins/channeltx/modam/ammodgui.cpp @@ -236,6 +236,19 @@ void AMModGUI::on_mic_toggled(bool checked) applySettings(); } +void AMModGUI::on_feedbackEnable_toggled(bool checked) +{ + m_settings.m_feedbackAudioEnable = checked; + applySettings(); +} + +void AMModGUI::on_feedbackVolume_valueChanged(int value) +{ + ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2)); + m_settings.m_feedbackVolumeFactor = value / 100.0; + applySettings(); +} + void AMModGUI::on_navTimeSlider_valueChanged(int value) { if (m_enableNavTime && ((value >= 0) && (value <= 100))) @@ -440,6 +453,10 @@ void AMModGUI::displaySettings() ui->play->setChecked(m_settings.m_modAFInput == AMModSettings::AMModInputAF::AMModInputFile); ui->morseKeyer->setChecked(m_settings.m_modAFInput == AMModSettings::AMModInputAF::AMModInputCWTone); + ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable); + ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0)); + ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2)); + blockApplySettings(false); } diff --git a/plugins/channeltx/modam/ammodgui.h b/plugins/channeltx/modam/ammodgui.h index 8aca20c81..bfee39faf 100644 --- a/plugins/channeltx/modam/ammodgui.h +++ b/plugins/channeltx/modam/ammodgui.h @@ -107,6 +107,9 @@ private slots: void on_navTimeSlider_valueChanged(int value); void on_showFileDialog_clicked(bool checked); + void on_feedbackEnable_toggled(bool checked); + void on_feedbackVolume_valueChanged(int value); + void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); diff --git a/plugins/channeltx/modam/ammodgui.ui b/plugins/channeltx/modam/ammodgui.ui index a6fb4f3a6..12f09db18 100644 --- a/plugins/channeltx/modam/ammodgui.ui +++ b/plugins/channeltx/modam/ammodgui.ui @@ -56,7 +56,16 @@ 3 - + + 2 + + + 2 + + + 2 + + 2 @@ -436,17 +445,10 @@ - - - - Qt::Vertical - - - - Left: Source audio input Right: Select audio input device + Left: source audio input - Right: select audio input device ... @@ -460,6 +462,75 @@ + + + + Qt::Vertical + + + + + + + Left: enable / disable audio feedback - Right: select audio output device + + + ... + + + + :/sound_off.png + :/sound_on.png:/sound_off.png + + + true + + + + + + + + 24 + 24 + + + + Audio feedback volume + + + 0 + + + 100 + + + 1 + + + 50 + + + + + + + + 30 + 16777215 + + + + Audio feedback volume + + + 1.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/plugins/channeltx/modam/ammodsettings.cpp b/plugins/channeltx/modam/ammodsettings.cpp index a16d47082..8ed84cb8c 100644 --- a/plugins/channeltx/modam/ammodsettings.cpp +++ b/plugins/channeltx/modam/ammodsettings.cpp @@ -43,7 +43,7 @@ void AMModSettings::resetToDefaults() m_modAFInput = AMModInputAF::AMModInputNone; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackVolumeFactor = 1.0f; + m_feedbackVolumeFactor = 0.5f; m_feedbackAudioEnable = false; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; diff --git a/plugins/channeltx/modfreedv/freedvmod.cpp b/plugins/channeltx/modfreedv/freedvmod.cpp index 5ca596d5b..d065dba82 100644 --- a/plugins/channeltx/modfreedv/freedvmod.cpp +++ b/plugins/channeltx/modfreedv/freedvmod.cpp @@ -68,7 +68,6 @@ FreeDVMod::FreeDVMod(DeviceAPI *deviceAPI) : m_SSBFilterBufferIndex(0), m_sampleSink(0), m_audioFifo(4800), - m_feedbackAudioFifo(4800), m_settingsMutex(QMutex::Recursive), m_fileSize(0), m_recordLength(0), @@ -90,9 +89,6 @@ FreeDVMod::FreeDVMod(DeviceAPI *deviceAPI) : DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue()); m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate(); - DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue()); - m_feedbackAudioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); - m_SSBFilter = new fftfilt(m_lowCutoff / m_audioSampleRate, m_hiCutoff / m_audioSampleRate, m_ssbFftLen); m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size std::fill(m_SSBFilterBuffer, m_SSBFilterBuffer+(m_ssbFftLen>>1), Complex{0,0}); @@ -100,9 +96,6 @@ FreeDVMod::FreeDVMod(DeviceAPI *deviceAPI) : m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; - m_feedbackAudioBuffer.resize(1<<14); - m_feedbackAudioBufferFill = 0; - m_sum.real(0.0f); m_sum.imag(0.0f); m_undersampleCount = 0; @@ -131,7 +124,6 @@ FreeDVMod::~FreeDVMod() disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); delete m_networkManager; - DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_feedbackAudioFifo); DSPEngine::instance()->getAudioDeviceManager()->removeAudioSource(&m_audioFifo); m_deviceAPI->removeChannelSourceAPI(this); diff --git a/plugins/channeltx/modfreedv/freedvmod.h b/plugins/channeltx/modfreedv/freedvmod.h index af59187c3..9f657b6a4 100644 --- a/plugins/channeltx/modfreedv/freedvmod.h +++ b/plugins/channeltx/modfreedv/freedvmod.h @@ -314,11 +314,6 @@ private: uint m_audioBufferFill; AudioFifo m_audioFifo; - quint32 m_feedbackAudioSampleRate; - AudioVector m_feedbackAudioBuffer; - uint m_feedbackAudioBufferFill; - AudioFifo m_feedbackAudioFifo; - QMutex m_settingsMutex; std::ifstream m_ifstream; diff --git a/plugins/channeltx/modfreedv/freedvmodsettings.cpp b/plugins/channeltx/modfreedv/freedvmodsettings.cpp index 7274e571f..392f57416 100644 --- a/plugins/channeltx/modfreedv/freedvmodsettings.cpp +++ b/plugins/channeltx/modfreedv/freedvmodsettings.cpp @@ -42,9 +42,6 @@ void FreeDVModSettings::resetToDefaults() m_title = "FreeDV Modulator"; m_modAFInput = FreeDVModInputAF::FreeDVModInputNone; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackVolumeFactor = 1.0f; - m_feedbackAudioEnable = false; m_freeDVMode = FreeDVMode::FreeDVMode2400A; m_gaugeInputElseModem = false; m_useReverseAPI = false; @@ -87,9 +84,6 @@ QByteArray FreeDVModSettings::serialize() const s.writeU32(24, m_reverseAPIPort); s.writeU32(25, m_reverseAPIDeviceIndex); s.writeU32(26, m_reverseAPIChannelIndex); - s.writeString(27, m_feedbackAudioDeviceName); - s.writeReal(28, m_feedbackVolumeFactor); - s.writeBool(29, m_feedbackAudioEnable); return s.final(); } @@ -168,9 +162,6 @@ bool FreeDVModSettings::deserialize(const QByteArray& data) m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; d.readU32(26, &utmp, 0); m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; - d.readString(27, &m_feedbackAudioDeviceName, AudioDeviceManager::m_defaultDeviceName); - d.readReal(28, &m_feedbackVolumeFactor, 1.0); - d.readBool(29, &m_feedbackAudioEnable, false); return true; } diff --git a/plugins/channeltx/modfreedv/freedvmodsettings.h b/plugins/channeltx/modfreedv/freedvmodsettings.h index 29b18e178..77d689cc1 100644 --- a/plugins/channeltx/modfreedv/freedvmodsettings.h +++ b/plugins/channeltx/modfreedv/freedvmodsettings.h @@ -55,9 +55,6 @@ struct FreeDVModSettings QString m_title; FreeDVModInputAF m_modAFInput; QString m_audioDeviceName; - QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback - float m_feedbackVolumeFactor; - bool m_feedbackAudioEnable; FreeDVMode m_freeDVMode; bool m_gaugeInputElseModem; //!< Volume gauge shows speech input level else modem level diff --git a/plugins/channeltx/modnfm/nfmmod.cpp b/plugins/channeltx/modnfm/nfmmod.cpp index f244b7822..1bbc62e5a 100644 --- a/plugins/channeltx/modnfm/nfmmod.cpp +++ b/plugins/channeltx/modnfm/nfmmod.cpp @@ -60,7 +60,7 @@ NFMMod::NFMMod(DeviceAPI *deviceAPI) : m_inputFrequencyOffset(0), m_modPhasor(0.0f), m_audioFifo(4800), - m_feedbackAudioFifo(4800), + m_feedbackAudioFifo(48000), m_settingsMutex(QMutex::Recursive), m_fileSize(0), m_recordLength(0), @@ -84,6 +84,7 @@ NFMMod::NFMMod(DeviceAPI *deviceAPI) : DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue()); m_feedbackAudioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); m_lowpass.create(301, m_audioSampleRate, 250.0); m_toneNco.setFreq(1000.0, m_audioSampleRate); @@ -178,6 +179,11 @@ void NFMMod::modulateSample() Real t; pullAF(t); + + if (m_settings.m_feedbackAudioEnable) { + pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f); + } + calculateLevel(t); m_audioBufferFill++; @@ -262,6 +268,50 @@ void NFMMod::pullAF(Real& sample) } } +void NFMMod::pushFeedback(Real sample) +{ + Complex c(sample, sample); + Complex ci; + + if (m_feedbackInterpolatorDistance < 1.0f) // interpolate + { + while (!m_feedbackInterpolator.interpolate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } + else // decimate + { + if (m_feedbackInterpolator.decimate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } +} + +void NFMMod::processOneSample(Complex& ci) +{ + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real(); + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag(); + ++m_feedbackAudioBufferFill; + + if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size()) + { + uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill); + + if (res != m_feedbackAudioBufferFill) + { + qDebug("AMDemod::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f", + res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance); + m_feedbackAudioFifo.clear(); + } + + m_feedbackAudioBufferFill = 0; + } +} + void NFMMod::calculateLevel(Real& sample) { if (m_levelCalcCount < m_levelNbSamples) @@ -376,12 +426,23 @@ bool NFMMod::handleMessage(const Message& cmd) { DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd; uint32_t sampleRate = cfg.getSampleRate(); + DSPConfigureAudio::AudioType audioType = cfg.getAudioType(); qDebug() << "NFMMod::handleMessage: DSPConfigureAudio:" - << " sampleRate: " << sampleRate; + << " sampleRate: " << sampleRate + << " audioType: " << audioType; - if (sampleRate != m_audioSampleRate) { - applyAudioSampleRate(sampleRate); + if (audioType == DSPConfigureAudio::AudioInput) + { + if (sampleRate != m_audioSampleRate) { + applyAudioSampleRate(sampleRate); + } + } + else if (audioType == DSPConfigureAudio::AudioOutput) + { + if (sampleRate != m_audioSampleRate) { + applyFeedbackAudioSampleRate(sampleRate); + } } return true; @@ -454,6 +515,24 @@ void NFMMod::applyAudioSampleRate(int sampleRate) m_settingsMutex.unlock(); m_audioSampleRate = sampleRate; + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); +} + +void NFMMod::applyFeedbackAudioSampleRate(unsigned int sampleRate) +{ + qDebug("AMMod::applyFeedbackAudioSampleRate: %u", sampleRate); + + m_settingsMutex.lock(); + + m_feedbackInterpolatorDistanceRemain = 0; + m_feedbackInterpolatorConsumed = false; + m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate; + Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f; + m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0); + + m_settingsMutex.unlock(); + + m_feedbackAudioSampleRate = sampleRate; } void NFMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force) @@ -588,6 +667,20 @@ void NFMMod::applySettings(const NFMModSettings& settings, bool force) } } + if ((settings.m_feedbackAudioDeviceName != m_settings.m_feedbackAudioDeviceName) || force) + { + reverseAPIKeys.append("feedbackAudioDeviceName"); + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName); + audioDeviceManager->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue(), audioDeviceIndex); + uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex); + + if (m_feedbackAudioSampleRate != audioSampleRate) { + reverseAPIKeys.append("feedbackAudioSampleRate"); + applyFeedbackAudioSampleRate(audioSampleRate); + } + } + if (settings.m_useReverseAPI) { bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || diff --git a/plugins/channeltx/modnfm/nfmmod.h b/plugins/channeltx/modnfm/nfmmod.h index 9069a4e46..ccd71b2c3 100644 --- a/plugins/channeltx/modnfm/nfmmod.h +++ b/plugins/channeltx/modnfm/nfmmod.h @@ -281,10 +281,17 @@ private: NCOF m_ctcssNco; float m_modPhasor; //!< baseband modulator phasor Complex m_modSample; + Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; bool m_interpolatorConsumed; + + Interpolator m_feedbackInterpolator; + Real m_feedbackInterpolatorDistance; + Real m_feedbackInterpolatorDistanceRemain; + bool m_feedbackInterpolatorConsumed; + Lowpass m_lowpass; Bandpass m_bandpass; @@ -322,9 +329,12 @@ private: static const int m_levelNbSamples; void applyAudioSampleRate(int sampleRate); + void applyFeedbackAudioSampleRate(unsigned int sampleRate); + void processOneSample(Complex& ci); void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false); void applySettings(const NFMModSettings& settings, bool force = false); void pullAF(Real& sample); + void pushFeedback(Real sample); void calculateLevel(Real& sample); void modulateSample(); void openFileStream(); diff --git a/plugins/channeltx/modnfm/nfmmodgui.cpp b/plugins/channeltx/modnfm/nfmmodgui.cpp index 9bf5c65ba..169058501 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.cpp +++ b/plugins/channeltx/modnfm/nfmmodgui.cpp @@ -240,6 +240,19 @@ void NFMModGUI::on_mic_toggled(bool checked) applySettings(); } +void NFMModGUI::on_feedbackEnable_toggled(bool checked) +{ + m_settings.m_feedbackAudioEnable = checked; + applySettings(); +} + +void NFMModGUI::on_feedbackVolume_valueChanged(int value) +{ + ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2)); + m_settings.m_feedbackVolumeFactor = value / 100.0; + applySettings(); +} + void NFMModGUI::on_navTimeSlider_valueChanged(int value) { if (m_enableNavTime && ((value >= 0) && (value <= 100))) @@ -474,6 +487,10 @@ void NFMModGUI::displaySettings() ui->play->setChecked(m_settings.m_modAFInput == NFMModSettings::NFMModInputAF::NFMModInputFile); ui->morseKeyer->setChecked(m_settings.m_modAFInput == NFMModSettings::NFMModInputAF::NFMModInputCWTone); + ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable); + ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0)); + ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2)); + blockApplySettings(false); } diff --git a/plugins/channeltx/modnfm/nfmmodgui.h b/plugins/channeltx/modnfm/nfmmodgui.h index 9fd04f0fe..085d9713d 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.h +++ b/plugins/channeltx/modnfm/nfmmodgui.h @@ -110,6 +110,9 @@ private slots: void on_ctcss_currentIndexChanged(int index); void on_ctcssOn_toggled(bool checked); + void on_feedbackEnable_toggled(bool checked); + void on_feedbackVolume_valueChanged(int value); + void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); diff --git a/plugins/channeltx/modnfm/nfmmodgui.ui b/plugins/channeltx/modnfm/nfmmodgui.ui index d6c935ba3..b6aeb16f0 100644 --- a/plugins/channeltx/modnfm/nfmmodgui.ui +++ b/plugins/channeltx/modnfm/nfmmodgui.ui @@ -56,7 +56,16 @@ 3 - + + 2 + + + 2 + + + 2 + + 2 @@ -476,13 +485,6 @@ - - - - Qt::Vertical - - - @@ -500,6 +502,75 @@ + + + + Qt::Vertical + + + + + + + Left: enable / disable audio feedback - Right: select audio output device + + + ... + + + + :/sound_off.png + :/sound_on.png:/sound_off.png + + + true + + + + + + + + 24 + 24 + + + + Audio feedback volume + + + 0 + + + 100 + + + 1 + + + 50 + + + + + + + + 30 + 16777215 + + + + Audio feedback volume + + + 1.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -520,6 +591,10 @@ + + + + @@ -550,6 +625,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + diff --git a/plugins/channeltx/modnfm/nfmmodsettings.cpp b/plugins/channeltx/modnfm/nfmmodsettings.cpp index ac197720e..85bd1e76c 100644 --- a/plugins/channeltx/modnfm/nfmmodsettings.cpp +++ b/plugins/channeltx/modnfm/nfmmodsettings.cpp @@ -61,7 +61,7 @@ void NFMModSettings::resetToDefaults() m_modAFInput = NFMModInputAF::NFMModInputNone; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackVolumeFactor = 1.0f; + m_feedbackVolumeFactor = 0.5f; m_feedbackAudioEnable = false; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index f14d2fa1c..841926260 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -66,7 +66,7 @@ SSBMod::SSBMod(DeviceAPI *deviceAPI) : m_DSBFilterBufferIndex(0), m_sampleSink(0), m_audioFifo(4800), - m_feedbackAudioFifo(4800), + m_feedbackAudioFifo(48000), m_settingsMutex(QMutex::Recursive), m_fileSize(0), m_recordLength(0), @@ -83,6 +83,7 @@ SSBMod::SSBMod(DeviceAPI *deviceAPI) : DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue()); m_feedbackAudioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); m_SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_audioSampleRate, m_settings.m_bandwidth / m_audioSampleRate, m_ssbFftLen); m_DSBFilter = new fftfilt((2.0f * m_settings.m_bandwidth) / m_audioSampleRate, 2 * m_ssbFftLen); @@ -206,6 +207,11 @@ void SSBMod::pullAudio(int nbSamples) void SSBMod::modulateSample() { pullAF(m_modSample); + + if (m_settings.m_feedbackAudioEnable) { + pushFeedback(m_modSample * m_settings.m_feedbackVolumeFactor * 16384.0f); + } + calculateLevel(m_modSample); m_audioBufferFill++; } @@ -503,6 +509,49 @@ void SSBMod::pullAF(Complex& sample) } } +void SSBMod::pushFeedback(Complex c) +{ + Complex ci; + + if (m_feedbackInterpolatorDistance < 1.0f) // interpolate + { + while (!m_feedbackInterpolator.interpolate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } + else // decimate + { + if (m_feedbackInterpolator.decimate(&m_feedbackInterpolatorDistanceRemain, c, &ci)) + { + processOneSample(ci); + m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance; + } + } +} + +void SSBMod::processOneSample(Complex& ci) +{ + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real(); + m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag(); + ++m_feedbackAudioBufferFill; + + if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size()) + { + uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill); + + if (res != m_feedbackAudioBufferFill) + { + qDebug("AMDemod::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f", + res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance); + m_feedbackAudioFifo.clear(); + } + + m_feedbackAudioBufferFill = 0; + } +} + void SSBMod::calculateLevel(Complex& sample) { Real t = sample.real(); // TODO: possibly adjust depending on sample type @@ -617,12 +666,23 @@ bool SSBMod::handleMessage(const Message& cmd) { DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd; uint32_t sampleRate = cfg.getSampleRate(); + DSPConfigureAudio::AudioType audioType = cfg.getAudioType(); qDebug() << "SSBMod::handleMessage: DSPConfigureAudio:" - << " sampleRate: " << sampleRate; + << " sampleRate: " << sampleRate + << " audioType: " << audioType; - if (sampleRate != m_audioSampleRate) { - applyAudioSampleRate(sampleRate); + if (audioType == DSPConfigureAudio::AudioInput) + { + if (sampleRate != m_audioSampleRate) { + applyAudioSampleRate(sampleRate); + } + } + else if (audioType == DSPConfigureAudio::AudioOutput) + { + if (sampleRate != m_audioSampleRate) { + applyFeedbackAudioSampleRate(sampleRate); + } } return true; @@ -727,6 +787,25 @@ void SSBMod::applyAudioSampleRate(int sampleRate) DSPConfigureAudio *cfg = new DSPConfigureAudio(m_audioSampleRate, DSPConfigureAudio::AudioInput); getMessageQueueToGUI()->push(cfg); } + + applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate); +} + +void SSBMod::applyFeedbackAudioSampleRate(unsigned int sampleRate) +{ + qDebug("AMMod::applyFeedbackAudioSampleRate: %u", sampleRate); + + m_settingsMutex.lock(); + + m_feedbackInterpolatorDistanceRemain = 0; + m_feedbackInterpolatorConsumed = false; + m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate; + Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f; + m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0); + + m_settingsMutex.unlock(); + + m_feedbackAudioSampleRate = sampleRate; } void SSBMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force) @@ -876,6 +955,20 @@ void SSBMod::applySettings(const SSBModSettings& settings, bool force) } } + if ((settings.m_feedbackAudioDeviceName != m_settings.m_feedbackAudioDeviceName) || force) + { + reverseAPIKeys.append("feedbackAudioDeviceName"); + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName); + audioDeviceManager->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue(), audioDeviceIndex); + uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex); + + if (m_feedbackAudioSampleRate != audioSampleRate) { + reverseAPIKeys.append("feedbackAudioSampleRate"); + applyFeedbackAudioSampleRate(audioSampleRate); + } + } + if (settings.m_useReverseAPI) { bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || diff --git a/plugins/channeltx/modssb/ssbmod.h b/plugins/channeltx/modssb/ssbmod.h index b73fa7ac0..9e49ec93f 100644 --- a/plugins/channeltx/modssb/ssbmod.h +++ b/plugins/channeltx/modssb/ssbmod.h @@ -282,11 +282,18 @@ private: NCOF m_carrierNco; NCOF m_toneNco; Complex m_modSample; + Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; bool m_interpolatorConsumed; - fftfilt* m_SSBFilter; + + Interpolator m_feedbackInterpolator; + Real m_feedbackInterpolatorDistance; + Real m_feedbackInterpolatorDistanceRemain; + bool m_feedbackInterpolatorConsumed; + + fftfilt* m_SSBFilter; fftfilt* m_DSBFilter; Complex* m_SSBFilterBuffer; Complex* m_DSBFilterBuffer; @@ -336,9 +343,12 @@ private: static const int m_levelNbSamples; void applyAudioSampleRate(int sampleRate); + void applyFeedbackAudioSampleRate(unsigned int sampleRate); + void processOneSample(Complex& ci); void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false); void applySettings(const SSBModSettings& settings, bool force = false); void pullAF(Complex& sample); + void pushFeedback(Complex sample); void calculateLevel(Complex& sample); void modulateSample(); void openFileStream(); diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index 0ae758919..71aaba9ab 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -292,6 +292,19 @@ void SSBModGUI::on_mic_toggled(bool checked) applySettings(); } +void SSBModGUI::on_feedbackEnable_toggled(bool checked) +{ + m_settings.m_feedbackAudioEnable = checked; + applySettings(); +} + +void SSBModGUI::on_feedbackVolume_valueChanged(int value) +{ + ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2)); + m_settings.m_feedbackVolumeFactor = value / 100.0; + applySettings(); +} + void SSBModGUI::on_agc_toggled(bool checked) { m_settings.m_agc = checked; @@ -679,6 +692,10 @@ void SSBModGUI::displaySettings() ui->play->setChecked(m_settings.m_modAFInput == SSBModSettings::SSBModInputAF::SSBModInputFile); ui->morseKeyer->setChecked(m_settings.m_modAFInput == SSBModSettings::SSBModInputAF::SSBModInputCWTone); + ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable); + ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0)); + ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2)); + blockApplySettings(false); } diff --git a/plugins/channeltx/modssb/ssbmodgui.h b/plugins/channeltx/modssb/ssbmodgui.h index e88c3b44e..e4a4e01f5 100644 --- a/plugins/channeltx/modssb/ssbmodgui.h +++ b/plugins/channeltx/modssb/ssbmodgui.h @@ -120,6 +120,9 @@ private slots: void on_navTimeSlider_valueChanged(int value); void on_showFileDialog_clicked(bool checked); + void on_feedbackEnable_toggled(bool checked); + void on_feedbackVolume_valueChanged(int value); + void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); diff --git a/plugins/channeltx/modssb/ssbmodgui.ui b/plugins/channeltx/modssb/ssbmodgui.ui index 89c01451a..a533b312c 100644 --- a/plugins/channeltx/modssb/ssbmodgui.ui +++ b/plugins/channeltx/modssb/ssbmodgui.ui @@ -811,13 +811,6 @@ - - - - Qt::Vertical - - - @@ -835,6 +828,75 @@ + + + + Qt::Vertical + + + + + + + Left: enable / disable audio feedback - Right: select audio output device + + + ... + + + + :/sound_off.png + :/sound_on.png:/sound_off.png + + + true + + + + + + + + 24 + 24 + + + + Audio feedback volume + + + 0 + + + 100 + + + 1 + + + 50 + + + + + + + + 30 + 16777215 + + + + Audio feedback volume + + + 1.00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/plugins/channeltx/modssb/ssbmodsettings.cpp b/plugins/channeltx/modssb/ssbmodsettings.cpp index 812700e1a..0b4e56f5e 100644 --- a/plugins/channeltx/modssb/ssbmodsettings.cpp +++ b/plugins/channeltx/modssb/ssbmodsettings.cpp @@ -64,7 +64,7 @@ void SSBModSettings::resetToDefaults() m_modAFInput = SSBModInputAF::SSBModInputNone; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackVolumeFactor = 1.0f; + m_feedbackVolumeFactor = 0.5f; m_feedbackAudioEnable = false; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; diff --git a/plugins/channeltx/modwfm/wfmmod.cpp b/plugins/channeltx/modwfm/wfmmod.cpp index a8d82c50f..868b7a029 100644 --- a/plugins/channeltx/modwfm/wfmmod.cpp +++ b/plugins/channeltx/modwfm/wfmmod.cpp @@ -60,7 +60,6 @@ WFMMod::WFMMod(DeviceAPI *deviceAPI) : m_inputFrequencyOffset(0), m_modPhasor(0.0f), m_audioFifo(4800), - m_feedbackAudioFifo(4800), m_settingsMutex(QMutex::Recursive), m_fileSize(0), m_recordLength(0), @@ -80,17 +79,11 @@ WFMMod::WFMMod(DeviceAPI *deviceAPI) : m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; - m_feedbackAudioBuffer.resize(1<<14); - m_feedbackAudioBufferFill = 0; - m_magsq = 0.0; DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue()); m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate(); - DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_feedbackAudioFifo, getInputMessageQueue()); - m_feedbackAudioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); - m_toneNcoRF.setFreq(1000.0, m_outputSampleRate); m_cwKeyer.setSampleRate(m_outputSampleRate); m_cwKeyer.reset(); @@ -111,7 +104,6 @@ WFMMod::~WFMMod() { disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); delete m_networkManager; - DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(&m_feedbackAudioFifo); DSPEngine::instance()->getAudioDeviceManager()->removeAudioSource(&m_audioFifo); m_deviceAPI->removeChannelSourceAPI(this); m_deviceAPI->removeChannelSource(m_threadedChannelizer); diff --git a/plugins/channeltx/modwfm/wfmmod.h b/plugins/channeltx/modwfm/wfmmod.h index 74c7b2a1b..c6370bc61 100644 --- a/plugins/channeltx/modwfm/wfmmod.h +++ b/plugins/channeltx/modwfm/wfmmod.h @@ -297,11 +297,6 @@ private: uint m_audioBufferFill; AudioFifo m_audioFifo; - quint32 m_feedbackAudioSampleRate; - AudioVector m_feedbackAudioBuffer; - uint m_feedbackAudioBufferFill; - AudioFifo m_feedbackAudioFifo; - SampleVector m_sampleBuffer; QMutex m_settingsMutex; diff --git a/plugins/channeltx/modwfm/wfmmodsettings.cpp b/plugins/channeltx/modwfm/wfmmodsettings.cpp index 2b6bb869d..78ddbae34 100644 --- a/plugins/channeltx/modwfm/wfmmodsettings.cpp +++ b/plugins/channeltx/modwfm/wfmmodsettings.cpp @@ -50,9 +50,6 @@ void WFMModSettings::resetToDefaults() m_title = "WFM Modulator"; m_modAFInput = WFMModInputNone; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; - m_feedbackVolumeFactor = 1.0f; - m_feedbackAudioEnable = false; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; m_reverseAPIPort = 8888; @@ -88,9 +85,6 @@ QByteArray WFMModSettings::serialize() const s.writeU32(15, m_reverseAPIPort); s.writeU32(16, m_reverseAPIDeviceIndex); s.writeU32(17, m_reverseAPIChannelIndex); - s.writeString(18, m_feedbackAudioDeviceName); - s.writeReal(19, m_feedbackVolumeFactor); - s.writeBool(20, m_feedbackAudioEnable); return s.final(); } @@ -154,9 +148,6 @@ bool WFMModSettings::deserialize(const QByteArray& data) m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; d.readU32(17, &utmp, 0); m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; - d.readString(18, &m_feedbackAudioDeviceName, AudioDeviceManager::m_defaultDeviceName); - d.readReal(19, &m_feedbackVolumeFactor, 1.0); - d.readBool(20, &m_feedbackAudioEnable, false); return true; } diff --git a/plugins/channeltx/modwfm/wfmmodsettings.h b/plugins/channeltx/modwfm/wfmmodsettings.h index 6501bb821..4b03e7c5e 100644 --- a/plugins/channeltx/modwfm/wfmmodsettings.h +++ b/plugins/channeltx/modwfm/wfmmodsettings.h @@ -48,9 +48,6 @@ struct WFMModSettings QString m_title; WFMModInputAF m_modAFInput; QString m_audioDeviceName; //!< This is the audio device you get the audio samples from - QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback - float m_feedbackVolumeFactor; - bool m_feedbackAudioEnable; bool m_useReverseAPI; QString m_reverseAPIAddress; uint16_t m_reverseAPIPort; diff --git a/sdrbase/dsp/dspcommands.h b/sdrbase/dsp/dspcommands.h index 0700530ea..886630590 100644 --- a/sdrbase/dsp/dspcommands.h +++ b/sdrbase/dsp/dspcommands.h @@ -388,7 +388,7 @@ public: { } int getSampleRate() const { return m_sampleRate; } - bool getAudioType() const { return m_autioType; } + AudioType getAudioType() const { return m_autioType; } private: int m_sampleRate;