mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-24 03:02:29 -04:00
Multiple audio support: WFM demodulator
This commit is contained in:
parent
ae0470218c
commit
44b4b3cc85
@ -453,6 +453,7 @@ void BFMDemod::applySettings(const BFMDemodSettings& settings, bool force)
|
|||||||
<< " m_rdsActive: " << settings.m_rdsActive
|
<< " m_rdsActive: " << settings.m_rdsActive
|
||||||
<< " m_udpAddress: " << settings.m_udpAddress
|
<< " m_udpAddress: " << settings.m_udpAddress
|
||||||
<< " m_udpPort: " << settings.m_udpPort
|
<< " m_udpPort: " << settings.m_udpPort
|
||||||
|
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||||
<< " force: " << force;
|
<< " force: " << force;
|
||||||
|
|
||||||
if ((settings.m_audioStereo && (settings.m_audioStereo != m_settings.m_audioStereo)) || force)
|
if ((settings.m_audioStereo && (settings.m_audioStereo != m_settings.m_audioStereo)) || force)
|
||||||
|
@ -224,9 +224,9 @@ private:
|
|||||||
|
|
||||||
static const int m_udpBlockSize;
|
static const int m_udpBlockSize;
|
||||||
|
|
||||||
|
void applyAudioSampleRate(int sampleRate);
|
||||||
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
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
project(wfm)
|
project(wfm)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
|
||||||
set(wfm_SOURCES
|
set(wfm_SOURCES
|
||||||
wfmdemod.cpp
|
wfmdemod.cpp
|
||||||
wfmdemodgui.cpp
|
wfmdemodgui.cpp
|
||||||
|
@ -60,6 +60,7 @@ WFMDemod::WFMDemod(DeviceSourceAPI* deviceAPI) :
|
|||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
|
m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate();
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically - no RTP
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically - no RTP
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
|
|
||||||
@ -243,6 +244,20 @@ bool WFMDemod::handleMessage(const Message& cmd)
|
|||||||
m_audioNetSink->moveToThread(const_cast<QThread*>(thread)); // use the thread for udp sinks
|
m_audioNetSink->moveToThread(const_cast<QThread*>(thread)); // use the thread for udp sinks
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (DSPConfigureAudio::match(cmd))
|
||||||
|
{
|
||||||
|
DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
|
||||||
|
uint32_t sampleRate = cfg.getSampleRate();
|
||||||
|
|
||||||
|
qDebug() << "WFMDemod::handleMessage: DSPConfigureAudio:"
|
||||||
|
<< " sampleRate: " << sampleRate;
|
||||||
|
|
||||||
|
if (sampleRate != m_audioSampleRate) {
|
||||||
|
applyAudioSampleRate(sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (DSPSignalNotification::match(cmd))
|
else if (DSPSignalNotification::match(cmd))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -253,6 +268,21 @@ bool WFMDemod::handleMessage(const Message& cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WFMDemod::applyAudioSampleRate(int sampleRate)
|
||||||
|
{
|
||||||
|
qDebug("WFMDemod::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_settingsMutex.unlock();
|
||||||
|
|
||||||
|
m_audioSampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
void WFMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
|
void WFMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force)
|
||||||
{
|
{
|
||||||
qDebug() << "WFMDemod::applyChannelSettings:"
|
qDebug() << "WFMDemod::applyChannelSettings:"
|
||||||
@ -269,8 +299,8 @@ void WFMDemod::applyChannelSettings(int inputSampleRate, int inputFrequencyOffse
|
|||||||
{
|
{
|
||||||
qDebug() << "WFMDemod::applyChannelSettings: m_interpolator.create";
|
qDebug() << "WFMDemod::applyChannelSettings: m_interpolator.create";
|
||||||
m_interpolator.create(16, inputSampleRate, m_settings.m_afBandwidth);
|
m_interpolator.create(16, inputSampleRate, m_settings.m_afBandwidth);
|
||||||
m_interpolatorDistanceRemain = (Real) inputSampleRate / (Real) m_settings.m_audioSampleRate;
|
m_interpolatorDistanceRemain = (Real) inputSampleRate / (Real) m_audioSampleRate;
|
||||||
m_interpolatorDistance = (Real) inputSampleRate / (Real) m_settings.m_audioSampleRate;
|
m_interpolatorDistance = (Real) inputSampleRate / (Real) m_audioSampleRate;
|
||||||
qDebug() << "WFMDemod::applySettings: m_rfFilter->create_filter";
|
qDebug() << "WFMDemod::applySettings: m_rfFilter->create_filter";
|
||||||
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / inputSampleRate;
|
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / inputSampleRate;
|
||||||
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / inputSampleRate;
|
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / inputSampleRate;
|
||||||
@ -295,17 +325,17 @@ void WFMDemod::applySettings(const WFMDemodSettings& settings, bool force)
|
|||||||
<< " m_copyAudioToUDP: " << settings.m_copyAudioToUDP
|
<< " m_copyAudioToUDP: " << settings.m_copyAudioToUDP
|
||||||
<< " m_udpAddress: " << settings.m_udpAddress
|
<< " m_udpAddress: " << settings.m_udpAddress
|
||||||
<< " m_udpPort: " << settings.m_udpPort
|
<< " m_udpPort: " << settings.m_udpPort
|
||||||
|
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||||
<< " force: " << force;
|
<< " force: " << force;
|
||||||
|
|
||||||
if((settings.m_audioSampleRate != m_settings.m_audioSampleRate) ||
|
if((settings.m_afBandwidth != m_settings.m_afBandwidth) ||
|
||||||
(settings.m_afBandwidth != m_settings.m_afBandwidth) ||
|
|
||||||
(settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
(settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
||||||
{
|
{
|
||||||
m_settingsMutex.lock();
|
m_settingsMutex.lock();
|
||||||
qDebug() << "WFMDemod::applySettings: m_interpolator.create";
|
qDebug() << "WFMDemod::applySettings: m_interpolator.create";
|
||||||
m_interpolator.create(16, m_inputSampleRate, settings.m_afBandwidth);
|
m_interpolator.create(16, m_inputSampleRate, settings.m_afBandwidth);
|
||||||
m_interpolatorDistanceRemain = (Real) m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
m_interpolatorDistanceRemain = (Real) m_inputSampleRate / (Real) m_audioSampleRate;
|
||||||
m_interpolatorDistance = (Real) m_inputSampleRate / (Real) settings.m_audioSampleRate;
|
m_interpolatorDistance = (Real) m_inputSampleRate / (Real) m_audioSampleRate;
|
||||||
qDebug() << "WFMDemod::applySettings: m_rfFilter->create_filter";
|
qDebug() << "WFMDemod::applySettings: m_rfFilter->create_filter";
|
||||||
Real lowCut = -(settings.m_rfBandwidth / 2.0) / m_inputSampleRate;
|
Real lowCut = -(settings.m_rfBandwidth / 2.0) / m_inputSampleRate;
|
||||||
Real hiCut = (settings.m_rfBandwidth / 2.0) / m_inputSampleRate;
|
Real hiCut = (settings.m_rfBandwidth / 2.0) / m_inputSampleRate;
|
||||||
@ -329,6 +359,19 @@ void WFMDemod::applySettings(const WFMDemodSettings& settings, bool force)
|
|||||||
m_audioNetSink->setDestination(settings.m_udpAddress, settings.m_udpPort);
|
m_audioNetSink->setDestination(settings.m_udpAddress, settings.m_udpPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||||
|
{
|
||||||
|
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;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ private:
|
|||||||
int m_inputSampleRate;
|
int m_inputSampleRate;
|
||||||
int m_inputFrequencyOffset;
|
int m_inputFrequencyOffset;
|
||||||
WFMDemodSettings m_settings;
|
WFMDemodSettings m_settings;
|
||||||
|
quint32 m_audioSampleRate;
|
||||||
|
|
||||||
NCO m_nco;
|
NCO m_nco;
|
||||||
Interpolator m_interpolator; //!< Interpolator between sample rate sent from DSP engine and requested RF bandwidth (rational)
|
Interpolator m_interpolator; //!< Interpolator between sample rate sent from DSP engine and requested RF bandwidth (rational)
|
||||||
@ -165,6 +166,7 @@ private:
|
|||||||
|
|
||||||
static const int m_udpBlockSize;
|
static const int m_udpBlockSize;
|
||||||
|
|
||||||
|
void applyAudioSampleRate(int sampleRate);
|
||||||
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false);
|
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force = false);
|
||||||
void applySettings(const WFMDemodSettings& settings, bool force = false);
|
void applySettings(const WFMDemodSettings& settings, bool force = false);
|
||||||
};
|
};
|
||||||
|
@ -13,6 +13,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 "wfmdemod.h"
|
#include "wfmdemod.h"
|
||||||
@ -177,6 +179,9 @@ WFMDemodGUI::WFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
|
|||||||
|
|
||||||
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||||
|
|
||||||
|
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute);
|
||||||
|
connect(audioMuteRightClickEnabler, SIGNAL(rightClick()), this, SLOT(audioSelect()));
|
||||||
|
|
||||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||||
@ -287,6 +292,19 @@ void WFMDemodGUI::enterEvent(QEvent*)
|
|||||||
m_channelMarker.setHighlighted(true);
|
m_channelMarker.setHighlighted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WFMDemodGUI::audioSelect()
|
||||||
|
{
|
||||||
|
qDebug("WFMDemodGUI::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 WFMDemodGUI::tick()
|
void WFMDemodGUI::tick()
|
||||||
{
|
{
|
||||||
double magsqAvg, magsqPeak;
|
double magsqAvg, magsqPeak;
|
||||||
|
@ -83,6 +83,7 @@ private slots:
|
|||||||
void on_copyAudioToUDP_toggled(bool copy);
|
void on_copyAudioToUDP_toggled(bool copy);
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||||
void onMenuDialogCalled(const QPoint& p);
|
void onMenuDialogCalled(const QPoint& p);
|
||||||
|
void audioSelect();
|
||||||
void tick();
|
void tick();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -377,6 +377,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="audioMute">
|
<widget class="QToolButton" name="audioMute">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Left: audio mute Right: select audio device</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
@ -42,12 +42,12 @@ void WFMDemodSettings::resetToDefaults()
|
|||||||
m_volume = 2.0;
|
m_volume = 2.0;
|
||||||
m_squelch = -60.0;
|
m_squelch = -60.0;
|
||||||
m_audioMute = false;
|
m_audioMute = false;
|
||||||
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
|
|
||||||
m_copyAudioToUDP = false;
|
m_copyAudioToUDP = false;
|
||||||
m_udpAddress = "127.0.0.1";
|
m_udpAddress = "127.0.0.1";
|
||||||
m_udpPort = 9999;
|
m_udpPort = 9999;
|
||||||
m_rgbColor = QColor(0, 0, 255).rgb();
|
m_rgbColor = QColor(0, 0, 255).rgb();
|
||||||
m_title = "WFM Demodulator";
|
m_title = "WFM Demodulator";
|
||||||
|
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray WFMDemodSettings::serialize() const
|
QByteArray WFMDemodSettings::serialize() const
|
||||||
@ -60,11 +60,13 @@ QByteArray WFMDemodSettings::serialize() const
|
|||||||
s.writeS32(5, m_squelch);
|
s.writeS32(5, m_squelch);
|
||||||
s.writeU32(7, m_rgbColor);
|
s.writeU32(7, m_rgbColor);
|
||||||
s.writeString(8, m_title);
|
s.writeString(8, m_title);
|
||||||
|
s.writeString(9, m_audioDeviceName);
|
||||||
|
|
||||||
if (m_channelMarker) {
|
if (m_channelMarker) {
|
||||||
s.writeBlob(11, m_channelMarker->serialize());
|
s.writeBlob(11, m_channelMarker->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +98,7 @@ bool WFMDemodSettings::deserialize(const QByteArray& data)
|
|||||||
m_squelch = tmp;
|
m_squelch = tmp;
|
||||||
d.readU32(7, &m_rgbColor);
|
d.readU32(7, &m_rgbColor);
|
||||||
d.readString(8, &m_title, "WFM Demodulator");
|
d.readString(8, &m_title, "WFM Demodulator");
|
||||||
|
d.readString(9, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||||
|
|
||||||
d.readBlob(11, &bytetmp);
|
d.readBlob(11, &bytetmp);
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ struct WFMDemodSettings
|
|||||||
Real m_volume;
|
Real m_volume;
|
||||||
Real m_squelch;
|
Real m_squelch;
|
||||||
bool m_audioMute;
|
bool m_audioMute;
|
||||||
quint32 m_audioSampleRate;
|
|
||||||
bool m_copyAudioToUDP;
|
bool m_copyAudioToUDP;
|
||||||
QString m_udpAddress;
|
QString m_udpAddress;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
const PluginDescriptor WFMPlugin::m_pluginDescriptor = {
|
const PluginDescriptor WFMPlugin::m_pluginDescriptor = {
|
||||||
QString("WFM Demodulator"),
|
QString("WFM 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