1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-05-23 18:52:28 -04:00

Multiple audio support: WFM modulator

This commit is contained in:
f4exb 2018-03-29 17:27:03 +02:00
parent d2a658d8a1
commit 75201ad303
8 changed files with 81 additions and 14 deletions

View File

@ -1,5 +1,7 @@
project(modwfm) project(modwfm)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(modwfm_SOURCES set(modwfm_SOURCES
wfmmod.cpp wfmmod.cpp
wfmmodgui.cpp wfmmodgui.cpp

View File

@ -60,9 +60,11 @@ Switches to the Morse keyer input. You must switch it off to make other inputs a
Adjusts the tone frequency from 0.1 to 2.5 kHz in 0.01 kHz steps Adjusts the tone frequency from 0.1 to 2.5 kHz in 0.01 kHz steps
<h4>10.4: Audio input select</h4> <h4>10.4: Audio input select and select audio input device</h4>
Switches to the audio input. You must switch it off to make other inputs available. Left click to switch to the audio input. You must switch it off to make other inputs available.
Right click to select audio input device.
<h3>11: CW (Morse) text</h3> <h3>11: CW (Morse) text</h3>

View File

@ -73,9 +73,10 @@ WFMMod::WFMMod(DeviceSinkAPI *deviceAPI) :
m_magsq = 0.0; m_magsq = 0.0;
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
m_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue()); DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate();
m_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
// CW keyer // CW keyer
m_cwKeyer.setSampleRate(m_outputSampleRate); m_cwKeyer.setSampleRate(m_outputSampleRate);
@ -164,7 +165,7 @@ void WFMMod::pull(Sample& sample)
void WFMMod::pullAudio(int nbSamples) void WFMMod::pullAudio(int nbSamples)
{ {
unsigned int nbSamplesAudio = nbSamples * ((Real) m_settings.m_audioSampleRate / (Real) m_basebandSampleRate); unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_basebandSampleRate);
if (nbSamplesAudio > m_audioBuffer.size()) if (nbSamplesAudio > m_audioBuffer.size())
{ {
@ -359,6 +360,20 @@ bool WFMMod::handleMessage(const Message& cmd)
return true; return true;
} }
else if (DSPConfigureAudio::match(cmd))
{
DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
uint32_t sampleRate = cfg.getSampleRate();
qDebug() << "WFMMod::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;
@ -404,6 +419,20 @@ void WFMMod::seekFileStream(int seekPercentage)
} }
} }
void WFMMod::applyAudioSampleRate(int sampleRate)
{
qDebug("WFMMod::applyAudioSampleRate: %d", sampleRate);
m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) sampleRate / (Real) m_outputSampleRate;
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
m_settingsMutex.unlock();
m_audioSampleRate = sampleRate;
}
void WFMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force) void WFMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force)
{ {
qDebug() << "WFMMod::applyChannelSettings:" qDebug() << "WFMMod::applyChannelSettings:"
@ -424,8 +453,8 @@ void WFMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate,
m_settingsMutex.lock(); m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0; m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false; m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) m_settings.m_audioSampleRate / (Real) outputSampleRate; m_interpolatorDistance = (Real) m_audioSampleRate / (Real) outputSampleRate;
m_interpolator.create(48, m_settings.m_audioSampleRate, m_settings.m_rfBandwidth / 2.2, 3.0); m_interpolator.create(48, m_audioSampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / outputSampleRate; Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / outputSampleRate;
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / outputSampleRate; Real hiCut = (m_settings.m_rfBandwidth / 2.0) / outputSampleRate;
m_rfFilter->create_filter(lowCut, hiCut); m_rfFilter->create_filter(lowCut, hiCut);
@ -451,16 +480,16 @@ void WFMMod::applySettings(const WFMModSettings& settings, bool force)
<< " m_toneFrequency: " << settings.m_toneFrequency << " m_toneFrequency: " << settings.m_toneFrequency
<< " m_channelMute: " << settings.m_channelMute << " m_channelMute: " << settings.m_channelMute
<< " m_playLoop: " << settings.m_playLoop << " m_playLoop: " << settings.m_playLoop
<< " 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) || force)
(settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
{ {
m_settingsMutex.lock(); m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0; m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false; m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) settings.m_audioSampleRate / (Real) m_outputSampleRate; m_interpolatorDistance = (Real) m_audioSampleRate / (Real) m_outputSampleRate;
m_interpolator.create(48, settings.m_audioSampleRate, settings.m_rfBandwidth / 2.2, 3.0); m_interpolator.create(48, m_audioSampleRate, settings.m_rfBandwidth / 2.2, 3.0);
m_settingsMutex.unlock(); m_settingsMutex.unlock();
} }
@ -480,6 +509,18 @@ void WFMMod::applySettings(const WFMModSettings& settings, bool force)
m_settingsMutex.unlock(); m_settingsMutex.unlock();
} }
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
{
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
audioDeviceManager->addAudioSource(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex);
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
if (m_audioSampleRate != audioSampleRate) {
applyAudioSampleRate(audioSampleRate);
}
}
m_settings = settings; m_settings = settings;
} }

View File

@ -277,9 +277,9 @@ private:
int m_outputSampleRate; int m_outputSampleRate;
int m_inputFrequencyOffset; int m_inputFrequencyOffset;
WFMModSettings m_settings; WFMModSettings m_settings;
quint32 m_audioSampleRate;
NCO m_carrierNco; NCO m_carrierNco;
NCOF m_toneNco;
NCOF m_toneNcoRF; NCOF m_toneNcoRF;
float m_modPhasor; //!< baseband modulator phasor float m_modPhasor; //!< baseband modulator phasor
Complex m_modSample; Complex m_modSample;
@ -316,6 +316,7 @@ private:
CWKeyer m_cwKeyer; CWKeyer m_cwKeyer;
static const int m_levelNbSamples; static const int m_levelNbSamples;
void applyAudioSampleRate(int sampleRate);
void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false); void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false);
void applySettings(const WFMModSettings& settings, bool force = false); void applySettings(const WFMModSettings& settings, bool force = false);
void pullAF(Complex& sample); void pullAF(Complex& sample);

View File

@ -28,6 +28,8 @@
#include "util/simpleserializer.h" #include "util/simpleserializer.h"
#include "util/db.h" #include "util/db.h"
#include "dsp/dspengine.h" #include "dsp/dspengine.h"
#include "gui/crightclickenabler.h"
#include "gui/audioselectdialog.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_wfmmodgui.h" #include "ui_wfmmodgui.h"
@ -299,6 +301,9 @@ WFMModGUI::WFMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
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);
@ -411,6 +416,19 @@ void WFMModGUI::enterEvent(QEvent*)
m_channelMarker.setHighlighted(true); m_channelMarker.setHighlighted(true);
} }
void WFMModGUI::audioSelect()
{
qDebug("WFMModGUI::audioSelect");
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, true); // true for input
audioSelect.exec();
if (audioSelect.m_selected)
{
m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
applySettings();
}
}
void WFMModGUI::tick() void WFMModGUI::tick()
{ {
double powDb = CalcDb::dbPower(m_wfmMod->getMagSq()); double powDb = CalcDb::dbPower(m_wfmMod->getMagSq());

View File

@ -122,6 +122,7 @@ private slots:
void onWidgetRolled(QWidget* widget, bool rollDown); void onWidgetRolled(QWidget* widget, bool rollDown);
void configureFileName(); void configureFileName();
void audioSelect();
void tick(); void tick();
}; };

View File

@ -42,12 +42,12 @@ void WFMModSettings::resetToDefaults()
m_afBandwidth = 15000.0f; m_afBandwidth = 15000.0f;
m_fmDeviation = 50000.0f; m_fmDeviation = 50000.0f;
m_toneFrequency = 1000.0f; m_toneFrequency = 1000.0f;
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_volumeFactor = 1.0f; m_volumeFactor = 1.0f;
m_channelMute = false; m_channelMute = false;
m_playLoop = false; m_playLoop = false;
m_rgbColor = QColor(0, 0, 255).rgb(); m_rgbColor = QColor(0, 0, 255).rgb();
m_title = "WFM Modulator"; m_title = "WFM Modulator";
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
} }
QByteArray WFMModSettings::serialize() const QByteArray WFMModSettings::serialize() const
@ -71,6 +71,7 @@ QByteArray WFMModSettings::serialize() const
} }
s.writeString(10, m_title); s.writeString(10, m_title);
s.writeString(11, m_audioDeviceName);
return s.final(); return s.final();
} }
@ -110,6 +111,7 @@ bool WFMModSettings::deserialize(const QByteArray& data)
} }
d.readString(10, &m_title, "WFM Modulator"); d.readString(10, &m_title, "WFM Modulator");
d.readString(11, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
return true; return true;
} }

View File

@ -32,11 +32,11 @@ struct WFMModSettings
float m_fmDeviation; float m_fmDeviation;
float m_toneFrequency; float m_toneFrequency;
float m_volumeFactor; float m_volumeFactor;
quint32 m_audioSampleRate;
bool m_channelMute; bool m_channelMute;
bool m_playLoop; bool m_playLoop;
quint32 m_rgbColor; quint32 m_rgbColor;
QString m_title; QString m_title;
QString m_audioDeviceName;
Serializable *m_channelMarker; Serializable *m_channelMarker;
Serializable *m_cwKeyerGUI; Serializable *m_cwKeyerGUI;