mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Multiple audio support: BFM demodulator
This commit is contained in:
		
							parent
							
								
									61aad30cbb
								
							
						
					
					
						commit
						ae0470218c
					
				| @ -1,5 +1,7 @@ | ||||
| project(bfm) | ||||
| 
 | ||||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | ||||
| 
 | ||||
| set(bfm_SOURCES | ||||
| 	bfmdemod.cpp | ||||
| 	bfmdemodgui.cpp | ||||
|  | ||||
| @ -54,6 +54,9 @@ BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) : | ||||
| { | ||||
| 	setObjectName(m_channelId); | ||||
| 
 | ||||
|     DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue()); | ||||
|     m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); | ||||
| 
 | ||||
|     m_magsq = 0.0f; | ||||
|     m_magsqSum = 0.0f; | ||||
|     m_magsqPeak = 0.0f; | ||||
| @ -77,15 +80,13 @@ BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) : | ||||
|     m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, filtFftLen); | ||||
| 
 | ||||
| 
 | ||||
| 	m_deemphasisFilterX.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6); | ||||
| 	m_deemphasisFilterY.configure(default_deemphasis * m_settings.m_audioSampleRate * 1.0e-6); | ||||
| 	m_deemphasisFilterX.configure(default_deemphasis * m_audioSampleRate * 1.0e-6); | ||||
| 	m_deemphasisFilterY.configure(default_deemphasis * m_audioSampleRate * 1.0e-6); | ||||
|  	m_phaseDiscri.setFMScaling(384000/m_fmExcursion); | ||||
| 
 | ||||
| 	m_audioBuffer.resize(16384); | ||||
| 	m_audioBufferFill = 0; | ||||
| 
 | ||||
| 	DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue()); | ||||
| 
 | ||||
|     applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true); | ||||
|     applySettings(m_settings, true); | ||||
| 
 | ||||
| @ -338,6 +339,20 @@ bool BFMDemod::handleMessage(const Message& cmd) | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (DSPConfigureAudio::match(cmd)) | ||||
|     { | ||||
|         DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd; | ||||
|         uint32_t sampleRate = cfg.getSampleRate(); | ||||
| 
 | ||||
|         qDebug() << "BFMDemod::handleMessage: DSPConfigureAudio:" | ||||
|                 << " sampleRate: " << sampleRate; | ||||
| 
 | ||||
|         if (sampleRate != m_audioSampleRate) { | ||||
|             applyAudioSampleRate(sampleRate); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (BasebandSampleSink::MsgThreadedSink::match(cmd)) | ||||
|     { | ||||
|         return true; | ||||
| @ -361,6 +376,28 @@ bool BFMDemod::handleMessage(const Message& cmd) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void BFMDemod::applyAudioSampleRate(int sampleRate) | ||||
| { | ||||
|     qDebug("BFMDemod::applyAudioSampleRate: %d", sampleRate); | ||||
| 
 | ||||
|     m_settingsMutex.lock(); | ||||
| 
 | ||||
|     m_interpolator.create(16, m_inputSampleRate, m_settings.m_afBandwidth); | ||||
|     m_interpolatorDistanceRemain = (Real) m_inputSampleRate / sampleRate; | ||||
|     m_interpolatorDistance =  (Real) m_inputSampleRate / (Real) sampleRate; | ||||
| 
 | ||||
|     m_interpolatorStereo.create(16, m_inputSampleRate, m_settings.m_afBandwidth); | ||||
|     m_interpolatorStereoDistanceRemain = (Real) m_inputSampleRate / sampleRate; | ||||
|     m_interpolatorStereoDistance =  (Real) m_inputSampleRate / (Real) sampleRate; | ||||
| 
 | ||||
|     m_deemphasisFilterX.configure(default_deemphasis * sampleRate * 1.0e-6); | ||||
|     m_deemphasisFilterY.configure(default_deemphasis * sampleRate * 1.0e-6); | ||||
| 
 | ||||
|     m_settingsMutex.unlock(); | ||||
| 
 | ||||
|     m_audioSampleRate = sampleRate; | ||||
| } | ||||
| 
 | ||||
| void BFMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force) | ||||
| { | ||||
|     qDebug() << "BFMDemod::applyChannelSettings:" | ||||
| @ -380,12 +417,12 @@ void BFMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffse | ||||
|         m_settingsMutex.lock(); | ||||
| 
 | ||||
|         m_interpolator.create(16, inputSampleRate, m_settings.m_afBandwidth); | ||||
|         m_interpolatorDistanceRemain = (Real) inputSampleRate / m_settings.m_audioSampleRate; | ||||
|         m_interpolatorDistance =  (Real) inputSampleRate / (Real) m_settings.m_audioSampleRate; | ||||
|         m_interpolatorDistanceRemain = (Real) inputSampleRate / m_audioSampleRate; | ||||
|         m_interpolatorDistance =  (Real) inputSampleRate / (Real) m_audioSampleRate; | ||||
| 
 | ||||
|         m_interpolatorStereo.create(16, inputSampleRate, m_settings.m_afBandwidth); | ||||
|         m_interpolatorStereoDistanceRemain = (Real) inputSampleRate / m_settings.m_audioSampleRate; | ||||
|         m_interpolatorStereoDistance =  (Real) inputSampleRate / (Real) m_settings.m_audioSampleRate; | ||||
|         m_interpolatorStereoDistanceRemain = (Real) inputSampleRate / m_audioSampleRate; | ||||
|         m_interpolatorStereoDistance =  (Real) inputSampleRate / (Real) m_audioSampleRate; | ||||
| 
 | ||||
|         m_interpolatorRDS.create(4, inputSampleRate, 600.0); | ||||
|         m_interpolatorRDSDistanceRemain = (Real) inputSampleRate / 250000.0; | ||||
| @ -428,12 +465,12 @@ void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force) | ||||
|         m_settingsMutex.lock(); | ||||
| 
 | ||||
|         m_interpolator.create(16, m_inputSampleRate, settings.m_afBandwidth); | ||||
|         m_interpolatorDistanceRemain = (Real) m_inputSampleRate / settings.m_audioSampleRate; | ||||
|         m_interpolatorDistance =  (Real) m_inputSampleRate / (Real) settings.m_audioSampleRate; | ||||
|         m_interpolatorDistanceRemain = (Real) m_inputSampleRate / m_audioSampleRate; | ||||
|         m_interpolatorDistance =  (Real) m_inputSampleRate / (Real) m_audioSampleRate; | ||||
| 
 | ||||
|         m_interpolatorStereo.create(16, m_inputSampleRate, settings.m_afBandwidth); | ||||
|         m_interpolatorStereoDistanceRemain = (Real) m_inputSampleRate / settings.m_audioSampleRate; | ||||
|         m_interpolatorStereoDistance =  (Real) m_inputSampleRate / (Real) settings.m_audioSampleRate; | ||||
|         m_interpolatorStereoDistanceRemain = (Real) m_inputSampleRate / m_audioSampleRate; | ||||
|         m_interpolatorStereoDistance =  (Real) m_inputSampleRate / (Real) m_audioSampleRate; | ||||
| 
 | ||||
|         m_interpolatorRDS.create(4, m_inputSampleRate, 600.0); | ||||
|         m_interpolatorRDSDistanceRemain = (Real) m_inputSampleRate / 250000.0; | ||||
| @ -453,12 +490,11 @@ void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force) | ||||
|         m_settingsMutex.unlock(); | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || | ||||
|         (settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) | ||||
|     if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || force) | ||||
|     { | ||||
|         m_settingsMutex.lock(); | ||||
|         qDebug() << "BFMDemod::handleMessage: m_lowpass.create"; | ||||
|         m_lowpass.create(21, settings.m_audioSampleRate, settings.m_afBandwidth); | ||||
|         m_lowpass.create(21, m_audioSampleRate, settings.m_afBandwidth); | ||||
|         m_settingsMutex.unlock(); | ||||
|     } | ||||
| 
 | ||||
| @ -469,10 +505,17 @@ void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force) | ||||
|         m_squelchLevel *= m_squelchLevel; | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) | ||||
|     if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) | ||||
|     { | ||||
|         m_deemphasisFilterX.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6); | ||||
|         m_deemphasisFilterY.configure(default_deemphasis * settings.m_audioSampleRate * 1.0e-6); | ||||
|         AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); | ||||
|         int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_audioDeviceName); | ||||
|         //qDebug("AMDemod::applySettings: audioDeviceName: %s audioDeviceIndex: %d", qPrintable(settings.m_audioDeviceName), audioDeviceIndex);
 | ||||
|         audioDeviceManager->addAudioSink(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex); | ||||
|         uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex); | ||||
| 
 | ||||
|         if (m_audioSampleRate != audioSampleRate) { | ||||
|             applyAudioSampleRate(audioSampleRate); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     m_settings = settings; | ||||
|  | ||||
| @ -169,6 +169,7 @@ private: | ||||
|     int m_inputSampleRate; | ||||
|     int m_inputFrequencyOffset; | ||||
|     BFMDemodSettings m_settings; | ||||
|     quint32 m_audioSampleRate; | ||||
| 
 | ||||
| 	NCO m_nco; | ||||
| 	Interpolator m_interpolator; //!< Interpolator between fixed demod bandwidth and audio bandwidth (rational)
 | ||||
| @ -225,6 +226,7 @@ private: | ||||
| 
 | ||||
|     void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false); | ||||
| 	void applySettings(const BFMDemodSettings& settings, bool force = false); | ||||
| 	void applyAudioSampleRate(int sampleRate); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_BFMDEMOD_H
 | ||||
|  | ||||
| @ -36,6 +36,8 @@ | ||||
| #include "util/simpleserializer.h" | ||||
| #include "util/db.h" | ||||
| #include "gui/basicchannelsettingsdialog.h" | ||||
| #include "gui/crightclickenabler.h" | ||||
| #include "gui/audioselectdialog.h" | ||||
| #include "mainwindow.h" | ||||
| 
 | ||||
| #include "bfmdemodsettings.h" | ||||
| @ -331,6 +333,9 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban | ||||
|     ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); | ||||
|     ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue); | ||||
| 
 | ||||
|     CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioStereo); | ||||
|     connect(audioMuteRightClickEnabler, SIGNAL(rightClick()), this, SLOT(audioSelect())); | ||||
| 
 | ||||
| 	setAttribute(Qt::WA_DeleteOnClose, true); | ||||
| 	connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); | ||||
|     connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); | ||||
| @ -455,6 +460,19 @@ void BFMDemodGUI::enterEvent(QEvent*) | ||||
| 	m_channelMarker.setHighlighted(true); | ||||
| } | ||||
| 
 | ||||
| void BFMDemodGUI::audioSelect() | ||||
| { | ||||
|     qDebug("BFMDemodGUI::audioSelect"); | ||||
|     AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName); | ||||
|     audioSelect.exec(); | ||||
| 
 | ||||
|     if (audioSelect.m_selected) | ||||
|     { | ||||
|         m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName; | ||||
|         applySettings(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void BFMDemodGUI::tick() | ||||
| { | ||||
|     double magsqAvg, magsqPeak; | ||||
|  | ||||
| @ -115,6 +115,7 @@ private slots: | ||||
| 	void onWidgetRolled(QWidget* widget, bool rollDown); | ||||
|     void onMenuDialogCalled(const QPoint& p); | ||||
|     void handleInputMessages(); | ||||
|     void audioSelect(); | ||||
| 	void tick(); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -163,7 +163,7 @@ | ||||
|         <item> | ||||
|          <widget class="QToolButton" name="audioStereo"> | ||||
|           <property name="toolTip"> | ||||
|            <string>Mono/Stereo toggle and pilot lock indicator</string> | ||||
|            <string>Light: Pilot lock indicator Left: Mono/Stereo toggle Right: select audio device</string> | ||||
|           </property> | ||||
|           <property name="autoFillBackground"> | ||||
|            <bool>true</bool> | ||||
|  | ||||
| @ -41,7 +41,6 @@ void BFMDemodSettings::resetToDefaults() | ||||
|     m_afBandwidth = 15000; | ||||
|     m_volume = 2.0; | ||||
|     m_squelch = -60.0; | ||||
|     m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate(); | ||||
|     m_audioStereo = false; | ||||
|     m_lsbStereo = false; | ||||
|     m_showPilot = false; | ||||
| @ -50,6 +49,7 @@ void BFMDemodSettings::resetToDefaults() | ||||
|     m_udpPort = 9999; | ||||
|     m_rgbColor = QColor(80, 120, 228).rgb(); | ||||
|     m_title = "Broadcast FM Demod"; | ||||
|     m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; | ||||
| } | ||||
| 
 | ||||
| QByteArray BFMDemodSettings::serialize() const | ||||
| @ -74,6 +74,7 @@ QByteArray BFMDemodSettings::serialize() const | ||||
|     } | ||||
| 
 | ||||
|     s.writeString(12, m_title); | ||||
|     s.writeString(13, m_audioDeviceName); | ||||
| 
 | ||||
|     return s.final(); | ||||
| } | ||||
| @ -122,6 +123,7 @@ bool BFMDemodSettings::deserialize(const QByteArray& data) | ||||
|         } | ||||
| 
 | ||||
|         d.readString(12, &m_title, "Broadcast FM Demod"); | ||||
|         d.readString(13, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @ -28,7 +28,6 @@ struct BFMDemodSettings | ||||
|     Real m_afBandwidth; | ||||
|     Real m_volume; | ||||
|     Real m_squelch; | ||||
|     quint32 m_audioSampleRate; | ||||
|     bool m_audioStereo; | ||||
|     bool m_lsbStereo; | ||||
|     bool m_showPilot; | ||||
| @ -37,6 +36,7 @@ struct BFMDemodSettings | ||||
|     quint16 m_udpPort; | ||||
|     quint32 m_rgbColor; | ||||
|     QString m_title; | ||||
|     QString m_audioDeviceName; | ||||
| 
 | ||||
|     Serializable *m_channelMarker; | ||||
|     Serializable *m_spectrumGUI; | ||||
|  | ||||
| @ -25,7 +25,7 @@ | ||||
| 
 | ||||
| const PluginDescriptor BFMPlugin::m_pluginDescriptor = { | ||||
| 	QString("Broadcast FM Demodulator"), | ||||
| 	QString("3.12.0"), | ||||
| 	QString("3.14.0"), | ||||
| 	QString("(c) Edouard Griffiths, F4EXB"), | ||||
| 	QString("https://github.com/f4exb/sdrangel"), | ||||
| 	true, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user