From 095ab14a14fc42f818f167c403dc4e2a520d4d02 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 26 Mar 2018 11:55:45 +0200 Subject: [PATCH] Multiple audio support: New audio preferences dialog (3). Application to AM demod --- plugins/channelrx/demodam/amdemod.cpp | 48 ++- plugins/channelrx/demodam/amdemod.h | 9 +- plugins/channelrx/demodam/amdemodgui.cpp | 2 +- plugins/channelrx/demodam/amdemodsettings.cpp | 1 - plugins/channelrx/demodam/amdemodsettings.h | 1 - sdrbase/audio/audiodevicemanager.cpp | 308 +++++++++++++++++- sdrbase/audio/audiodevicemanager.h | 33 +- sdrbase/dsp/dspcommands.cpp | 1 + sdrbase/dsp/dspcommands.h | 13 + sdrbase/dsp/dspengine.h | 4 +- sdrbase/resources/webapi/doc/html2/index.html | 8 +- .../webapi/doc/swagger/include/AMDemod.yaml | 5 +- sdrgui/gui/audiodialog.cpp | 183 +++++++++-- sdrgui/gui/audiodialog.h | 23 +- sdrgui/gui/audiodialog.ui | 148 ++++++++- .../sdrangel/api/swagger/include/AMDemod.yaml | 5 +- swagger/sdrangel/code/html2/index.html | 8 +- .../code/qt5/client/SWGAMDemodReport.cpp | 21 ++ .../code/qt5/client/SWGAMDemodReport.h | 6 + .../code/qt5/client/SWGAMDemodSettings.cpp | 21 -- .../code/qt5/client/SWGAMDemodSettings.h | 6 - 21 files changed, 742 insertions(+), 112 deletions(-) diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index ee0a0c158..5333a03f5 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -64,6 +64,7 @@ AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) : m_magsq = 0.0; DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue()); + m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort); @@ -205,12 +206,45 @@ bool AMDemod::handleMessage(const Message& cmd) { return true; } + else if (DSPConfigureAudio::match(cmd)) + { + DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd; + uint32_t sampleRate = cfg.getSampleRate(); + + qDebug() << "AMDemod::handleMessage: DSPConfigureAudio:" + << " sampleRate: " << sampleRate; + + if (sampleRate != m_audioSampleRate) { + applyAudioSampleRate(sampleRate); + } + + AMDemodSettings settings = m_settings; + applyAudioSampleRate(cfg.getSampleRate()); + + return true; + } else { return false; } } +void AMDemod::applyAudioSampleRate(int sampleRate) +{ + MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create( + sampleRate, m_settings.m_inputFrequencyOffset); + m_inputMessageQueue.push(channelConfigMsg); + + m_settingsMutex.lock(); + m_interpolator.create(16, m_inputSampleRate, m_settings.m_rfBandwidth / 2.2f); + m_interpolatorDistanceRemain = 0; + m_interpolatorDistance = (Real) m_inputSampleRate / (Real) sampleRate; + m_bandpass.create(301, sampleRate, 300.0, m_settings.m_rfBandwidth / 2.0f); + m_settingsMutex.unlock(); + + m_audioSampleRate = sampleRate; +} + void AMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force) { qDebug() << "AMDemod::applyChannelSettings:" @@ -228,7 +262,7 @@ void AMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset m_settingsMutex.lock(); m_interpolator.create(16, inputSampleRate, m_settings.m_rfBandwidth / 2.2f); m_interpolatorDistanceRemain = 0; - m_interpolatorDistance = (Real) inputSampleRate / (Real) m_settings.m_audioSampleRate; + m_interpolatorDistance = (Real) inputSampleRate / (Real) m_audioSampleRate; m_settingsMutex.unlock(); } @@ -252,14 +286,13 @@ void AMDemod::applySettings(const AMDemodSettings& settings, bool force) << " force: " << force; if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || - (m_settings.m_audioSampleRate != settings.m_audioSampleRate) || (m_settings.m_bandpassEnable != settings.m_bandpassEnable) || force) { m_settingsMutex.lock(); m_interpolator.create(16, m_inputSampleRate, settings.m_rfBandwidth / 2.2f); m_interpolatorDistanceRemain = 0; - m_interpolatorDistance = (Real) m_inputSampleRate / (Real) settings.m_audioSampleRate; - m_bandpass.create(301, settings.m_audioSampleRate, 300.0, settings.m_rfBandwidth / 2.0f); + m_interpolatorDistance = (Real) m_inputSampleRate / (Real) m_audioSampleRate; + m_bandpass.create(301, m_audioSampleRate, 300.0, settings.m_rfBandwidth / 2.0f); m_settingsMutex.unlock(); } @@ -341,9 +374,6 @@ int AMDemod::webapiSettingsPutPatch( if (channelSettingsKeys.contains("audioMute")) { settings.m_audioMute = response.getAmDemodSettings()->getAudioMute() != 0; } - if (channelSettingsKeys.contains("audioSampleRate")) { - settings.m_audioSampleRate = response.getAmDemodSettings()->getAudioSampleRate(); - } if (channelSettingsKeys.contains("copyAudioToUDP")) { settings.m_copyAudioToUDP = response.getAmDemodSettings()->getCopyAudioToUdp() != 0; } @@ -383,7 +413,7 @@ int AMDemod::webapiSettingsPutPatch( if (frequencyOffsetChanged) { MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create( - 48000, settings.m_inputFrequencyOffset); + m_audioSampleRate, settings.m_inputFrequencyOffset); m_inputMessageQueue.push(channelConfigMsg); } @@ -415,7 +445,6 @@ int AMDemod::webapiReportGet( void AMDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const AMDemodSettings& settings) { response.getAmDemodSettings()->setAudioMute(settings.m_audioMute ? 1 : 0); - response.getAmDemodSettings()->setAudioSampleRate(settings.m_audioSampleRate); response.getAmDemodSettings()->setCopyAudioToUdp(settings.m_copyAudioToUDP ? 1 : 0); response.getAmDemodSettings()->setCopyAudioUseRtp(settings.m_copyAudioUseRTP ? 1 : 0); response.getAmDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); @@ -447,5 +476,6 @@ void AMDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) response.getAmDemodReport()->setChannelPowerDb(CalcDb::dbPower(magsqAvg)); response.getAmDemodReport()->setSquelch(m_squelchOpen ? 1 : 0); + response.getAmDemodReport()->setAudioSampleRate(m_audioSampleRate); } diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index 06e57d601..6c56bdaba 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -115,6 +115,7 @@ public: SWGSDRangel::SWGChannelReport& response, QString& errorMessage); + uint32_t getAudioSampleRate() const { return m_audioSampleRate; } double getMagSq() const { return m_magsq; } bool getSquelchOpen() const { return m_squelchOpen; } @@ -146,6 +147,7 @@ private: int m_inputSampleRate; int m_inputFrequencyOffset; AMDemodSettings m_settings; + uint32_t m_audioSampleRate; bool m_running; NCO m_nco; @@ -176,6 +178,7 @@ private: void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false); void applySettings(const AMDemodSettings& settings, bool force = false); + void applyAudioSampleRate(int sampleRate); void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const AMDemodSettings& settings); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); @@ -197,7 +200,7 @@ private: if (m_magsq >= m_squelchLevel) { - if (m_squelchCount <= m_settings.m_audioSampleRate / 10) + if (m_squelchCount <= m_audioSampleRate / 10) { m_squelchCount++; } @@ -212,7 +215,7 @@ private: qint16 sample; - if ((m_squelchCount >= m_settings.m_audioSampleRate / 20) && !m_settings.m_audioMute) + if ((m_squelchCount >= m_audioSampleRate / 20) && !m_settings.m_audioMute) { Real demod = sqrt(magsq); m_volumeAGC.feed(demod); @@ -224,7 +227,7 @@ private: demod /= 301.0f; } - Real attack = (m_squelchCount - 0.05f * m_settings.m_audioSampleRate) / (0.05f * m_settings.m_audioSampleRate); + Real attack = (m_squelchCount - 0.05f * m_audioSampleRate) / (0.05f * m_audioSampleRate); sample = demod * attack * 2048 * m_settings.m_volume; if (m_settings.m_copyAudioToUDP) { m_audioNetSink->write(demod * attack * 32768.0f); diff --git a/plugins/channelrx/demodam/amdemodgui.cpp b/plugins/channelrx/demodam/amdemodgui.cpp index 25bbde910..3a26230c7 100644 --- a/plugins/channelrx/demodam/amdemodgui.cpp +++ b/plugins/channelrx/demodam/amdemodgui.cpp @@ -281,7 +281,7 @@ void AMDemodGUI::applySettings(bool force) if (m_doApplySettings) { AMDemod::MsgConfigureChannelizer* channelConfigMsg = AMDemod::MsgConfigureChannelizer::create( - 48000, m_channelMarker.getCenterFrequency()); + m_amDemod->getAudioSampleRate(), m_channelMarker.getCenterFrequency()); m_amDemod->getInputMessageQueue()->push(channelConfigMsg); diff --git a/plugins/channelrx/demodam/amdemodsettings.cpp b/plugins/channelrx/demodam/amdemodsettings.cpp index 2094c6b45..f1d94a1d6 100644 --- a/plugins/channelrx/demodam/amdemodsettings.cpp +++ b/plugins/channelrx/demodam/amdemodsettings.cpp @@ -33,7 +33,6 @@ void AMDemodSettings::resetToDefaults() m_rfBandwidth = 5000; m_squelch = -40.0; m_volume = 2.0; - m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate(); m_audioMute = false; m_bandpassEnable = false; m_copyAudioToUDP = false; diff --git a/plugins/channelrx/demodam/amdemodsettings.h b/plugins/channelrx/demodam/amdemodsettings.h index 4c908a144..129ef810d 100644 --- a/plugins/channelrx/demodam/amdemodsettings.h +++ b/plugins/channelrx/demodam/amdemodsettings.h @@ -27,7 +27,6 @@ struct AMDemodSettings Real m_rfBandwidth; Real m_squelch; Real m_volume; - quint32 m_audioSampleRate; bool m_audioMute; bool m_bandpassEnable; bool m_copyAudioToUDP; diff --git a/sdrbase/audio/audiodevicemanager.cpp b/sdrbase/audio/audiodevicemanager.cpp index c6f113490..f88a8da6c 100644 --- a/sdrbase/audio/audiodevicemanager.cpp +++ b/sdrbase/audio/audiodevicemanager.cpp @@ -17,12 +17,16 @@ #include "audio/audiodevicemanager.h" #include "util/simpleserializer.h" +#include "util/messagequeue.h" +#include "dsp/dspcommands.h" #include +#include #include const float AudioDeviceManager::m_defaultAudioInputVolume = 0.15f; const QString AudioDeviceManager::m_defaultUDPAddress = "127.0.0.1"; +const QString AudioDeviceManager::m_defaultDeviceName = "System default device"; QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info) { @@ -67,7 +71,7 @@ bool AudioDeviceManager::getOutputDeviceName(int outputDeviceIndex, QString &dev { if (outputDeviceIndex < 0) { - deviceName = "System default device"; + deviceName = m_defaultDeviceName; return true; } else @@ -88,7 +92,7 @@ bool AudioDeviceManager::getInputDeviceName(int inputDeviceIndex, QString &devic { if (inputDeviceIndex < 0) { - deviceName = "System default device"; + deviceName = m_defaultDeviceName; return true; } else @@ -212,7 +216,8 @@ void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sample } m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO - m_sampleSinkMessageQueues[audioFifo] = sampleSinkMessageQueue; + m_audioFifoToSinkMessageQueues[audioFifo] = sampleSinkMessageQueue; + m_outputDeviceSinkMessageQueues[outputDeviceIndex].append(sampleSinkMessageQueue); } void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo) @@ -233,7 +238,8 @@ void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo) } m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO - m_sampleSinkMessageQueues.remove(audioFifo); + m_outputDeviceSinkMessageQueues[audioOutputDeviceIndex].removeOne(m_audioFifoToSinkMessageQueues[audioFifo]); + m_audioFifoToSinkMessageQueues.remove(audioFifo); } void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex) @@ -264,7 +270,8 @@ void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *samp } m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO - m_sampleSourceMessageQueues[audioFifo] = sampleSourceMessageQueue; + m_audioFifoToSourceMessageQueues[audioFifo] = sampleSourceMessageQueue; + m_outputDeviceSinkMessageQueues[inputDeviceIndex].append(sampleSourceMessageQueue); } void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo) @@ -285,7 +292,8 @@ void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo) } m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO - m_sampleSourceMessageQueues.remove(audioFifo); + m_inputDeviceSourceMessageQueues[audioInputDeviceIndex].removeOne(m_audioFifoToSourceMessageQueues[audioFifo]); + m_audioFifoToSourceMessageQueues.remove(audioFifo); } void AudioDeviceManager::startAudioOutput(int outputDeviceIndex) @@ -373,6 +381,294 @@ void AudioDeviceManager::stopAudioInput(int inputDeviceIndex) m_audioInputs[inputDeviceIndex]->stop(); } +bool AudioDeviceManager::getInputDeviceInfo(const QString& deviceName, InputDeviceInfo& deviceInfo) const +{ + if (m_audioInputInfos.find(deviceName) == m_audioInputInfos.end()) + { + return false; + } + else + { + deviceInfo = m_audioInputInfos[deviceName]; + return true; + } +} + +bool AudioDeviceManager::getOutputDeviceInfo(const QString& deviceName, OutputDeviceInfo& deviceInfo) const +{ + if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end()) + { + return false; + } + else + { + deviceInfo = m_audioOutputInfos[deviceName]; + return true; + } +} + +int AudioDeviceManager::getInputSampleRate(int inputDeviceIndex) +{ + QString deviceName; + + if (!getInputDeviceName(inputDeviceIndex, deviceName)) + { + qDebug("AudioDeviceManager::getInputSampleRate: unknown device index %d", inputDeviceIndex); + return m_defaultAudioSampleRate; + } + + InputDeviceInfo deviceInfo; + + if (!getInputDeviceInfo(deviceName, deviceInfo)) + { + qDebug("AudioDeviceManager::getInputSampleRate: unknown device %s", qPrintable(deviceName)); + return m_defaultAudioSampleRate; + } + else + { + return deviceInfo.sampleRate; + } +} + +int AudioDeviceManager::getOutputSampleRate(int outputDeviceIndex) +{ + QString deviceName; + + if (!getOutputDeviceName(outputDeviceIndex, deviceName)) + { + qDebug("AudioDeviceManager::getOutputSampleRate: unknown device index %d", outputDeviceIndex); + return m_defaultAudioSampleRate; + } + + OutputDeviceInfo deviceInfo; + + if (!getOutputDeviceInfo(deviceName, deviceInfo)) + { + qDebug("AudioDeviceManager::getOutputSampleRate: unknown device %s", qPrintable(deviceName)); + return m_defaultAudioSampleRate; + } + else + { + return deviceInfo.sampleRate; + } +} + + +void AudioDeviceManager::setInputDeviceInfo(int inputDeviceIndex, const InputDeviceInfo& deviceInfo) +{ + QString deviceName; + + if (!getInputDeviceName(inputDeviceIndex, deviceName)) + { + qWarning("AudioDeviceManager::setInputDeviceInfo: unknown device index %d", inputDeviceIndex); + return; + } + + InputDeviceInfo oldDeviceInfo; + + if (!getInputDeviceInfo(deviceName, oldDeviceInfo)) + { + qDebug("AudioDeviceManager::setInputDeviceInfo: unknown device %s", qPrintable(deviceName)); + } + + m_audioInputInfos[deviceName] = deviceInfo; + + if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet + return; + } + + AudioInput *audioInput = m_audioInputs[inputDeviceIndex]; + + if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate) + { + audioInput->stop(); + audioInput->start(inputDeviceIndex, deviceInfo.sampleRate); + m_audioInputInfos[deviceName].sampleRate = audioInput->getRate(); // store actual sample rate + + // send message to attached channels + QList::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin(); + + for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it) + { + DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioInputInfos[deviceName].sampleRate); + (*it)->push(msg); + } + } + + audioInput->setVolume(deviceInfo.volume); +} + +void AudioDeviceManager::setOutputDeviceInfo(int outputDeviceIndex, const OutputDeviceInfo& deviceInfo) +{ + QString deviceName; + + if (!getOutputDeviceName(outputDeviceIndex, deviceName)) + { + qWarning("AudioDeviceManager::setOutputDeviceInfo: unknown device index %d", outputDeviceIndex); + return; + } + + OutputDeviceInfo oldDeviceInfo; + + if (!getOutputDeviceInfo(deviceName, oldDeviceInfo)) + { + qDebug("AudioDeviceManager::setOutputDeviceInfo: unknown device %s", qPrintable(deviceName)); + } + + m_audioOutputInfos[deviceName] = deviceInfo; + + if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { // no FIFO registered yet hence no audio output has been allocated yet + return; + } + + AudioOutput *audioOutput = m_audioOutputs[outputDeviceIndex]; + + if (oldDeviceInfo.sampleRate != deviceInfo.sampleRate) + { + audioOutput->stop(); + audioOutput->start(outputDeviceIndex, deviceInfo.sampleRate); + m_audioOutputInfos[deviceName].sampleRate = audioOutput->getRate(); // store actual sample rate + + // send message to attached channels + QList::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); + + for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) + { + DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate); + (*it)->push(msg); + } + } + + audioOutput->setUdpCopyToUDP(deviceInfo.copyToUDP); + audioOutput->setUdpDestination(deviceInfo.udpAddress, deviceInfo.udpPort); + audioOutput->setUdpStereo(deviceInfo.udpStereo); + audioOutput->setUdpUseRTP(deviceInfo.udpUseRTP); +} + +void AudioDeviceManager::unsetOutputDeviceInfo(int outputDeviceIndex) +{ + QString deviceName; + + if (!getOutputDeviceName(outputDeviceIndex, deviceName)) + { + qWarning("AudioDeviceManager::unsetOutputDeviceInfo: unknown device index %d", outputDeviceIndex); + return; + } + + OutputDeviceInfo oldDeviceInfo; + + if (!getOutputDeviceInfo(deviceName, oldDeviceInfo)) + { + qDebug("AudioDeviceManager::unsetOutputDeviceInfo: unregistered device %s", qPrintable(deviceName)); + return; + } + + m_audioOutputInfos.remove(deviceName); + + if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end()) { // no FIFO registered yet hence no audio output has been allocated yet + return; + } + + stopAudioOutput(outputDeviceIndex); + startAudioOutput(outputDeviceIndex); + + if (oldDeviceInfo.sampleRate != m_audioOutputInfos[deviceName].sampleRate) + { + // send message to attached channels + QList::const_iterator it = m_outputDeviceSinkMessageQueues[outputDeviceIndex].begin(); + + for (; it != m_outputDeviceSinkMessageQueues[outputDeviceIndex].end(); ++it) + { + DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioOutputInfos[deviceName].sampleRate); + (*it)->push(msg); + } + } +} + +void AudioDeviceManager::unsetInputDeviceInfo(int inputDeviceIndex) +{ + QString deviceName; + + if (!getInputDeviceName(inputDeviceIndex, deviceName)) + { + qWarning("AudioDeviceManager::unsetInputDeviceInfo: unknown device index %d", inputDeviceIndex); + return; + } + + InputDeviceInfo oldDeviceInfo; + + if (!getInputDeviceInfo(deviceName, oldDeviceInfo)) + { + qDebug("AudioDeviceManager::unsetInputDeviceInfo: unregistered device %s", qPrintable(deviceName)); + return; + } + + m_audioInputInfos.remove(deviceName); + + if (m_audioInputs.find(inputDeviceIndex) == m_audioInputs.end()) { // no FIFO registered yet hence no audio input has been allocated yet + return; + } + + stopAudioInput(inputDeviceIndex); + startAudioInput(inputDeviceIndex); + + if (oldDeviceInfo.sampleRate != m_audioInputInfos[deviceName].sampleRate) + { + // send message to attached channels + QList::const_iterator it = m_inputDeviceSourceMessageQueues[inputDeviceIndex].begin(); + + for (; it != m_inputDeviceSourceMessageQueues[inputDeviceIndex].end(); ++it) + { + DSPConfigureAudio *msg = new DSPConfigureAudio(m_audioInputInfos[deviceName].sampleRate); + (*it)->push(msg); + } + } +} + +void AudioDeviceManager::inputInfosCleanup() +{ + QSet deviceNames; + deviceNames.insert(m_defaultDeviceName); + QList::const_iterator itd = m_inputDevicesInfo.begin(); + + for (; itd != m_inputDevicesInfo.end(); ++itd) { + deviceNames.insert(itd->deviceName()); + } + + QMap::iterator itm = m_audioInputInfos.begin(); + + for (; itm != m_audioInputInfos.end(); ++itm) + { + if (!deviceNames.contains(itm.key())) + { + qDebug("AudioDeviceManager::inputInfosCleanup: removing key: %s", qPrintable(itm.key())); + m_audioInputInfos.remove(itm.key()); + } + } +} + +void AudioDeviceManager::outputInfosCleanup() +{ + QSet deviceNames; + deviceNames.insert(m_defaultDeviceName); + QList::const_iterator itd = m_outputDevicesInfo.begin(); + + for (; itd != m_outputDevicesInfo.end(); ++itd) { + deviceNames.insert(itd->deviceName()); + } + + QMap::iterator itm = m_audioOutputInfos.begin(); + + for (; itm != m_audioOutputInfos.end(); ++itm) + { + if (!deviceNames.contains(itm.key())) + { + qDebug("AudioDeviceManager::outputInfosCleanup: removing key: %s", qPrintable(itm.key())); + m_audioOutputInfos.remove(itm.key()); + } + } +} + void AudioDeviceManager::debugAudioInputInfos() const { QMap::const_iterator it = m_audioInputInfos.begin(); diff --git a/sdrbase/audio/audiodevicemanager.h b/sdrbase/audio/audiodevicemanager.h index 63b852dce..6cb24d456 100644 --- a/sdrbase/audio/audiodevicemanager.h +++ b/sdrbase/audio/audiodevicemanager.h @@ -40,6 +40,10 @@ public: sampleRate(m_defaultAudioSampleRate), volume(m_defaultAudioInputVolume) {} + void resetToDefaults() { + sampleRate = m_defaultAudioSampleRate; + volume = m_defaultAudioInputVolume; + } unsigned int sampleRate; float volume; friend QDataStream& operator<<(QDataStream& ds, const InputDeviceInfo& info); @@ -57,6 +61,14 @@ public: udpStereo(false), udpUseRTP(false) {} + void resetToDefaults() { + sampleRate = m_defaultAudioSampleRate; + udpAddress = m_defaultUDPAddress; + udpPort = m_defaultUDPPort; + copyToUDP = false; + udpStereo = false; + udpUseRTP = false; + } unsigned int sampleRate; QString udpAddress; quint16 udpPort; @@ -70,12 +82,11 @@ public: AudioDeviceManager(); ~AudioDeviceManager(); - const QList& getInputDevices() const { return m_inputDevicesInfo; } const QList& getOutputDevices() const { return m_outputDevicesInfo; } bool getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const; - bool getInputDeviceName(int outputDeviceIndex, QString &deviceName) const; + bool getInputDeviceName(int inputDeviceIndex, QString &deviceName) const; void addAudioSink(AudioFifo* audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex = -1); //!< Add the audio sink void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink @@ -83,22 +94,36 @@ public: void addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex = -1); //!< Add an audio source void removeAudioSource(AudioFifo* audioFifo); //!< Remove an audio source + bool getInputDeviceInfo(const QString& deviceName, InputDeviceInfo& deviceInfo) const; + bool getOutputDeviceInfo(const QString& deviceName, OutputDeviceInfo& deviceInfo) const; + int getInputSampleRate(int inputDeviceIndex = -1); + int getOutputSampleRate(int outputDeviceIndex = -1); + void setInputDeviceInfo(int inputDeviceIndex, const InputDeviceInfo& deviceInfo); + void setOutputDeviceInfo(int outputDeviceIndex, const OutputDeviceInfo& deviceInfo); + void unsetInputDeviceInfo(int inputDeviceIndex); + void unsetOutputDeviceInfo(int outputDeviceIndex); + void inputInfosCleanup(); //!< Remove input info from map for input devices not present + void outputInfosCleanup(); //!< Remove output info from map for output devices not present + static const unsigned int m_defaultAudioSampleRate = 48000; static const float m_defaultAudioInputVolume; static const QString m_defaultUDPAddress; static const quint16 m_defaultUDPPort = 9998; + static const QString m_defaultDeviceName; private: QList m_inputDevicesInfo; QList m_outputDevicesInfo; QMap m_audioSinkFifos; //< audio sink FIFO to audio output device index-1 map - QMap m_sampleSinkMessageQueues; //!< audio sink FIFO to attached sink message queue + QMap m_audioFifoToSinkMessageQueues; //!< audio sink FIFO to attached sink message queue + QMap > m_outputDeviceSinkMessageQueues; //!< sink message queues attached to device QMap m_audioOutputs; //!< audio device index to audio output map (index -1 is default device) QMap m_audioOutputInfos; //!< audio device name to audio output info QMap m_audioSourceFifos; //< audio source FIFO to audio input device index-1 map - QMap m_sampleSourceMessageQueues; //!< audio source FIFO to attached source message queue + QMap m_audioFifoToSourceMessageQueues; //!< audio source FIFO to attached source message queue + QMap > m_inputDeviceSourceMessageQueues; //!< sink message queues attached to device QMap m_audioInputs; //!< audio device index to audio input map (index -1 is default device) QMap m_audioInputInfos; //!< audio device name to audio input device info diff --git a/sdrbase/dsp/dspcommands.cpp b/sdrbase/dsp/dspcommands.cpp index 1c15142d1..71ab79ca2 100644 --- a/sdrbase/dsp/dspcommands.cpp +++ b/sdrbase/dsp/dspcommands.cpp @@ -46,3 +46,4 @@ MESSAGE_CLASS_DEFINITION(DSPEngineReport, Message) MESSAGE_CLASS_DEFINITION(DSPConfigureScopeVis, Message) MESSAGE_CLASS_DEFINITION(DSPSignalNotification, Message) MESSAGE_CLASS_DEFINITION(DSPConfigureChannelizer, Message) +MESSAGE_CLASS_DEFINITION(DSPConfigureAudio, Message) diff --git a/sdrbase/dsp/dspcommands.h b/sdrbase/dsp/dspcommands.h index e354498a2..ca1a5343b 100644 --- a/sdrbase/dsp/dspcommands.h +++ b/sdrbase/dsp/dspcommands.h @@ -371,4 +371,17 @@ private: int m_centerFrequency; }; +class SDRBASE_API DSPConfigureAudio : public Message { + MESSAGE_CLASS_DECLARATION + +public: + DSPConfigureAudio(int sampleRate) : m_sampleRate(sampleRate) + { } + + int getSampleRate() const { return m_sampleRate; } + +private: + int m_sampleRate; +}; + #endif // INCLUDE_DSPCOMMANDS_H diff --git a/sdrbase/dsp/dspengine.h b/sdrbase/dsp/dspengine.h index b5a210e0e..a156d9190 100644 --- a/sdrbase/dsp/dspengine.h +++ b/sdrbase/dsp/dspengine.h @@ -18,11 +18,11 @@ #ifndef INCLUDE_DSPENGINE_H #define INCLUDE_DSPENGINE_H -#include