mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
Modulator plugins with configurable audio: fixed audio sample rate handling
This commit is contained in:
parent
7917d595f5
commit
674a4ccd27
@ -643,3 +643,13 @@ void AMMod::setLevelMeter(QObject *levelMeter)
|
||||
{
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
int AMMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
int AMMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
@ -225,6 +225,8 @@ public:
|
||||
double getMagSq() const;
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
|
||||
static const QString m_channelIdURI;
|
||||
static const QString m_channelId;
|
||||
|
@ -159,6 +159,7 @@ bool AMModBaseband::handleMessage(const Message& cmd)
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
|
||||
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -183,18 +184,23 @@ void AMModBaseband::applySettings(const AMModSettings& settings, bool force)
|
||||
{
|
||||
if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || force)
|
||||
{
|
||||
m_channelizer->setChannelization(48000, settings.m_inputFrequencyOffset);
|
||||
m_channelizer->setChannelization(m_source.getAudioSampleRate(), settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
}
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate) {
|
||||
if (getAudioSampleRate() != audioSampleRate)
|
||||
{
|
||||
m_channelizer->setChannelization(audioSampleRate, settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
}
|
||||
}
|
||||
@ -203,8 +209,9 @@ void AMModBaseband::applySettings(const AMModSettings& settings, bool force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName);
|
||||
audioDeviceManager->removeAudioSink(getFeedbackAudioFifo());
|
||||
audioDeviceManager->addAudioSink(getFeedbackAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getFeedbackAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyFeedbackAudioSampleRate(audioSampleRate);
|
||||
|
@ -63,8 +63,8 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
unsigned int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getChannelSampleRate() const;
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
|
@ -346,6 +346,8 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampl
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_feedbackAudioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false)
|
||||
{
|
||||
@ -526,6 +528,32 @@ void AMModGUI::tick()
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_amMod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
int feedbackAudioSampleRate = m_amMod->getFeedbackAudioSampleRate();
|
||||
|
||||
if (feedbackAudioSampleRate != m_feedbackAudioSampleRate)
|
||||
{
|
||||
if (feedbackAudioSampleRate < 0) {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background-color : red; }");
|
||||
} else {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_feedbackAudioSampleRate = feedbackAudioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == AMModSettings::AMModInputFile))
|
||||
{
|
||||
AMMod::MsgConfigureFileSourceStreamTiming* message = AMMod::MsgConfigureFileSourceStreamTiming::create();
|
||||
|
@ -73,6 +73,8 @@ private:
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
@ -262,8 +262,14 @@ void AMModSource::calculateLevel(Real& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void AMModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
void AMModSource::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("AMModSource::applyAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("AMModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
@ -277,8 +283,14 @@ void AMModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
}
|
||||
|
||||
void AMModSource::applyFeedbackAudioSampleRate(unsigned int sampleRate)
|
||||
void AMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("AMModSource::applyFeedbackAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("AMModSource::applyFeedbackAudioSampleRate: %u", sampleRate);
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
|
@ -46,10 +46,10 @@ public:
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
AudioFifo *getFeedbackAudioFifo() { return &m_feedbackAudioFifo; }
|
||||
void applyAudioSampleRate(unsigned int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(unsigned int sampleRate);
|
||||
unsigned int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
@ -83,12 +83,12 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
quint32 m_audioSampleRate;
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
uint m_audioBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
||||
quint32 m_feedbackAudioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
@ -624,7 +624,7 @@ void FreeDVMod::networkManagerFinished(QNetworkReply *reply)
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
uint32_t FreeDVMod::getAudioSampleRate() const
|
||||
int FreeDVMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ public:
|
||||
SWGSDRangel::SWGChannelSettings& response);
|
||||
|
||||
SpectrumVis *getSpectrumVis() { return &m_spectrumVis; }
|
||||
uint32_t getAudioSampleRate() const;
|
||||
int getAudioSampleRate() const;
|
||||
uint32_t getModemSampleRate() const;
|
||||
Real getLowCutoff() const;
|
||||
Real getHiCutoff() const;
|
||||
|
@ -194,8 +194,9 @@ void FreeDVModBaseband::applySettings(const FreeDVModSettings& settings, bool fo
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
void setSpectrumSampleSink(BasebandSampleSink* sampleSink) { m_source.setSpectrumSink(sampleSink); }
|
||||
unsigned int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
unsigned int getModemSampleRate() const { return m_source.getModemSampleRate(); }
|
||||
Real getLowCutoff() const { return m_source.getLowCutoff(); }
|
||||
Real getHiCutoff() const { return m_source.getHiCutoff(); }
|
||||
|
@ -361,6 +361,7 @@ FreeDVModGUI::FreeDVModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false)
|
||||
{
|
||||
@ -559,6 +560,19 @@ void FreeDVModGUI::tick()
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_freeDVMod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == FreeDVModSettings::FreeDVModInputFile))
|
||||
{
|
||||
FreeDVMod::MsgConfigureFileSourceStreamTiming* message = FreeDVMod::MsgConfigureFileSourceStreamTiming::create();
|
||||
|
@ -76,6 +76,7 @@ private:
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
@ -364,6 +364,12 @@ void FreeDVModSource::calculateLevel(qint16& sample)
|
||||
|
||||
void FreeDVModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("FreeDVModSource::applyAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("FreeDVModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
// TODO: put up simple IIR interpolator when sampleRate < m_modemSampleRate
|
||||
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
peakLevel = m_peakLevelOut;
|
||||
numSamples = m_levelNbSamples;
|
||||
}
|
||||
unsigned int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
unsigned int getModemSampleRate() const { return m_modemSampleRate; }
|
||||
Real getLowCutoff() const { return m_lowCutoff; }
|
||||
Real getHiCutoff() const { return m_hiCutoff; }
|
||||
@ -100,7 +100,7 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
quint32 m_audioSampleRate;
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
uint m_audioBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
@ -711,3 +711,13 @@ uint32_t NFMMod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSinkStreams();
|
||||
}
|
||||
|
||||
int NFMMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
int NFMMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
@ -225,6 +225,8 @@ public:
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
|
||||
static const QString m_channelIdURI;
|
||||
static const QString m_channelId;
|
||||
|
@ -159,6 +159,7 @@ bool NFMModBaseband::handleMessage(const Message& cmd)
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
|
||||
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -182,18 +183,24 @@ void NFMModBaseband::applySettings(const NFMModSettings& settings, bool force)
|
||||
{
|
||||
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
|
||||
{
|
||||
m_channelizer->setChannelization(48000, settings.m_inputFrequencyOffset); // Fixed 48000 S/s source sample rate
|
||||
m_channelizer->setChannelization(m_source.getAudioSampleRate(), settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
}
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate) {
|
||||
if (getAudioSampleRate() != audioSampleRate)
|
||||
{
|
||||
m_channelizer->setChannelization(audioSampleRate, settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
}
|
||||
}
|
||||
@ -202,8 +209,9 @@ void NFMModBaseband::applySettings(const NFMModSettings& settings, bool force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName);
|
||||
audioDeviceManager->removeAudioSink(getFeedbackAudioFifo());
|
||||
audioDeviceManager->addAudioSink(getFeedbackAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getFeedbackAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyFeedbackAudioSampleRate(audioSampleRate);
|
||||
|
@ -63,8 +63,8 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
unsigned int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getChannelSampleRate() const;
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
|
@ -364,6 +364,8 @@ NFMModGUI::NFMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_feedbackAudioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false)
|
||||
{
|
||||
@ -561,6 +563,32 @@ void NFMModGUI::tick()
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_nfmMod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
int feedbackAudioSampleRate = m_nfmMod->getFeedbackAudioSampleRate();
|
||||
|
||||
if (feedbackAudioSampleRate != m_feedbackAudioSampleRate)
|
||||
{
|
||||
if (feedbackAudioSampleRate < 0) {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background-color : red; }");
|
||||
} else {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_feedbackAudioSampleRate = feedbackAudioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == NFMModSettings::NFMModInputFile))
|
||||
{
|
||||
NFMMod::MsgConfigureFileSourceStreamTiming* message = NFMMod::MsgConfigureFileSourceStreamTiming::create();
|
||||
|
@ -71,6 +71,8 @@ private:
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
NFMModSettings::NFMModInputAF m_modAFInput;
|
||||
|
@ -282,9 +282,15 @@ void NFMModSource::calculateLevel(Real& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void NFMModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
void NFMModSource::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
qDebug("NFMModSource::applyAudioSampleRate: %u", sampleRate);
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("NFMModSource::applyAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("NFMModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorConsumed = false;
|
||||
@ -301,9 +307,15 @@ void NFMModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
}
|
||||
|
||||
void NFMModSource::applyFeedbackAudioSampleRate(unsigned int sampleRate)
|
||||
void NFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
{
|
||||
qDebug("NFMModSource::applyFeedbackAudioSampleRate: %u", sampleRate);
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("NFMModSource::applyFeedbackAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("NFMModSource::applyFeedbackAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
|
@ -49,10 +49,10 @@ public:
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
AudioFifo *getFeedbackAudioFifo() { return &m_feedbackAudioFifo; }
|
||||
void applyAudioSampleRate(unsigned int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(unsigned int sampleRate);
|
||||
unsigned int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
@ -92,12 +92,12 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
quint32 m_audioSampleRate;
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
uint m_audioBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
||||
quint32 m_feedbackAudioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
@ -694,11 +694,16 @@ void SSBMod::setLevelMeter(QObject *levelMeter)
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
unsigned int SSBMod::getAudioSampleRate() const
|
||||
int SSBMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
int SSBMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
||||
uint32_t SSBMod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSinkStreams();
|
||||
|
@ -227,7 +227,8 @@ public:
|
||||
double getMagSq() const;
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
unsigned int getAudioSampleRate() const;
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
|
||||
static const QString m_channelIdURI;
|
||||
|
@ -159,6 +159,7 @@ bool SSBModBaseband::handleMessage(const Message& cmd)
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
|
||||
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -184,20 +185,22 @@ void SSBModBaseband::applySettings(const SSBModSettings& settings, bool force)
|
||||
{
|
||||
m_channelizer->setChannelization(m_source.getAudioSampleRate(), settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
}
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate)
|
||||
{
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
m_channelizer->setChannelization(audioSampleRate, m_settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,8 +208,9 @@ void SSBModBaseband::applySettings(const SSBModSettings& settings, bool force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName);
|
||||
audioDeviceManager->removeAudioSink(getFeedbackAudioFifo());
|
||||
audioDeviceManager->addAudioSink(getFeedbackAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getFeedbackAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyFeedbackAudioSampleRate(audioSampleRate);
|
||||
|
@ -64,8 +64,8 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
unsigned int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getChannelSampleRate() const;
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
|
@ -411,6 +411,8 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_feedbackAudioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false)
|
||||
{
|
||||
@ -769,6 +771,32 @@ void SSBModGUI::tick()
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_ssbMod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
int feedbackAudioSampleRate = m_ssbMod->getFeedbackAudioSampleRate();
|
||||
|
||||
if (feedbackAudioSampleRate != m_feedbackAudioSampleRate)
|
||||
{
|
||||
if (feedbackAudioSampleRate < 0) {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background-color : red; }");
|
||||
} else {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_feedbackAudioSampleRate = feedbackAudioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == SSBModSettings::SSBModInputFile))
|
||||
{
|
||||
SSBMod::MsgConfigureFileSourceStreamTiming* message = SSBMod::MsgConfigureFileSourceStreamTiming::create();
|
||||
|
@ -76,6 +76,8 @@ private:
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
|
@ -510,9 +510,15 @@ void SSBModSource::calculateLevel(Complex& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void SSBModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
void SSBModSource::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
qDebug("SSBModSource::applyAudioSampleRate: %u", sampleRate);
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("SSBModSource::applyAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("SSBModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorConsumed = false;
|
||||
@ -551,9 +557,15 @@ void SSBModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
}
|
||||
|
||||
void SSBModSource::applyFeedbackAudioSampleRate(unsigned int sampleRate)
|
||||
void SSBModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
{
|
||||
qDebug("SSBModSource::applyFeedbackAudioSampleRate: %u", sampleRate);
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("SSBModSource::applyFeedbackAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("SSBModSource::applyFeedbackAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
|
@ -49,10 +49,10 @@ public:
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
AudioFifo *getFeedbackAudioFifo() { return &m_feedbackAudioFifo; }
|
||||
void applyAudioSampleRate(unsigned int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(unsigned int sampleRate);
|
||||
unsigned int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
unsigned int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
@ -102,12 +102,12 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
quint32 m_audioSampleRate;
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
uint m_audioBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
||||
quint32 m_feedbackAudioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
@ -638,3 +638,13 @@ uint32_t WFMMod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSinkStreams();
|
||||
}
|
||||
|
||||
int WFMMod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
int WFMMod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
||||
|
@ -225,6 +225,8 @@ public:
|
||||
CWKeyer *getCWKeyer();
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
|
||||
static const QString m_channelIdURI;
|
||||
static const QString m_channelId;
|
||||
|
@ -43,6 +43,9 @@ WFMModBaseband::WFMModBaseband() :
|
||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(m_source.getAudioFifo(), getInputMessageQueue());
|
||||
m_source.applyAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getInputSampleRate());
|
||||
|
||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(m_source.getFeedbackAudioFifo(), getInputMessageQueue());
|
||||
m_source.applyFeedbackAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate());
|
||||
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
}
|
||||
|
||||
@ -155,6 +158,7 @@ bool WFMModBaseband::handleMessage(const Message& cmd)
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
|
||||
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -181,14 +185,16 @@ void WFMModBaseband::applySettings(const WFMModSettings& settings, bool force)
|
||||
{
|
||||
m_channelizer->setChannelization(settings.m_rfBandwidth, settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
}
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
|
@ -63,7 +63,8 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
CWKeyer& getCWKeyer() { return m_source.getCWKeyer(); }
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
unsigned int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getChannelSampleRate() const;
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QColor>
|
||||
#include <QFileDialog>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
@ -242,6 +243,19 @@ void WFMModGUI::on_mic_toggled(bool checked)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WFMModGUI::on_feedbackEnable_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_feedbackAudioEnable = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WFMModGUI::on_feedbackVolume_valueChanged(int value)
|
||||
{
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2));
|
||||
m_settings.m_feedbackVolumeFactor = value / 100.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void WFMModGUI::on_navTimeSlider_valueChanged(int value)
|
||||
{
|
||||
if (m_enableNavTime && ((value >= 0) && (value <= 100)))
|
||||
@ -339,6 +353,8 @@ WFMModGUI::WFMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_feedbackAudioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false)
|
||||
{
|
||||
@ -366,6 +382,9 @@ WFMModGUI::WFMModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
|
||||
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
|
||||
connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
|
||||
|
||||
CRightClickEnabler *feedbackRightClickEnabler = new CRightClickEnabler(ui->feedbackEnable);
|
||||
connect(feedbackRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioFeedbackSelect()));
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
ui->deltaFrequency->setValueRange(false, 8, -99999999, 99999999);
|
||||
@ -469,6 +488,10 @@ void WFMModGUI::displaySettings()
|
||||
ui->play->setChecked(m_settings.m_modAFInput == WFMModSettings::WFMModInputAF::WFMModInputFile);
|
||||
ui->morseKeyer->setChecked(m_settings.m_modAFInput == WFMModSettings::WFMModInputAF::WFMModInputCWTone);
|
||||
|
||||
ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable);
|
||||
ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0));
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2));
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -504,12 +527,51 @@ void WFMModGUI::audioSelect()
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModGUI::audioFeedbackSelect()
|
||||
{
|
||||
qDebug("WFMModGUI::audioFeedbackSelect");
|
||||
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, false); // false for output
|
||||
audioSelect.exec();
|
||||
|
||||
if (audioSelect.m_selected)
|
||||
{
|
||||
m_settings.m_feedbackAudioDeviceName = audioSelect.m_audioDeviceName;
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModGUI::tick()
|
||||
{
|
||||
double powDb = CalcDb::dbPower(m_wfmMod->getMagSq());
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_wfmMod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
int feedbackAudioSampleRate = m_wfmMod->getFeedbackAudioSampleRate();
|
||||
|
||||
if (feedbackAudioSampleRate != m_feedbackAudioSampleRate)
|
||||
{
|
||||
if (feedbackAudioSampleRate < 0) {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background-color : red; }");
|
||||
} else {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_feedbackAudioSampleRate = feedbackAudioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == WFMModSettings::WFMModInputFile))
|
||||
{
|
||||
WFMMod::MsgConfigureFileSourceStreamTiming* message = WFMMod::MsgConfigureFileSourceStreamTiming::create();
|
||||
|
@ -71,6 +71,8 @@ private:
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
@ -116,11 +118,15 @@ private slots:
|
||||
void on_navTimeSlider_valueChanged(int value);
|
||||
void on_showFileDialog_clicked(bool checked);
|
||||
|
||||
void on_feedbackEnable_toggled(bool checked);
|
||||
void on_feedbackVolume_valueChanged(int value);
|
||||
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
|
||||
void configureFileName();
|
||||
void audioSelect();
|
||||
void audioFeedbackSelect();
|
||||
void tick();
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
<rect>
|
||||
<x>2</x>
|
||||
<y>2</y>
|
||||
<width>280</width>
|
||||
<width>291</width>
|
||||
<height>271</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -56,7 +56,16 @@
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -476,13 +485,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="mic">
|
||||
<property name="toolTip">
|
||||
@ -500,6 +502,75 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="feedbackEnable">
|
||||
<property name="toolTip">
|
||||
<string>Left: enable / disable audio feedback - Right: select audio output device</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/sound_off.png</normaloff>
|
||||
<normalon>:/sound_on.png</normalon>:/sound_off.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="feedbackVolume">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio feedback volume</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="feedbackVolumeText">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio feedback volume</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.00</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
|
@ -50,6 +50,9 @@ void WFMModSettings::resetToDefaults()
|
||||
m_title = "WFM Modulator";
|
||||
m_modAFInput = WFMModInputNone;
|
||||
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
m_feedbackVolumeFactor = 0.5f;
|
||||
m_feedbackAudioEnable = false;
|
||||
m_streamIndex = 0;
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
@ -89,6 +92,9 @@ QByteArray WFMModSettings::serialize() const
|
||||
s.writeU32(16, m_reverseAPIDeviceIndex);
|
||||
s.writeU32(17, m_reverseAPIChannelIndex);
|
||||
s.writeS32(18, m_streamIndex);
|
||||
s.writeString(19, m_feedbackAudioDeviceName);
|
||||
s.writeReal(20, m_feedbackVolumeFactor);
|
||||
s.writeBool(21, m_feedbackAudioEnable);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -155,6 +161,9 @@ bool WFMModSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(17, &utmp, 0);
|
||||
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readS32(18, &m_streamIndex, 0);
|
||||
d.readString(19, &m_feedbackAudioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
d.readReal(20, &m_feedbackVolumeFactor, 1.0);
|
||||
d.readBool(21, &m_feedbackAudioEnable, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ struct WFMModSettings
|
||||
QString m_title;
|
||||
WFMModInputAF m_modAFInput;
|
||||
QString m_audioDeviceName; //!< This is the audio device you get the audio samples from
|
||||
QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback
|
||||
float m_feedbackVolumeFactor;
|
||||
bool m_feedbackAudioEnable;
|
||||
int m_streamIndex;
|
||||
bool m_useReverseAPI;
|
||||
QString m_reverseAPIAddress;
|
||||
|
@ -26,11 +26,13 @@ WFMModSource::WFMModSource() :
|
||||
m_channelFrequencyOffset(0),
|
||||
m_modPhasor(0.0f),
|
||||
m_audioFifo(4800),
|
||||
m_feedbackAudioFifo(48000),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f),
|
||||
m_ifstream(nullptr),
|
||||
m_audioSampleRate(48000)
|
||||
m_audioSampleRate(48000),
|
||||
m_feedbackAudioSampleRate(48000)
|
||||
{
|
||||
m_rfFilter = new fftfilt(-62500.0 / 384000.0, 62500.0 / 384000.0, m_rfFilterFFTLength);
|
||||
m_rfFilterBuffer = new Complex[m_rfFilterFFTLength];
|
||||
@ -39,6 +41,8 @@ WFMModSource::WFMModSource() :
|
||||
m_audioBuffer.resize(1<<14);
|
||||
m_audioBufferFill = 0;
|
||||
m_magsq = 0.0;
|
||||
m_feedbackAudioBuffer.resize(1<<14);
|
||||
m_feedbackAudioBufferFill = 0;
|
||||
|
||||
applySettings(m_settings, true);
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
@ -76,7 +80,8 @@ void WFMModSource::pullOne(Sample& sample)
|
||||
Real t;
|
||||
|
||||
if ((m_settings.m_modAFInput == WFMModSettings::WFMModInputFile)
|
||||
|| (m_settings.m_modAFInput == WFMModSettings::WFMModInputAudio))
|
||||
|| (m_settings.m_modAFInput == WFMModSettings::WFMModInputAudio)
|
||||
|| (m_settings.m_modAFInput == WFMModSettings::WFMModInputCWTone))
|
||||
{
|
||||
if (m_interpolatorDistance > 1.0f) // decimate
|
||||
{
|
||||
@ -141,6 +146,10 @@ void WFMModSource::modulateAudio()
|
||||
calculateLevel(t);
|
||||
m_modSample.real(t);
|
||||
m_modSample.imag(0.0f);
|
||||
|
||||
if (m_settings.m_feedbackAudioEnable) {
|
||||
pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModSource::prefetch(unsigned int nbSamples)
|
||||
@ -217,18 +226,18 @@ void WFMModSource::pullAF(Real& sample)
|
||||
if (m_cwKeyer.getSample())
|
||||
{
|
||||
m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
|
||||
sample = m_toneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
||||
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
|
||||
{
|
||||
sample = m_toneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
||||
sample = m_cwToneNco.next() * m_settings.m_volumeFactor * fadeFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
sample = 0.0f;
|
||||
m_toneNco.setPhase(0);
|
||||
m_cwToneNco.setPhase(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -239,6 +248,49 @@ void WFMModSource::pullAF(Real& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModSource::pushFeedback(Complex c)
|
||||
{
|
||||
Complex ci;
|
||||
|
||||
if (m_feedbackInterpolatorDistance < 1.0f) // interpolate
|
||||
{
|
||||
while (!m_feedbackInterpolator.interpolate(&m_feedbackInterpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance;
|
||||
}
|
||||
}
|
||||
else // decimate
|
||||
{
|
||||
if (m_feedbackInterpolator.decimate(&m_feedbackInterpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModSource::processOneSample(Complex& ci)
|
||||
{
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag();
|
||||
++m_feedbackAudioBufferFill;
|
||||
|
||||
if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size())
|
||||
{
|
||||
unsigned int res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill);
|
||||
|
||||
if (res != m_feedbackAudioBufferFill)
|
||||
{
|
||||
qDebug("WFMModSource::processOneSample: %u/%u audio samples written m_feedbackInterpolatorDistance: %f",
|
||||
res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance);
|
||||
m_feedbackAudioFifo.clear();
|
||||
}
|
||||
|
||||
m_feedbackAudioBufferFill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModSource::calculateLevel(const Real& sample)
|
||||
{
|
||||
if (m_levelCalcCount < m_levelNbSamples)
|
||||
@ -257,16 +309,44 @@ void WFMModSource::calculateLevel(const Real& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void WFMModSource::applyAudioSampleRate(unsigned int sampleRate)
|
||||
void WFMModSource::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("WFMModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("WFMModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorConsumed = false;
|
||||
m_interpolatorDistance = (Real) sampleRate / (Real) m_channelSampleRate;
|
||||
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
|
||||
|
||||
m_cwToneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_cwKeyer.setSampleRate(sampleRate);
|
||||
m_cwKeyer.reset();
|
||||
m_audioSampleRate = sampleRate;
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
}
|
||||
|
||||
void WFMModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("WFMModSource::applyFeedbackAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("WFMModSource::applyFeedbackAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||
|
||||
m_feedbackAudioSampleRate = sampleRate;
|
||||
}
|
||||
|
||||
void WFMModSource::applySettings(const WFMModSettings& settings, bool force)
|
||||
@ -286,8 +366,10 @@ void WFMModSource::applySettings(const WFMModSettings& settings, bool force)
|
||||
m_rfFilter->create_filter(lowCut, hiCut);
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force)
|
||||
{
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_channelSampleRate);
|
||||
m_cwToneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
@ -314,8 +396,6 @@ void WFMModSource::applyChannelSettings(int channelSampleRate, int channelFreque
|
||||
Real hiCut = (m_settings.m_rfBandwidth / 2.0) / channelSampleRate;
|
||||
m_rfFilter->create_filter(lowCut, hiCut);
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, channelSampleRate);
|
||||
m_cwKeyer.setSampleRate(channelSampleRate);
|
||||
m_cwKeyer.reset();
|
||||
}
|
||||
|
||||
m_channelSampleRate = channelSampleRate;
|
||||
|
@ -46,9 +46,11 @@ public:
|
||||
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
void applyAudioSampleRate(unsigned int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(unsigned int sampleRate);
|
||||
unsigned int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
AudioFifo *getFeedbackAudioFifo() { return &m_feedbackAudioFifo; }
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
CWKeyer& getCWKeyer() { return m_cwKeyer; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
@ -67,6 +69,7 @@ private:
|
||||
|
||||
NCO m_carrierNco;
|
||||
NCOF m_toneNco;
|
||||
NCOF m_cwToneNco;
|
||||
float m_modPhasor; //!< baseband modulator phasor
|
||||
Complex m_modSample;
|
||||
|
||||
@ -75,6 +78,11 @@ private:
|
||||
Real m_interpolatorDistanceRemain;
|
||||
bool m_interpolatorConsumed;
|
||||
|
||||
Interpolator m_feedbackInterpolator;
|
||||
Real m_feedbackInterpolatorDistance;
|
||||
Real m_feedbackInterpolatorDistanceRemain;
|
||||
bool m_feedbackInterpolatorConsumed;
|
||||
|
||||
fftfilt* m_rfFilter;
|
||||
static const int m_rfFilterFFTLength;
|
||||
fftfilt::cmplx *m_rfFilterBuffer;
|
||||
@ -83,11 +91,16 @@ private:
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
quint32 m_audioSampleRate;
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
uint m_audioBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
||||
quint32 m_levelCalcCount;
|
||||
qreal m_rmsLevel;
|
||||
qreal m_peakLevelOut;
|
||||
@ -102,6 +115,7 @@ private:
|
||||
void processOneSample(Complex& ci);
|
||||
void pullAF(Real& sample);
|
||||
void pullAudio(unsigned int nbSamples);
|
||||
void pushFeedback(Complex sample);
|
||||
void calculateLevel(const Real& sample);
|
||||
void modulateAudio();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user