mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-22 16:08:39 -05:00
Multiple audio support: AM modulator
This commit is contained in:
parent
e0db2adc6b
commit
2380211533
@ -1,5 +1,7 @@
|
||||
project(modam)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
|
||||
set(modam_SOURCES
|
||||
ammod.cpp
|
||||
ammodgui.cpp
|
||||
|
@ -65,11 +65,12 @@ AMMod::AMMod(DeviceSinkAPI *deviceAPI) :
|
||||
|
||||
m_magsq = 0.0;
|
||||
|
||||
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
|
||||
m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate();
|
||||
m_toneNco.setFreq(1000.0, m_audioSampleRate);
|
||||
|
||||
// CW keyer
|
||||
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
||||
m_cwKeyer.setSampleRate(m_audioSampleRate);
|
||||
m_cwKeyer.setWPM(13);
|
||||
m_cwKeyer.setMode(CWKeyerSettings::CWNone);
|
||||
|
||||
@ -139,7 +140,7 @@ void AMMod::pull(Sample& sample)
|
||||
void AMMod::pullAudio(int nbSamples)
|
||||
{
|
||||
// qDebug("AMMod::pullAudio: %d", nbSamples);
|
||||
unsigned int nbAudioSamples = nbSamples * ((Real) m_settings.m_audioSampleRate / (Real) m_basebandSampleRate);
|
||||
unsigned int nbAudioSamples = nbSamples * ((Real) m_audioSampleRate / (Real) m_basebandSampleRate);
|
||||
|
||||
if (nbAudioSamples > m_audioBuffer.size())
|
||||
{
|
||||
@ -335,6 +336,20 @@ bool AMMod::handleMessage(const Message& cmd)
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPConfigureAudio::match(cmd))
|
||||
{
|
||||
DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
|
||||
uint32_t sampleRate = cfg.getSampleRate();
|
||||
|
||||
qDebug() << "AMMod::handleMessage: DSPConfigureAudio:"
|
||||
<< " sampleRate: " << sampleRate;
|
||||
|
||||
if (sampleRate != m_audioSampleRate) {
|
||||
applyAudioSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
return true;
|
||||
@ -380,6 +395,28 @@ void AMMod::seekFileStream(int seekPercentage)
|
||||
}
|
||||
}
|
||||
|
||||
void AMMod::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
qDebug("AMMod::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
MsgConfigureChannelizer* channelConfigMsg = MsgConfigureChannelizer::create(
|
||||
sampleRate, m_settings.m_inputFrequencyOffset);
|
||||
m_inputMessageQueue.push(channelConfigMsg);
|
||||
|
||||
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_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_cwKeyer.setSampleRate(sampleRate);
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
m_audioSampleRate = sampleRate;
|
||||
}
|
||||
|
||||
void AMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force)
|
||||
{
|
||||
qDebug() << "AMMod::applyChannelSettings:"
|
||||
@ -400,8 +437,8 @@ void AMMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, i
|
||||
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);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
@ -419,30 +456,37 @@ void AMMod::applySettings(const AMModSettings& settings, bool force)
|
||||
<< " m_toneFrequency: " << settings.m_toneFrequency
|
||||
<< " m_volumeFactor: " << settings.m_volumeFactor
|
||||
<< " m_audioMute: " << settings.m_channelMute
|
||||
<< " m_playLoop: " << settings.m_playLoop;
|
||||
<< " m_playLoop: " << settings.m_playLoop
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " force: " << force;
|
||||
|
||||
if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) ||
|
||||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
|
||||
if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || 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();
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) ||
|
||||
(settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force)
|
||||
{
|
||||
m_settingsMutex.lock();
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, settings.m_audioSampleRate);
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
m_settingsMutex.unlock();
|
||||
}
|
||||
|
||||
if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force)
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
m_cwKeyer.setSampleRate(settings.m_audioSampleRate);
|
||||
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;
|
||||
|
@ -276,6 +276,7 @@ private:
|
||||
int m_outputSampleRate;
|
||||
int m_inputFrequencyOffset;
|
||||
AMModSettings m_settings;
|
||||
quint32 m_audioSampleRate;
|
||||
|
||||
NCO m_carrierNco;
|
||||
NCOF m_toneNco;
|
||||
@ -309,6 +310,7 @@ private:
|
||||
|
||||
static const int m_levelNbSamples;
|
||||
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force = false);
|
||||
void applySettings(const AMModSettings& settings, bool force = false);
|
||||
void pullAF(Real& sample);
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "util/simpleserializer.h"
|
||||
#include "util/db.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "gui/crightclickenabler.h"
|
||||
#include "gui/audioselectdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
AMModGUI* AMModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
|
||||
@ -282,6 +284,9 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampl
|
||||
|
||||
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);
|
||||
@ -391,6 +396,19 @@ void AMModGUI::enterEvent(QEvent*)
|
||||
m_channelMarker.setHighlighted(true);
|
||||
}
|
||||
|
||||
void AMModGUI::audioSelect()
|
||||
{
|
||||
qDebug("AMModGUI::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 AMModGUI::tick()
|
||||
{
|
||||
double powDb = CalcDb::dbPower(m_amMod->getMagSq());
|
||||
|
@ -110,6 +110,7 @@ private slots:
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
|
||||
void configureFileName();
|
||||
void audioSelect();
|
||||
void tick();
|
||||
};
|
||||
|
||||
|
@ -56,16 +56,7 @@
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -449,7 +440,7 @@
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="mic">
|
||||
<property name="toolTip">
|
||||
<string>Audio input</string>
|
||||
<string>Left: Source audio input Right: Select audio input device</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
@ -34,12 +34,12 @@ void AMModSettings::resetToDefaults()
|
||||
m_rfBandwidth = 12500.0;
|
||||
m_modFactor = 0.2f;
|
||||
m_toneFrequency = 1000.0f;
|
||||
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
|
||||
m_volumeFactor = 1.0f;
|
||||
m_channelMute = false;
|
||||
m_playLoop = false;
|
||||
m_rgbColor = QColor(255, 255, 0).rgb();
|
||||
m_title = "AM Modulator";
|
||||
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
}
|
||||
|
||||
QByteArray AMModSettings::serialize() const
|
||||
@ -62,6 +62,7 @@ QByteArray AMModSettings::serialize() const
|
||||
}
|
||||
|
||||
s.writeString(9, m_title);
|
||||
s.writeString(10, m_audioDeviceName);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -100,6 +101,7 @@ bool AMModSettings::deserialize(const QByteArray& data)
|
||||
}
|
||||
|
||||
d.readString(9, &m_title, "AM Modulator");
|
||||
d.readString(10, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ struct AMModSettings
|
||||
float m_modFactor;
|
||||
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;
|
||||
|
@ -56,9 +56,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>9.4: Audio input select</h4>
|
||||
<h4>9.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>10: CW (Morse) text</h3>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user