SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
freedvmod.cpp
Go to the documentation of this file.
1 // Copyright (C) 2019 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include "freedvmod.h"
19 
20 #include <QTime>
21 #include <QDebug>
22 #include <QMutexLocker>
23 #include <QNetworkAccessManager>
24 #include <QNetworkReply>
25 #include <QBuffer>
26 
27 #include <stdio.h>
28 #include <complex.h>
29 #include <algorithm>
30 
31 #include "codec2/freedv_api.h"
32 
33 #include "SWGChannelSettings.h"
34 #include "SWGChannelReport.h"
35 #include "SWGFreeDVModReport.h"
36 
37 #include "dsp/upchannelizer.h"
38 #include "dsp/dspengine.h"
40 #include "dsp/dspcommands.h"
41 #include "device/deviceapi.h"
42 #include "util/db.h"
43 
51 
52 const QString FreeDVMod::m_channelIdURI = "sdrangel.channeltx.freedvmod";
53 const QString FreeDVMod::m_channelId = "FreeDVMod";
54 const int FreeDVMod::m_levelNbSamples = 80; // every 10ms
55 const int FreeDVMod::m_ssbFftLen = 1024;
56 
58  ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
59  m_deviceAPI(deviceAPI),
60  m_basebandSampleRate(48000),
61  m_outputSampleRate(48000),
62  m_modemSampleRate(48000), // // default 2400A mode
63  m_inputFrequencyOffset(0),
64  m_lowCutoff(0.0),
65  m_hiCutoff(6000.0),
66  m_SSBFilter(0),
67  m_SSBFilterBuffer(0),
68  m_SSBFilterBufferIndex(0),
69  m_sampleSink(0),
70  m_audioFifo(4800),
71  m_settingsMutex(QMutex::Recursive),
72  m_fileSize(0),
73  m_recordLength(0),
74  m_inputSampleRate(8000), // all modes take 8000 S/s input
75  m_levelCalcCount(0),
76  m_peakLevel(0.0f),
77  m_levelSum(0.0f),
78  m_freeDV(0),
79  m_nSpeechSamples(0),
80  m_nNomModemSamples(0),
81  m_iSpeech(0),
82  m_iModem(0),
83  m_speechIn(0),
84  m_modOut(0),
85  m_scaleFactor(SDR_TX_SCALEF)
86 {
87  setObjectName(m_channelId);
88 
91 
93  m_SSBFilterBuffer = new Complex[m_ssbFftLen>>1]; // filter returns data exactly half of its size
95 
96  m_audioBuffer.resize(1<<14);
98 
99  m_sum.real(0.0f);
100  m_sum.imag(0.0f);
101  m_undersampleCount = 0;
102  m_sumCount = 0;
103 
104  m_magsq = 0.0;
105 
108  m_cwKeyer.reset();
109 
110  m_channelizer = new UpChannelizer(this);
114 
115  applySettings(m_settings, true);
117 
118  m_networkManager = new QNetworkAccessManager();
119  connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
120 }
121 
123 {
124  disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
125  delete m_networkManager;
126 
128 
131  delete m_threadedChannelizer;
132  delete m_channelizer;
133 
134  delete m_SSBFilter;
135  delete[] m_SSBFilterBuffer;
136 
137  if (m_freeDV) {
138  freedv_close(m_freeDV);
139  }
140 }
141 
142 void FreeDVMod::pull(Sample& sample)
143 {
144  Complex ci;
145 
146  m_settingsMutex.lock();
147 
148  if (m_interpolatorDistance > 1.0f) // decimate
149  {
150  modulateSample();
151 
153  {
154  modulateSample();
155  }
156  }
157  else
158  {
160  {
161  modulateSample();
162  }
163  }
164 
166 
167  ci *= m_carrierNco.nextIQ(); // shift to carrier frequency
168  ci *= 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
169 
170  m_settingsMutex.unlock();
171 
172  double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
173  magsq /= (SDR_TX_SCALED*SDR_TX_SCALED);
174  m_movingAverage(magsq);
176 
177  sample.m_real = (FixReal) ci.real();
178  sample.m_imag = (FixReal) ci.imag();
179 }
180 
181 void FreeDVMod::pullAudio(int nbSamples)
182 {
183  unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_modemSampleRate);
184 
185  if (nbSamplesAudio > m_audioBuffer.size())
186  {
187  m_audioBuffer.resize(nbSamplesAudio);
188  }
189 
190  m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioBuffer[0]), nbSamplesAudio);
191  m_audioBufferFill = 0;
192 }
193 
195 {
199  }
201 }
202 
204 {
206  {
207  sample.real(0.0f);
208  sample.imag(0.0f);
209  return;
210  }
211 
212  Complex ci;
213  fftfilt::cmplx *filtered;
214  int n_out = 0;
215 
216  int decim = 1<<(m_settings.m_spanLog2 - 1);
217  unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
218 
220  {
221  switch (m_settings.m_modAFInput)
222  {
224  for (int i = 0; i < m_nSpeechSamples; i++)
225  {
229  }
230  }
231  freedv_tx(m_freeDV, m_modOut, m_speechIn);
232  break;
235  {
236  if (m_ifstream.is_open())
237  {
238  std::fill(m_speechIn, m_speechIn + m_nSpeechSamples, 0);
239 
240  if (m_ifstream.eof())
241  {
243  {
244  m_ifstream.clear();
245  m_ifstream.seekg(0, std::ios::beg);
246  }
247  }
248 
249  if (m_ifstream.eof())
250  {
251  std::fill(m_modOut, m_modOut + m_nNomModemSamples, 0);
252  }
253  else
254  {
255 
256  m_ifstream.read(reinterpret_cast<char*>(m_speechIn), sizeof(int16_t) * m_nSpeechSamples);
257 
259  {
260  for (int i = 0; i < m_nSpeechSamples; i++)
261  {
262  if (m_settings.m_volumeFactor != 1.0) {
264  }
267  }
268  }
269  }
270 
271  freedv_tx(m_freeDV, m_modOut, m_speechIn);
272  }
273  }
274  else
275  {
276  std::fill(m_modOut, m_modOut + m_nNomModemSamples, 0);
277  }
278  }
279  break;
281  for (int i = 0; i < m_nSpeechSamples; i++)
282  {
285 
286  while (!m_audioResampler.downSample(audioSample, m_speechIn[i]))
287  {
290  }
291 
294  }
295  }
296  freedv_tx(m_freeDV, m_modOut, m_speechIn);
297  break;
299  for (int i = 0; i < m_nSpeechSamples; i++)
300  {
301  Real fadeFactor;
302 
303  if (m_cwKeyer.getSample())
304  {
305  m_cwKeyer.getCWSmoother().getFadeSample(true, fadeFactor);
306  m_speechIn[i] = m_toneNco.next() * 32768.0f * fadeFactor * m_settings.m_volumeFactor;
307  }
308  else
309  {
310  if (m_cwKeyer.getCWSmoother().getFadeSample(false, fadeFactor))
311  {
312  m_speechIn[i] = m_toneNco.next() * 32768.0f * fadeFactor * m_settings.m_volumeFactor;
313  }
314  else
315  {
316  m_speechIn[i] = 0;
317  m_toneNco.setPhase(0);
318  }
319  }
320 
323  }
324  }
325  freedv_tx(m_freeDV, m_modOut, m_speechIn);
326  break;
328  default:
329  std::fill(m_speechIn, m_speechIn + m_nSpeechSamples, 0);
330  freedv_tx(m_freeDV, m_modOut, m_speechIn);
331  break;
332  }
333 
334  m_iModem = 0;
335  }
336 
337  ci.real(m_modOut[m_iModem++] / m_scaleFactor);
338  ci.imag(0.0f);
339 
340  n_out = m_SSBFilter->runSSB(ci, &filtered, true); // USB
341 
342  if (n_out > 0)
343  {
344  memcpy((void *) m_SSBFilterBuffer, (const void *) filtered, n_out*sizeof(Complex));
346 
347  for (int i = 0; i < n_out; i++)
348  {
349  // Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
350  // smart decimation with bit gain using float arithmetic (23 bits significand)
351 
352  m_sum += filtered[i];
353 
354  if (!(m_undersampleCount++ & decim_mask))
355  {
356  Real avgr = (m_sum.real() / decim) * 0.891235351562f * SDR_TX_SCALEF; //scaling at -1 dB to account for possible filter overshoot
357  Real avgi = (m_sum.imag() / decim) * 0.891235351562f * SDR_TX_SCALEF;
358  m_sampleBuffer.push_back(Sample(avgr, avgi));
359  m_sum.real(0.0);
360  m_sum.imag(0.0);
361  }
362  }
363 
364  if (m_sampleSink != 0)
365  {
366  m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), true); // SSB
367  }
368 
369  m_sampleBuffer.clear();
370  }
371 
373 }
374 
376 {
377  Real t = sample.real(); // TODO: possibly adjust depending on sample type
378 
380  {
381  m_peakLevel = std::max(std::fabs(m_peakLevel), t);
382  m_levelSum += t * t;
384  }
385  else
386  {
387  qreal rmsLevel = sqrt(m_levelSum / m_levelNbSamples);
388  //qDebug("NFMMod::calculateLevel: %f %f", rmsLevel, m_peakLevel);
389  emit levelChanged(rmsLevel, m_peakLevel, m_levelNbSamples);
390  m_peakLevel = 0.0f;
391  m_levelSum = 0.0f;
392  m_levelCalcCount = 0;
393  }
394 }
395 
396 void FreeDVMod::calculateLevel(qint16& sample)
397 {
398  Real t = sample / SDR_TX_SCALEF;
399 
401  {
402  m_peakLevel = std::max(std::fabs(m_peakLevel), t);
403  m_levelSum += t * t;
405  }
406  else
407  {
408  qreal rmsLevel = sqrt(m_levelSum / m_levelNbSamples);
409  //qDebug("FreeDVMod::calculateLevel: %f %f", rmsLevel, m_peakLevel);
410  emit levelChanged(rmsLevel, m_peakLevel, m_levelNbSamples);
411  m_peakLevel = 0.0f;
412  m_levelSum = 0.0f;
413  m_levelCalcCount = 0;
414  }
415 }
416 
418 {
419  qDebug() << "FreeDVMod::start: m_outputSampleRate: " << m_outputSampleRate
420  << " m_inputFrequencyOffset: " << m_settings.m_inputFrequencyOffset;
421 
422  m_audioFifo.clear();
424 }
425 
427 {
428 }
429 
431 {
433  {
435  qDebug() << "FreeDVMod::handleMessage: MsgChannelizerNotification";
436 
438 
439  return true;
440  }
441  else if (MsgConfigureChannelizer::match(cmd))
442  {
444  qDebug() << "FreeDVMod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.getSampleRate()
445  << " centerFrequency: " << cfg.getCenterFrequency();
446 
448  cfg.getSampleRate(),
449  cfg.getCenterFrequency());
450 
451  return true;
452  }
453  else if (MsgConfigureFreeDVMod::match(cmd))
454  {
456  qDebug() << "FreeDVMod::handleMessage: MsgConfigureFreeDVMod";
457 
458  applySettings(cfg.getSettings(), cfg.getForce());
459 
460  return true;
461  }
462  else if (MsgConfigureFileSourceName::match(cmd))
463  {
465  m_fileName = conf.getFileName();
466  openFileStream();
467  return true;
468  }
469  else if (MsgConfigureFileSourceSeek::match(cmd))
470  {
472  int seekPercentage = conf.getPercentage();
473  seekFileStream(seekPercentage);
474 
475  return true;
476  }
478  {
479  std::size_t samplesCount;
480 
481  if (m_ifstream.eof()) {
482  samplesCount = m_fileSize / sizeof(int16_t);
483  } else {
484  samplesCount = m_ifstream.tellg() / sizeof(int16_t);
485  }
486 
487  if (getMessageQueueToGUI())
488  {
490  report = MsgReportFileSourceStreamTiming::create(samplesCount);
491  getMessageQueueToGUI()->push(report);
492  }
493 
494  return true;
495  }
497  {
499 
502  }
503 
504  return true;
505  }
506  else if (DSPConfigureAudio::match(cmd))
507  {
508  DSPConfigureAudio& cfg = (DSPConfigureAudio&) cmd;
509  uint32_t sampleRate = cfg.getSampleRate();
510 
511  qDebug() << "FreeDVMod::handleMessage: DSPConfigureAudio:"
512  << " sampleRate: " << sampleRate;
513 
514  if (sampleRate != m_audioSampleRate) {
515  applyAudioSampleRate(sampleRate);
516  }
517 
518  return true;
519  }
520  else if (DSPSignalNotification::match(cmd))
521  {
522  return true;
523  }
524  else
525  {
526  return false;
527  }
528 }
529 
531 {
532  if (m_ifstream.is_open()) {
533  m_ifstream.close();
534  }
535 
536  m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary | std::ios::ate);
537  m_fileSize = m_ifstream.tellg();
538  m_ifstream.seekg(0,std::ios_base::beg);
539 
541 
542  qDebug() << "FreeDVMod::openFileStream: " << m_fileName.toStdString().c_str()
543  << " fileSize: " << m_fileSize << "bytes"
544  << " length: " << m_recordLength << " seconds";
545 
546  if (getMessageQueueToGUI())
547  {
550  getMessageQueueToGUI()->push(report);
551  }
552 }
553 
554 void FreeDVMod::seekFileStream(int seekPercentage)
555 {
556  QMutexLocker mutexLocker(&m_settingsMutex);
557 
558  if (m_ifstream.is_open())
559  {
560  int seekPoint = ((m_recordLength * seekPercentage) / 100) * m_inputSampleRate;
561  seekPoint *= sizeof(Real);
562  m_ifstream.clear();
563  m_ifstream.seekg(seekPoint, std::ios::beg);
564  }
565 }
566 
568 {
569  qDebug("FreeDVMod::applyAudioSampleRate: %d", sampleRate);
570  // TODO: put up simple IIR interpolator when sampleRate < m_modemSampleRate
571 
572  m_settingsMutex.lock();
574  m_audioResampler.setAudioFilters(sampleRate, sampleRate, 250, 3300);
575  m_settingsMutex.unlock();
576 
577  m_audioSampleRate = sampleRate;
578 }
579 
580 void FreeDVMod::applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force)
581 {
582  qDebug() << "FreeDVMod::applyChannelSettings:"
583  << " basebandSampleRate: " << basebandSampleRate
584  << " outputSampleRate: " << outputSampleRate
585  << " inputFrequencyOffset: " << inputFrequencyOffset;
586 
587  if ((inputFrequencyOffset != m_inputFrequencyOffset) ||
588  (outputSampleRate != m_outputSampleRate) || force)
589  {
590  m_settingsMutex.lock();
591  m_carrierNco.setFreq(inputFrequencyOffset, outputSampleRate);
592  m_settingsMutex.unlock();
593  }
594 
595  if ((outputSampleRate != m_outputSampleRate) || force)
596  {
597  m_settingsMutex.lock();
599  m_interpolatorConsumed = false;
600  m_interpolatorDistance = (Real) m_modemSampleRate / (Real) outputSampleRate;
602  m_settingsMutex.unlock();
603  }
604 
605  m_basebandSampleRate = basebandSampleRate;
606  m_outputSampleRate = outputSampleRate;
607  m_inputFrequencyOffset = inputFrequencyOffset;
608 }
609 
611 {
614  int modemSampleRate = FreeDVModSettings::getModSampleRate(mode);
615 
616  m_settingsMutex.lock();
617  m_SSBFilter->create_filter(m_lowCutoff / modemSampleRate, m_hiCutoff / modemSampleRate);
618 
619  // baseband interpolator and filter
620  if (modemSampleRate != m_modemSampleRate)
621  {
623  modemSampleRate, m_settings.m_inputFrequencyOffset);
624  m_inputMessageQueue.push(channelConfigMsg);
625 
627  m_interpolatorConsumed = false;
628  m_interpolatorDistance = (Real) modemSampleRate / (Real) m_outputSampleRate;
629  m_interpolator.create(48, modemSampleRate, m_hiCutoff, 3.0);
630  m_modemSampleRate = modemSampleRate;
631 
632  if (getMessageQueueToGUI())
633  {
635  getMessageQueueToGUI()->push(cfg);
636  }
637  }
638 
639  // FreeDV object
640 
641  if (m_freeDV) {
642  freedv_close(m_freeDV);
643  }
644 
645  int fdv_mode = -1;
646 
647  switch(mode)
648  {
650  fdv_mode = FREEDV_MODE_700C;
651  m_scaleFactor = SDR_TX_SCALEF / 3.2f;
652  break;
654  fdv_mode = FREEDV_MODE_700D;
655  m_scaleFactor = SDR_TX_SCALEF / 3.2f;
656  break;
658  fdv_mode = FREEDV_MODE_800XA;
659  m_scaleFactor = SDR_TX_SCALEF / 8.2f;
660  break;
662  fdv_mode = FREEDV_MODE_1600;
663  m_scaleFactor = SDR_TX_SCALEF / 3.2f;
664  break;
666  default:
667  fdv_mode = FREEDV_MODE_2400A;
668  m_scaleFactor = SDR_TX_SCALEF / 8.2f;
669  break;
670  }
671 
672  if (fdv_mode == FREEDV_MODE_700D)
673  {
674  struct freedv_advanced adv;
675  adv.interleave_frames = 1;
676  m_freeDV = freedv_open_advanced(fdv_mode, &adv);
677  }
678  else
679  {
680  m_freeDV = freedv_open(fdv_mode);
681  }
682 
683  if (m_freeDV)
684  {
685  freedv_set_test_frames(m_freeDV, 0);
686  freedv_set_snr_squelch_thresh(m_freeDV, -100.0);
687  freedv_set_squelch_en(m_freeDV, 1);
688  freedv_set_clip(m_freeDV, 0);
689  freedv_set_tx_bpf(m_freeDV, 1);
690  freedv_set_ext_vco(m_freeDV, 0);
691 
692  freedv_set_callback_txt(m_freeDV, nullptr, nullptr, nullptr);
693  freedv_set_callback_protocol(m_freeDV, nullptr, nullptr, nullptr);
694  freedv_set_callback_data(m_freeDV, nullptr, nullptr, nullptr);
695 
696  int nSpeechSamples = freedv_get_n_speech_samples(m_freeDV);
697  int nNomModemSamples = freedv_get_n_nom_modem_samples(m_freeDV);
698  int Fs = freedv_get_modem_sample_rate(m_freeDV);
699  int Rs = freedv_get_modem_symbol_rate(m_freeDV);
700 
701  if (nSpeechSamples != m_nSpeechSamples)
702  {
703  if (m_speechIn) {
704  delete[] m_speechIn;
705  }
706 
707  m_speechIn = new int16_t[nSpeechSamples];
708  m_nSpeechSamples = nSpeechSamples;
709  }
710 
711  if (nNomModemSamples != m_nNomModemSamples)
712  {
713  if (m_modOut) {
714  delete[] m_modOut;
715  }
716 
717  m_modOut = new int16_t[nNomModemSamples];
718  m_nNomModemSamples = nNomModemSamples;
719  }
720 
721  m_iSpeech = 0;
722  m_iModem = 0;
723 
724  qDebug() << "FreeDVMod::applyFreeDVMode:"
725  << " fdv_mode: " << fdv_mode
726  << " m_modemSampleRate: " << m_modemSampleRate
727  << " m_lowCutoff: " << m_lowCutoff
728  << " m_hiCutoff: " << m_hiCutoff
729  << " Fs: " << Fs
730  << " Rs: " << Rs
731  << " m_nSpeechSamples: " << m_nSpeechSamples
732  << " m_nNomModemSamples: " << m_nNomModemSamples;
733  }
734 
735  m_settingsMutex.unlock();
736 }
737 
738 void FreeDVMod::applySettings(const FreeDVModSettings& settings, bool force)
739 {
740  QList<QString> reverseAPIKeys;
741 
742  if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
743  reverseAPIKeys.append("inputFrequencyOffset");
744  }
745  if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
746  reverseAPIKeys.append("toneFrequency");
747  }
748  if ((settings.m_volumeFactor != m_settings.m_volumeFactor) || force) {
749  reverseAPIKeys.append("volumeFactor");
750  }
751  if ((settings.m_spanLog2 != m_settings.m_spanLog2) || force) {
752  reverseAPIKeys.append("spanLog2");
753  }
754  if ((settings.m_audioMute != m_settings.m_audioMute) || force) {
755  reverseAPIKeys.append("audioMute");
756  }
757  if ((settings.m_playLoop != m_settings.m_playLoop) || force) {
758  reverseAPIKeys.append("playLoop");
759  }
760  if ((settings.m_playLoop != m_settings.m_gaugeInputElseModem) || force) {
761  reverseAPIKeys.append("gaugeInputElseModem");
762  }
763  if ((settings.m_rgbColor != m_settings.m_rgbColor) || force) {
764  reverseAPIKeys.append("rgbColor");
765  }
766  if ((settings.m_title != m_settings.m_title) || force) {
767  reverseAPIKeys.append("title");
768  }
769  if ((settings.m_freeDVMode != m_settings.m_freeDVMode) || force) {
770  reverseAPIKeys.append("freeDVMode");
771  }
772  if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) {
773  reverseAPIKeys.append("modAFInput");
774  }
775  if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) {
776  reverseAPIKeys.append("audioDeviceName");
777  }
778 
779  if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force)
780  {
781  m_settingsMutex.lock();
783  m_settingsMutex.unlock();
784  }
785 
786  if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
787  {
789  int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
790  audioDeviceManager->addAudioSource(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex);
791  uint32_t audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
792 
793  if (m_audioSampleRate != audioSampleRate) {
794  applyAudioSampleRate(audioSampleRate);
795  }
796  }
797 
798  if ((m_settings.m_freeDVMode != settings.m_freeDVMode) || force) {
799  applyFreeDVMode(settings.m_freeDVMode);
800  }
801 
802  if (settings.m_useReverseAPI)
803  {
804  bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
809  webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
810  }
811 
812  m_settings = settings;
813 }
814 
815 QByteArray FreeDVMod::serialize() const
816 {
817  return m_settings.serialize();
818 }
819 
820 bool FreeDVMod::deserialize(const QByteArray& data)
821 {
822  if (m_settings.deserialize(data))
823  {
826  return true;
827  }
828  else
829  {
833  return false;
834  }
835 }
836 
839  QString& errorMessage)
840 {
841  (void) errorMessage;
843  response.getFreeDvModSettings()->init();
845  return 200;
846 }
847 
849  bool force,
850  const QStringList& channelSettingsKeys,
852  QString& errorMessage)
853 {
854  (void) errorMessage;
855  FreeDVModSettings settings = m_settings;
856  bool frequencyOffsetChanged = false;
857 
858  if (channelSettingsKeys.contains("inputFrequencyOffset"))
859  {
861  frequencyOffsetChanged = true;
862  }
863  if (channelSettingsKeys.contains("toneFrequency")) {
864  settings.m_toneFrequency = response.getFreeDvModSettings()->getToneFrequency();
865  }
866  if (channelSettingsKeys.contains("volumeFactor")) {
867  settings.m_volumeFactor = response.getFreeDvModSettings()->getVolumeFactor();
868  }
869  if (channelSettingsKeys.contains("spanLog2")) {
870  settings.m_spanLog2 = response.getFreeDvModSettings()->getSpanLog2();
871  }
872  if (channelSettingsKeys.contains("audioMute")) {
873  settings.m_audioMute = response.getFreeDvModSettings()->getAudioMute() != 0;
874  }
875  if (channelSettingsKeys.contains("playLoop")) {
876  settings.m_playLoop = response.getFreeDvModSettings()->getPlayLoop() != 0;
877  }
878  if (channelSettingsKeys.contains("gaugeInputElseModem")) {
880  }
881  if (channelSettingsKeys.contains("rgbColor")) {
882  settings.m_rgbColor = response.getFreeDvModSettings()->getRgbColor();
883  }
884  if (channelSettingsKeys.contains("title")) {
885  settings.m_title = *response.getFreeDvModSettings()->getTitle();
886  }
887  if (channelSettingsKeys.contains("freeDVMode")) {
889  }
890  if (channelSettingsKeys.contains("modAFInput")) {
892  }
893  if (channelSettingsKeys.contains("audioDeviceName")) {
895  }
896  if (channelSettingsKeys.contains("useReverseAPI")) {
897  settings.m_useReverseAPI = response.getFreeDvModSettings()->getUseReverseApi() != 0;
898  }
899  if (channelSettingsKeys.contains("reverseAPIAddress")) {
901  }
902  if (channelSettingsKeys.contains("reverseAPIPort")) {
904  }
905  if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
907  }
908  if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
910  }
911 
912  if (channelSettingsKeys.contains("cwKeyer"))
913  {
914  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getFreeDvModSettings()->getCwKeyer();
915  CWKeyerSettings cwKeyerSettings = m_cwKeyer.getSettings();
916  m_cwKeyer.webapiSettingsPutPatch(channelSettingsKeys, cwKeyerSettings, apiCwKeyerSettings);
917 
918  CWKeyer::MsgConfigureCWKeyer *msgCwKeyer = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force);
919  m_cwKeyer.getInputMessageQueue()->push(msgCwKeyer);
920 
921  if (m_guiMessageQueue) // forward to GUI if any
922  {
923  CWKeyer::MsgConfigureCWKeyer *msgCwKeyerToGUI = CWKeyer::MsgConfigureCWKeyer::create(cwKeyerSettings, force);
924  m_guiMessageQueue->push(msgCwKeyerToGUI);
925  }
926  }
927 
928  if (frequencyOffsetChanged)
929  {
932  m_inputMessageQueue.push(msgChan);
933  }
934 
937 
938  if (m_guiMessageQueue) // forward to GUI if any
939  {
940  MsgConfigureFreeDVMod *msgToGUI = MsgConfigureFreeDVMod::create(settings, force);
941  m_guiMessageQueue->push(msgToGUI);
942  }
943 
944  webapiFormatChannelSettings(response, settings);
945 
946  return 200;
947 }
948 
951  QString& errorMessage)
952 {
953  (void) errorMessage;
955  response.getFreeDvModReport()->init();
956  webapiFormatChannelReport(response);
957  return 200;
958 }
959 
961 {
965  response.getFreeDvModSettings()->setSpanLog2(settings.m_spanLog2);
966  response.getFreeDvModSettings()->setAudioMute(settings.m_audioMute ? 1 : 0);
967  response.getFreeDvModSettings()->setPlayLoop(settings.m_playLoop ? 1 : 0);
968  response.getFreeDvModSettings()->setRgbColor(settings.m_rgbColor);
970 
971  if (response.getFreeDvModSettings()->getTitle()) {
972  *response.getFreeDvModSettings()->getTitle() = settings.m_title;
973  } else {
974  response.getFreeDvModSettings()->setTitle(new QString(settings.m_title));
975  }
976 
977  response.getFreeDvModSettings()->setModAfInput((int) settings.m_modAFInput);
978  response.getFreeDvModSettings()->setFreeDvMode((int) settings.m_freeDVMode);
979 
980  if (response.getFreeDvModSettings()->getAudioDeviceName()) {
982  } else {
983  response.getFreeDvModSettings()->setAudioDeviceName(new QString(settings.m_audioDeviceName));
984  }
985 
986  if (!response.getFreeDvModSettings()->getCwKeyer()) {
988  }
989 
990  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = response.getFreeDvModSettings()->getCwKeyer();
991  const CWKeyerSettings& cwKeyerSettings = m_cwKeyer.getSettings();
992  m_cwKeyer.webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
993 
994  response.getFreeDvModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
995 
996  if (response.getFreeDvModSettings()->getReverseApiAddress()) {
998  } else {
999  response.getFreeDvModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
1000  }
1001 
1005 }
1006 
1008 {
1012 }
1013 
1014 void FreeDVMod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const FreeDVModSettings& settings, bool force)
1015 {
1017  swgChannelSettings->setDirection(1); // single source (Tx)
1018  swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
1019  swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
1020  swgChannelSettings->setChannelType(new QString("FreeDVMod"));
1021  swgChannelSettings->setFreeDvModSettings(new SWGSDRangel::SWGFreeDVModSettings());
1022  SWGSDRangel::SWGFreeDVModSettings *swgFreeDVModSettings = swgChannelSettings->getFreeDvModSettings();
1023 
1024  // transfer data that has been modified. When force is on transfer all data except reverse API data
1025 
1026  if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
1027  swgFreeDVModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
1028  }
1029  if (channelSettingsKeys.contains("toneFrequency") || force) {
1030  swgFreeDVModSettings->setToneFrequency(settings.m_toneFrequency);
1031  }
1032  if (channelSettingsKeys.contains("volumeFactor") || force) {
1033  swgFreeDVModSettings->setVolumeFactor(settings.m_volumeFactor);
1034  }
1035  if (channelSettingsKeys.contains("spanLog2") || force) {
1036  swgFreeDVModSettings->setSpanLog2(settings.m_spanLog2);
1037  }
1038  if (channelSettingsKeys.contains("audioMute") || force) {
1039  swgFreeDVModSettings->setAudioMute(settings.m_audioMute ? 1 : 0);
1040  }
1041  if (channelSettingsKeys.contains("playLoop") || force) {
1042  swgFreeDVModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0);
1043  }
1044  if (channelSettingsKeys.contains("gaugeInputElseModem") || force) {
1045  swgFreeDVModSettings->setPlayLoop(settings.m_gaugeInputElseModem ? 1 : 0);
1046  }
1047  if (channelSettingsKeys.contains("rgbColor") || force) {
1048  swgFreeDVModSettings->setRgbColor(settings.m_rgbColor);
1049  }
1050  if (channelSettingsKeys.contains("title") || force) {
1051  swgFreeDVModSettings->setTitle(new QString(settings.m_title));
1052  }
1053  if (channelSettingsKeys.contains("freeDVMode") || force) {
1054  swgFreeDVModSettings->setFreeDvMode((int) settings.m_freeDVMode);
1055  }
1056  if (channelSettingsKeys.contains("modAFInput") || force) {
1057  swgFreeDVModSettings->setModAfInput((int) settings.m_modAFInput);
1058  }
1059  if (channelSettingsKeys.contains("audioDeviceName") || force) {
1060  swgFreeDVModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
1061  }
1062 
1063  if (force)
1064  {
1065  const CWKeyerSettings& cwKeyerSettings = m_cwKeyer.getSettings();
1066  swgFreeDVModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
1067  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgFreeDVModSettings->getCwKeyer();
1068  m_cwKeyer.webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
1069  }
1070 
1071  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1072  .arg(settings.m_reverseAPIAddress)
1073  .arg(settings.m_reverseAPIPort)
1074  .arg(settings.m_reverseAPIDeviceIndex)
1075  .arg(settings.m_reverseAPIChannelIndex);
1076  m_networkRequest.setUrl(QUrl(channelSettingsURL));
1077  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1078 
1079  QBuffer *buffer=new QBuffer();
1080  buffer->open((QBuffer::ReadWrite));
1081  buffer->write(swgChannelSettings->asJson().toUtf8());
1082  buffer->seek(0);
1083 
1084  // Always use PATCH to avoid passing reverse API settings
1085  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1086 
1087  delete swgChannelSettings;
1088 }
1089 
1091 {
1093  swgChannelSettings->setDirection(1); // single source (Tx)
1094  swgChannelSettings->setChannelType(new QString("FreeDVMod"));
1095  swgChannelSettings->setFreeDvModSettings(new SWGSDRangel::SWGFreeDVModSettings());
1096  SWGSDRangel::SWGFreeDVModSettings *swgFreeDVModSettings = swgChannelSettings->getFreeDvModSettings();
1097 
1098  swgFreeDVModSettings->setCwKeyer(new SWGSDRangel::SWGCWKeyerSettings());
1099  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings = swgFreeDVModSettings->getCwKeyer();
1100  m_cwKeyer.webapiFormatChannelSettings(apiCwKeyerSettings, cwKeyerSettings);
1101 
1102  QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1107  m_networkRequest.setUrl(QUrl(channelSettingsURL));
1108  m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
1109 
1110  QBuffer *buffer=new QBuffer();
1111  buffer->open((QBuffer::ReadWrite));
1112  buffer->write(swgChannelSettings->asJson().toUtf8());
1113  buffer->seek(0);
1114 
1115  // Always use PATCH to avoid passing reverse API settings
1116  m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
1117 
1118  delete swgChannelSettings;
1119 }
1120 
1121 void FreeDVMod::networkManagerFinished(QNetworkReply *reply)
1122 {
1123  QNetworkReply::NetworkError replyError = reply->error();
1124 
1125  if (replyError)
1126  {
1127  qWarning() << "FreeDVMod::networkManagerFinished:"
1128  << " error(" << (int) replyError
1129  << "): " << replyError
1130  << ": " << reply->errorString();
1131  return;
1132  }
1133 
1134  QString answer = reply->readAll();
1135  answer.chop(1); // remove last \n
1136  qDebug("FreeDVMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
1137 }
void setVolumeFactor(float volume_factor)
short int16_t
Definition: rtptypes_win.h:43
QNetworkRequest m_networkRequest
Definition: freedvmod.h:331
void setAudioDeviceName(QString *audio_device_name)
void setOriginatorChannelIndex(qint32 originator_channel_index)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const FreeDVModSettings &settings, bool force)
Definition: freedvmod.cpp:1014
void setUseReverseApi(qint32 use_reverse_api)
Real m_interpolatorDistance
Definition: freedvmod.h:294
virtual void start()
Definition: freedvmod.cpp:417
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
NCOF m_toneNco
Definition: freedvmod.h:291
bool decimate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:38
FreeDVMod(DeviceAPI *deviceAPI)
Definition: freedvmod.cpp:57
static MsgConfigureFreeDVMod * create(const FreeDVModSettings &settings, bool force)
Definition: freedvmod.h:62
uint16_t m_reverseAPIDeviceIndex
void push(Message *message, bool emitSignal=true)
Push message onto queue.
int m_inputSampleRate
speech (input) sample rate (fixed 8000 S/s)
Definition: freedvmod.h:323
void applyFreeDVMode(FreeDVModSettings::FreeDVMode mode)
Definition: freedvmod.cpp:610
quint32 m_audioSampleRate
Definition: freedvmod.h:312
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:181
static double dbPower(double magsq, double floor=1e-12)
Definition: db.cpp:22
const QString & getFileName() const
Definition: freedvmod.h:106
Real m_interpolatorDistanceRemain
Definition: freedvmod.h:295
CWKeyer m_cwKeyer
Definition: freedvmod.h:328
void setCwKeyer(SWGCWKeyerSettings *cw_keyer)
int getInputSampleRate(int inputDeviceIndex=-1)
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
void setFreeDvModReport(SWGFreeDVModReport *free_dv_mod_report)
int16_t * m_speechIn
Definition: freedvmod.h:338
void setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh, float gain=1.0f)
bool interpolate(Real *distance, const Complex &next, Complex *result)
Definition: interpolator.h:53
void setReverseApiPort(qint32 reverse_api_port)
void clear()
Definition: audiofifo.cpp:156
int m_nNomModemSamples
Definition: freedvmod.h:335
Real m_hiCutoff
Definition: freedvmod.h:287
int getDeviceSetIndex() const
Definition: channelapi.h:89
void setChannelSampleRate(qint32 channel_sample_rate)
void setDecimation(uint32_t decimation)
int m_iModem
Definition: freedvmod.h:337
AudioResampler m_audioResampler
Definition: freedvmod.h:341
static MsgConfigureCWKeyer * create(const CWKeyerSettings &settings, bool force)
Definition: cwkeyer.h:63
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
Definition: deviceapi.cpp:147
int m_SSBFilterBufferIndex
Definition: freedvmod.h:299
Complex m_modSample
Definition: freedvmod.h:292
QByteArray serialize() const
void networkManagerFinished(QNetworkReply *reply)
Definition: freedvmod.cpp:1121
void applySettings(const FreeDVModSettings &settings, bool force=false)
Definition: freedvmod.cpp:738
static int getLowCutoff(FreeDVMode freeDVMode)
void pullAF(Complex &sample)
Definition: freedvmod.cpp:203
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
Definition: freedvmod.cpp:1007
int m_inputFrequencyOffset
Definition: freedvmod.h:285
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
uint m_audioBufferFill
Definition: freedvmod.h:314
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: freedvmod.cpp:848
ThreadedBasebandSampleSource * m_threadedChannelizer
Definition: freedvmod.h:279
static const int m_ssbFftLen
Definition: freedvmod.h:300
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
Definition: freedvmod.cpp:837
const FreeDVModSettings & getSettings() const
Definition: freedvmod.h:59
static MsgReportFileSourceStreamData * create(int sampleRate, quint32 recordLength)
Definition: freedvmod.h:188
int m_undersampleCount
Definition: freedvmod.h:306
quint32 m_recordLength
record length in seconds computed from file size
Definition: freedvmod.h:322
static MsgReportFileSourceStreamTiming * create(std::size_t samplesCount)
Definition: freedvmod.h:167
int m_iSpeech
Definition: freedvmod.h:336
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
void addChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Add a channel source (Tx)
Definition: deviceapi.cpp:138
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
float m_scaleFactor
divide by this amount to scale from int16 to float in [-1.0, 1.0] interval
Definition: freedvmod.h:340
bool m_gaugeInputElseModem
Volume gauge shows speech input level else modem level.
bool m_interpolatorConsumed
Definition: freedvmod.h:296
void setReverseApiAddress(QString *reverse_api_address)
static int getHiCutoff(FreeDVMode freeDVMode)
std::complex< float > cmplx
Definition: fftfilt.h:21
void setGaugeInputElseModem(qint32 gauge_input_else_modem)
Complex nextIQ()
Return next complex sample.
Definition: ncof.cpp:63
unsigned int uint32_t
Definition: rtptypes_win.h:46
fftfilt::cmplx m_sum
Definition: freedvmod.h:305
void addAudioSource(AudioFifo *audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex=-1)
Add an audio source.
DeviceAPI * m_deviceAPI
Definition: freedvmod.h:278
void setToneFrequency(float tone_frequency)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
Definition: cwkeyer.h:104
FreeDVModSettings m_settings
Definition: freedvmod.h:288
void setPhase(Real phase)
Definition: ncof.h:42
#define SDR_TX_SCALEF
Definition: dsptypes.h:39
void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force=false)
Definition: freedvmod.cpp:580
double getMagSq() const
Definition: freedvmod.h:253
Interpolator m_interpolator
Definition: freedvmod.h:293
int m_outputSampleRate
Definition: freedvmod.h:283
void openFileStream()
Definition: freedvmod.cpp:530
virtual void stop()
Definition: freedvmod.cpp:426
std::ifstream m_ifstream
Definition: freedvmod.h:319
static const QString m_channelId
Definition: freedvmod.h:260
SWGFreeDVModSettings * getFreeDvModSettings()
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
bool getFadeSample(bool on, float &sample)
Definition: cwkeyer.cpp:487
void seekFileStream(int seekPercentage)
Definition: freedvmod.cpp:554
void create_filter(float f1, float f2)
Definition: fftfilt.cpp:107
static const int m_levelNbSamples
Definition: freedvmod.h:343
int getSampleRate() const
Definition: dspcommands.h:390
static DSPEngine * instance()
Definition: dspengine.cpp:51
CWSmoother & getCWSmoother()
Definition: cwkeyer.h:111
MovingAverageUtil< double, double, 16 > m_movingAverage
Definition: freedvmod.h:310
AudioVector m_audioBuffer
Definition: freedvmod.h:313
QMutex m_settingsMutex
Definition: freedvmod.h:317
QNetworkAccessManager * m_networkManager
Definition: freedvmod.h:330
AudioFifo m_audioFifo
Definition: freedvmod.h:315
FixReal m_real
Definition: dsptypes.h:64
int m_sumCount
Definition: freedvmod.h:307
static int getModSampleRate(FreeDVMode freeDVMode)
int32_t i
Definition: decimators.h:244
quint64 m_fileSize
raw file size (bytes)
Definition: freedvmod.h:321
void webapiReverseSendCWSettings(const CWKeyerSettings &settings)
Definition: freedvmod.cpp:1090
virtual void pullAudio(int nbSamples)
Definition: freedvmod.cpp:181
static bool match(const Message *message)
Definition: message.cpp:45
FreeDVModInputAF m_modAFInput
void setInputFrequencyOffset(qint64 input_frequency_offset)
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2283
void setChannelPowerDb(float channel_power_db)
void applyAudioSampleRate(int sampleRate)
Definition: freedvmod.cpp:567
SampleVector m_sampleBuffer
Definition: freedvmod.h:303
uint32_t read(quint8 *data, uint32_t numSamples)
Definition: audiofifo.cpp:103
void modulateSample()
Definition: freedvmod.cpp:194
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
Definition: freedvmod.cpp:949
virtual QString asJson() override
virtual void pull(Sample &sample)
Definition: freedvmod.cpp:142
void setFreeDvMode(qint32 free_dv_mode)
static void webapiFormatChannelSettings(SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings, const CWKeyerSettings &cwKeyerSettings)
Definition: cwkeyer.cpp:637
int getSample()
Definition: cwkeyer.cpp:194
double m_magsq
Definition: freedvmod.h:309
int16_t * m_modOut
Definition: freedvmod.h:339
struct freedv * m_freeDV
Definition: freedvmod.h:333
AudioDeviceManager * getAudioDeviceManager()
Definition: dspengine.h:55
bool deserialize(const QByteArray &data)
void setModAfInput(qint32 mod_af_input)
NCOF m_carrierNco
Definition: freedvmod.h:290
MessageQueue * getMessageQueueToGUI()
static void webapiSettingsPutPatch(const QStringList &channelSettingsKeys, CWKeyerSettings &cwKeyerSettings, SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings)
Definition: cwkeyer.cpp:599
SWGFreeDVModReport * getFreeDvModReport()
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
Definition: fftfilt.cpp:284
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
static MsgConfigureChannelizer * create(int sampleRate, int centerFrequency)
Definition: freedvmod.h:85
void setFreq(Real freq, Real sampleRate)
Definition: ncof.cpp:51
void calculateLevel(Complex &sample)
Definition: freedvmod.cpp:375
FixReal m_imag
Definition: dsptypes.h:65
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
Definition: freedvmod.cpp:430
int getInputDeviceIndex(const QString &deviceName) const
static const QString m_channelIdURI
Definition: freedvmod.h:259
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const FreeDVModSettings &settings)
Definition: freedvmod.cpp:960
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
Definition: deviceapi.cpp:174
virtual bool deserialize(const QByteArray &data)
Definition: freedvmod.cpp:820
virtual QByteArray serialize() const
Definition: freedvmod.cpp:815
int m_modemSampleRate
Definition: freedvmod.h:284
void reset()
Definition: cwkeyer.h:109
const CWKeyerSettings & getSettings() const
Definition: cwkeyer.h:107
uint16_t m_reverseAPIChannelIndex
QString m_fileName
Definition: freedvmod.h:320
int getIndexInDeviceSet() const
Definition: channelapi.h:87
Real next()
Return next real sample.
Definition: ncof.cpp:57
std::complex< Real > Complex
Definition: dsptypes.h:43
Real m_levelSum
Definition: freedvmod.h:327
double asDouble() const
Definition: movingaverage.h:57
fftfilt * m_SSBFilter
Definition: freedvmod.h:297
float Real
Definition: dsptypes.h:42
#define SDR_TX_SCALED
Definition: dsptypes.h:40
int m_basebandSampleRate
Definition: freedvmod.h:282
void setSampleRate(int sampleRate)
Definition: cwkeyer.cpp:186
Real m_lowCutoff
Definition: freedvmod.h:286
UpChannelizer * m_channelizer
Definition: freedvmod.h:280
qint16 FixReal
Definition: dsptypes.h:35
void setAudioSampleRate(qint32 audio_sample_rate)
T max(const T &x, const T &y)
Definition: framework.h:446
const CWKeyerSettings & getSettings() const
Definition: cwkeyer.h:60
void removeAudioSource(AudioFifo *audioFifo)
Remove an audio source.
int m_nSpeechSamples
Definition: freedvmod.h:334
bool downSample(qint16 sampleIn, qint16 &sampleOut)
BasebandSampleSink * m_sampleSink
Definition: freedvmod.h:302
Real m_peakLevel
Definition: freedvmod.h:326
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
Complex * m_SSBFilterBuffer
Definition: freedvmod.h:298
void setFreeDvModSettings(SWGFreeDVModSettings *free_dv_mod_settings)
quint32 m_levelCalcCount
Definition: freedvmod.h:325