20 #include <QMutexLocker> 21 #include <QNetworkAccessManager> 22 #include <QNetworkReply> 57 m_deviceAPI(deviceAPI),
58 m_basebandSampleRate(48000),
59 m_outputSampleRate(48000),
60 m_inputFrequencyOffset(0),
63 m_feedbackAudioFifo(48000),
64 m_settingsMutex(QMutex::Recursive),
155 double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
306 qDebug(
"AMDemod::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f",
352 qDebug() <<
"NFMMod::handleMessage: UpChannelizer::MsgChannelizerNotification";
361 qDebug() <<
"NFMMod::handleMessage: MsgConfigureChannelizer:" 374 qDebug() <<
"NFMMod::handleMessage: MsgConfigureNFMMod";
385 qDebug() <<
"NFMMod::handleMessage: MsgConfigureFileSourceName:" 394 qDebug() <<
"NFMMod::handleMessage: MsgConfigureFileSourceSeek:" 395 <<
" seekPercentage: " << seekPercentage;
401 std::size_t samplesCount;
431 qDebug() <<
"NFMMod::handleMessage: DSPConfigureAudio:" 432 <<
" sampleRate: " << sampleRate
433 <<
" audioType: " << audioType;
473 qDebug() <<
"NFMMod::openFileStream: " <<
m_fileName.toStdString().c_str()
489 seekPoint *=
sizeof(
Real);
497 qDebug(
"NFMMod::applyAudioSampleRate: %d", sampleRate);
523 qDebug(
"NFMMod::applyFeedbackAudioSampleRate: %u", sampleRate);
540 qDebug() <<
"NFMMod::applyChannelSettings:" 541 <<
" basebandSampleRate: " << basebandSampleRate
542 <<
" outputSampleRate: " << outputSampleRate
543 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
570 qDebug() <<
"NFMMod::applySettings:" 588 <<
" force: " << force;
590 QList<QString> reverseAPIKeys;
593 reverseAPIKeys.append(
"inputFrequencyOffset");
597 reverseAPIKeys.append(
"fmDeviation");
601 reverseAPIKeys.append(
"volumeFactor");
605 reverseAPIKeys.append(
"ctcssOn");
609 reverseAPIKeys.append(
"channelMute");
613 reverseAPIKeys.append(
"playLoop");
617 reverseAPIKeys.append(
"modAFInput");
622 reverseAPIKeys.append(
"rfBandwidth");
633 reverseAPIKeys.append(
"afBandwidth");
642 reverseAPIKeys.append(
"toneFrequency");
650 reverseAPIKeys.append(
"ctcssIndex");
658 reverseAPIKeys.append(
"audioDeviceName");
665 reverseAPIKeys.append(
"audioSampleRate");
672 reverseAPIKeys.append(
"feedbackAudioDeviceName");
679 reverseAPIKeys.append(
"feedbackAudioSampleRate");
724 QString& errorMessage)
735 const QStringList& channelSettingsKeys,
737 QString& errorMessage)
741 bool frequencyOffsetChanged =
false;
747 if (channelSettingsKeys.contains(
"afBandwidth")) {
750 if (channelSettingsKeys.contains(
"channelMute")) {
753 if (channelSettingsKeys.contains(
"ctcssIndex")) {
756 if (channelSettingsKeys.contains(
"ctcssOn")) {
759 if (channelSettingsKeys.contains(
"fmDeviation")) {
762 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
765 frequencyOffsetChanged =
true;
767 if (channelSettingsKeys.contains(
"modAFInput")) {
770 if (channelSettingsKeys.contains(
"playLoop")) {
773 if (channelSettingsKeys.contains(
"rfBandwidth")) {
776 if (channelSettingsKeys.contains(
"rgbColor")) {
779 if (channelSettingsKeys.contains(
"title")) {
782 if (channelSettingsKeys.contains(
"toneFrequency")) {
785 if (channelSettingsKeys.contains(
"volumeFactor")) {
788 if (channelSettingsKeys.contains(
"useReverseAPI")) {
791 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
794 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
797 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
800 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
804 if (channelSettingsKeys.contains(
"cwKeyer"))
820 if (frequencyOffsetChanged)
843 QString& errorMessage)
922 if (channelSettingsKeys.contains(
"channelMute") || force) {
925 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
928 if (channelSettingsKeys.contains(
"modAFInput") || force) {
931 if (channelSettingsKeys.contains(
"audioDeviceName") || force) {
934 if (channelSettingsKeys.contains(
"playLoop") || force) {
937 if (channelSettingsKeys.contains(
"afBandwidth") || force) {
940 if (channelSettingsKeys.contains(
"fmDeviation") || force) {
943 if (channelSettingsKeys.contains(
"rfBandwidth") || force) {
946 if (channelSettingsKeys.contains(
"rgbColor") || force) {
949 if (channelSettingsKeys.contains(
"title") || force) {
952 if (channelSettingsKeys.contains(
"toneFrequency") || force) {
955 if (channelSettingsKeys.contains(
"volumeFactor") || force) {
958 if (channelSettingsKeys.contains(
"ctcssOn") || force) {
961 if (channelSettingsKeys.contains(
"ctcssIndex") || force) {
973 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
979 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
981 QBuffer *buffer=
new QBuffer();
982 buffer->open((QBuffer::ReadWrite));
983 buffer->write(swgChannelSettings->
asJson().toUtf8());
989 delete swgChannelSettings;
1004 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
1010 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1012 QBuffer *buffer=
new QBuffer();
1013 buffer->open((QBuffer::ReadWrite));
1014 buffer->write(swgChannelSettings->
asJson().toUtf8());
1020 delete swgChannelSettings;
1025 QNetworkReply::NetworkError replyError = reply->error();
1029 qWarning() <<
"NFMMod::networkManagerFinished:" 1030 <<
" error(" << (int) replyError
1031 <<
"): " << replyError
1032 <<
": " << reply->errorString();
1036 QString answer = reply->readAll();
1038 qDebug(
"NFMMod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setFmDeviation(float fm_deviation)
void setAudioSampleRate(qint32 audio_sample_rate)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const NFMModSettings &settings, bool force)
void processOneSample(Complex &ci)
void setOriginatorChannelIndex(qint32 originator_channel_index)
static const int m_levelNbSamples
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
void calculateLevel(Real &sample)
static const QString m_channelIdURI
void setVolumeFactor(float volume_factor)
uint m_feedbackAudioBufferFill
int getOutputSampleRate(int outputDeviceIndex=-1)
SWGCWKeyerSettings * getCwKeyer()
void setChannelMute(qint32 channel_mute)
bool deserialize(const QByteArray &data)
Complex nextIQ()
Return next complex sample.
bool decimate(Real *distance, const Complex &next, Complex *result)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
void networkManagerFinished(QNetworkReply *reply)
void pushFeedback(Real sample)
void applyChannelSettings(int basebandSampleRate, int outputSampleRate, int inputFrequencyOffset, bool force=false)
void removeChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
void pullAF(Real &sample)
void create(int nTaps, double sampleRate, double lowCutoff, double highCutoff)
static double dbPower(double magsq, double floor=1e-12)
void setRgbColor(qint32 rgb_color)
void setReverseApiAddress(QString *reverse_api_address)
int getInputSampleRate(int inputDeviceIndex=-1)
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
void setNfmModSettings(SWGNFMModSettings *nfm_mod_settings)
void webapiReverseSendCWSettings(const CWKeyerSettings &settings)
bool interpolate(Real *distance, const Complex &next, Complex *result)
Bandpass< Real > m_bandpass
void create(int nTaps, double sampleRate, double cutoff)
Interpolator m_feedbackInterpolator
int getDeviceSetIndex() const
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
int getOutputDeviceIndex(const QString &deviceName) const
void removeChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Remove a channel source (Tx)
bool m_feedbackAudioEnable
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
void setInputFrequencyOffset(qint64 input_frequency_offset)
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const NFMModSettings &settings)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
Interpolator m_interpolator
SWGNFMModReport * getNfmModReport()
static float getCTCSSFreq(int index)
qint64 getInputFrequencyOffset()
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
void setChannelType(QString *channel_type)
void addChannelSource(ThreadedBasebandSampleSource *sink, int streamIndex=0)
Add a channel source (Tx)
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
static MsgReportFileSourceStreamData * create(int sampleRate, quint32 recordLength)
void addAudioSource(AudioFifo *audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex=-1)
Add an audio source.
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
virtual bool deserialize(const QByteArray &data)
void setPhase(Real phase)
qint64 m_inputFrequencyOffset
void setChannelPowerDb(float channel_power_db)
AudioVector m_audioBuffer
void setChannelSampleRate(qint32 channel_sample_rate)
void setToneFrequency(float tone_frequency)
int getBasebandSampleRate() const
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
bool getFadeSample(bool on, float &sample)
void setReverseApiPort(qint32 reverse_api_port)
QString * getAudioDeviceName()
virtual void pullAudio(int nbSamples)
static DSPEngine * instance()
CWSmoother & getCWSmoother()
quint32 m_recordLength
record length in seconds computed from file size
Real m_interpolatorDistanceRemain
AudioVector m_feedbackAudioBuffer
void setCwKeyer(SWGCWKeyerSettings *cw_keyer)
void setTitle(QString *title)
virtual void pull(Sample &sample)
MovingAverageUtil< double, double, 16 > m_movingAverage
static MsgReportFileSourceStreamTiming * create(std::size_t samplesCount)
quint32 m_feedbackAudioSampleRate
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
virtual QByteArray serialize() const
UpChannelizer * m_channelizer
static bool match(const Message *message)
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
NFMModSettings m_settings
Real m_feedbackInterpolatorDistance
void setFreq(Real freq, Real sampleRate)
QNetworkRequest m_networkRequest
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
void setDirection(qint32 direction)
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
uint32_t read(quint8 *data, uint32_t numSamples)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
void setCtcssIndex(qint32 ctcss_index)
void seekFileStream(int seekPercentage)
virtual QString asJson() override
QString * getReverseApiAddress()
bool m_interpolatorConsumed
uint16_t m_reverseAPIDeviceIndex
static void webapiFormatChannelSettings(SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings, const CWKeyerSettings &cwKeyerSettings)
float m_feedbackVolumeFactor
AudioDeviceManager * getAudioDeviceManager()
void setUseReverseApi(qint32 use_reverse_api)
void applySettings(const NFMModSettings &settings, bool force=false)
qint64 getFrequencyOffset() const
void setCtcssOn(qint32 ctcss_on)
void setRfBandwidth(float rf_bandwidth)
quint32 m_audioSampleRate
Lowpass< Real > m_lowpass
QNetworkAccessManager * m_networkManager
MessageQueue * getMessageQueueToGUI()
static void webapiSettingsPutPatch(const QStringList &channelSettingsKeys, CWKeyerSettings &cwKeyerSettings, SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
NFMMod(DeviceAPI *deviceAPI)
QByteArray serialize() const
void applyFeedbackAudioSampleRate(unsigned int sampleRate)
qint32 getUseReverseApi()
static const QString m_channelId
ThreadedBasebandSampleSource * m_threadedChannelizer
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
void setFreq(Real freq, Real sampleRate)
NFMModInputAF m_modAFInput
quint64 m_fileSize
raw file size (bytes)
float m_modPhasor
baseband modulator phasor
QString m_audioDeviceName
This is the audio device you get the audio samples from.
int getInputDeviceIndex(const QString &deviceName) const
AudioFifo m_feedbackAudioFifo
int getSampleRate() const
qint32 getReverseApiPort()
bool m_feedbackInterpolatorConsumed
void addChannelSourceAPI(ChannelAPI *channelAPI, int streamIndex=0)
SWGNFMModSettings * getNfmModSettings()
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
void setAudioDeviceName(QString *audio_device_name)
void setNfmModReport(SWGNFMModReport *nfm_mod_report)
void setPlayLoop(qint32 play_loop)
const CWKeyerSettings & getSettings() const
QString m_reverseAPIAddress
int getIndexInDeviceSet() const
Real next()
Return next real sample.
std::complex< Real > Complex
void setModAfInput(qint32 mod_af_input)
uint16_t m_reverseAPIPort
QString m_feedbackAudioDeviceName
This is the audio device you send the audio samples to for audio feedback.
void setSampleRate(int sampleRate)
void setAfBandwidth(float af_bandwidth)
void applyAudioSampleRate(int sampleRate)
int m_inputFrequencyOffset
Real m_interpolatorDistance
T max(const T &x, const T &y)
uint32_t write(const quint8 *data, uint32_t numSamples)
Real m_feedbackInterpolatorDistanceRemain
qint32 getReverseApiChannelIndex()
void removeAudioSource(AudioFifo *audioFifo)
Remove an audio source.
qint32 getReverseApiDeviceIndex()
uint16_t m_reverseAPIChannelIndex
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
T min(const T &x, const T &y)