1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-05-29 05:22:25 -04:00

NFM demod: implemented option to copy audio to UDP

This commit is contained in:
f4exb 2017-08-27 00:27:11 +02:00
parent 939e423c02
commit af63a8ed5c
6 changed files with 70 additions and 17 deletions

View File

@ -28,10 +28,11 @@
#include "dsp/dspengine.h" #include "dsp/dspengine.h"
#include "nfmdemodgui.h" #include "nfmdemodgui.h"
static const double afSqTones[2] = {1000.0, 6000.0}; // {1200.0, 8000.0};
MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message) MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message)
static const double afSqTones[2] = {1000.0, 6000.0}; // {1200.0, 8000.0};
const int NFMDemod::m_udpBlockSize = 512;
NFMDemod::NFMDemod() : NFMDemod::NFMDemod() :
m_ctcssIndex(0), m_ctcssIndex(0),
m_sampleCount(0), m_sampleCount(0),
@ -77,11 +78,13 @@ NFMDemod::NFMDemod() :
m_afSquelch.setCoefficients(24, 600, 48000.0, 200, 0); // 0.5ms test period, 300ms average span, 48kS/s SR, 100ms attack, no decay m_afSquelch.setCoefficients(24, 600, 48000.0, 200, 0); // 0.5ms test period, 300ms average span, 48kS/s SR, 100ms attack, no decay
DSPEngine::instance()->addAudioSink(&m_audioFifo); DSPEngine::instance()->addAudioSink(&m_audioFifo);
m_udpBufferAudio = new UDPSink<qint16>(this, m_udpBlockSize, m_config.m_udpPort);
} }
NFMDemod::~NFMDemod() NFMDemod::~NFMDemod()
{ {
DSPEngine::instance()->removeAudioSink(&m_audioFifo); DSPEngine::instance()->removeAudioSink(&m_audioFifo);
delete m_udpBufferAudio;
} }
void NFMDemod::configure(MessageQueue* messageQueue, void NFMDemod::configure(MessageQueue* messageQueue,
@ -94,6 +97,9 @@ void NFMDemod::configure(MessageQueue* messageQueue,
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute, bool audioMute,
bool copyAudioToUDP,
const QString& udpAddress,
qint16 udpPort,
bool force) bool force)
{ {
Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth, Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth,
@ -105,6 +111,9 @@ void NFMDemod::configure(MessageQueue* messageQueue,
squelch, squelch,
ctcssOn, ctcssOn,
audioMute, audioMute,
copyAudioToUDP,
udpAddress,
udpPort,
force); force);
messageQueue->push(cmd); messageQueue->push(cmd);
} }
@ -282,12 +291,14 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
if (m_running.m_ctcssOn && m_ctcssIndexSelected && (m_ctcssIndexSelected != m_ctcssIndex)) if (m_running.m_ctcssOn && m_ctcssIndexSelected && (m_ctcssIndexSelected != m_ctcssIndex))
{ {
sample = 0; sample = 0;
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(0);
} }
else else
{ {
demod = m_bandpass.filter(demod); demod = m_bandpass.filter(demod);
Real squelchFactor = StepFunctions::smootherstep((Real) (m_squelchCount - m_squelchGate) / 480.0f); Real squelchFactor = StepFunctions::smootherstep((Real) (m_squelchCount - m_squelchGate) / 480.0f);
sample = demod * m_running.m_volume * squelchFactor; sample = demod * m_running.m_volume * squelchFactor;
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(demod * 5.0f * squelchFactor);
} }
} }
else else
@ -299,6 +310,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
} }
sample = 0; sample = 0;
if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(0);
} }
m_audioBuffer[m_audioBufferFill].l = sample; m_audioBuffer[m_audioBufferFill].l = sample;
@ -380,6 +392,9 @@ bool NFMDemod::handleMessage(const Message& cmd)
m_config.m_squelch = cfg.getSquelch(); m_config.m_squelch = cfg.getSquelch();
m_config.m_ctcssOn = cfg.getCtcssOn(); m_config.m_ctcssOn = cfg.getCtcssOn();
m_config.m_audioMute = cfg.getAudioMute(); m_config.m_audioMute = cfg.getAudioMute();
m_config.m_copyAudioToUDP = cfg.getCopyAudioToUDP();
m_config.m_udpAddress = cfg.getUDPAddress();
m_config.m_udpPort = cfg.getUDPPort();
apply(cfg.getForce()); apply(cfg.getForce());
@ -392,6 +407,9 @@ bool NFMDemod::handleMessage(const Message& cmd)
<< " m_squelch: " << m_squelchLevel << " m_squelch: " << m_squelchLevel
<< " m_ctcssOn: " << m_config.m_ctcssOn << " m_ctcssOn: " << m_config.m_ctcssOn
<< " m_audioMute: " << m_config.m_audioMute << " m_audioMute: " << m_config.m_audioMute
<< " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP
<< " m_udpAddress: " << m_config.m_udpAddress
<< " m_udpPort: " << m_config.m_udpPort
<< " force: " << cfg.getForce(); << " force: " << cfg.getForce();
return true; return true;
@ -458,16 +476,12 @@ void NFMDemod::apply(bool force)
//m_afSquelch.setThreshold(m_squelchLevel); //m_afSquelch.setThreshold(m_squelchLevel);
} }
m_running.m_inputSampleRate = m_config.m_inputSampleRate; if ((m_config.m_udpAddress != m_running.m_udpAddress)
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset; || (m_config.m_udpPort != m_running.m_udpPort) || force)
m_running.m_rfBandwidth = m_config.m_rfBandwidth; {
m_running.m_afBandwidth = m_config.m_afBandwidth; m_udpBufferAudio->setAddress(m_config.m_udpAddress);
m_running.m_fmDeviation = m_config.m_fmDeviation; m_udpBufferAudio->setPort(m_config.m_udpPort);
m_running.m_squelchGate = m_config.m_squelchGate; }
m_running.m_deltaSquelch = m_config.m_deltaSquelch;
m_running.m_squelch = m_config.m_squelch; m_running = m_config;
m_running.m_volume = m_config.m_volume;
m_running.m_audioSampleRate = m_config.m_audioSampleRate;
m_running.m_ctcssOn = m_config.m_ctcssOn;
m_running.m_audioMute = m_config.m_audioMute;
} }

View File

@ -50,6 +50,9 @@ public:
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute, bool audioMute,
bool copyAudioToUDP,
const QString& udpAddress,
qint16 udpPort,
bool force); bool force);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
@ -98,6 +101,9 @@ private:
Real getSquelch() const { return m_squelch; } Real getSquelch() const { return m_squelch; }
bool getCtcssOn() const { return m_ctcssOn; } bool getCtcssOn() const { return m_ctcssOn; }
bool getAudioMute() const { return m_audioMute; } bool getAudioMute() const { return m_audioMute; }
bool getCopyAudioToUDP() const { return m_copyAudioToUDP; }
const QString& getUDPAddress() const { return m_udpAddress; }
quint16 getUDPPort() const { return m_udpPort; }
bool getForce() const { return m_force; } bool getForce() const { return m_force; }
static MsgConfigureNFMDemod* create(Real rfBandwidth, static MsgConfigureNFMDemod* create(Real rfBandwidth,
@ -109,6 +115,9 @@ private:
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute, bool audioMute,
bool copyAudioToUDP,
const QString& udpAddress,
qint16 udpPort,
bool force) bool force)
{ {
return new MsgConfigureNFMDemod( return new MsgConfigureNFMDemod(
@ -121,6 +130,9 @@ private:
squelch, squelch,
ctcssOn, ctcssOn,
audioMute, audioMute,
copyAudioToUDP,
udpAddress,
udpPort,
force); force);
} }
@ -134,6 +146,9 @@ private:
Real m_squelch; Real m_squelch;
bool m_ctcssOn; bool m_ctcssOn;
bool m_audioMute; bool m_audioMute;
bool m_copyAudioToUDP;
QString m_udpAddress;
quint16 m_udpPort;
bool m_force; bool m_force;
MsgConfigureNFMDemod(Real rfBandwidth, MsgConfigureNFMDemod(Real rfBandwidth,
@ -145,6 +160,9 @@ private:
Real squelch, Real squelch,
bool ctcssOn, bool ctcssOn,
bool audioMute, bool audioMute,
bool copyAudioToUDP,
const QString& udpAddress,
qint16 udpPort,
bool force) : bool force) :
Message(), Message(),
m_rfBandwidth(rfBandwidth), m_rfBandwidth(rfBandwidth),
@ -156,6 +174,9 @@ private:
m_squelch(squelch), m_squelch(squelch),
m_ctcssOn(ctcssOn), m_ctcssOn(ctcssOn),
m_audioMute(audioMute), m_audioMute(audioMute),
m_copyAudioToUDP(copyAudioToUDP),
m_udpAddress(udpAddress),
m_udpPort(udpPort),
m_force(force) m_force(force)
{ } { }
}; };
@ -179,6 +200,9 @@ private:
bool m_audioMute; bool m_audioMute;
int m_ctcssIndex; int m_ctcssIndex;
quint32 m_audioSampleRate; quint32 m_audioSampleRate;
bool m_copyAudioToUDP;
QString m_udpAddress;
quint16 m_udpPort;
Config() : Config() :
m_inputSampleRate(-1), m_inputSampleRate(-1),
@ -193,7 +217,10 @@ private:
m_ctcssOn(false), m_ctcssOn(false),
m_audioMute(false), m_audioMute(false),
m_ctcssIndex(0), m_ctcssIndex(0),
m_audioSampleRate(0) m_audioSampleRate(0),
m_copyAudioToUDP(false),
m_udpAddress("127.0.0.1"),
m_udpPort(9999)
{ } { }
}; };
@ -237,13 +264,16 @@ private:
uint m_audioBufferFill; uint m_audioBufferFill;
AudioFifo m_audioFifo; AudioFifo m_audioFifo;
UDPSink<qint16> *m_udpBufferAudio;
NFMDemodGUI *m_nfmDemodGUI; NFMDemodGUI *m_nfmDemodGUI;
QMutex m_settingsMutex; QMutex m_settingsMutex;
PhaseDiscriminators m_phaseDiscri; PhaseDiscriminators m_phaseDiscri;
void apply(bool force = false); static const int m_udpBlockSize;
void apply(bool force = false);
}; };
#endif // INCLUDE_NFMDEMOD_H #endif // INCLUDE_NFMDEMOD_H

View File

@ -247,6 +247,11 @@ void NFMDemodGUI::on_audioMute_toggled(bool checked)
applySettings(); applySettings();
} }
void NFMDemodGUI::on_copyAudioToUDP_toggled(bool checked __attribute__((unused)))
{
applySettings();
}
void NFMDemodGUI::on_ctcss_currentIndexChanged(int index) void NFMDemodGUI::on_ctcss_currentIndexChanged(int index)
{ {
if (m_nfmDemod != 0) if (m_nfmDemod != 0)
@ -378,6 +383,9 @@ void NFMDemodGUI::applySettings(bool force)
ui->squelch->value(), // -1000 -> 0 ui->squelch->value(), // -1000 -> 0
ui->ctcssOn->isChecked(), ui->ctcssOn->isChecked(),
ui->audioMute->isChecked(), ui->audioMute->isChecked(),
ui->copyAudioToUDP->isChecked(),
m_channelMarker.getUDPAddress(),
m_channelMarker.getUDPSendPort(),
force); force);
} }
} }

View File

@ -51,6 +51,7 @@ private slots:
void on_ctcss_currentIndexChanged(int index); void on_ctcss_currentIndexChanged(int index);
void on_ctcssOn_toggled(bool checked); void on_ctcssOn_toggled(bool checked);
void on_audioMute_toggled(bool checked); void on_audioMute_toggled(bool checked);
void on_copyAudioToUDP_toggled(bool checked);
void onWidgetRolled(QWidget* widget, bool rollDown); void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p); void onMenuDialogCalled(const QPoint& p);
void tick(); void tick();

View File

@ -404,6 +404,7 @@ private:
else else
{ {
m_udpHandler.readSample(t); m_udpHandler.readSample(t);
t *= m_running.m_gainIn;
} }
} }
}; };

View File

@ -110,7 +110,6 @@ bool UDPSinkGUI::deserialize(const QByteArray& data)
QByteArray bytetmp; QByteArray bytetmp;
QString strtmp; QString strtmp;
qint32 s32tmp; qint32 s32tmp;
quint32 u32tmp;
Real realtmp; Real realtmp;
bool booltmp; bool booltmp;