diff --git a/audio_sink/src/main.cpp b/audio_sink/src/main.cpp index de4ad311..fd40272b 100644 --- a/audio_sink/src/main.cpp +++ b/audio_sink/src/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -35,6 +36,9 @@ public: monoRB.init(&s2m.out); stereoRB.init(_stream->sinkOut); + // monoPacker.init(&s2m.out, 240); + // stereoPacker.init(_stream->sinkOut, 240); + // Initialize PortAudio devCount = Pa_GetDeviceCount(); devId = Pa_GetDefaultOutputDevice(); @@ -156,12 +160,18 @@ private: if (dev->channels == 2) { stereoRB.data.setMaxLatency(bufferSize * 2); stereoRB.start(); + // stereoPacker.setSampleCount(bufferSize); + // stereoPacker.start(); err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, paFramesPerBufferUnspecified, 0, _stereo_cb, this); + //err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _stereo_cb, this); } else { monoRB.data.setMaxLatency(bufferSize * 2); monoRB.start(); + // stereoPacker.setSampleCount(bufferSize); + // monoPacker.start(); err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, paFramesPerBufferUnspecified, 0, _mono_cb, this); + //err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _mono_cb, this); } if (err != 0) { @@ -182,12 +192,18 @@ private: s2m.stop(); monoRB.stop(); stereoRB.stop(); + // monoPacker.stop(); + // stereoPacker.stop(); monoRB.data.stopReader(); stereoRB.data.stopReader(); + // monoPacker.out.stopReader(); + // stereoPacker.out.stopReader(); Pa_StopStream(stream); Pa_CloseStream(stream); monoRB.data.clearReadStop(); stereoRB.data.clearReadStop(); + // monoPacker.out.clearReadStop(); + // stereoPacker.out.clearWriteStop(); } static int _mono_cb(const void *input, void *output, unsigned long frameCount, @@ -203,11 +219,34 @@ private: _this->stereoRB.data.read((dsp::stereo_t*)output, frameCount); return 0; } + + // static int _mono_cb(const void *input, void *output, unsigned long frameCount, + // const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { + // AudioSink* _this = (AudioSink*)userData; + // if (_this->monoPacker.out.read() < 0) { return 0; } + // memcpy((float*)output, _this->monoPacker.out.readBuf, frameCount * sizeof(float)); + // _this->monoPacker.out.flush(); + // return 0; + // } + + // static int _stereo_cb(const void *input, void *output, unsigned long frameCount, + // const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { + // AudioSink* _this = (AudioSink*)userData; + // if (_this->stereoPacker.out.read() < 0) { spdlog::warn("CB killed"); return 0; } + // memcpy((dsp::stereo_t*)output, _this->stereoPacker.out.readBuf, frameCount * sizeof(dsp::stereo_t)); + // _this->stereoPacker.out.flush(); + // return 0; + // } + SinkManager::Stream* _stream; dsp::StereoToMono s2m; dsp::RingBufferSink monoRB; dsp::RingBufferSink stereoRB; + + // dsp::Packer monoPacker; + // dsp::Packer stereoPacker; + std::string _streamName; PaStream *stream; diff --git a/core/src/dsp/audio.h b/core/src/dsp/audio.h index 4178ad37..21fef95b 100644 --- a/core/src/dsp/audio.h +++ b/core/src/dsp/audio.h @@ -47,6 +47,65 @@ namespace dsp { }; + class ChannelsToStereo : public generic_block { + public: + ChannelsToStereo() {} + + ChannelsToStereo(stream* in_left, stream* in_right) { init(in_left, in_right); } + + ~ChannelsToStereo() { generic_block::stop(); } + + void init(stream* in_left, stream* in_right) { + _in_left = in_left; + _in_right = in_right; + generic_block::registerInput(_in_left); + generic_block::registerInput(_in_right); + generic_block::registerOutput(&out); + } + + void setInput(stream* in_left, stream* in_right) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in_left); + generic_block::unregisterInput(_in_right); + _in_left = in_left; + _in_right = in_right; + generic_block::registerInput(_in_left); + generic_block::registerInput(_in_right); + generic_block::tempStart(); + } + + int run() { + count_l = _in_left->read(); + if (count_l < 0) { return -1; } + count_r = _in_right->read(); + if (count_r < 0) { return -1; } + + if (count_l != count_r) { + spdlog::warn("ChannelsToStereo block size missmatch"); + } + + for (int i = 0; i < count_l; i++) { + out.writeBuf[i].l = _in_left->readBuf[i]; + out.writeBuf[i].r = _in_right->readBuf[i]; + } + + _in_left->flush(); + _in_right->flush(); + if (!out.swap(count_l)) { return -1; } + return count_l; + } + + stream out; + + private: + int count_l; + int count_r; + stream* _in_left; + stream* _in_right; + + }; + class StereoToMono : public generic_block { public: StereoToMono() {} @@ -90,4 +149,52 @@ namespace dsp { stream* _in; }; + + class StereoToChannels : public generic_block { + public: + StereoToChannels() {} + + StereoToChannels(stream* in) { init(in); } + + ~StereoToChannels() { generic_block::stop(); } + + void init(stream* in) { + _in = in; + generic_block::registerInput(_in); + generic_block::registerOutput(&out_left); + generic_block::registerOutput(&out_right); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + count = _in->read(); + if (count < 0) { return -1; } + + for (int i = 0; i < count; i++) { + out_left.writeBuf[i] = _in->readBuf[i].l; + out_right.writeBuf[i] = _in->readBuf[i].r; + } + + _in->flush(); + if (!out_left.swap(count)) { return -1; } + if (!out_right.swap(count)) { return -1; } + return count; + } + + stream out_left; + stream out_right; + + private: + int count; + stream* _in; + + }; } \ No newline at end of file diff --git a/core/src/dsp/demodulator.h b/core/src/dsp/demodulator.h index 1bf0da91..fc51a47a 100644 --- a/core/src/dsp/demodulator.h +++ b/core/src/dsp/demodulator.h @@ -1,6 +1,8 @@ #pragma once #include #include +#include +#include #include @@ -26,6 +28,86 @@ inline float fast_arctan2(float y, float x) { } namespace dsp { + class FloatFMDemod : public generic_block { + public: + FloatFMDemod() {} + + FloatFMDemod(stream* in, float sampleRate, float deviation) { init(in, sampleRate, deviation); } + + ~FloatFMDemod() { generic_block::stop(); } + + void init(stream* in, float sampleRate, float deviation) { + _in = in; + _sampleRate = sampleRate; + _deviation = deviation; + phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation); + generic_block::registerInput(_in); + generic_block::registerOutput(&out); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + void setSampleRate(float sampleRate) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + _sampleRate = sampleRate; + phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation); + generic_block::tempStart(); + } + + float getSampleRate() { + return _sampleRate; + } + + void setDeviation(float deviation) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + _deviation = deviation; + phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation); + generic_block::tempStart(); + } + + float getDeviation() { + return _deviation; + } + + int run() { + count = _in->read(); + if (count < 0) { return -1; } + + // This is somehow faster than volk... + + float diff, currentPhase; + for (int i = 0; i < count; i++) { + currentPhase = fast_arctan2(_in->readBuf[i].i, _in->readBuf[i].q); + diff = currentPhase - phase; + if (diff > 3.1415926535f) { diff -= 2 * 3.1415926535f; } + else if (diff <= -3.1415926535f) { diff += 2 * 3.1415926535f; } + out.writeBuf[i] = diff / phasorSpeed; + phase = currentPhase; + } + + _in->flush(); + if (!out.swap(count)) { return -1; } + return count; + } + + stream out; + + private: + int count; + float phase, phasorSpeed, _sampleRate, _deviation; + stream* _in; + + }; + class FMDemod : public generic_block { public: FMDemod() {} @@ -88,7 +170,8 @@ namespace dsp { diff = currentPhase - phase; if (diff > 3.1415926535f) { diff -= 2 * 3.1415926535f; } else if (diff <= -3.1415926535f) { diff += 2 * 3.1415926535f; } - out.writeBuf[i] = diff / phasorSpeed; + out.writeBuf[i].l = diff / phasorSpeed; + out.writeBuf[i].r = diff / phasorSpeed; phase = currentPhase; } @@ -97,7 +180,7 @@ namespace dsp { return count; } - stream out; + stream out; private: int count; @@ -106,6 +189,149 @@ namespace dsp { }; + class StereoFMDemod : public generic_block { + public: + StereoFMDemod() {} + + StereoFMDemod(stream* in, float sampleRate, float deviation) { init(in, sampleRate, deviation); } + + ~StereoFMDemod() { + stop(); + delete[] doubledPilot; + delete[] a_minus_b; + delete[] a_out; + delete[] b_out; + } + + void init(stream* in, float sampleRate, float deviation) { + _sampleRate = sampleRate; + + doubledPilot = new float[STREAM_BUFFER_SIZE]; + a_minus_b = new float[STREAM_BUFFER_SIZE]; + a_out = new float[STREAM_BUFFER_SIZE]; + b_out = new float[STREAM_BUFFER_SIZE]; + + fmDemod.init(in, sampleRate, deviation); + split.init(&fmDemod.out); + split.bindStream(&filterInput); + split.bindStream(&decodeInput); + + // Filter init + win.init(1000, 1000, 19000, sampleRate); + filter.init(&filterInput, &win); + agc.init(&filter.out, 20.0f, sampleRate); + + generic_block::registerInput(&decodeInput); + generic_block::registerOutput(&out); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + fmDemod.setInput(in); + generic_block::tempStart(); + } + + void setSampleRate(float sampleRate) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + _sampleRate = sampleRate; + fmDemod.setSampleRate(sampleRate); + win.setSampleRate(_sampleRate); + filter.updateWindow(&win); + generic_block::tempStart(); + } + + float getSampleRate() { + return _sampleRate; + } + + void setDeviation(float deviation) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + fmDemod.setDeviation(deviation); + generic_block::tempStart(); + } + + float getDeviation() { + return fmDemod.getDeviation(); + } + + int run() { + count = decodeInput.read(); + if (count < 0) { return -1; } + countFilter = agc.out.read(); + if (countFilter < 0) { return -1; } + + volk_32f_x2_multiply_32f(doubledPilot, agc.out.readBuf, agc.out.readBuf, count); + + volk_32f_x2_multiply_32f(a_minus_b, decodeInput.readBuf, doubledPilot, count); + + volk_32f_x2_add_32f(a_out, decodeInput.readBuf, a_minus_b, count); + volk_32f_x2_subtract_32f(b_out, decodeInput.readBuf, a_minus_b, count); + + decodeInput.flush(); + agc.out.flush(); + + volk_32f_x2_interleave_32fc((lv_32fc_t*)out.writeBuf, a_out, b_out, count); + + if (!out.swap(count)) { return -1; } + return count; + } + + void start() { + std::lock_guard lck(generic_block::ctrlMtx); + if (generic_block::running) { + return; + } + generic_block::running = true; + generic_block::doStart(); + fmDemod.start(); + split.start(); + filter.start(); + agc.start(); + } + + void stop() { + std::lock_guard lck(generic_block::ctrlMtx); + if (!generic_block::running) { + return; + } + fmDemod.stop(); + split.stop(); + filter.stop(); + agc.stop(); + generic_block::doStop(); + generic_block::running = false; + } + + stream out; + + private: + int count; + int countFilter; + + float _sampleRate; + + FloatFMDemod fmDemod; + Splitter split; + + // Pilot tone filtering + stream filterInput; + FIR filter; + filter_window::BlackmanBandpassWindow win; + AGC agc; + + stream decodeInput; + + // Buffers + float* doubledPilot; + float* a_minus_b; + float* a_out; + float* b_out; + + }; + class AMDemod : public generic_block { public: AMDemod() {} diff --git a/core/src/dsp/filter.h b/core/src/dsp/filter.h index d32b0e3d..190b471c 100644 --- a/core/src/dsp/filter.h +++ b/core/src/dsp/filter.h @@ -92,11 +92,11 @@ namespace dsp { public: BFMDeemp() {} - BFMDeemp(stream* in, float sampleRate, float tau) { init(in, sampleRate, tau); } + BFMDeemp(stream* in, float sampleRate, float tau) { init(in, sampleRate, tau); } ~BFMDeemp() { generic_block::stop(); } - void init(stream* in, float sampleRate, float tau) { + void init(stream* in, float sampleRate, float tau) { _in = in; _sampleRate = sampleRate; _tau = tau; @@ -106,7 +106,7 @@ namespace dsp { generic_block::registerOutput(&out); } - void setInput(stream* in) { + void setInput(stream* in) { std::lock_guard lck(generic_block::ctrlMtx); generic_block::tempStop(); generic_block::unregisterInput(_in); @@ -132,20 +132,26 @@ namespace dsp { if (count < 0) { return -1; } if (bypass) { - memcpy(out.writeBuf, _in->readBuf, count * sizeof(float)); + memcpy(out.writeBuf, _in->readBuf, count * sizeof(stereo_t)); _in->flush(); if (!out.swap(count)) { return -1; } return count; } - if (isnan(lastOut)) { - lastOut = 0.0f; + if (isnan(lastOutL)) { + lastOutL = 0.0f; } - out.writeBuf[0] = (alpha * _in->readBuf[0]) + ((1-alpha) * lastOut); + if (isnan(lastOutR)) { + lastOutR = 0.0f; + } + out.writeBuf[0].l = (alpha * _in->readBuf[0].l) + ((1-alpha) * lastOutL); + out.writeBuf[0].r = (alpha * _in->readBuf[0].r) + ((1-alpha) * lastOutR); for (int i = 1; i < count; i++) { - out.writeBuf[i] = (alpha * _in->readBuf[i]) + ((1 - alpha) * out.writeBuf[i - 1]); + out.writeBuf[i].l = (alpha * _in->readBuf[i].l) + ((1 - alpha) * out.writeBuf[i - 1].l); + out.writeBuf[i].r = (alpha * _in->readBuf[i].r) + ((1 - alpha) * out.writeBuf[i - 1].r); } - lastOut = out.writeBuf[count - 1]; + lastOutL = out.writeBuf[count - 1].l; + lastOutR = out.writeBuf[count - 1].r; _in->flush(); if (!out.swap(count)) { return -1; } @@ -154,15 +160,16 @@ namespace dsp { bool bypass = false; - stream out; + stream out; private: int count; - float lastOut = 0.0f; + float lastOutL = 0.0f; + float lastOutR = 0.0f; float alpha; float _tau; float _sampleRate; - stream* _in; + stream* _in; }; } \ No newline at end of file diff --git a/core/src/dsp/math.h b/core/src/dsp/math.h index 4893049d..a43dfaba 100644 --- a/core/src/dsp/math.h +++ b/core/src/dsp/math.h @@ -10,14 +10,14 @@ namespace dsp { Add(stream* a, stream* b) { init(a, b); } - ~Add() { generic_block::stop(); } + ~Add() { generic_block>::stop(); } void init(stream* a, stream* b) { _a = a; _b = b; - generic_block::registerInput(a); - generic_block::registerInput(b); - generic_block::registerOutput(&out); + generic_block>::registerInput(a); + generic_block>::registerInput(b); + generic_block>::registerOutput(&out); } int run() { @@ -32,7 +32,57 @@ namespace dsp { } if constexpr (std::is_same_v || std::is_same_v) { - volk_32fc_x2_add_32fc(out.writeBuf, _a->readBuf, _b->readBuf, a_count); + volk_32fc_x2_add_32fc((lv_32fc_t*)out.writeBuf, (lv_32fc_t*)_a->readBuf, (lv_32fc_t*)_b->readBuf, a_count); + } + else { + volk_32f_x2_add_32f(out.writeBuf, _a->readBuf, _b->readBuf, a_count); + } + + _a->flush(); + _b->flush(); + if (!out.swap(a_count)) { return -1; } + return a_count; + } + + stream out; + + private: + int a_count, b_count; + stream* _a; + stream* _b; + + }; + + template + class Substract : public generic_block> { + public: + Substract() {} + + Substract(stream* a, stream* b) { init(a, b); } + + ~Substract() { generic_block>::stop(); } + + void init(stream* a, stream* b) { + _a = a; + _b = b; + generic_block>::registerInput(a); + generic_block>::registerInput(b); + generic_block>::registerOutput(&out); + } + + int run() { + a_count = _a->read(); + if (a_count < 0) { return -1; } + b_count = _b->read(); + if (b_count < 0) { return -1; } + if (a_count != b_count) { + _a->flush(); + _b->flush(); + return 0; + } + + if constexpr (std::is_same_v || std::is_same_v) { + volk_32f_x2_subtract_32f((float*)out.writeBuf, (float*)_a->readBuf, (float*)_b->readBuf, a_count * 2); } else { volk_32f_x2_add_32f(out.writeBuf, _a->readBuf, _b->readBuf, a_count); diff --git a/core/src/dsp/measure.h b/core/src/dsp/measure.h index b8d79710..58c8b271 100644 --- a/core/src/dsp/measure.h +++ b/core/src/dsp/measure.h @@ -44,7 +44,7 @@ namespace dsp { _in->flush(); float _lvlL = 10.0f * logf(maxL); - float _lvlR = 10.0f * logf(maxL); + float _lvlR = 10.0f * logf(maxR); // Update max values { diff --git a/core/src/dsp/processing.h b/core/src/dsp/processing.h index 7226b3c1..a775ceec 100644 --- a/core/src/dsp/processing.h +++ b/core/src/dsp/processing.h @@ -297,4 +297,72 @@ namespace dsp { stream* _in; }; + + template + class Packer : public generic_block> { + public: + Packer() {} + + Packer(stream* in, int count) { init(in, count); } + + ~Packer() { + generic_block>::stop(); + } + + void init(stream* in, int count) { + _in = in; + samples = count; + generic_block>::registerInput(_in); + generic_block>::registerOutput(&out); + } + + void setInput(stream* in) { + std::lock_guard lck(generic_block>::ctrlMtx); + generic_block>::tempStop(); + generic_block>::unregisterInput(_in); + _in = in; + generic_block>::registerInput(_in); + generic_block>::tempStart(); + } + + void setSampleCount(int count) { + std::lock_guard lck(generic_block>::ctrlMtx); + generic_block>::tempStop(); + samples = count; + generic_block>::tempStart(); + } + + int run() { + count = _in->read(); + if (count < 0) { + read = 0; + return -1; + } + + for (int i = 0; i < count; i++) { + out.writeBuf[read++] = _in->readBuf[i]; + if (read >= samples) { + read = 0; + if (!out.swap(samples)) { + _in->flush(); + read = 0; + return -1; + } + } + } + + _in->flush(); + + return count; + } + + stream out; + + private: + int count; + int samples = 1; + int read = 0; + stream* _in; + + }; } \ No newline at end of file diff --git a/core/src/dsp/resampling.h b/core/src/dsp/resampling.h index cb801292..bf60b3d3 100644 --- a/core/src/dsp/resampling.h +++ b/core/src/dsp/resampling.h @@ -117,7 +117,7 @@ namespace dsp { outIndex++; } } - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { for (int i = 0; outIndex < outCount; i += _decim) { int phase = i % _interp; volk_32fc_32f_dot_prod_32fc((lv_32fc_t*)&out.writeBuf[outIndex], (lv_32fc_t*)&buffer[(i / _interp)], tapPhases[phase], tapsPerPhase); diff --git a/core/src/dsp/window.h b/core/src/dsp/window.h index ad96d0ff..7cc120ee 100644 --- a/core/src/dsp/window.h +++ b/core/src/dsp/window.h @@ -1,5 +1,6 @@ #pragma once #include +#include namespace dsp { namespace filter_window { @@ -9,6 +10,12 @@ namespace dsp { virtual void createTaps(float* taps, int tapCount, float factor = 1.0f) {} }; + class generic_complex_window { + public: + virtual int getTapCount() { return -1; } + virtual void createTaps(dsp::complex_t* taps, int tapCount, float factor = 1.0f) {} + }; + class BlackmanWindow : public filter_window::generic_window { public: BlackmanWindow() {} @@ -72,5 +79,145 @@ namespace dsp { float _cutoff, _transWidth, _sampleRate; }; + + class BlackmanBandpassWindow : public filter_window::generic_window { + public: + BlackmanBandpassWindow() {} + BlackmanBandpassWindow(float cutoff, float transWidth, float offset, float sampleRate) { init(cutoff, transWidth, offset, sampleRate); } + + void init(float cutoff, float transWidth, float offset, float sampleRate) { + _cutoff = cutoff; + _transWidth = transWidth; + _offset = offset; + _sampleRate = sampleRate; + } + + void setSampleRate(float sampleRate) { + _sampleRate = sampleRate; + } + + void setCutoff(float cutoff) { + _cutoff = cutoff; + } + + void setTransWidth(float transWidth) { + _transWidth = transWidth; + } + + void setOffset(float offset) { + _offset = offset; + } + + int getTapCount() { + float fc = _cutoff / _sampleRate; + if (fc > 1.0f) { + fc = 1.0f; + } + + int _M = 4.0f / (_transWidth / _sampleRate); + if (_M < 4) { + _M = 4; + } + + if (_M % 2 == 0) { _M++; } + + return _M; + } + + void createTaps(float* taps, int tapCount, float factor = 1.0f) { + float fc = _cutoff / _sampleRate; + if (fc > 1.0f) { + fc = 1.0f; + } + float tc = tapCount; + float sum = 0.0f; + float val; + for (int i = 0; i < tapCount; i++) { + val = (sin(2.0f * FL_M_PI * fc * ((float)i - (tc / 2))) / ((float)i - (tc / 2))) * + (0.42f - (0.5f * cos(2.0f * FL_M_PI / tc)) + (0.8f * cos(4.0f * FL_M_PI / tc))); + taps[i] = val; // tapCount - i - 1 + sum += val; + } + for (int i = 0; i < tapCount; i++) { + taps[i] *= cos(2.0f * (_offset / _sampleRate) * FL_M_PI * (float)i); + taps[i] *= factor; + taps[i] /= sum; + } + } + + private: + float _cutoff, _transWidth, _sampleRate, _offset; + + }; + + class BlackmanBandpassWindow : public filter_window::generic_complex_window { + public: + BlackmanBandpassWindow() {} + BlackmanBandpassWindow(float cutoff, float transWidth, float offset, float sampleRate) { init(cutoff, transWidth, offset, sampleRate); } + + void init(float cutoff, float transWidth, float offset, float sampleRate) { + _cutoff = cutoff; + _transWidth = transWidth; + _offset = offset; + _sampleRate = sampleRate; + } + + void setSampleRate(float sampleRate) { + _sampleRate = sampleRate; + } + + void setCutoff(float cutoff) { + _cutoff = cutoff; + } + + void setTransWidth(float transWidth) { + _transWidth = transWidth; + } + + void setOffset(float offset) { + _offset = offset; + } + + int getTapCount() { + float fc = _cutoff / _sampleRate; + if (fc > 1.0f) { + fc = 1.0f; + } + + int _M = 4.0f / (_transWidth / _sampleRate); + if (_M < 4) { + _M = 4; + } + + if (_M % 2 == 0) { _M++; } + + return _M; + } + + void createTaps(dsp::complex_t* taps, int tapCount, float factor = 1.0f) { + float fc = _cutoff / _sampleRate; + if (fc > 1.0f) { + fc = 1.0f; + } + float tc = tapCount; + float sum = 0.0f; + float val; + for (int i = 0; i < tapCount; i++) { + val = (sin(2.0f * FL_M_PI * fc * ((float)i - (tc / 2))) / ((float)i - (tc / 2))) * + (0.42f - (0.5f * cos(2.0f * FL_M_PI / tc)) + (0.8f * cos(4.0f * FL_M_PI / tc))); + taps[i] = val; // tapCount - i - 1 + sum += val; + } + for (int i = 0; i < tapCount; i++) { + taps[i] *= cos(2.0f * (_offset / _sampleRate) * FL_M_PI * (float)i); + taps[i] *= factor; + taps[i] /= sum; + } + } + + private: + float _cutoff, _transWidth, _sampleRate, _offset; + + }; } } \ No newline at end of file diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index ab8c39eb..2da1cd85 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -61,29 +61,30 @@ double findBestRange(double bandwidth, int maxSteps) { } void printAndScale(double freq, char* buf) { - if (freq < 1000) { - sprintf(buf, "%.3lf", freq); + double freqAbs = fabs(freq); + if (freqAbs < 1000) { + sprintf(buf, "%.6g", freq); } - else if (freq < 1000000) { - sprintf(buf, "%.3lfK", freq / 1000.0); + else if (freqAbs < 1000000) { + sprintf(buf, "%.6lgK", freq / 1000.0); } - else if (freq < 1000000000) { - sprintf(buf, "%.3lfM", freq / 1000000.0); + else if (freqAbs < 1000000000) { + sprintf(buf, "%.6lgM", freq / 1000000.0); } - else if (freq < 1000000000000) { - sprintf(buf, "%.3lfG", freq / 1000000000.0); - } - for (int i = strlen(buf) - 2; i >= 0; i--) { - if (buf[i] != '0') { - if (buf[i] == '.') { - i--; - } - char scale = buf[strlen(buf) - 1]; - buf[i + 1] = scale; - buf[i + 2] = 0; - return; - } + else if (freqAbs < 1000000000000) { + sprintf(buf, "%.6lgG", freq / 1000000000.0); } + // for (int i = strlen(buf) - 2; i >= 0; i--) { + // if (buf[i] != '0') { + // if (buf[i] == '.') { + // i--; + // } + // char scale = buf[strlen(buf) - 1]; + // buf[i + 1] = scale; + // buf[i + 2] = 0; + // return; + // } + // } } namespace ImGui { diff --git a/core/src/module.cpp b/core/src/module.cpp index 58a79e4e..71923266 100644 --- a/core/src/module.cpp +++ b/core/src/module.cpp @@ -17,7 +17,7 @@ ModuleManager::Module_t ModuleManager::loadModule(std::string path) { #ifdef _WIN32 mod.handle = LoadLibraryA(path.c_str()); if (mod.handle == NULL) { - spdlog::error("Couldn't load {0}.", path); + spdlog::error("Couldn't load {0}. Error code: {1}", path, GetLastError()); mod.handle = NULL; return mod; } diff --git a/radio/src/cw_demod.h b/radio/src/cw_demod.h index 77a07aca..d106a0f5 100644 --- a/radio/src/cw_demod.h +++ b/radio/src/cw_demod.h @@ -170,7 +170,7 @@ private: const float bwMax = 500; const float bwMin = 100; - const float bbSampRate = 6000; + const float bbSampRate = 500; std::string uiPrefix; float snapInterval = 10; diff --git a/radio/src/fm_demod.h b/radio/src/fm_demod.h index 9af09b36..cd8e2ac8 100644 --- a/radio/src/fm_demod.h +++ b/radio/src/fm_demod.h @@ -48,15 +48,12 @@ public: resamp.init(&demod.out, &win, bbSampRate, audioSampRate); win.setSampleRate(bbSampRate * resamp.getInterpolation()); resamp.updateWindow(&win); - - m2s.init(&resamp.out); } void start() { squelch.start(); demod.start(); resamp.start(); - m2s.start(); running = true; } @@ -64,7 +61,6 @@ public: squelch.stop(); demod.stop(); resamp.stop(); - m2s.stop(); running = false; } @@ -108,7 +104,7 @@ public: } dsp::stream* getOutput() { - return &m2s.out; + return &resamp.out; } void showMenu() { @@ -172,8 +168,7 @@ private: dsp::Squelch squelch; dsp::FMDemod demod; dsp::filter_window::BlackmanWindow win; - dsp::PolyphaseResampler resamp; - dsp::MonoToStereo m2s; + dsp::PolyphaseResampler resamp; ConfigManager* _config; diff --git a/radio/src/wfm_demod.h b/radio/src/wfm_demod.h index 9c9d0cb1..ffe48203 100644 --- a/radio/src/wfm_demod.h +++ b/radio/src/wfm_demod.h @@ -57,7 +57,6 @@ public: deemp.init(&resamp.out, audioSampRate, tau); - m2s.init(&deemp.out); } void start() { @@ -65,7 +64,6 @@ public: demod.start(); resamp.start(); deemp.start(); - m2s.start(); running = true; } @@ -74,7 +72,6 @@ public: demod.stop(); resamp.stop(); deemp.stop(); - m2s.stop(); running = false; } @@ -121,7 +118,7 @@ public: } dsp::stream* getOutput() { - return &m2s.out; + return &deemp.out; } void showMenu() { @@ -209,9 +206,8 @@ private: dsp::Squelch squelch; dsp::FMDemod demod; dsp::filter_window::BlackmanWindow win; - dsp::PolyphaseResampler resamp; + dsp::PolyphaseResampler resamp; dsp::BFMDeemp deemp; - dsp::MonoToStereo m2s; ConfigManager* _config; diff --git a/sdrplay_source/src/main.cpp b/sdrplay_source/src/main.cpp index 079135c0..3f6cb9b5 100644 --- a/sdrplay_source/src/main.cpp +++ b/sdrplay_source/src/main.cpp @@ -34,7 +34,7 @@ public: sdrplay_api_Open(); - sampleRate = 10000000.0; + sampleRate = 8000000.0; handler.ctx = this; handler.selectHandler = menuSelected; @@ -185,12 +185,14 @@ private: // Do start procedure here sdrplay_api_ErrT err; - _this->openDevParams->devParams->samplesPerPkt = 8000000 / 200; + _this->bufferIndex = 0; + _this->bufferSize = 8000000 / 200; + _this->openDevParams->devParams->fsFreq.fsHz = 8000000; _this->openDevParams->rxChannelA->tunerParams.bwType = sdrplay_api_BW_8_000; _this->openDevParams->rxChannelA->tunerParams.rfFreq.rfHz = _this->freq; - _this->openDevParams->rxChannelA->tunerParams.gain.gRdB = 30; - _this->openDevParams->rxChannelA->tunerParams.gain.LNAstate = 0; + _this->openDevParams->rxChannelA->tunerParams.gain.gRdB = 59; + _this->openDevParams->rxChannelA->tunerParams.gain.LNAstate = 9; _this->openDevParams->rxChannelA->ctrlParams.agc.enable = sdrplay_api_AGC_DISABLE; //_this->openDevParams->devParams-> @@ -275,7 +277,27 @@ private: } void RSP1AMenu(float menuWidth) { - + ImGui::PushItemWidth(menuWidth - ImGui::CalcTextSize("LNA Gain").x - 10); + ImGui::Text("LNA Gain"); + ImGui::SameLine(); + float pos = ImGui::GetCursorPosX(); + if (ImGui::SliderInt(CONCAT("##sdrplay_lna_gain", name), &gainTest, 9, 0, "")) { + openDevParams->rxChannelA->tunerParams.gain.LNAstate = gainTest; + sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None); + } + + ImGui::Text("IF Gain"); + ImGui::SameLine(); + ImGui::SetCursorPosX(pos); + if (ImGui::SliderInt(CONCAT("##sdrplay_gain", name), &gainTest2, 59, 20, "")) { + openDevParams->rxChannelA->tunerParams.gain.gRdB = gainTest2; + sdrplay_api_Update(openDev.dev, openDev.tuner, sdrplay_api_Update_Tuner_Gr, sdrplay_api_Update_Ext1_None); + } + ImGui::PopItemWidth(); + + bool test = false; + ImGui::Checkbox("FM Notch", &test); + ImGui::Checkbox("DAB Notch", &test); } void RSP2Menu(float menuWidth) { @@ -299,10 +321,15 @@ private: SDRPlaySourceModule* _this = (SDRPlaySourceModule*)cbContext; if (!_this->running) { return; } for (int i = 0; i < numSamples; i++) { - _this->stream.writeBuf[i].i = (float)xq[i] / 32768.0f; - _this->stream.writeBuf[i].q = (float)xi[i] / 32768.0f; + int id = _this->bufferIndex++; + _this->stream.writeBuf[id].i = (float)xq[i] / 32768.0f; + _this->stream.writeBuf[id].q = (float)xi[i] / 32768.0f; + + if (_this->bufferIndex >= _this->bufferSize) { + _this->stream.swap(_this->bufferSize); + _this->bufferIndex = 0; + } } - _this->stream.swap(numSamples); } static void eventCB(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, @@ -327,7 +354,11 @@ private: int devId = 0; int srId = 0; - int gainTest = 0; + int gainTest = 9; + int gainTest2 = 59; + + int bufferSize = 0; + int bufferIndex = 0; std::vector devList; std::string devListTxt;