diff --git a/plugins/channeltx/modssb/ssbmod.cpp b/plugins/channeltx/modssb/ssbmod.cpp index 581b81882..22053cd06 100644 --- a/plugins/channeltx/modssb/ssbmod.cpp +++ b/plugins/channeltx/modssb/ssbmod.cpp @@ -27,6 +27,7 @@ #include "util/db.h" MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureSSBMod, Message) +MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureChannelizer, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceName, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureFileSourceSeek, Message) MESSAGE_CLASS_DEFINITION(SSBMod::MsgConfigureAFInput, Message) @@ -59,26 +60,16 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) : { setObjectName("SSBMod"); - m_SSBFilter = new fftfilt(m_config.m_lowCutoff / m_config.m_audioSampleRate, m_config.m_bandwidth / m_config.m_audioSampleRate, m_ssbFftLen); - m_DSBFilter = new fftfilt((2.0f * m_config.m_bandwidth) / m_config.m_audioSampleRate, 2 * m_ssbFftLen); + m_SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_settings.m_audioSampleRate, m_settings.m_bandwidth / m_settings.m_audioSampleRate, m_ssbFftLen); + m_DSBFilter = new fftfilt((2.0f * m_settings.m_bandwidth) / m_settings.m_audioSampleRate, 2 * m_ssbFftLen); m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size m_DSBFilterBuffer = new Complex[m_ssbFftLen]; memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1)); memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); - m_config.m_outputSampleRate = 48000; - m_config.m_inputFrequencyOffset = 0; - m_config.m_bandwidth = 12500; - m_config.m_toneFrequency = 1000.0f; - m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); - m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; -// m_magsqSpectrum = 0.0f; -// m_magsqSum = 0.0f; -// m_magsqPeak = 0.0f; -// m_magsqCount = 0; m_sum.real(0.0f); m_sum.imag(0.0f); m_undersampleCount = 0; @@ -87,18 +78,18 @@ SSBMod::SSBMod(BasebandSampleSink* sampleSink) : m_movingAverage.resize(16, 0); m_magsq = 0.0; - m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate); + m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate); DSPEngine::instance()->addAudioSource(&m_audioFifo); // CW keyer - m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); + m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate); m_cwKeyer.setWPM(13); m_cwKeyer.setMode(CWKeyer::CWNone); - m_inAGC.setGate(m_config.m_agcThresholdGate); - m_inAGC.setStepDownDelay(m_config.m_agcThresholdDelay); + m_inAGC.setGate(m_settings.m_agcThresholdGate); + m_inAGC.setStepDownDelay(m_settings.m_agcThresholdDelay); m_inAGC.setClamping(true); - apply(); + applySettings(m_settings, true); } SSBMod::~SSBMod() @@ -122,43 +113,6 @@ SSBMod::~SSBMod() DSPEngine::instance()->removeAudioSource(&m_audioFifo); } -void SSBMod::configure(MessageQueue* messageQueue, - Real bandwidth, - Real lowCutoff, - float toneFrequency, - float volumeFactor, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool playLoop, - bool agc, - float agcOrder, - int agcTime, - int agcThreshold, - int agcThresholdGate, - int agcThresholdDelay) -{ - Message* cmd = MsgConfigureSSBMod::create(bandwidth, - lowCutoff, - toneFrequency, - volumeFactor, - spanLog2, - audioBinaural, - audioFlipChannels, - dsb, - audioMute, - playLoop, - agc, - agcOrder, - agcTime, - agcThreshold, - agcThresholdGate, - agcThresholdDelay); - messageQueue->push(cmd); -} - void SSBMod::pull(Sample& sample) { Complex ci; @@ -200,7 +154,7 @@ void SSBMod::pull(Sample& sample) void SSBMod::pullAudio(int nbSamples) { - unsigned int nbSamplesAudio = nbSamples * ((Real) m_config.m_audioSampleRate / (Real) m_config.m_basebandSampleRate); + unsigned int nbSamplesAudio = nbSamples * ((Real) m_settings.m_audioSampleRate / (Real) m_settings.m_basebandSampleRate); if (nbSamplesAudio > m_audioBuffer.size()) { @@ -220,7 +174,7 @@ void SSBMod::modulateSample() void SSBMod::pullAF(Complex& sample) { - if (m_running.m_audioMute) + if (m_settings.m_audioMute) { sample.real(0.0f); sample.imag(0.0f); @@ -231,13 +185,13 @@ void SSBMod::pullAF(Complex& sample) fftfilt::cmplx *filtered; int n_out = 0; - int decim = 1<<(m_running.m_spanLog2 - 1); + int decim = 1<<(m_settings.m_spanLog2 - 1); unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1) switch (m_afInput) { case SSBModInputTone: - if (m_running.m_dsb) + if (m_settings.m_dsb) { Real t = m_toneNco.next()/1.25; sample.real(t); @@ -245,7 +199,7 @@ void SSBMod::pullAF(Complex& sample) } else { - if (m_running.m_usb) { + if (m_settings.m_usb) { sample = m_toneNco.nextIQ(); } else { sample = m_toneNco.nextQI(); @@ -263,7 +217,7 @@ void SSBMod::pullAF(Complex& sample) { if (m_ifstream.eof()) { - if (m_running.m_playLoop) + if (m_settings.m_playLoop) { m_ifstream.clear(); m_ifstream.seekg(0, std::ios::beg); @@ -277,19 +231,19 @@ void SSBMod::pullAF(Complex& sample) } else { - if (m_running.m_audioBinaural) + if (m_settings.m_audioBinaural) { Complex c; m_ifstream.read(reinterpret_cast<char*>(&c), sizeof(Complex)); - if (m_running.m_audioFlipChannels) + if (m_settings.m_audioFlipChannels) { - ci.real(c.imag() * m_running.m_volumeFactor); - ci.imag(c.real() * m_running.m_volumeFactor); + ci.real(c.imag() * m_settings.m_volumeFactor); + ci.imag(c.real() * m_settings.m_volumeFactor); } else { - ci = c * m_running.m_volumeFactor; + ci = c * m_settings.m_volumeFactor; } } else @@ -297,16 +251,16 @@ void SSBMod::pullAF(Complex& sample) Real real; m_ifstream.read(reinterpret_cast<char*>(&real), sizeof(Real)); - if (m_running.m_agc) + if (m_settings.m_agc) { ci.real(real); ci.imag(0.0f); m_inAGC.feed(ci); - ci *= m_running.m_volumeFactor; + ci *= m_settings.m_volumeFactor; } else { - ci.real(real * m_running.m_volumeFactor); + ci.real(real * m_settings.m_volumeFactor); ci.imag(0.0f); } } @@ -319,31 +273,31 @@ void SSBMod::pullAF(Complex& sample) } break; case SSBModInputAudio: - if (m_running.m_audioBinaural) + if (m_settings.m_audioBinaural) { - if (m_running.m_audioFlipChannels) + if (m_settings.m_audioFlipChannels) { - ci.real((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_running.m_volumeFactor); - ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_running.m_volumeFactor); + ci.real((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor); + ci.imag((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_settings.m_volumeFactor); } else { - ci.real((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_running.m_volumeFactor); - ci.imag((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_running.m_volumeFactor); + ci.real((m_audioBuffer[m_audioBufferFill].l / 32768.0f) * m_settings.m_volumeFactor); + ci.imag((m_audioBuffer[m_audioBufferFill].r / 32768.0f) * m_settings.m_volumeFactor); } } else { - if (m_running.m_agc) + if (m_settings.m_agc) { ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f)); ci.imag(0.0f); m_inAGC.feed(ci); - ci *= m_running.m_volumeFactor; + ci *= m_settings.m_volumeFactor; } else { - ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_running.m_volumeFactor); + ci.real(((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor); ci.imag(0.0f); } } @@ -356,7 +310,7 @@ void SSBMod::pullAF(Complex& sample) { m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor); - if (m_running.m_dsb) + if (m_settings.m_dsb) { Real t = m_toneNco.next() * fadeFactor; sample.real(t); @@ -364,7 +318,7 @@ void SSBMod::pullAF(Complex& sample) } else { - if (m_running.m_usb) { + if (m_settings.m_usb) { sample = m_toneNco.nextIQ() * fadeFactor; } else { sample = m_toneNco.nextQI() * fadeFactor; @@ -375,7 +329,7 @@ void SSBMod::pullAF(Complex& sample) { if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor)) { - if (m_running.m_dsb) + if (m_settings.m_dsb) { Real t = (m_toneNco.next() * fadeFactor)/1.25; sample.real(t); @@ -383,7 +337,7 @@ void SSBMod::pullAF(Complex& sample) } else { - if (m_running.m_usb) { + if (m_settings.m_usb) { sample = m_toneNco.nextIQ() * fadeFactor; } else { sample = m_toneNco.nextQI() * fadeFactor; @@ -406,7 +360,7 @@ void SSBMod::pullAF(Complex& sample) if ((m_afInput == SSBModInputFile) || (m_afInput == SSBModInputAudio)) // real audio { - if (m_running.m_dsb) + if (m_settings.m_dsb) { n_out = m_DSBFilter->runDSB(ci, &filtered); @@ -421,7 +375,7 @@ void SSBMod::pullAF(Complex& sample) } else { - n_out = m_SSBFilter->runSSB(ci, &filtered, m_running.m_usb); + n_out = m_SSBFilter->runSSB(ci, &filtered, m_settings.m_usb); if (n_out > 0) { @@ -457,7 +411,7 @@ void SSBMod::pullAF(Complex& sample) // // m_magsqCount++; - if (!m_running.m_dsb & !m_running.m_usb) + if (!m_settings.m_dsb & !m_settings.m_usb) { // invert spectrum for LSB m_sampleBuffer.push_back(Sample(avgi, avgr)); } @@ -491,7 +445,7 @@ void SSBMod::pullAF(Complex& sample) // // m_magsqCount++; - if (!m_running.m_dsb & !m_running.m_usb) + if (!m_settings.m_dsb & !m_settings.m_usb) { // invert spectrum for LSB m_sampleBuffer.push_back(Sample(avgi, avgr)); } @@ -504,7 +458,7 @@ void SSBMod::pullAF(Complex& sample) m_sum.imag(0.0); } - if (m_sumCount < (m_running.m_dsb ? m_ssbFftLen : m_ssbFftLen>>1)) + if (m_sumCount < (m_settings.m_dsb ? m_ssbFftLen : m_ssbFftLen>>1)) { n_out = 0; m_sumCount++; @@ -520,7 +474,7 @@ void SSBMod::pullAF(Complex& sample) { if (m_sampleSink != 0) { - m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_running.m_dsb); + m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), !m_settings.m_dsb); } m_sampleBuffer.clear(); @@ -550,8 +504,8 @@ void SSBMod::calculateLevel(Complex& sample) void SSBMod::start() { - qDebug() << "SSBMod::start: m_outputSampleRate: " << m_config.m_outputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + qDebug() << "SSBMod::start: m_outputSampleRate: " << m_settings.m_outputSampleRate + << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset; m_audioFifo.clear(); } @@ -566,91 +520,82 @@ bool SSBMod::handleMessage(const Message& cmd) { UpChannelizer::MsgChannelizerNotification& notif = (UpChannelizer::MsgChannelizerNotification&) cmd; - m_config.m_basebandSampleRate = notif.getBasebandSampleRate(); - m_config.m_outputSampleRate = notif.getSampleRate(); - m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); + SSBModSettings settings = m_settings; - apply(); + settings.m_basebandSampleRate = notif.getBasebandSampleRate(); + settings.m_outputSampleRate = notif.getSampleRate(); + settings.m_inputFrequencyOffset = notif.getFrequencyOffset(); + + applySettings(settings); qDebug() << "SSBMod::handleMessage: MsgChannelizerNotification:" - << " m_basebandSampleRate: " << m_config.m_basebandSampleRate - << " m_outputSampleRate: " << m_config.m_outputSampleRate - << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + << " m_basebandSampleRate: " << settings.m_basebandSampleRate + << " m_outputSampleRate: " << settings.m_outputSampleRate + << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset; return true; } - else if (MsgConfigureSSBMod::match(cmd)) - { - float band, lowCutoff; + else if (MsgConfigureSSBMod::match(cmd)) + { + float band, lowCutoff; + MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd; - MsgConfigureSSBMod& cfg = (MsgConfigureSSBMod&) cmd; - m_settingsMutex.lock(); + SSBModSettings settings = cfg.getSettings(); - band = cfg.getBandwidth(); - lowCutoff = cfg.getLowCutoff(); + // These settings are set with UpChannelizer::MsgChannelizerNotification + settings.m_basebandSampleRate = m_settings.m_basebandSampleRate; + settings.m_outputSampleRate = m_settings.m_outputSampleRate; + settings.m_inputFrequencyOffset = m_settings.m_inputFrequencyOffset; - if (band < 0) // negative means LSB - { - band = -band; // turn to positive - lowCutoff = -lowCutoff; - m_config.m_usb = false; // and take note of side band - } - else - { - m_config.m_usb = true; - } + band = settings.m_bandwidth; + lowCutoff = settings.m_lowCutoff; - if (band < 100.0f) // at least 100 Hz - { - band = 100.0f; - lowCutoff = 0; - } + if (band < 0) // negative means LSB + { + band = -band; // turn to positive + lowCutoff = -lowCutoff; + settings.m_usb = false; // and take note of side band + } + else + { + settings.m_usb = true; + } - m_config.m_bandwidth = band; - m_config.m_lowCutoff = lowCutoff; + if (band < 100.0f) // at least 100 Hz + { + band = 100.0f; + lowCutoff = 0; + } - m_config.m_toneFrequency = cfg.getToneFrequency(); - m_config.m_volumeFactor = cfg.getVolumeFactor(); - m_config.m_spanLog2 = cfg.getSpanLog2(); - m_config.m_audioBinaural = cfg.getAudioBinaural(); - m_config.m_audioFlipChannels = cfg.getAudioFlipChannels(); - m_config.m_dsb = cfg.getDSB(); - m_config.m_audioMute = cfg.getAudioMute(); - m_config.m_playLoop = cfg.getPlayLoop(); - m_config.m_agc = cfg.getAGC(); + settings.m_bandwidth = band; + settings.m_lowCutoff = lowCutoff; - m_config.m_agcTime = cfg.getAGCTime(); // ms - m_config.m_agcOrder = cfg.getAGCOrder(); - m_config.m_agcThresholdEnable = cfg.getAGCThreshold() != -99; - m_config.m_agcThreshold = CalcDb::powerFromdB(cfg.getAGCThreshold()); // power dB - m_config.m_agcThresholdGate = cfg.getAGCThresholdGate(); // ms - m_config.m_agcThresholdDelay = cfg.getAGCThresholdDelay(); // ms + applySettings(settings, cfg.getForce()); - apply(); + qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod:" + << " m_bandwidth: " << settings.m_bandwidth + << " m_lowCutoff: " << settings.m_lowCutoff + << " m_toneFrequency: " << settings.m_toneFrequency + << " m_volumeFactor: " << settings.m_volumeFactor + << " m_spanLog2: " << settings.m_spanLog2 + << " m_outputSampleRate: " << m_settings.m_outputSampleRate + << " m_audioSampleRate: " << settings.m_audioSampleRate + << " m_audioBinaural: " << settings.m_audioBinaural + << " m_audioFlipChannels: " << settings.m_audioFlipChannels + << " m_dsb: " << settings.m_dsb + << " m_audioMute: " << settings.m_audioMute + << " m_playLoop: " << settings.m_playLoop + << " m_agc: " << settings.m_agc + << " m_agcTime: " << settings.m_agcTime + << " m_agcOrder: " << settings.m_agcOrder + << " m_agcThresholdEnable: " << settings.m_agcThresholdEnable + << " m_agcThreshold: " << settings.m_agcThreshold + << " m_agcThresholdGate: " << settings.m_agcThresholdGate + << " m_agcThresholdDelay: " << settings.m_agcThresholdDelay + << " force: " << cfg.getForce(); - m_settingsMutex.unlock(); - - qDebug() << "SSBMod::handleMessage: MsgConfigureSSBMod:" - << " m_bandwidth: " << m_config.m_bandwidth - << " m_lowCutoff: " << m_config.m_lowCutoff - << " m_toneFrequency: " << m_config.m_toneFrequency - << " m_volumeFactor: " << m_config.m_volumeFactor - << " m_spanLog2: " << m_config.m_spanLog2 - << " m_audioBinaural: " << m_config.m_audioBinaural - << " m_audioFlipChannels: " << m_config.m_audioFlipChannels - << " m_dsb: " << m_config.m_dsb - << " m_audioMute: " << m_config.m_audioMute - << " m_playLoop: " << m_config.m_playLoop - << " m_agc: " << m_config.m_agc - << " m_agcTime: " << m_config.m_agcTime - << " m_agcOrder: " << m_config.m_agcOrder - << " m_agcThresholdEnable: " << m_config.m_agcThresholdEnable - << " m_agcThreshold: " << m_config.m_agcThreshold - << " m_agcThresholdGate: " << m_config.m_agcThresholdGate - << " m_agcThresholdDelay: " << m_config.m_agcThresholdDelay; - - return true; - } + return true; + } else if (MsgConfigureFileSourceName::match(cmd)) { MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd; @@ -695,115 +640,6 @@ bool SSBMod::handleMessage(const Message& cmd) } } -void SSBMod::apply() -{ - if ((m_config.m_bandwidth != m_running.m_bandwidth) || - (m_config.m_lowCutoff != m_running.m_lowCutoff) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate)) - { - m_settingsMutex.lock(); - m_SSBFilter->create_filter(m_config.m_lowCutoff / m_config.m_audioSampleRate, m_config.m_bandwidth / m_config.m_audioSampleRate); - m_DSBFilter->create_dsb_filter((2.0f * m_config.m_bandwidth) / m_config.m_audioSampleRate); - m_settingsMutex.unlock(); - } - - if ((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || - (m_config.m_outputSampleRate != m_running.m_outputSampleRate)) - { - m_settingsMutex.lock(); - m_carrierNco.setFreq(m_config.m_inputFrequencyOffset, m_config.m_outputSampleRate); - m_settingsMutex.unlock(); - } - - if((m_config.m_outputSampleRate != m_running.m_outputSampleRate) || - (m_config.m_bandwidth != m_running.m_bandwidth) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate)) - { - m_settingsMutex.lock(); - m_interpolatorDistanceRemain = 0; - m_interpolatorConsumed = false; - m_interpolatorDistance = (Real) m_config.m_audioSampleRate / (Real) m_config.m_outputSampleRate; - m_interpolator.create(48, m_config.m_audioSampleRate, m_config.m_bandwidth, 3.0); - m_settingsMutex.unlock(); - } - - if ((m_config.m_toneFrequency != m_running.m_toneFrequency) || - (m_config.m_audioSampleRate != m_running.m_audioSampleRate)) - { - m_settingsMutex.lock(); - m_toneNco.setFreq(m_config.m_toneFrequency, m_config.m_audioSampleRate); - m_settingsMutex.unlock(); - } - - if (m_config.m_audioSampleRate != m_running.m_audioSampleRate) - { - m_settingsMutex.lock(); - m_cwKeyer.setSampleRate(m_config.m_audioSampleRate); - m_settingsMutex.unlock(); - } - - if (m_config.m_dsb != m_running.m_dsb) - { - if (m_config.m_dsb) - { - memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); - m_DSBFilterBufferIndex = 0; - } - else - { - memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1)); - m_SSBFilterBufferIndex = 0; - } - } - - if ((m_config.m_agcTime != m_running.m_agcTime) || (m_config.m_agcOrder != m_running.m_agcOrder)) - { - m_inAGC.resize(m_config.m_agcTime, m_config.m_agcOrder); - } - - if (m_config.m_agcThresholdEnable != m_running.m_agcThresholdEnable) - { - m_inAGC.setThresholdEnable(m_config.m_agcThresholdEnable); - } - - if (m_config.m_agcThreshold != m_running.m_agcThreshold) - { - m_inAGC.setThreshold(m_config.m_agcThreshold); - } - - if (m_config.m_agcThresholdGate != m_running.m_agcThresholdGate) - { - m_inAGC.setGate(m_config.m_agcThresholdGate); - } - - if (m_config.m_agcThresholdDelay != m_running.m_agcThresholdDelay) - { - m_inAGC.setStepDownDelay(m_config.m_agcThresholdDelay); - } - - m_running.m_outputSampleRate = m_config.m_outputSampleRate; - m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset; - m_running.m_bandwidth = m_config.m_bandwidth; - m_running.m_lowCutoff = m_config.m_lowCutoff; - m_running.m_usb = m_config.m_usb; - m_running.m_toneFrequency = m_config.m_toneFrequency; - m_running.m_volumeFactor = m_config.m_volumeFactor; - m_running.m_audioSampleRate = m_config.m_audioSampleRate; - m_running.m_spanLog2 = m_config.m_spanLog2; - m_running.m_audioBinaural = m_config.m_audioBinaural; - m_running.m_audioFlipChannels = m_config.m_audioFlipChannels; - m_running.m_dsb = m_config.m_dsb; - m_running.m_audioMute = m_config.m_audioMute; - m_running.m_playLoop = m_config.m_playLoop; - m_running.m_agc = m_config.m_agc; - m_running.m_agcOrder = m_config.m_agcOrder; - m_running.m_agcTime = m_config.m_agcTime; - m_running.m_agcThresholdEnable = m_config.m_agcThresholdEnable; - m_running.m_agcThreshold = m_config.m_agcThreshold; - m_running.m_agcThresholdGate = m_config.m_agcThresholdGate; - m_running.m_agcThresholdDelay = m_config.m_agcThresholdDelay; -} - void SSBMod::openFileStream() { if (m_ifstream.is_open()) { @@ -838,3 +674,93 @@ void SSBMod::seekFileStream(int seekPercentage) m_ifstream.seekg(seekPoint, std::ios::beg); } } + +void SSBMod::applySettings(const SSBModSettings& settings, bool force) +{ + if ((settings.m_bandwidth != m_settings.m_bandwidth) || + (settings.m_lowCutoff != m_settings.m_lowCutoff) || + (settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_settingsMutex.lock(); + m_SSBFilter->create_filter(settings.m_lowCutoff / settings.m_audioSampleRate, settings.m_bandwidth / settings.m_audioSampleRate); + m_DSBFilter->create_dsb_filter((2.0f * settings.m_bandwidth) / settings.m_audioSampleRate); + m_settingsMutex.unlock(); + } + + if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || + (settings.m_outputSampleRate != m_settings.m_outputSampleRate) || force) + { + m_settingsMutex.lock(); + m_carrierNco.setFreq(settings.m_inputFrequencyOffset, settings.m_outputSampleRate); + m_settingsMutex.unlock(); + } + + if((settings.m_outputSampleRate != m_settings.m_outputSampleRate) || + (settings.m_bandwidth != m_settings.m_bandwidth) || + (settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_settingsMutex.lock(); + m_interpolatorDistanceRemain = 0; + m_interpolatorConsumed = false; + m_interpolatorDistance = (Real) settings.m_audioSampleRate / (Real) settings.m_outputSampleRate; + m_interpolator.create(48, settings.m_audioSampleRate, settings.m_bandwidth, 3.0); + m_settingsMutex.unlock(); + } + + if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || + (settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_settingsMutex.lock(); + m_toneNco.setFreq(settings.m_toneFrequency, settings.m_audioSampleRate); + m_settingsMutex.unlock(); + } + + if ((settings.m_audioSampleRate != m_settings.m_audioSampleRate) || force) + { + m_settingsMutex.lock(); + m_cwKeyer.setSampleRate(settings.m_audioSampleRate); + m_settingsMutex.unlock(); + } + + if ((settings.m_dsb != m_settings.m_dsb) || force) + { + if (settings.m_dsb) + { + memset(m_DSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen)); + m_DSBFilterBufferIndex = 0; + } + else + { + memset(m_SSBFilterBuffer, 0, sizeof(Complex)*(m_ssbFftLen>>1)); + m_SSBFilterBufferIndex = 0; + } + } + + if ((settings.m_agcTime != m_settings.m_agcTime) || + (settings.m_agcOrder != m_settings.m_agcOrder) || force) + { + m_inAGC.resize(settings.m_agcTime, settings.m_agcOrder); + } + + if ((settings.m_agcThresholdEnable != m_settings.m_agcThresholdEnable) || force) + { + m_inAGC.setThresholdEnable(settings.m_agcThresholdEnable); + } + + if ((settings.m_agcThreshold != m_settings.m_agcThreshold) || force) + { + m_inAGC.setThreshold(settings.m_agcThreshold); + } + + if ((settings.m_agcThresholdGate != m_settings.m_agcThresholdGate) || force) + { + m_inAGC.setGate(settings.m_agcThresholdGate); + } + + if ((settings.m_agcThresholdDelay != m_settings.m_agcThresholdDelay) || force) + { + m_inAGC.setStepDownDelay(settings.m_agcThresholdDelay); + } + + m_settings = settings; +} diff --git a/plugins/channeltx/modssb/ssbmod.h b/plugins/channeltx/modssb/ssbmod.h index 63dd0f4aa..150c91310 100644 --- a/plugins/channeltx/modssb/ssbmod.h +++ b/plugins/channeltx/modssb/ssbmod.h @@ -33,6 +33,8 @@ #include "audio/audiofifo.h" #include "util/message.h" +#include "ssbmodsettings.h" + class SSBMod : public BasebandSampleSource { Q_OBJECT @@ -46,6 +48,52 @@ public: SSBModInputCWTone } SSBModInputAF; + class MsgConfigureSSBMod : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const SSBModSettings& getSettings() const { return m_settings; } + bool getForce() const { return m_force; } + + static MsgConfigureSSBMod* create(const SSBModSettings& settings, bool force) + { + return new MsgConfigureSSBMod(settings, force); + } + + private: + SSBModSettings m_settings; + bool m_force; + + MsgConfigureSSBMod(const SSBModSettings& settings, bool force) : + Message(), + m_settings(settings), + m_force(force) + { } + }; + + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + int getCenterFrequency() const { return m_centerFrequency; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + int m_sampleRate; + int m_centerFrequency; + + MsgConfigureChannelizer(int sampleRate, int centerFrequency) : + Message(), + m_sampleRate(sampleRate), + m_centerFrequency(centerFrequency) + { } + }; + class MsgConfigureFileSourceName : public Message { MESSAGE_CLASS_DECLARATION @@ -177,24 +225,6 @@ public: SSBMod(BasebandSampleSink* sampleSink); ~SSBMod(); - void configure(MessageQueue* messageQueue, - Real bandwidth, - Real lowCutoff, - float toneFrequency, - float volumeFactor, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool playLoop, - bool agc, - float agcOrder, - int agcTime, - int agcThreshold, - int agcThresholdGate, - int agcThresholdDelay); - virtual void pull(Sample& sample); virtual void pullAudio(int nbSamples); virtual void start(); @@ -216,178 +246,12 @@ signals: private: - class MsgConfigureSSBMod : public Message - { - MESSAGE_CLASS_DECLARATION - - public: - Real getBandwidth() const { return m_bandwidth; } - Real getLowCutoff() const { return m_lowCutoff; } - float getToneFrequency() const { return m_toneFrequency; } - float getVolumeFactor() const { return m_volumeFactor; } - int getSpanLog2() const { return m_spanLog2; } - bool getAudioBinaural() const { return m_audioBinaural; } - bool getAudioFlipChannels() const { return m_audioFlipChannels; } - bool getDSB() const { return m_dsb; } - bool getAudioMute() const { return m_audioMute; } - bool getPlayLoop() const { return m_playLoop; } - bool getAGC() const { return m_agc; } - float getAGCOrder() const { return m_agcOrder; } - int getAGCTime() const { return m_agcTime; } - int getAGCThreshold() const { return m_agcThreshold; } - int getAGCThresholdGate() const { return m_agcThresholdGate; } - int getAGCThresholdDelay() const { return m_agcThresholdDelay; } - - static MsgConfigureSSBMod* create(Real bandwidth, - Real lowCutoff, - float toneFrequency, - float volumeFactor, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool playLoop, - bool agc, - float agcOrder, - int agcTime, - int agcThreshold, - int agcThresholdGate, - int agcThresholdDelay) - { - return new MsgConfigureSSBMod(bandwidth, - lowCutoff, - toneFrequency, - volumeFactor, - spanLog2, - audioBinaural, - audioFlipChannels, - dsb, - audioMute, - playLoop, - agc, - agcOrder, - agcTime, - agcThreshold, - agcThresholdGate, - agcThresholdDelay); - } - - private: - Real m_bandwidth; - Real m_lowCutoff; - float m_toneFrequency; - float m_volumeFactor; - int m_spanLog2; - bool m_audioBinaural; - bool m_audioFlipChannels; - bool m_dsb; - bool m_audioMute; - bool m_playLoop; - bool m_agc; - float m_agcOrder; - int m_agcTime; - int m_agcThreshold; - int m_agcThresholdGate; - int m_agcThresholdDelay; - - MsgConfigureSSBMod(Real bandwidth, - Real lowCutoff, - float toneFrequency, - float volumeFactor, - int spanLog2, - bool audioBinaural, - bool audioFlipChannels, - bool dsb, - bool audioMute, - bool playLoop, - bool agc, - float agcOrder, - int agcTime, - int agcThreshold, - int agcThresholdGate, - int agcThresholdDelay) : - Message(), - m_bandwidth(bandwidth), - m_lowCutoff(lowCutoff), - m_toneFrequency(toneFrequency), - m_volumeFactor(volumeFactor), - m_spanLog2(spanLog2), - m_audioBinaural(audioBinaural), - m_audioFlipChannels(audioFlipChannels), - m_dsb(dsb), - m_audioMute(audioMute), - m_playLoop(playLoop), - m_agc(agc), - m_agcOrder(agcOrder), - m_agcTime(agcTime), - m_agcThreshold(agcThreshold), - m_agcThresholdGate(agcThresholdGate), - m_agcThresholdDelay(agcThresholdDelay) - { } - }; - - //================================================================= - enum RateState { RSInitialFill, RSRunning }; - struct Config { - int m_basebandSampleRate; - int m_outputSampleRate; - qint64 m_inputFrequencyOffset; - Real m_bandwidth; - Real m_lowCutoff; - bool m_usb; - float m_toneFrequency; - float m_volumeFactor; - quint32 m_audioSampleRate; - int m_spanLog2; - bool m_audioBinaural; - bool m_audioFlipChannels; - bool m_dsb; - bool m_audioMute; - bool m_playLoop; - bool m_agc; - float m_agcOrder; - int m_agcTime; - bool m_agcThresholdEnable; - double m_agcThreshold; - int m_agcThresholdGate; - int m_agcThresholdDelay; - - Config() : - m_basebandSampleRate(0), - m_outputSampleRate(0), - m_inputFrequencyOffset(0), - m_bandwidth(3000.0f), - m_lowCutoff(300.0f), - m_usb(true), - m_toneFrequency(1000.0f), - m_volumeFactor(1.0f), - m_audioSampleRate(0), - m_spanLog2(3), - m_audioBinaural(false), - m_audioFlipChannels(false), - m_dsb(false), - m_audioMute(false), - m_playLoop(false), - m_agc(false), - m_agcOrder(0.2), - m_agcTime(9600), - m_agcThresholdEnable(true), - m_agcThreshold(1e-4), - m_agcThresholdGate(192), - m_agcThresholdDelay(2400) - { } - }; - - //================================================================= - - Config m_config; - Config m_running; + SSBModSettings m_settings; NCOF m_carrierNco; NCOF m_toneNco; @@ -407,10 +271,6 @@ private: BasebandSampleSink* m_sampleSink; SampleVector m_sampleBuffer; -// Real m_magsqSpectrum; -// Real m_magsqSum; -// Real m_magsqPeak; -// int m_magsqCount; fftfilt::cmplx m_sum; int m_undersampleCount; int m_sumCount; @@ -440,7 +300,7 @@ private: static const int m_levelNbSamples; - void apply(); + void applySettings(const SSBModSettings& settings, bool force = false); void pullAF(Complex& sample); void calculateLevel(Complex& sample); void modulateSample(); diff --git a/plugins/channeltx/modssb/ssbmodgui.cpp b/plugins/channeltx/modssb/ssbmodgui.cpp index 9ed3fbb27..220f50af2 100644 --- a/plugins/channeltx/modssb/ssbmodgui.cpp +++ b/plugins/channeltx/modssb/ssbmodgui.cpp @@ -63,6 +63,7 @@ qint64 SSBModGUI::getCenterFrequency() const { void SSBModGUI::setCenterFrequency(qint64 centerFrequency) { m_channelMarker.setCenterFrequency(centerFrequency); + m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); applySettings(); } @@ -81,14 +82,14 @@ bool SSBModGUI::deserialize(const QByteArray& data) if(m_settings.deserialize(data)) { displaySettings(); - applySettings(); // will have true + applySettings(true); // will have true return true; } else { m_settings.resetToDefaults(); displaySettings(); - applySettings(); // will have true + applySettings(true); // will have true return false; } } @@ -478,7 +479,6 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); - //m_channelMarker = new ChannelMarker(this); m_channelMarker.setColor(Qt::green); m_channelMarker.setBandwidth(m_rate); m_channelMarker.setSidebands(ChannelMarker::usb); @@ -497,7 +497,7 @@ SSBModGUI::SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa m_settings.setCWKeyerGUI(ui->cwKeyerGUI); displaySettings(); - applySettings(); + applySettings(true); setNewRate(m_settings.m_spanLog2); connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); @@ -512,7 +512,6 @@ SSBModGUI::~SSBModGUI() delete m_channelizer; delete m_ssbMod; delete m_spectrumVis; - //delete m_channelMarker; delete ui; } @@ -597,35 +596,16 @@ void SSBModGUI::blockApplySettings(bool block) m_doApplySettings = !block; } -void SSBModGUI::applySettings() +void SSBModGUI::applySettings(bool force) { if (m_doApplySettings) { - setTitleColor(m_channelMarker.getColor()); - m_channelizer->configure(m_channelizer->getInputMessageQueue(), 48000, m_channelMarker.getCenterFrequency()); - ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); - - m_ssbMod->configure(m_ssbMod->getInputMessageQueue(), - m_settings.m_bandwidth, - m_settings.m_lowCutoff, - m_settings.m_toneFrequency, - m_settings.m_volumeFactor, - m_settings.m_spanLog2, - m_settings.m_audioBinaural, - m_settings.m_audioFlipChannels, - m_settings.m_dsb, - m_settings.m_audioMute, - m_settings.m_playLoop, - m_settings.m_agc, - m_settings.m_agcOrder, - m_settings.m_agcTime, - m_settings.m_agcThreshold, - m_settings.m_agcThresholdGate, - m_settings.m_agcThresholdDelay); + SSBMod::MsgConfigureSSBMod *msg = SSBMod::MsgConfigureSSBMod::create(m_settings, force); + m_ssbMod->getInputMessageQueue()->push(msg); } } diff --git a/plugins/channeltx/modssb/ssbmodgui.h b/plugins/channeltx/modssb/ssbmodgui.h index 71db67a66..f3b6d4182 100644 --- a/plugins/channeltx/modssb/ssbmodgui.h +++ b/plugins/channeltx/modssb/ssbmodgui.h @@ -101,7 +101,6 @@ private: bool m_basicSettingsShown; bool m_doApplySettings; int m_rate; - int m_spanLog2; ThreadedBasebandSampleSource* m_threadedChannelizer; UpChannelizer* m_channelizer; @@ -118,8 +117,6 @@ private: SSBMod::SSBModInputAF m_modAFInput; MessageQueue m_inputMessageQueue; - //static const int m_agcTimeConstant[]; //!< time constant index to value in ms - explicit SSBModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL); virtual ~SSBModGUI(); @@ -127,7 +124,7 @@ private: bool setNewRate(int spanLog2); void blockApplySettings(bool block); - void applySettings(); + void applySettings(bool force = false); void displaySettings(); void displayAGCPowerThreshold(); void updateWithStreamData();