22 #include <QNetworkAccessManager> 23 #include <QNetworkReply> 26 #include "codec2/freedv_api.h" 27 #include "codec2/modem_stats.h" 74 struct MODEM_STATS stats;
76 freedv_get_modem_extended_stats(freeDV, &stats);
135 m_sum = level * level;
136 m_peak = std::fabs(level);
142 m_sum += level * level;
143 m_peak =
std::max(m_peak, std::fabs(level));
227 bool audioFlipChannel,
233 int agcPowerThreshold,
234 int agcThresholdGate)
250 messageQueue->
push(cmd);
253 void FreeDVDemod::feed(
const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end,
bool positiveOnly)
263 unsigned char decim_mask = decim - 1;
265 for(SampleVector::const_iterator it = begin; it < end; ++it)
267 Complex c(it->real(), it->imag());
312 unsigned char decim_mask = decim - 1;
316 for (
int i = 0;
i < n_out;
i++)
344 Real demod = sideband[
i].real();
377 qDebug(
"FreeDVDemod::handleMessage: MsgChannelizerNotification: m_sampleRate");
386 qDebug() <<
"FreeDVDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.
getSampleRate()
398 qDebug(
"FreeDVDemod::handleMessage: MsgConfigureFreeDVDemod");
406 qDebug(
"FreeDVDemod::handleMessage: MsgResyncFreeDVDemod");
408 freedv_set_sync(
m_freeDV, FREEDV_SYNC_UNSYNC);
416 qDebug(
"FreeDVDemod::handleMessage: BasebandSampleSink::MsgThreadedSink: %p", thread);
424 qDebug() <<
"FreeDVDemod::handleMessage: DSPConfigureAudio:" 425 <<
" sampleRate: " << sampleRate;
479 for (
int i = 0;
i < nout;
i++)
507 qDebug(
"FreeDVDemod::pushSampleToAudio: %u/%u samples written", res,
m_audioBufferFill);
516 qDebug() <<
"FreeDVDemod::applyChannelSettings:" 517 <<
" inputSampleRate: " << inputSampleRate
518 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
541 qDebug(
"FreeDVDemod::applyAudioSampleRate: %d", sampleRate);
595 fdv_mode = FREEDV_MODE_700C;
598 fdv_mode = FREEDV_MODE_700D;
601 fdv_mode = FREEDV_MODE_800XA;
604 fdv_mode = FREEDV_MODE_1600;
608 fdv_mode = FREEDV_MODE_2400A;
612 if (fdv_mode == FREEDV_MODE_700D)
614 struct freedv_advanced adv;
615 adv.interleave_frames = 1;
616 m_freeDV = freedv_open_advanced(fdv_mode, &adv);
625 freedv_set_test_frames(
m_freeDV, 0);
626 freedv_set_snr_squelch_thresh(
m_freeDV, -100.0);
630 freedv_set_sync(
m_freeDV, FREEDV_SYNC_MANUAL);
632 freedv_set_callback_txt(
m_freeDV,
nullptr,
nullptr,
nullptr);
633 freedv_set_callback_protocol(
m_freeDV,
nullptr,
nullptr,
nullptr);
634 freedv_set_callback_data(
m_freeDV,
nullptr,
nullptr,
nullptr);
636 int nSpeechSamples = freedv_get_n_speech_samples(
m_freeDV);
637 int nMaxModemSamples = freedv_get_n_max_modem_samples(
m_freeDV);
638 int Fs = freedv_get_modem_sample_rate(
m_freeDV);
639 int Rs = freedv_get_modem_symbol_rate(
m_freeDV);
670 qDebug() <<
"FreeDVMod::applyFreeDVMode:" 671 <<
" fdv_mode: " << fdv_mode
679 <<
" m_nin: " <<
m_nin 688 qDebug() <<
"FreeDVDemod::applySettings:" 690 <<
" m_volume: " << settings.
m_volume 694 <<
" m_agcActive: " << settings.
m_agc 701 <<
" force: " << force;
703 QList<QString> reverseAPIKeys;
706 reverseAPIKeys.append(
"inputFrequencyOffset");
711 reverseAPIKeys.append(
"volume");
718 reverseAPIKeys.append(
"volumeIn");
723 reverseAPIKeys.append(
"audioDeviceName");
735 reverseAPIKeys.append(
"spanLog2");
738 reverseAPIKeys.append(
"audioMute");
741 reverseAPIKeys.append(
"agc");
806 QString& errorMessage)
817 const QStringList& channelSettingsKeys,
819 QString& errorMessage)
823 bool frequencyOffsetChanged =
false;
825 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
828 frequencyOffsetChanged =
true;
830 if (channelSettingsKeys.contains(
"freeDVMode")) {
833 if (channelSettingsKeys.contains(
"volume")) {
836 if (channelSettingsKeys.contains(
"volumeIn")) {
839 if (channelSettingsKeys.contains(
"spanLog2")) {
842 if (channelSettingsKeys.contains(
"audioMute")) {
845 if (channelSettingsKeys.contains(
"agc")) {
848 if (channelSettingsKeys.contains(
"rgbColor")) {
851 if (channelSettingsKeys.contains(
"title")) {
854 if (channelSettingsKeys.contains(
"audioDeviceName")) {
857 if (channelSettingsKeys.contains(
"useReverseAPI")) {
860 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
863 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
866 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
869 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
873 if (frequencyOffsetChanged)
883 qDebug(
"FreeDVDemod::webapiSettingsPutPatch: forward to GUI: %p",
m_guiMessageQueue);
897 QString& errorMessage)
945 double magsqAvg, magsqPeak;
967 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
970 if (channelSettingsKeys.contains(
"freeDVMode") || force) {
973 if (channelSettingsKeys.contains(
"volume") || force) {
976 if (channelSettingsKeys.contains(
"volumeIn") || force) {
979 if (channelSettingsKeys.contains(
"spanLog2") || force) {
982 if (channelSettingsKeys.contains(
"audioMute") || force) {
985 if (channelSettingsKeys.contains(
"agc") || force) {
986 swgFreeDVDemodSettings->
setAgc(settings.
m_agc ? 1 : 0);
988 if (channelSettingsKeys.contains(
"rgbColor") || force) {
991 if (channelSettingsKeys.contains(
"title") || force) {
994 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
998 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1004 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1006 QBuffer *buffer=
new QBuffer();
1007 buffer->open((QBuffer::ReadWrite));
1008 buffer->write(swgChannelSettings->
asJson().toUtf8());
1014 delete swgChannelSettings;
1019 QNetworkReply::NetworkError replyError = reply->error();
1023 qWarning() <<
"FreeDVDemod::networkManagerFinished:" 1024 <<
" error(" << (int) replyError
1025 <<
"): " << replyError
1026 <<
": " << reply->errorString();
1030 QString answer = reply->readAll();
1032 qDebug(
"FreeDVDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setTitle(QString *title)
void setOriginatorChannelIndex(qint32 originator_channel_index)
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
const QThread * getThread() const
void setAudioDeviceName(QString *audio_device_name)
Interpolator m_interpolator
int getOutputSampleRate(int outputDeviceIndex=-1)
void getSNRLevels(double &avg, double &peak, int &nbSamples)
bool decimate(Real *distance, const Complex &next, Complex *result)
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void configure(MessageQueue *messageQueue, Real Bandwidth, Real LowCutoff, Real volume, int spanLog2, bool audioBinaural, bool audioFlipChannels, bool dsb, bool audioMute, bool agc, bool agcClamping, int agcTimeLog2, int agcPowerThreshold, int agcThresholdGate)
bool upSample(qint16 sampleIn, qint16 &sampleOut)
virtual bool deserialize(const QByteArray &data)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
QString * getReverseApiAddress()
void setAudioMute(qint32 audio_mute)
void pushSampleToAudio(int16_t sample)
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
static double dbPower(double magsq, double floor=1e-12)
void levelInChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
AudioResampler m_audioResampler
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
void setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh, float gain=1.0f)
uint16_t m_reverseAPIDeviceIndex
bool interpolate(Real *distance, const Complex &next, Complex *result)
FreeDVStats m_freeDVStats
void setRgbColor(qint32 rgb_color)
QString * getAudioDeviceName()
void pushSampleToDV(int16_t sample)
int getDeviceSetIndex() const
void setDecimation(uint32_t decimation)
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
int getOutputDeviceIndex(const QString &deviceName) const
uint32_t getDecimation() const
void applyAudioSampleRate(int sampleRate)
void applySettings(const FreeDVDemodSettings &settings, bool force=false)
static const QString m_channelId
int getSampleRate() const
void setVolume(float volume)
int m_ber
estimated BER (b/s)
BasebandSampleSink * m_sampleSink
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
AudioVector m_audioBuffer
uint32_t m_modemSampleRate
std::complex< float > cmplx
void collect(struct freedv *freedv)
FreeDVDemod(DeviceAPI *deviceAPI)
static const QString m_channelIdURI
qint32 getReverseApiPort()
void setChannelPowerDb(float channel_power_db)
QNetworkAccessManager * m_networkManager
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
DoubleBufferFIFO< fftfilt::cmplx > m_squelchDelayLine
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
std::complex< float > cmplx
Complex nextIQ()
Return next complex sample.
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
void setFreeDvMode(qint32 free_dv_mode)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const FreeDVDemodSettings &settings)
FreeDVDemodSettings m_settings
uint32_t m_audioSampleRate
QString m_reverseAPIAddress
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
ThreadedBasebandSampleSink * m_threadedChannelizer
virtual bool handleMessage(const Message &cmd)=0
Processing of a message. Returns true if message has actually been processed.
Real m_interpolatorDistanceRemain
void applyFreeDVMode(FreeDVDemodSettings::FreeDVMode mode)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
void create_filter(float f1, float f2)
void setVolumeIn(float volume_in)
static DSPEngine * instance()
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
bool m_audioActive
True if an audio signal is produced (no AGC or AGC and above threshold)
void setReverseApiPort(qint32 reverse_api_port)
QString m_audioDeviceName
bool deserialize(const QByteArray &data)
qint32 getReverseApiDeviceIndex()
static bool match(const Message *message)
Real m_interpolatorDistance
uint32_t m_berFrameCount
count of frames for BER estimation
int m_inputFrequencyOffset
uint16_t m_reverseAPIPort
void setInputFrequencyOffset(qint64 input_frequency_offset)
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
void setReverseApiAddress(QString *reverse_api_address)
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
QNetworkRequest m_networkRequest
void setAudioSampleRate(qint32 audio_sample_rate)
void setDirection(qint32 direction)
MessageQueue * getMessageQueueToGUI()
void accumulate(float snrdB)
void setSpanLog2(qint32 span_log2)
virtual QString asJson() override
uint32_t m_speechSampleRate
Exposes a single sink stream (input, Rx)
void setSquelch(qint32 squelch)
void setFreeDvDemodReport(SWGFreeDVDemodReport *free_dv_demod_report)
AudioDeviceManager * getAudioDeviceManager()
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
qint32 getUseReverseApi()
bool setSize(uint32_t numSamples)
void setFreeDvDemodSettings(SWGFreeDVDemodSettings *free_dv_demod_settings)
void resizeNew(uint32_t newSize, Real initial, Real cutoff=0, Real clip=0)
SWGFreeDVDemodSettings * getFreeDvDemodSettings()
virtual QByteArray serialize() const
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
void setFreq(Real freq, Real sampleRate)
uint32_t m_fps
frames per second
QByteArray serialize() const
uint16_t m_reverseAPIChannelIndex
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
qint32 m_inputFrequencyOffset
SimpleAGC< 4800 > m_simpleAGC
void setUseReverseApi(qint32 use_reverse_api)
qint32 getReverseApiChannelIndex()
static int getHiCutoff(FreeDVMode freeDVMode)
int getIndexInDeviceSet() const
void accumulate(float fsample)
std::complex< Real > Complex
void setChannelSampleRate(qint32 channel_sample_rate)
SampleVector m_sampleBuffer
qint64 getFrequencyOffset() const
void processOneSample(Complex &ci)
static double powerFromdB(double powerdB)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)
static int getLowCutoff(FreeDVMode freeDVMode)
void networkManagerFinished(QNetworkReply *reply)
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
T max(const T &x, const T &y)
uint32_t write(const quint8 *data, uint32_t numSamples)
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
static int getModSampleRate(FreeDVMode freeDVMode)
SWGFreeDVDemodReport * getFreeDvDemodReport()
qint64 getInputFrequencyOffset()
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const FreeDVDemodSettings &settings, bool force)
DownChannelizer * m_channelizer