mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-24 11:12:27 -04:00
Multiple audio support: WFM modulator
This commit is contained in:
parent
d2a658d8a1
commit
75201ad303
@ -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
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user