20 #include <QHostAddress> 21 #include <QNetworkAccessManager> 22 #include <QNetworkReply> 50 m_deviceAPI(deviceAPI),
51 m_inputSampleRate(48000),
52 m_inputFrequencyOffset(0),
53 m_outMovingAverage(480, 1e-10),
54 m_inMovingAverage(480, 1e-10),
55 m_amMovingAverage(1200, 1e-10),
60 m_squelchOpenCount(0),
61 m_squelchCloseCount(0),
63 m_squelchRelease(4800),
64 m_agc(9600, m_agcTarget, 1e-6),
65 m_settingsMutex(QMutex::Recursive)
98 connect(m_audioSocket, SIGNAL(readyRead()),
this, SLOT(
audioReadyRead()), Qt::QueuedConnection);
102 qWarning(
"UDPSink::UDPSink: cannot bind audio port");
142 messageQueue->
push(cmd);
145 void UDPSink::feed(
const SampleVector::const_iterator& begin,
const SampleVector::const_iterator& end,
bool positiveOnly)
154 for(SampleVector::const_iterator it = begin; it < end; ++it)
156 Complex c(it->real(), it->imag());
162 double agcFactor = 1.0;
175 inMagSq = ci.real()*ci.real() + ci.imag()*ci.imag();
181 Sample ss(ci.real(), ci.imag());
195 for (
int i = 0;
i < n_out;
i++)
211 for (
int i = 0;
i < n_out;
i++)
239 for (
int i = 0;
i < n_out;
i++)
254 for (
int i = 0;
i < n_out;
i++)
273 double demodf =
sqrt(inMagSq);
290 double demodf =
sqrt(inMagSq);
347 qDebug() <<
"UDPSink::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << notif.
getSampleRate()
358 qDebug() <<
"UDPSink::handleMessage: MsgConfigureChannelizer:" 371 qDebug(
"UDPSink::handleMessage: MsgConfigureUDPSource");
383 qDebug() <<
"UDPSink::handleMessage: MsgUDPSinkSpectrum: m_spectrumEnabled: " <<
m_spectrumEnabled;
408 qint64 pendingDataSize =
m_audioSocket->pendingDatagramSize();
416 for (
int i = 0;
i < udpReadBytes - 3;
i += 4)
430 qDebug(
"UDPSink::audioReadyRead: (stereo) lost %u samples",
m_audioBufferFill - res);
439 for (
int i = 0;
i < udpReadBytes - 1;
i += 2)
452 qDebug(
"UDPSink::audioReadyRead: (mono) lost %u samples",
m_audioBufferFill - res);
462 qDebug(
"UDPSink::audioReadyRead: lost samples");
474 qDebug() <<
"UDPSink::applyChannelSettings:" 475 <<
" inputSampleRate: " << inputSampleRate
476 <<
" inputFrequencyOffset: " << inputFrequencyOffset;
498 qDebug() <<
"UDPSink::applySettings:" 502 <<
" m_gain: " << settings.
m_gain 503 <<
" m_volume: " << settings.
m_volume 507 <<
" m_agc" << settings.
m_agc 520 <<
" force: " << force;
522 QList<QString> reverseAPIKeys;
525 reverseAPIKeys.append(
"inputFrequencyOffset");
528 reverseAPIKeys.append(
"audioActive");
531 reverseAPIKeys.append(
"audioStereo");
534 reverseAPIKeys.append(
"gain");
537 reverseAPIKeys.append(
"volume");
540 reverseAPIKeys.append(
"squelchEnabled");
543 reverseAPIKeys.append(
"squelchDB");
546 reverseAPIKeys.append(
"squelchGate");
549 reverseAPIKeys.append(
"agc");
552 reverseAPIKeys.append(
"sampleFormat");
555 reverseAPIKeys.append(
"outputSampleRate");
558 reverseAPIKeys.append(
"rfBandwidth");
561 reverseAPIKeys.append(
"fmDeviation");
564 reverseAPIKeys.append(
"udpAddress");
567 reverseAPIKeys.append(
"udpPort");
570 reverseAPIKeys.append(
"audioPort");
670 qDebug(
"UDPSink::handleMessage: audio socket bound to port %d", settings.
m_audioPort);
674 qWarning(
"UDPSink::handleMessage: cannot bind audio socket");
722 QString& errorMessage)
733 const QStringList& channelSettingsKeys,
735 QString& errorMessage)
739 bool frequencyOffsetChanged =
false;
741 if (channelSettingsKeys.contains(
"outputSampleRate")) {
744 if (channelSettingsKeys.contains(
"sampleFormat")) {
747 if (channelSettingsKeys.contains(
"inputFrequencyOffset"))
750 frequencyOffsetChanged =
true;
752 if (channelSettingsKeys.contains(
"rfBandwidth")) {
755 if (channelSettingsKeys.contains(
"fmDeviation")) {
758 if (channelSettingsKeys.contains(
"channelMute")) {
761 if (channelSettingsKeys.contains(
"gain")) {
764 if (channelSettingsKeys.contains(
"squelchDB")) {
767 if (channelSettingsKeys.contains(
"squelchGate")) {
770 if (channelSettingsKeys.contains(
"squelchEnabled")) {
773 if (channelSettingsKeys.contains(
"agc")) {
776 if (channelSettingsKeys.contains(
"audioActive")) {
779 if (channelSettingsKeys.contains(
"audioStereo")) {
782 if (channelSettingsKeys.contains(
"volume")) {
785 if (channelSettingsKeys.contains(
"udpAddress")) {
788 if (channelSettingsKeys.contains(
"udpPort")) {
791 if (channelSettingsKeys.contains(
"audioPort")) {
794 if (channelSettingsKeys.contains(
"rgbColor")) {
797 if (channelSettingsKeys.contains(
"title")) {
800 if (channelSettingsKeys.contains(
"useReverseAPI")) {
803 if (channelSettingsKeys.contains(
"reverseAPIAddress")) {
806 if (channelSettingsKeys.contains(
"reverseAPIPort")) {
809 if (channelSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
812 if (channelSettingsKeys.contains(
"reverseAPIChannelIndex")) {
816 if (frequencyOffsetChanged)
827 qDebug(
"getUdpSinkSettings::webapiSettingsPutPatch: forward to GUI: %p",
m_guiMessageQueue);
841 QString& errorMessage)
916 if (channelSettingsKeys.contains(
"outputSampleRate") || force) {
919 if (channelSettingsKeys.contains(
"sampleFormat") || force) {
922 if (channelSettingsKeys.contains(
"inputFrequencyOffset") || force) {
925 if (channelSettingsKeys.contains(
"rfBandwidth") || force) {
928 if (channelSettingsKeys.contains(
"fmDeviation") || force) {
931 if (channelSettingsKeys.contains(
"channelMute") || force) {
934 if (channelSettingsKeys.contains(
"gain") || force) {
937 if (channelSettingsKeys.contains(
"squelchDB") || force) {
940 if (channelSettingsKeys.contains(
"squelchGate") || force) {
943 if (channelSettingsKeys.contains(
"squelchEnabled") || force) {
946 if (channelSettingsKeys.contains(
"agc") || force) {
947 swgUDPSinkSettings->
setAgc(settings.
m_agc ? 1 : 0);
949 if (channelSettingsKeys.contains(
"audioActive") || force) {
952 if (channelSettingsKeys.contains(
"audioStereo") || force) {
955 if (channelSettingsKeys.contains(
"volume") || force) {
958 if (channelSettingsKeys.contains(
"udpAddress") || force) {
961 if (channelSettingsKeys.contains(
"udpPort") || force) {
964 if (channelSettingsKeys.contains(
"audioPort") || force) {
967 if (channelSettingsKeys.contains(
"rgbColor") || force) {
970 if (channelSettingsKeys.contains(
"title") || force) {
974 QString channelSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
980 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
982 QBuffer *buffer=
new QBuffer();
983 buffer->open((QBuffer::ReadWrite));
984 buffer->write(swgChannelSettings->
asJson().toUtf8());
990 delete swgChannelSettings;
995 QNetworkReply::NetworkError replyError = reply->error();
999 qWarning() <<
"UDPSink::networkManagerFinished:" 1000 <<
" error(" << (int) replyError
1001 <<
"): " << replyError
1002 <<
": " << reply->errorString();
1006 QString answer = reply->readAll();
1008 qDebug(
"UDPSink::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
void setSquelchGate(qint32 squelch_gate)
qint32 getReverseApiPort()
void setOriginatorChannelIndex(qint32 originator_channel_index)
void addAudioSink(AudioFifo *audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex=-1)
Add the audio sink.
static const QString m_channelId
Complex nextIQ()
Return next complex sample.
bool decimate(Real *distance, const Complex &next, Complex *result)
void configure(MessageQueue *messageQueue, int sampleRate, int centerFrequency)
void setSampleFormat(qint32 sample_format)
bool deserialize(const QByteArray &data)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
DownChannelizer * m_channelizer
QString * getReverseApiAddress()
void removeChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setTitle(QString *title)
void create(int nTaps, double sampleRate, double lowCutoff, double highCutoff)
static double dbPower(double magsq, double floor=1e-12)
void addChannelSinkAPI(ChannelAPI *channelAPI, int streamIndex=0)
void setPort(unsigned int port)
void setChannelMute(qint32 channel_mute)
QString * getUdpAddress()
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
MessageQueue * getInputMessageQueue()
Get the queue for asynchronous inbound communication.
void setFMScaling(Real fmScaling)
void setFmDeviation(qint32 fm_deviation)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
int getDeviceSetIndex() const
virtual bool deserialize(const QByteArray &data)
void setReverseApiPort(qint32 reverse_api_port)
void udpWriteNorm(Real real, Real imag)
virtual int webapiSettingsPutPatch(bool force, const QStringList &channelSettingsKeys, SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
int getSampleRate() const
void setAddress(QString &address)
void removeAudioSink(AudioFifo *audioFifo)
Remove the audio sink.
void udpWrite(FixReal real, FixReal imag)
void setSquelchDb(qint32 squelch_db)
virtual bool handleMessage(const Message &cmd)
Processing of a message. Returns true if message has actually been processed.
uint16_t m_reverseAPIPort
void calculateSquelch(double value)
UDPSinkSettings m_settings
void setChannelType(QString *channel_type)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)=0
MovingAverage< double > m_amMovingAverage
void setOriginatorDeviceSetIndex(qint32 originator_device_set_index)
void setRfBandwidth(float rf_bandwidth)
SampleVector m_sampleBuffer
void setSpectrum(BasebandSampleSink *spectrum)
double getInMagSq() const
MessageQueue m_inputMessageQueue
Queue for asynchronous inbound communication.
double feedAndGetValue(const Complex &ci)
qint64 getInputFrequencyOffset()
std::complex< float > cmplx
static const int m_udpAudioPayloadSize
UDP audio samples buffer. No UDP block on Earth is larger than this.
int m_squelchGate
100ths seconds
void setUdpSinkReport(SWGUDPSinkReport *udp_sink_report)
static const Real m_agcTarget
AudioVector m_audioBuffer
void applyChannelSettings(int inputSampleRate, int inputFrequencyOffset, bool force=true)
void setInputFrequencyOffset(qint64 input_frequency_offset)
QByteArray serialize() const
void setReverseApiChannelIndex(qint32 reverse_api_channel_index)
BasebandSampleSink * m_spectrum
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
virtual int webapiReportGet(SWGSDRangel::SWGChannelReport &response, QString &errorMessage)
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)
MovingAverage< double > m_outMovingAverage
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings &response, const UDPSinkSettings &settings)
void networkManagerFinished(QNetworkReply *reply)
void setUdpAddress(QString *udp_address)
void udpWriteMono(FixReal sample)
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
virtual QByteArray serialize() const
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport &response)
uint16_t m_reverseAPIDeviceIndex
QNetworkAccessManager * m_networkManager
static DSPEngine * instance()
UDPSinkUtil< int16_t > * m_udpBufferMono16
qint32 getReverseApiChannelIndex()
ThreadedBasebandSampleSink * m_threadedChannelizer
qint32 getUseReverseApi()
Bandpass< double > m_bandpass
qint32 getReverseApiDeviceIndex()
QUdpSocket * m_audioSocket
void setUdpPort(qint32 udp_port)
void setInputSampleRate(qint32 input_sample_rate)
void setAudioPort(qint32 audio_port)
void setClampMax(double clampMax)
virtual void feed(const SampleVector::const_iterator &begin, const SampleVector::const_iterator &end, bool positiveOnly)
void setUdpSinkSettings(SWGUDPSinkSettings *udp_sink_settings)
void setAudioStereo(qint32 audio_stereo)
Real phaseDiscriminator(const Complex &sample)
static bool match(const Message *message)
void setFreq(Real freq, Real sampleRate)
int m_inputFrequencyOffset
Interpolator m_interpolator
int m_squelchGate
number of samples computed from given gate
void setSquelchEnabled(qint32 squelch_enabled)
void udpWriteNormMono(Real sample)
void removeChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Remove a channel sink (Rx)
void setOutputPowerDb(float output_power_db)
Fixed< IntType, IntBits > sqrt(Fixed< IntType, IntBits > const &x)
void setDirection(qint32 direction)
SWGUDPSinkReport * getUdpSinkReport()
void setRgbColor(qint32 rgb_color)
virtual QString asJson() override
void setSquelch(qint32 squelch)
void setChannelPowerDb(float channel_power_db)
virtual int webapiSettingsGet(SWGSDRangel::SWGChannelSettings &response, QString &errorMessage)
static const int udpBlockSize
UDPSinkUtil< Sample16 > * m_udpBuffer16
uint16_t m_reverseAPIChannelIndex
SampleFormat m_sampleFormat
void setAudioActive(qint32 audio_active)
float getOutputSampleRate()
AudioDeviceManager * getAudioDeviceManager()
UDPSink(DeviceAPI *deviceAPI)
void webapiReverseSendSettings(QList< QString > &channelSettingsKeys, const UDPSinkSettings &settings, bool force)
void addChannelSink(ThreadedBasebandSampleSink *sink, int streamIndex=0)
Add a channel sink (Rx)
QNetworkRequest m_networkRequest
Real m_sampleDistanceRemain
void setUseReverseApi(qint32 use_reverse_api)
int runSSB(const cmplx &in, cmplx **out, bool usb, bool getDC=true)
UDPSinkUtil< Sample24 > * m_udpBuffer24
PhaseDiscriminators m_phaseDiscri
void applySettings(const UDPSinkSettings &settings, bool force=false)
void setClamping(bool clamping)
void setThreshold(double threshold)
qint32 getSquelchEnabled()
void setStepDownDelay(int stepDownDelay)
int64_t m_inputFrequencyOffset
MovingAverage< double > m_inMovingAverage
void setOutputSampleRate(float output_sample_rate)
void setReverseApiAddress(QString *reverse_api_address)
SWGUDPSinkSettings * getUdpSinkSettings()
static MsgUDPSinkSpectrum * create(bool enabled)
int getIndexInDeviceSet() const
static const QString m_channelIdURI
std::complex< Real > Complex
qint64 getFrequencyOffset() const
void resize(int historySize, Type initial)
static double powerFromdB(double powerdB)
void setVolume(qint32 volume)
QString m_reverseAPIAddress
uint32_t write(const quint8 *data, uint32_t numSamples)
void initSquelch(bool open)