22 #include <QMutexLocker> 23 #include <QNetworkAccessManager> 24 #include <QNetworkReply> 31 #include "codec2/freedv_api.h" 59 m_deviceAPI(deviceAPI),
60 m_basebandSampleRate(48000),
61 m_outputSampleRate(48000),
62 m_modemSampleRate(48000),
63 m_inputFrequencyOffset(0),
68 m_SSBFilterBufferIndex(0),
71 m_settingsMutex(QMutex::Recursive),
74 m_inputSampleRate(8000),
80 m_nNomModemSamples(0),
172 double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
217 unsigned char decim_mask = decim - 1;
347 for (
int i = 0;
i < n_out;
i++)
377 Real t = sample.real();
435 qDebug() <<
"FreeDVMod::handleMessage: MsgChannelizerNotification";
444 qDebug() <<
"FreeDVMod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.
getSampleRate()
456 qDebug() <<
"FreeDVMod::handleMessage: MsgConfigureFreeDVMod";
479 std::size_t samplesCount;
511 qDebug() <<
"FreeDVMod::handleMessage: DSPConfigureAudio:" 512 <<
" sampleRate: " << sampleRate;
542 qDebug() <<
"FreeDVMod::openFileStream: " <<
m_fileName.toStdString().c_str()
561 seekPoint *=
sizeof(
Real);
569 qDebug(
"FreeDVMod::applyAudioSampleRate: %d", sampleRate);
582 qDebug() <<
"FreeDVMod::applyChannelSettings:" 583 <<
" basebandSampleRate: " << basebandSampleRate
584 <<
" outputSampleRate: " << outputSampleRate
585 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
650 fdv_mode = FREEDV_MODE_700C;
654 fdv_mode = FREEDV_MODE_700D;
658 fdv_mode = FREEDV_MODE_800XA;
662 fdv_mode = FREEDV_MODE_1600;
667 fdv_mode = FREEDV_MODE_2400A;
672 if (fdv_mode == FREEDV_MODE_700D)
674 struct freedv_advanced adv;
675 adv.interleave_frames = 1;
676 m_freeDV = freedv_open_advanced(fdv_mode, &adv);
685 freedv_set_test_frames(
m_freeDV, 0);
686 freedv_set_snr_squelch_thresh(
m_freeDV, -100.0);
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);
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);
724 qDebug() <<
"FreeDVMod::applyFreeDVMode:" 725 <<
" fdv_mode: " << fdv_mode
740 QList<QString> reverseAPIKeys;
743 reverseAPIKeys.append(
"inputFrequencyOffset");
746 reverseAPIKeys.append(
"toneFrequency");
749 reverseAPIKeys.append(
"volumeFactor");
752 reverseAPIKeys.append(
"spanLog2");
755 reverseAPIKeys.append(
"audioMute");
758 reverseAPIKeys.append(
"playLoop");
761 reverseAPIKeys.append(
"gaugeInputElseModem");
764 reverseAPIKeys.append(
"rgbColor");
767 reverseAPIKeys.append(
"title");
770 reverseAPIKeys.append(
"freeDVMode");
773 reverseAPIKeys.append(
"modAFInput");
776 reverseAPIKeys.append(
"audioDeviceName");
839 QString& errorMessage)
850 const QStringList& channelSettingsKeys,
852 QString& errorMessage)
856 bool frequencyOffsetChanged =
false;
858 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
861 frequencyOffsetChanged =
true;
863 if (channelSettingsKeys.contains(
"toneFrequency")) {
866 if (channelSettingsKeys.contains(
"volumeFactor")) {
869 if (channelSettingsKeys.contains(
"spanLog2")) {
872 if (channelSettingsKeys.contains(
"audioMute")) {
875 if (channelSettingsKeys.contains(
"playLoop")) {
878 if (channelSettingsKeys.contains(
"gaugeInputElseModem")) {
881 if (channelSettingsKeys.contains(
"rgbColor")) {
884 if (channelSettingsKeys.contains(
"title")) {
887 if (channelSettingsKeys.contains(
"freeDVMode")) {
890 if (channelSettingsKeys.contains(
"modAFInput")) {
893 if (channelSettingsKeys.contains(
"audioDeviceName")) {
896 if (channelSettingsKeys.contains(
"useReverseAPI")) {
899 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
902 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
905 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
908 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
912 if (channelSettingsKeys.contains(
"cwKeyer"))
928 if (frequencyOffsetChanged)
951 QString& errorMessage)
1026 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
1029 if (channelSettingsKeys.contains(
"toneFrequency") || force) {
1032 if (channelSettingsKeys.contains(
"volumeFactor") || force) {
1035 if (channelSettingsKeys.contains(
"spanLog2") || force) {
1038 if (channelSettingsKeys.contains(
"audioMute") || force) {
1041 if (channelSettingsKeys.contains(
"playLoop") || force) {
1044 if (channelSettingsKeys.contains(
"gaugeInputElseModem") || force) {
1047 if (channelSettingsKeys.contains(
"rgbColor") || force) {
1050 if (channelSettingsKeys.contains(
"title") || force) {
1053 if (channelSettingsKeys.contains(
"freeDVMode") || force) {
1056 if (channelSettingsKeys.contains(
"modAFInput") || force) {
1059 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
1071 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1077 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1079 QBuffer *buffer=
new QBuffer();
1080 buffer->open((QBuffer::ReadWrite));
1081 buffer->write(swgChannelSettings->
asJson().toUtf8());
1087 delete swgChannelSettings;
1102 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1108 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1110 QBuffer *buffer=
new QBuffer();
1111 buffer->open((QBuffer::ReadWrite));
1112 buffer->write(swgChannelSettings->
asJson().toUtf8());
1118 delete swgChannelSettings;
1123 QNetworkReply::NetworkError replyError = reply->error();
1127 qWarning() <<
"FreeDVMod::networkManagerFinished:" 1128 <<
" error(" << (int) replyError
1129 <<
"): " << replyError
1130 <<
": " << reply->errorString();
1134 QString answer = reply->readAll();
1136 qDebug(
"FreeDVMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setVolumeFactor(float volume_factor)
QNetworkRequest m_networkRequest
void setAudioDeviceName(QString *audio_device_name)
qint32 getReverseApiPort()
void setOriginatorChannelIndex(qint32 originator_channel_index)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const FreeDVModSettings &settings, bool force)
void setUseReverseApi(qint32 use_reverse_api)
Real m_interpolatorDistance
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
bool decimate(Real *distance, const Complex &next, Complex *result)
FreeDVMod(DeviceAPI *deviceAPI)
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)
void applyFreeDVMode(FreeDVModSettings::FreeDVMode mode)
quint32 m_audioSampleRate
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
qint64 getInputFrequencyOffset()
static double dbPower(double magsq, double floor=1e-12)
Real m_interpolatorDistanceRemain
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)
void setAudioFilters(int srHigh, int srLow, int fcLow, int fcHigh, float gain=1.0f)
bool interpolate(Real *distance, const Complex &next, Complex *result)
void setReverseApiPort(qint32 reverse_api_port)
int getDeviceSetIndex() const
void setChannelSampleRate(qint32 channel_sample_rate)
void setDecimation(uint32_t decimation)
AudioResampler m_audioResampler
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
QString m_audioDeviceName
int m_SSBFilterBufferIndex
QByteArray serialize() const
void networkManagerFinished(QNetworkReply *reply)
void applySettings(const FreeDVModSettings &settings, bool force=false)
static int getLowCutoff(FreeDVMode freeDVMode)
void pullAF(Complex &sample)
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
int m_inputFrequencyOffset
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
ThreadedBasebandSampleSource * m_threadedChannelizer
static const int m_ssbFftLen
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
qint32 getUseReverseApi()
static MsgReportFileSourceStreamData * create(int sampleRate, quint32 recordLength)
qint32 getReverseApiDeviceIndex()
quint32 m_recordLength
record length in seconds computed from file size
static MsgReportFileSourceStreamTiming * create(std::size_t samplesCount)
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)
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
void setSpanLog2(qint32 span_log2)
float m_scaleFactor
divide by this amount to scale from int16 to float in [-1.0, 1.0] interval
bool m_gaugeInputElseModem
Volume gauge shows speech input level else modem level.
bool m_interpolatorConsumed
void setReverseApiAddress(QString *reverse_api_address)
static int getHiCutoff(FreeDVMode freeDVMode)
std::complex< float > cmplx
void setGaugeInputElseModem(qint32 gauge_input_else_modem)
Complex nextIQ()
Return next complex sample.
void addAudioSource(AudioFifo *audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex=-1)
Add an audio source.
void setToneFrequency(float tone_frequency)
qint32 getReverseApiChannelIndex()
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
FreeDVModSettings m_settings
void setPhase(Real phase)
void setAudioMute(qint32 audio_mute)
void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force=false)
Interpolator m_interpolator
void setTitle(QString *title)
static const QString m_channelId
QString * getReverseApiAddress()
SWGFreeDVModSettings * getFreeDvModSettings()
int getBasebandSampleRate() const
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
bool getFadeSample(bool on, float &sample)
void seekFileStream(int seekPercentage)
void create_filter(float f1, float f2)
static const int m_levelNbSamples
static DSPEngine * instance()
CWSmoother & getCWSmoother()
MovingAverageUtil< double, double, 16 > m_movingAverage
AudioVector m_audioBuffer
QNetworkAccessManager * m_networkManager
static int getModSampleRate(FreeDVMode freeDVMode)
quint64 m_fileSize
raw file size (bytes)
void setRgbColor(qint32 rgb_color)
void webapiReverseSendCWSettings(const CWKeyerSettings &settings)
virtual void pullAudio(int nbSamples)
static bool match(const Message *message)
FreeDVModInputAF m_modAFInput
void setInputFrequencyOffset(qint64 input_frequency_offset)
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
void setChannelPowerDb(float channel_power_db)
void applyAudioSampleRate(int sampleRate)
SampleVector m_sampleBuffer
void setDirection(qint32 direction)
uint32_t read(quint8 *data, uint32_t numSamples)
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void setPlayLoop(qint32 play_loop)
virtual QString asJson() override
virtual void pull(Sample &sample)
void setFreeDvMode(qint32 free_dv_mode)
static void webapiFormatChannelSettings(SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings, const CWKeyerSettings &cwKeyerSettings)
AudioDeviceManager * getAudioDeviceManager()
bool deserialize(const QByteArray &data)
void setModAfInput(qint32 mod_af_input)
qint64 getFrequencyOffset() const
MessageQueue * getMessageQueueToGUI()
static void webapiSettingsPutPatch(const QStringList &channelSettingsKeys, CWKeyerSettings &cwKeyerSettings, SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings)
SWGFreeDVModReport * getFreeDvModReport()
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
void setFreq(Real freq, Real sampleRate)
void calculateLevel(Complex &sample)
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
int getInputDeviceIndex(const QString &deviceName) const
static const QString m_channelIdURI
int getSampleRate() const
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const FreeDVModSettings &settings)
QString m_reverseAPIAddress
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
virtual bool deserialize(const QByteArray &data)
qint32 getGaugeInputElseModem()
virtual QByteArray serialize() const
qint64 m_inputFrequencyOffset
const CWKeyerSettings & getSettings() const
uint16_t m_reverseAPIChannelIndex
int getIndexInDeviceSet() const
Real next()
Return next real sample.
std::complex< Real > Complex
SWGCWKeyerSettings * getCwKeyer()
void setSampleRate(int sampleRate)
QString * getAudioDeviceName()
UpChannelizer * m_channelizer
void setAudioSampleRate(qint32 audio_sample_rate)
T max(const T &x, const T &y)
void removeAudioSource(AudioFifo *audioFifo)
Remove an audio source.
bool downSample(qint16 sampleIn, qint16 &sampleOut)
uint16_t m_reverseAPIPort
BasebandSampleSink * m_sampleSink
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
Complex * m_SSBFilterBuffer
void setFreeDvModSettings(SWGFreeDVModSettings *free_dv_mod_settings)