25 #include <QNetworkAccessManager> 26 #include <QNetworkReply> 53 m_deviceAPI(deviceAPI),
54 m_audioBinaual(false),
55 m_audioFlipChannels(false),
61 m_agcNbSamples(12000),
62 m_agcPowerThreshold(1e-2),
63 m_agcThresholdGate(0),
64 m_squelchDelayLine(2*48000),
68 m_settingsMutex(QMutex::Recursive)
131 bool audioFlipChannel,
137 int agcPowerThreshold,
138 int agcThresholdGate)
154 messageQueue->
push(cmd);
157 void SSBDemod::feed(
const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end,
bool positiveOnly)
163 for(SampleVector::const_iterator it = begin; it < end; ++it)
165 Complex c(it->real(), it->imag());
194 unsigned char decim_mask = decim - 1;
202 for (
int i = 0;
i < n_out;
i++)
266 Real demod = (z.real() + z.imag()) * 0.7;
267 qint16 sample = (qint16)(demod *
m_volume);
320 qDebug(
"SSBDemod::handleMessage: MsgChannelizerNotification: m_sampleRate");
329 qDebug() <<
"SSBDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.
getSampleRate()
341 qDebug(
"SSBDemod::handleMessage: MsgConfigureSSBDemod");
351 qDebug(
"SSBDemod::handleMessage: BasebandSampleSink::MsgThreadedSink: %p", thread);
359 qDebug() <<
"SSBDemod::handleMessage: DSPConfigureAudio:" 360 <<
" sampleRate: " << sampleRate;
387 qDebug() <<
"SSBDemod::applyChannelSettings:" 388 <<
" inputSampleRate: " << inputSampleRate
389 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
413 qDebug(
"SSBDemod::applyAudioSampleRate: %d", sampleRate);
460 qDebug() <<
"SSBDemod::applySettings:" 464 <<
" m_volume: " << settings.
m_volume 468 <<
" m_dsb: " << settings.
m_dsb 470 <<
" m_agcActive: " << settings.
m_agc 481 <<
" force: " << force;
483 QList<QString> reverseAPIKeys;
486 reverseAPIKeys.append(
"inputFrequencyOffset");
489 reverseAPIKeys.append(
"rfBandwidth");
492 reverseAPIKeys.append(
"lowCutoff");
498 float band, lowCutoff;
505 lowCutoff = -lowCutoff;
532 reverseAPIKeys.append(
"volume");
538 reverseAPIKeys.append(
"agcTimeLog2");
541 reverseAPIKeys.append(
"agcPowerThreshold");
544 reverseAPIKeys.append(
"agcThresholdGate");
547 reverseAPIKeys.append(
"agcClamping");
588 qDebug() <<
"SBDemod::applySettings: AGC:" 589 <<
" agcNbSamples: " << agcNbSamples
590 <<
" agcPowerThreshold: " << agcPowerThreshold
591 <<
" agcThresholdGate: " << agcThresholdGate
592 <<
" agcClamping: " << agcClamping;
597 reverseAPIKeys.append(
"audioDeviceName");
609 reverseAPIKeys.append(
"spanLog2");
612 reverseAPIKeys.append(
"audioBinaural");
615 reverseAPIKeys.append(
"audioFlipChannels");
618 reverseAPIKeys.append(
"dsb");
621 reverseAPIKeys.append(
"audioMute");
624 reverseAPIKeys.append(
"agc");
671 QString& errorMessage)
682 const QStringList& channelSettingsKeys,
684 QString& errorMessage)
688 bool frequencyOffsetChanged =
false;
690 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
693 frequencyOffsetChanged =
true;
695 if (channelSettingsKeys.contains(
"rfBandwidth")) {
698 if (channelSettingsKeys.contains(
"lowCutoff")) {
701 if (channelSettingsKeys.contains(
"volume")) {
704 if (channelSettingsKeys.contains(
"spanLog2")) {
707 if (channelSettingsKeys.contains(
"audioBinaural")) {
710 if (channelSettingsKeys.contains(
"audioFlipChannels")) {
713 if (channelSettingsKeys.contains(
"dsb")) {
716 if (channelSettingsKeys.contains(
"audioMute")) {
719 if (channelSettingsKeys.contains(
"agc")) {
722 if (channelSettingsKeys.contains(
"agcClamping")) {
725 if (channelSettingsKeys.contains(
"agcTimeLog2")) {
728 if (channelSettingsKeys.contains(
"agcPowerThreshold")) {
731 if (channelSettingsKeys.contains(
"agcThresholdGate")) {
734 if (channelSettingsKeys.contains(
"rgbColor")) {
737 if (channelSettingsKeys.contains(
"title")) {
740 if (channelSettingsKeys.contains(
"audioDeviceName")) {
743 if (channelSettingsKeys.contains(
"useReverseAPI")) {
746 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
749 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
752 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
755 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
759 if (frequencyOffsetChanged)
769 qDebug(
"SSBDemod::webapiSettingsPutPatch: forward to GUI: %p",
m_guiMessageQueue);
783 QString& errorMessage)
838 double magsqAvg, magsqPeak;
860 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
863 if (channelSettingsKeys.contains(
"rfBandwidth") || force) {
866 if (channelSettingsKeys.contains(
"lowCutoff") || force) {
869 if (channelSettingsKeys.contains(
"volume") || force) {
872 if (channelSettingsKeys.contains(
"spanLog2") || force) {
875 if (channelSettingsKeys.contains(
"audioBinaural") || force) {
878 if (channelSettingsKeys.contains(
"audioFlipChannels") || force) {
881 if (channelSettingsKeys.contains(
"dsb") || force) {
882 swgSSBDemodSettings->
setDsb(settings.
m_dsb ? 1 : 0);
884 if (channelSettingsKeys.contains(
"audioMute") || force) {
887 if (channelSettingsKeys.contains(
"agc") || force) {
888 swgSSBDemodSettings->
setAgc(settings.
m_agc ? 1 : 0);
890 if (channelSettingsKeys.contains(
"agcClamping") || force) {
893 if (channelSettingsKeys.contains(
"agcTimeLog2") || force) {
896 if (channelSettingsKeys.contains(
"agcPowerThreshold") || force) {
899 if (channelSettingsKeys.contains(
"agcThresholdGate") || force) {
902 if (channelSettingsKeys.contains(
"rgbColor") || force) {
905 if (channelSettingsKeys.contains(
"title") || force) {
908 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
912 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
918 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
920 QBuffer *buffer=
new QBuffer();
921 buffer->open((QBuffer::ReadWrite));
922 buffer->write(swgChannelSettings->
asJson().toUtf8());
928 delete swgChannelSettings;
933 QNetworkReply::NetworkError replyError = reply->error();
937 qWarning() <<
"SSBDemod::networkManagerFinished:" 938 <<
" error(" << (int) replyError
939 <<
"): " << replyError
940 <<
": " << reply->errorString();
944 QString answer = reply->readAll();
946 qDebug(
"SSBDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const SSBDemodSettings &settings, bool force)
qint32 getAgcThresholdGate()
void setOriginatorChannelIndex(qint32 originator_channel_index)
qint32 getAgcPowerThreshold()
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
void setSsbDemodSettings(SWGSSBDemodSettings *ssb_demod_settings)
const QThread * getThread() const
static const QString m_channelId
int getOutputSampleRate(int outputDeviceIndex=-1)
void setInputFrequencyOffset(qint64 input_frequency_offset)
int m_agcThresholdGate
Gate length in number of samples befor threshold triggers.
bool decimate(Real *distance, const Complex &next, Complex *result)
SWGSSBDemodReport * getSsbDemodReport()
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void setSpanLog2(qint32 span_log2)
uint16_t m_reverseAPIPort
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setAudioBinaural(qint32 audio_binaural)
void setSsbDemodReport(SWGSSBDemodReport *ssb_demod_report)
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setThresholdEnable(bool enable)
static double dbPower(double magsq, double floor=1e-12)
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
bool interpolate(Real *distance, const Complex &next, Complex *result)
Real m_interpolatorDistance
void setLowCutoff(float low_cutoff)
qint32 getAudioBinaural()
int getDeviceSetIndex() const
void setAudioSampleRate(qint32 audio_sample_rate)
int getOutputDeviceIndex(const QString &deviceName) const
void setRgbColor(qint32 rgb_color)
QString * getReverseApiAddress()
int getSampleRate() const
void setAgcClamping(qint32 agc_clamping)
QString * getAudioDeviceName()
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
qint32 getReverseApiDeviceIndex()
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
static const QString m_channelIdURI
QString m_audioDeviceName
static const int m_minPowerThresholdDB
QByteArray serialize() const
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
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)
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
void setAudioDeviceName(QString *audio_device_name)
double feedAndGetValue(const Complex &ci)
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
std::complex< float > cmplx
void write(const T &element)
void setSquelch(qint32 squelch)
Complex nextIQ()
Return next complex sample.
bool deserialize(const QByteArray &data)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void networkManagerFinished(QNetworkReply *reply)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const SSBDemodSettings &settings)
BasebandSampleSink * m_sampleSink
void applyAudioSampleRate(int sampleRate)
void setAgcThresholdGate(qint32 agc_threshold_gate)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
virtual bool handleMessage(const Message &cmd)=0
Processing of a message. Returns true if message has actually been processed.
void resize(int historySize, int stepLength, Real R)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
void create_filter(float f1, float f2)
static DSPEngine * instance()
qint32 getReverseApiPort()
void setVolume(float volume)
qint64 getInputFrequencyOffset()
SSBDemod(DeviceAPI *deviceAPI)
void setClampMax(double clampMax)
void setAgcPowerThreshold(qint32 agc_power_threshold)
static bool match(const Message *message)
qint32 getReverseApiChannelIndex()
void setRfBandwidth(float rf_bandwidth)
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
int m_agcNbSamples
number of audio (48 kHz) samples for AGC averaging
int m_inputFrequencyOffset
bool m_audioActive
True if an audio signal is produced (no AGC or AGC and above threshold)
void setDirection(qint32 direction)
void setChannelSampleRate(qint32 channel_sample_rate)
DoubleBufferFIFO< fftfilt::cmplx > m_squelchDelayLine
virtual QString asJson() override
uint16_t m_reverseAPIDeviceIndex
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)
qint32 getUseReverseApi()
virtual bool deserialize(const QByteArray &data)
SSBDemodSettings m_settings
AudioVector m_audioBuffer
DownChannelizer * m_channelizer
qint32 getAudioFlipChannels()
int getStepDownDelay() const
AudioDeviceManager * getAudioDeviceManager()
uint16_t m_reverseAPIChannelIndex
qint32 m_inputFrequencyOffset
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
SWGSSBDemodSettings * getSsbDemodSettings()
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void setUseReverseApi(qint32 use_reverse_api)
bool setSize(uint32_t numSamples)
void applySettings(const SSBDemodSettings &settings, bool force=false)
void setAudioFlipChannels(qint32 audio_flip_channels)
ThreadedBasebandSampleSink * m_threadedChannelizer
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
void setFreq(Real freq, Real sampleRate)
double m_agcPowerThreshold
AGC power threshold (linear)
SampleVector m_sampleBuffer
QString m_reverseAPIAddress
void setClamping(bool clamping)
QNetworkAccessManager * m_networkManager
void setThreshold(double threshold)
void setStepDownDelay(int stepDownDelay)
void setAgcTimeLog2(qint32 agc_time_log2)
void setReverseApiAddress(QString *reverse_api_address)
quint32 m_audioSampleRate
void processOneSample(Complex &ci)
int getIndexInDeviceSet() const
float getStepValue() const
std::complex< Real > Complex
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
qint64 getFrequencyOffset() const
Real m_interpolatorDistanceRemain
int runDSB(const cmplx &in, cmplx **out, bool getDC=true)
void setAudioMute(qint32 audio_mute)
static double powerFromdB(double powerdB)
void setChannelPowerDb(float channel_power_db)
void setReverseApiPort(qint32 reverse_api_port)
uint32_t write(const quint8 *data, uint32_t numSamples)
void create_dsb_filter(float f2)
void setTitle(QString *title)
Interpolator m_interpolator
QNetworkRequest m_networkRequest
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)
virtual QByteArray serialize() const