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