#pragma once #include #include #include #include #include namespace dsp { class VFO { public: VFO() {} ~VFO() { if (!_init) { return; } stop(); _init = false; } VFO(stream* in, float offset, float inSampleRate, float outSampleRate, float bandWidth) { init(in, offset, inSampleRate, outSampleRate, bandWidth); }; void init(stream* in, float offset, float inSampleRate, float outSampleRate, float bandWidth) { _in = in; _offset = offset; _inSampleRate = inSampleRate; _outSampleRate = outSampleRate; _bandWidth = bandWidth; float realCutoff = std::min(_bandWidth, std::min(_inSampleRate, _outSampleRate)) / 2.0f; xlator.init(_in, _inSampleRate, -_offset); win.init(realCutoff, realCutoff, inSampleRate); resamp.init(&xlator.out, &win, _inSampleRate, _outSampleRate); win.setSampleRate(_inSampleRate * resamp.getInterpolation()); resamp.updateWindow(&win); out = &resamp.out; _init = true; } void start() { assert(_init); if (running) { return; } xlator.start(); resamp.start(); } void stop() { assert(_init); if (!running) { return; } xlator.stop(); resamp.stop(); } void setInSampleRate(float inSampleRate) { assert(_init); _inSampleRate = inSampleRate; if (running) { xlator.stop(); resamp.stop(); } xlator.setSampleRate(_inSampleRate); resamp.setInSampleRate(_inSampleRate); float realCutoff = std::min(_bandWidth, std::min(_inSampleRate, _outSampleRate)) / 2.0f; win.setSampleRate(_inSampleRate * resamp.getInterpolation()); win.setCutoff(realCutoff); win.setTransWidth(realCutoff); resamp.updateWindow(&win); if (running) { xlator.start(); resamp.start(); } } void setOutSampleRate(float outSampleRate) { assert(_init); _outSampleRate = outSampleRate; if (running) { resamp.stop(); } resamp.setOutSampleRate(_outSampleRate); float realCutoff = std::min(_bandWidth, std::min(_inSampleRate, _outSampleRate)) / 2.0f; win.setSampleRate(_inSampleRate * resamp.getInterpolation()); win.setCutoff(realCutoff); win.setTransWidth(realCutoff); resamp.updateWindow(&win); if (running) { resamp.start(); } } void setOutSampleRate(float outSampleRate, float bandWidth) { assert(_init); _outSampleRate = outSampleRate; _bandWidth = bandWidth; if (running) { resamp.stop(); } resamp.setOutSampleRate(_outSampleRate); float realCutoff = std::min(_bandWidth, std::min(_inSampleRate, _outSampleRate)) / 2.0f; win.setSampleRate(_inSampleRate * resamp.getInterpolation()); win.setCutoff(realCutoff); win.setTransWidth(realCutoff); resamp.updateWindow(&win); if (running) { resamp.start(); } } void setOffset(float offset) { assert(_init); _offset = offset; xlator.setFrequency(-_offset); } void setBandwidth(float bandWidth) { assert(_init); _bandWidth = bandWidth; float realCutoff = std::min(_bandWidth, std::min(_inSampleRate, _outSampleRate)) / 2.0f; win.setCutoff(realCutoff); win.setTransWidth(realCutoff); resamp.updateWindow(&win); } stream* out; private: bool _init = false; bool running = false; float _offset, _inSampleRate, _outSampleRate, _bandWidth; filter_window::BlackmanWindow win; stream* _in; FrequencyXlator xlator; PolyphaseResampler resamp; }; }