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)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(modwfm_SOURCES
wfmmod.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
<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>

View File

@ -73,9 +73,10 @@ WFMMod::WFMMod(DeviceSinkAPI *deviceAPI) :
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());
m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate();
m_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
// CW keyer
m_cwKeyer.setSampleRate(m_outputSampleRate);
@ -164,7 +165,7 @@ void WFMMod::pull(Sample& sample)
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())
{
@ -359,6 +360,20 @@ bool WFMMod::handleMessage(const Message& cmd)
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))
{
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)
{
qDebug() << "WFMMod::applyChannelSettings:"
@ -424,8 +453,8 @@ void WFMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate,
m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) m_settings.m_audioSampleRate / (Real) outputSampleRate;
m_interpolator.create(48, m_settings.m_audioSampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
m_interpolatorDistance = (Real) m_audioSampleRate / (Real) outputSampleRate;
m_interpolator.create(48, m_audioSampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
Real lowCut = -(m_settings.m_rfBandwidth / 2.0) / outputSampleRate;
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / outputSampleRate;
m_rfFilter->create_filter(lowCut, hiCut);
@ -451,16 +480,16 @@ void WFMMod::applySettings(const WFMModSettings& settings, bool force)
<< " m_toneFrequency: " << settings.m_toneFrequency
<< " m_channelMute: " << settings.m_channelMute
<< " m_playLoop: " << settings.m_playLoop
<< " m_audioDeviceName: " << settings.m_audioDeviceName
<< " force: " << force;
if((settings.m_audioSampleRate != m_settings.m_audioSampleRate) ||
(settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
if((settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
{
m_settingsMutex.lock();
m_interpolatorDistanceRemain = 0;
m_interpolatorConsumed = false;
m_interpolatorDistance = (Real) settings.m_audioSampleRate / (Real) m_outputSampleRate;
m_interpolator.create(48, settings.m_audioSampleRate, settings.m_rfBandwidth / 2.2, 3.0);
m_interpolatorDistance = (Real) m_audioSampleRate / (Real) m_outputSampleRate;
m_interpolator.create(48, m_audioSampleRate, settings.m_rfBandwidth / 2.2, 3.0);
m_settingsMutex.unlock();
}
@ -480,6 +509,18 @@ void WFMMod::applySettings(const WFMModSettings& settings, bool force)
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;
}

View File

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

View File

@ -28,6 +28,8 @@
#include "util/simpleserializer.h"
#include "util/db.h"
#include "dsp/dspengine.h"
#include "gui/crightclickenabler.h"
#include "gui/audioselectdialog.h"
#include "mainwindow.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()));
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
connect(audioMuteRightClickEnabler, SIGNAL(rightClick()), this, SLOT(audioSelect()));
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
@ -411,6 +416,19 @@ void WFMModGUI::enterEvent(QEvent*)
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()
{
double powDb = CalcDb::dbPower(m_wfmMod->getMagSq());

View File

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

View File

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

View File

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