19 #include "boost/format.hpp" 25 #include <QNetworkAccessManager> 26 #include <QNetworkReply> 57 m_deviceAPI(deviceAPI),
58 m_inputSampleRate(384000),
59 m_inputFrequencyOffset(0),
61 m_settingsMutex(QMutex::Recursive),
62 m_pilotPLL(19000/384000, 50/384000, 0.01),
63 m_deemphasisFilterX(default_deemphasis * 48000 * 1.0e-6),
64 m_deemphasisFilterY(default_deemphasis * 48000 * 1.0e-6),
65 m_fmExcursion(default_excursion)
127 void BFMDemod::feed(
const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end,
bool firstOfBurst)
140 for (SampleVector::const_iterator it = begin; it != end; ++it)
147 for (
int i =0 ;
i <rf_out;
i++)
149 msq = rf[
i].real()*rf[
i].real() + rf[
i].imag()*rf[
i].imag();
201 Real sampleStereo = 0.0f;
220 sampleStereo = cs.real() + cs.imag();
230 sampleStereo = cs.real();
242 Real deemph_l, deemph_r;
313 qDebug() <<
"BFMDemod::handleMessage: MsgChannelizerNotification:" 331 qDebug() <<
"BFMDemod::handleMessage: MsgConfigureChannelizer: sampleRate: " << cfg.
getSampleRate()
343 qDebug() <<
"BFMDemod::handleMessage: MsgConfigureBFMDemod";
354 qDebug() <<
"BFMDemod::handleMessage: DSPConfigureAudio:" 355 <<
" sampleRate: " << sampleRate;
373 qDebug() <<
"BFMDemod::handleMessage: passed: " << cmd.
getIdentifier();
388 qDebug(
"BFMDemod::applyAudioSampleRate: %d", sampleRate);
410 qDebug() <<
"BFMDemod::applyChannelSettings:" 411 <<
" inputSampleRate: " << inputSampleRate
412 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
452 qDebug() <<
"BFMDemod::applySettings: MsgConfigureBFMDemod:" 456 <<
" m_volume: " << settings.
m_volume 464 <<
" force: " << force;
466 QList<QString> reverseAPIKeys;
469 reverseAPIKeys.append(
"inputFrequencyOffset");
472 reverseAPIKeys.append(
"volume");
475 reverseAPIKeys.append(
"audioStereo");
478 reverseAPIKeys.append(
"lsbStereo");
481 reverseAPIKeys.append(
"showPilot");
484 reverseAPIKeys.append(
"rdsActive");
494 reverseAPIKeys.append(
"afBandwidth");
516 reverseAPIKeys.append(
"rfBandwidth");
527 reverseAPIKeys.append(
"squelch");
533 reverseAPIKeys.append(
"audioDeviceName");
582 QString& errorMessage)
593 const QStringList& channelSettingsKeys,
595 QString& errorMessage)
599 bool frequencyOffsetChanged =
false;
601 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
604 frequencyOffsetChanged =
true;
606 if (channelSettingsKeys.contains(
"rfBandwidth")) {
609 if (channelSettingsKeys.contains(
"afBandwidth")) {
612 if (channelSettingsKeys.contains(
"volume")) {
615 if (channelSettingsKeys.contains(
"squelch")) {
618 if (channelSettingsKeys.contains(
"audioStereo")) {
621 if (channelSettingsKeys.contains(
"lsbStereo")) {
624 if (channelSettingsKeys.contains(
"showPilot")) {
627 if (channelSettingsKeys.contains(
"rdsActive")) {
630 if (channelSettingsKeys.contains(
"rgbColor")) {
633 if (channelSettingsKeys.contains(
"title")) {
636 if (channelSettingsKeys.contains(
"audioDeviceName")) {
639 if (channelSettingsKeys.contains(
"useReverseAPI")) {
642 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
645 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
648 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
651 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
655 if (frequencyOffsetChanged)
665 qDebug(
"BFMDemod::webapiSettingsPutPatch: forward to GUI: %p",
m_guiMessageQueue);
679 QString& errorMessage)
728 double magsqAvg, magsqPeak;
756 report->
setPid(
new QString(str(boost::format(
"%04X") %
getRDSParser().m_pi_program_identification).c_str()));
763 std::string time = str(boost::format(
"%4i-%02i-%02i %02i:%02i (%+.1fh)")\
765 report->
setTime(
new QString(time.c_str()));
790 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
793 if (channelSettingsKeys.contains(
"rfBandwidth") || force) {
796 if (channelSettingsKeys.contains(
"afBandwidth") || force) {
799 if (channelSettingsKeys.contains(
"volume") || force) {
802 if (channelSettingsKeys.contains(
"squelch") || force) {
805 if (channelSettingsKeys.contains(
"audioStereo") || force) {
808 if (channelSettingsKeys.contains(
"lsbStereo") || force) {
811 if (channelSettingsKeys.contains(
"showPilot") || force) {
814 if (channelSettingsKeys.contains(
"rdsActive") || force) {
817 if (channelSettingsKeys.contains(
"rgbColor") || force) {
820 if (channelSettingsKeys.contains(
"title") || force) {
823 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
827 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
833 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
835 QBuffer *buffer=
new QBuffer();
836 buffer->open((QBuffer::ReadWrite));
837 buffer->write(swgChannelSettings->
asJson().toUtf8());
843 delete swgChannelSettings;
848 QNetworkReply::NetworkError replyError = reply->error();
852 qWarning() <<
"BFMDemod::networkManagerFinished:" 853 <<
" error(" << (int) replyError
854 <<
"): " << replyError
855 <<
": " << reply->errorString();
859 QString answer = reply->readAll();
861 qDebug(
"BFMDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setAltFrequencies(QList< SWGRDSReport_altFrequencies *> *alt_frequencies)
void setRadioText(QString *radio_text)
void setOriginatorChannelIndex(qint32 originator_channel_index)
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
QString m_reverseAPIAddress
int getOutputSampleRate(int outputDeviceIndex=-1)
bool process(Real rdsSample, bool &bit)
Complex nextIQ()
Return next complex sample.
bool decimate(Real *distance, const Complex &next, Complex *result)
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
Real m_interpolatorRDSDistanceRemain
Real m_pilotPLLSamples[4]
void setReverseApiPort(qint32 reverse_api_port)
void setBfmDemodSettings(SWGBFMDemodSettings *bfm_demod_settings)
void setUseReverseApi(qint32 use_reverse_api)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setProgServiceName(QString *prog_service_name)
void webapiFormatRDSReport(SWGSDRangel::SWGRDSReport *report)
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
BFMDemod(DeviceAPI *deviceAPI)
bool deserialize(const QByteArray &data)
SWGBFMDemodReport * getBfmDemodReport()
QString * getAudioDeviceName()
void parseGroup(unsigned int *group)
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
uint16_t m_reverseAPIChannelIndex
static double dbPower(double magsq, double floor=1e-12)
Interpolator m_interpolator
Interpolator between fixed demod bandwidth and audio bandwidth (rational)
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setChannelSampleRate(qint32 channel_sample_rate)
static const QString m_channelIdURI
quint32 m_audioSampleRate
qint64 m_inputFrequencyOffset
QList< SWGRDSReport_altFrequencies * > * getAltFrequencies()
AudioVector m_audioBuffer
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
virtual bool deserialize(const QByteArray &data)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
void setFMScaling(Real fmScaling)
unsigned int * getGroup()
void configure(Real timeout)
void setLsbStereo(qint32 lsb_stereo)
static MsgReportChannelSampleRateChanged * create(int sampleRate)
void create(int nTaps, double sampleRate, double cutoff)
static const Real default_deemphasis
int getDeviceSetIndex() const
void process(const Real &sample_in, Real &sample_out)
int getOutputDeviceIndex(const QString &deviceName) const
void configure(Real freq, Real bandwidth, Real minsignal)
int runFilt(const cmplx &in, cmplx **out)
int getSampleRate() const
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
QString * getReverseApiAddress()
static const QString m_channelId
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
LowPassFilterRC m_deemphasisFilterY
void setAudioDeviceName(QString *audio_device_name)
void setDemodStatus(qint32 demod_status)
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool po)
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
Real m_interpolatorDistanceRemain
uint16_t m_reverseAPIDeviceIndex
std::complex< float > cmplx
static int requiredBW(int rfBW)
void setSquelch(qint32 squelch)
qint32 getReverseApiChannelIndex()
void setRdsActive(qint32 rds_active)
ThreadedBasebandSampleSink * m_threadedChannelizer
QByteArray serialize() const
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setRdsDemodFrequency(float rds_demod_frequency)
void applyAudioSampleRate(int sampleRate)
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.
SWGBFMDemodSettings * getBfmDemodSettings()
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void setVolume(float volume)
void create_filter(float f1, float f2)
void setAudioSampleRate(qint32 audio_sample_rate)
static DSPEngine * instance()
SampleVector m_sampleBuffer
LowPassFilterRC m_deemphasisFilterX
void setSquelch(float squelch)
std::set< double > m_g0_alt_freq
void process(const std::vector< Real > &samples_in, std::vector< Real > &samples_out)
void setBfmDemodReport(SWGBFMDemodReport *bfm_demod_report)
void setRgbColor(qint32 rgb_color)
uint16_t m_reverseAPIPort
void setPilotPowerDb(float pilot_power_db)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const BFMDemodSettings &settings)
qint32 getReverseApiPort()
DownChannelizer * m_channelizer
Real phaseDiscriminator(const Complex &sample)
static bool match(const Message *message)
void setDecodStatus(qint32 decod_status)
void setFreq(Real freq, Real sampleRate)
Interpolator m_interpolatorStereo
Twin Interpolator for stereo subcarrier.
void setRdsDemodAccumDb(float rds_demod_accum_db)
int m_inputFrequencyOffset
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
static const int m_udpBlockSize
void setDirection(qint32 direction)
MessageQueue * getMessageQueueToGUI()
void applySettings(const BFMDemodSettings &settings, bool force=false)
void setTitle(QString *title)
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
virtual QString asJson() override
qint64 getInputFrequencyOffset()
qint32 getUseReverseApi()
BFMDemodSettings m_settings
void setChannelPowerDb(float channel_power_db)
Real m_interpolatorRDSDistance
AudioDeviceManager * getAudioDeviceManager()
static const int filtFftLen
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
void setReverseApiAddress(QString *reverse_api_address)
void setMonoStereo(QString *mono_stereo)
Real m_interpolatorStereoDistanceRemain
void setPilotLocked(qint32 pilot_locked)
Real getDecoderQua() const
void setPiCoverage(QString *pi_coverage)
Real getDemodFclk() const
Real getPilotLevel() const
void getMagSqLevels(double &avg, double &peak, int &nbSamples)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const BFMDemodSettings &settings, bool force)
Lowpass< Real > m_lowpass
virtual const char * getIdentifier() const
void setRdsReport(SWGRDSReport *rds_report)
Interpolator m_interpolatorRDS
Twin Interpolator for stereo subcarrier.
PhaseDiscriminators m_phaseDiscri
void setInputFrequencyOffset(qint64 input_frequency_offset)
QString m_audioDeviceName
virtual QByteArray serialize() const
double m_magsq
x^-1 real sample
void setPiType(QString *pi_type)
void setShowPilot(qint32 show_pilot)
QNetworkAccessManager * m_networkManager
void setAudioStereo(qint32 audio_stereo)
Real m_interpolatorDistance
void setTime(QString *time)
void setPid(QString *pid)
RDSParser & getRDSParser()
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=false)
int getIndexInDeviceSet() const
std::complex< Real > Complex
Real m_interpolatorStereoDistance
SWGRDSReport * getRdsReport()
qint32 getReverseApiDeviceIndex()
QNetworkRequest m_networkRequest
qint64 getFrequencyOffset() const
int getSampleRate() const
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
bool getPilotLock() const
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void networkManagerFinished(QNetworkReply *reply)
BasebandSampleSink * m_sampleSink
uint32_t write(const quint8 *data, uint32_t numSamples)
void setAfBandwidth(float af_bandwidth)
void setRfBandwidth(float rf_bandwidth)
void setMusicSpeech(QString *music_speech)