diff --git a/plugins/channelrx/demodam/CMakeLists.txt b/plugins/channelrx/demodam/CMakeLists.txt index 0c6721c3b..cbbd3ae9c 100644 --- a/plugins/channelrx/demodam/CMakeLists.txt +++ b/plugins/channelrx/demodam/CMakeLists.txt @@ -3,12 +3,14 @@ project(am) set(am_SOURCES amdemod.cpp amdemodgui.cpp + amdemodsettings.cpp amdemodplugin.cpp ) set(am_HEADERS amdemod.h amdemodgui.h + amdemodsettings.h amdemodplugin.h ) diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index f4c1f7e60..9ef6b2d57 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -43,14 +43,12 @@ AMDemod::AMDemod() : { setObjectName("AMDemod"); - m_config.m_inputSampleRate = 96000; - m_config.m_inputFrequencyOffset = 0; - m_config.m_rfBandwidth = 5000; - m_config.m_squelch = -40.0; - m_config.m_volume = 2.0; - m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); - - apply(); +// m_config.m_inputSampleRate = 96000; +// m_config.m_inputFrequencyOffset = 0; +// m_config.m_rfBandwidth = 5000; +// m_config.m_squelch = -40.0; +// m_config.m_volume = 2.0; +// m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; @@ -60,7 +58,9 @@ AMDemod::AMDemod() : m_magsq = 0.0; DSPEngine::instance()->addAudioSink(&m_audioFifo); - m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_config.m_udpPort); + m_udpBufferAudio = new UDPSink(this, m_udpBlockSize, m_settings.m_udpPort); + + applySettings(m_settings, true); } AMDemod::~AMDemod() @@ -142,8 +142,8 @@ void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector void AMDemod::start() { - qDebug() << "AMDemod::start: m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + qDebug() << "AMDemod::start: m_inputSampleRate: " << m_settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset; m_squelchCount = 0; m_audioFifo.clear(); @@ -161,41 +161,45 @@ bool AMDemod::handleMessage(const Message& cmd) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_config.m_inputSampleRate = notif.getSampleRate(); - m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); + AMDemodSettings settings = m_settings; - apply(); + settings.m_inputSampleRate = notif.getSampleRate(); + settings.m_inputFrequencyOffset = notif.getFrequencyOffset(); - qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:" - << " m_inputSampleRate: " << m_config.m_inputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + applySettings(settings); + + qDebug() << "AMDemod::handleMessage: MsgChannelizerNotification:" + << " m_inputSampleRate: " << settings.m_inputSampleRate + << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset; return true; } else if (MsgConfigureAMDemod::match(cmd)) { - MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd; + MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd; - m_config.m_rfBandwidth = cfg.getRFBandwidth(); - m_config.m_volume = cfg.getVolume(); - m_config.m_squelch = cfg.getSquelch(); - m_config.m_audioMute = cfg.getAudioMute(); - m_config.m_bandpassEnable = cfg.getBandpassEnable(); - m_config.m_copyAudioToUDP = cfg.getCopyAudioToUDP(); - m_config.m_udpAddress = cfg.getUDPAddress(); - m_config.m_udpPort = cfg.getUDPPort(); + AMDemodSettings settings = m_settings; - apply(cfg.getForce()); + settings.m_rfBandwidth = cfg.getRFBandwidth(); + settings.m_volume = cfg.getVolume(); + settings.m_squelch = cfg.getSquelch(); + settings.m_audioMute = cfg.getAudioMute(); + settings.m_bandpassEnable = cfg.getBandpassEnable(); + settings.m_copyAudioToUDP = cfg.getCopyAudioToUDP(); + settings.m_udpAddress = cfg.getUDPAddress(); + settings.m_udpPort = cfg.getUDPPort(); - qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:" - << " m_rfBandwidth: " << m_config.m_rfBandwidth - << " m_volume: " << m_config.m_volume - << " m_squelch: " << m_config.m_squelch - << " m_audioMute: " << m_config.m_audioMute - << " m_bandpassEnable: " << m_config.m_bandpassEnable - << " m_copyAudioToUDP: " << m_config.m_copyAudioToUDP - << " m_udpAddress: " << m_config.m_udpAddress - << " m_udpPort: " << m_config.m_udpPort; + applySettings(settings); + + qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:" + << " m_rfBandwidth: " << settings.m_rfBandwidth + << " m_volume: " << settings.m_volume + << " m_squelch: " << settings.m_squelch + << " m_audioMute: " << settings.m_audioMute + << " m_bandpassEnable: " << settings.m_bandpassEnable + << " m_copyAudioToUDP: " << settings.m_copyAudioToUDP + << " m_udpAddress: " << settings.m_udpAddress + << " m_udpPort: " << settings.m_udpPort; return true; } @@ -205,40 +209,77 @@ bool AMDemod::handleMessage(const Message& cmd) } } -void AMDemod::apply(bool force) +//void AMDemod::apply(bool force) +//{ +// +// if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || +// (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) +// { +// m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); +// } +// +// if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || +// (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || +// (m_config.m_audioSampleRate != m_running.m_audioSampleRate) || +// (m_config.m_bandpassEnable != m_running.m_bandpassEnable) || force) +// { +// m_settingsMutex.lock(); +// m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2f); +// m_interpolatorDistanceRemain = 0; +// m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; +// m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_rfBandwidth / 2.0f); +// m_settingsMutex.unlock(); +// } +// +// if ((m_config.m_squelch != m_running.m_squelch) || force) +// { +// m_squelchLevel = pow(10.0, m_config.m_squelch / 20.0); +// m_squelchLevel *= m_squelchLevel; +// qDebug("AMDemod::applySettings: m_squelchLevel: %f", m_squelchLevel); +// } +// +// if ((m_config.m_udpAddress != m_running.m_udpAddress) +// || (m_config.m_udpPort != m_running.m_udpPort) || force) +// { +// m_udpBufferAudio->setAddress(m_config.m_udpAddress); +// m_udpBufferAudio->setPort(m_config.m_udpPort); +// } +// +// m_running = m_config; +//} + +void AMDemod::applySettings(const AMDemodSettings& settings, bool force) { - - if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_inputSampleRate != m_running.m_inputSampleRate) || force) - { - m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); - } - - if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || - (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate) || - (m_config.m_bandpassEnable != m_running.m_bandpassEnable) || force) - { - m_settingsMutex.lock(); - m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2f); - m_interpolatorDistanceRemain = 0; - m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; - m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_rfBandwidth / 2.0f); - m_settingsMutex.unlock(); - } - - if ((m_config.m_squelch != m_running.m_squelch) || force) - { - m_squelchLevel = pow(10.0, m_config.m_squelch / 20.0); - m_squelchLevel *= m_squelchLevel; - } - - if ((m_config.m_udpAddress != m_running.m_udpAddress) - || (m_config.m_udpPort != m_running.m_udpPort) || force) + if ((m_settings.m_inputFrequencyOffset != settings.m_inputFrequencyOffset) || + (m_settings.m_inputSampleRate != settings.m_inputSampleRate) || force) { - m_udpBufferAudio->setAddress(m_config.m_udpAddress); - m_udpBufferAudio->setPort(m_config.m_udpPort); + m_nco.setFreq(-settings.m_inputFrequencyOffset, settings.m_inputSampleRate); } - m_running = m_config; + if((m_settings.m_inputSampleRate != settings.m_inputSampleRate) || + (m_settings.m_rfBandwidth != settings.m_rfBandwidth) || + (m_settings.m_audioSampleRate != settings.m_audioSampleRate) || + (m_settings.m_bandpassEnable != settings.m_bandpassEnable) || force) + { + m_settingsMutex.lock(); + m_interpolator.create(16, settings.m_inputSampleRate, settings.m_rfBandwidth / 2.2f); + m_interpolatorDistanceRemain = 0; + m_interpolatorDistance = (Real) settings.m_inputSampleRate / (Real) settings.m_audioSampleRate; + m_bandpass.create(301, settings.m_audioSampleRate, 300.0, settings.m_rfBandwidth / 2.0f); + m_settingsMutex.unlock(); + } + + if ((m_settings.m_squelch != settings.m_squelch) || force) + { + m_squelchLevel = pow(10.0, settings.m_squelch / 10.0); + } + + if ((m_settings.m_udpAddress != settings.m_udpAddress) + || (m_settings.m_udpPort != settings.m_udpPort) || force) + { + m_udpBufferAudio->setAddress(const_cast(settings.m_udpAddress)); + m_udpBufferAudio->setPort(settings.m_udpPort); + } + + m_settings = settings; } diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index 2bf2ad7ca..3e459807d 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -27,6 +27,7 @@ #include "dsp/bandpass.h" #include "audio/audiofifo.h" #include "util/message.h" +#include "amdemodsettings.h" class AMDemod : public BasebandSampleSink { Q_OBJECT @@ -137,36 +138,37 @@ private: RSRunning }; - struct Config { - int m_inputSampleRate; - qint64 m_inputFrequencyOffset; - Real m_rfBandwidth; - Real m_squelch; - Real m_volume; - quint32 m_audioSampleRate; - bool m_audioMute; - bool m_bandpassEnable; - bool m_copyAudioToUDP; - QString m_udpAddress; - quint16 m_udpPort; +// struct Config { +// int m_inputSampleRate; +// qint64 m_inputFrequencyOffset; +// Real m_rfBandwidth; +// Real m_squelch; +// Real m_volume; +// quint32 m_audioSampleRate; +// bool m_audioMute; +// bool m_bandpassEnable; +// bool m_copyAudioToUDP; +// QString m_udpAddress; +// quint16 m_udpPort; +// +// Config() : +// m_inputSampleRate(-1), +// m_inputFrequencyOffset(0), +// m_rfBandwidth(-1), +// m_squelch(0), +// m_volume(0), +// m_audioSampleRate(0), +// m_audioMute(false), +// m_bandpassEnable(false), +// m_copyAudioToUDP(false), +// m_udpAddress("127.0.0.1"), +// m_udpPort(9999) +// { } +// }; - Config() : - m_inputSampleRate(-1), - m_inputFrequencyOffset(0), - m_rfBandwidth(-1), - m_squelch(0), - m_volume(0), - m_audioSampleRate(0), - m_audioMute(false), - m_bandpassEnable(false), - m_copyAudioToUDP(false), - m_udpAddress("127.0.0.1"), - m_udpPort(9999) - { } - }; - - Config m_config; - Config m_running; + AMDemodSettings m_settings; +// Config m_config; +// Config m_running; NCO m_nco; Interpolator m_interpolator; @@ -194,7 +196,8 @@ private: QMutex m_settingsMutex; - void apply(bool force = false); +// void apply(bool force = false); + void applySettings(const AMDemodSettings& settings, bool force = false); void processOneSample(Complex &ci) { @@ -213,9 +216,9 @@ private: if (m_magsq >= m_squelchLevel) { - if (m_squelchCount <= m_running.m_audioSampleRate / 10) + if (m_squelchCount <= m_settings.m_audioSampleRate / 10) { - if (m_squelchCount == m_running.m_audioSampleRate / 20) { + if (m_squelchCount == m_settings.m_audioSampleRate / 20) { m_volumeAGC.fill(1.0); } @@ -232,28 +235,28 @@ private: qint16 sample; - if ((m_squelchCount >= m_running.m_audioSampleRate / 20) && !m_running.m_audioMute) + if ((m_squelchCount >= m_settings.m_audioSampleRate / 20) && !m_settings.m_audioMute) { Real demod = sqrt(magsq); m_volumeAGC.feed(demod); demod = (demod - m_volumeAGC.getValue()) / m_volumeAGC.getValue(); - if (m_running.m_bandpassEnable) + if (m_settings.m_bandpassEnable) { demod = m_bandpass.filter(demod); demod /= 301.0f; } - Real attack = (m_squelchCount - 0.05f * m_running.m_audioSampleRate) / (0.05f * m_running.m_audioSampleRate); - sample = demod * attack * 2048 * m_running.m_volume; - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768); + Real attack = (m_squelchCount - 0.05f * m_settings.m_audioSampleRate) / (0.05f * m_settings.m_audioSampleRate); + sample = demod * attack * 2048 * m_settings.m_volume; + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(demod * attack * 32768); m_squelchOpen = true; } else { sample = 0; - if (m_running.m_copyAudioToUDP) m_udpBufferAudio->write(0); + if (m_settings.m_copyAudioToUDP) m_udpBufferAudio->write(0); m_squelchOpen = false; } @@ -273,6 +276,7 @@ private: m_audioBufferFill = 0; } } + }; #endif // INCLUDE_AMDEMOD_H diff --git a/plugins/channelrx/demodam/amdemodsettings.cpp b/plugins/channelrx/demodam/amdemodsettings.cpp new file mode 100644 index 000000000..d5a969368 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodsettings.cpp @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "dsp/dspengine.h" +#include "util/simpleserializer.h" +#include "amdemodsettings.h" + +AMDemodSettings::AMDemodSettings() +{ + resetToDefaults(); +} + +void AMDemodSettings::resetToDefaults() +{ + m_inputSampleRate = 96000; + m_inputFrequencyOffset = 0; + m_rfBandwidth = 5000; + m_squelch = -40.0; + m_volume = 2.0; + m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); + m_audioMute = false; + m_bandpassEnable = false; + m_copyAudioToUDP = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9999; +} + +QByteArray AMDemodSettings::serialize() const +{ + SimpleSerializer s(1); + s.writeS32(1, m_inputFrequencyOffset); + s.writeS32(2, m_rfBandwidth/1000); + s.writeS32(4, m_volume*10); + s.writeS32(5, m_squelch*10); + s.writeBlob(6, m_channelMarkerBytes); + s.writeBool(8, m_bandpassEnable); + return s.final(); +} + +bool AMDemodSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if(!d.isValid()) + { + resetToDefaults(); + return false; + } + + if(d.getVersion() == 1) + { + QByteArray bytetmp; + qint32 tmp; + QString strtmp; + + d.readS32(1, &m_inputFrequencyOffset, 0); + d.readS32(2, &tmp, 4); + m_rfBandwidth = 1000 * tmp; + d.readS32(4, &tmp, 20); + m_volume = tmp * 0.1; + d.readS32(5, &tmp, -40); + m_squelch = tmp * 0.1; + d.readBlob(6, &m_channelMarkerBytes); + d.readBool(8, &m_bandpassEnable, false); + return true; + } + else + { + resetToDefaults(); + return false; + } +} + + diff --git a/plugins/channelrx/demodam/amdemodsettings.h b/plugins/channelrx/demodam/amdemodsettings.h new file mode 100644 index 000000000..fb54136d5 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodsettings.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2015 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ + +#include + +struct AMDemodSettings +{ + int m_inputSampleRate; + qint32 m_inputFrequencyOffset; + Real m_rfBandwidth; + Real m_squelch; + Real m_volume; + quint32 m_audioSampleRate; + bool m_audioMute; + bool m_bandpassEnable; + bool m_copyAudioToUDP; + QString m_udpAddress; + quint16 m_udpPort; + QByteArray m_channelMarkerBytes; + + AMDemodSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + + + +#endif /* PLUGINS_CHANNELRX_DEMODAM_AMDEMODSETTINGS_H_ */