more work

This commit is contained in:
AlexandreRouma 2023-07-09 18:34:52 +02:00
parent 2a741932e0
commit 4c584847de
13 changed files with 131 additions and 126 deletions

View File

@ -35,6 +35,9 @@ namespace streamsmenu {
sink->showMenu();
// Volume slider + mute button
ImGui::FillWidth();
if (ImGui::Button(CONCAT("Remove##sdrpp_streams_remove_type_", name))) {
sinksToBeRemoved.push_back(id);
@ -50,7 +53,7 @@ namespace streamsmenu {
ImGui::SameLine();
ImGui::FillWidth();
if (ImGui::Button(CONCAT("Add##sdrpp_streams_add_btn_", name))) {
stream->addSink("Sink 2");
stream->addSink("Audio");
}
ImGui::EndTable();

View File

@ -144,7 +144,6 @@ AudioStream::AudioStream(StreamManager* manager, const std::string& name, dsp::s
// Initialize DSP
split.init(stream);
split.start();
}
AudioStream::~AudioStream() {
@ -173,11 +172,14 @@ void AudioStream::setInput(dsp::stream<dsp::stereo_t>* stream, double samplerate
this->samplerate = samplerate;
// Stop DSP
split.stop();
for (auto& [id, sink] : sinks) {
sink->stopDSP();
if (running) {
split.stop();
for (auto& [id, sink] : sinks) {
sink->stopDSP();
}
}
// Set input and samplerate
split.setInput(stream);
for (auto& [id, sink] : sinks) {
@ -185,10 +187,12 @@ void AudioStream::setInput(dsp::stream<dsp::stereo_t>* stream, double samplerate
}
// Start DSP
for (auto& [id, sink] : sinks) {
sink->startDSP();
if (running) {
for (auto& [id, sink] : sinks) {
sink->startDSP();
}
split.start();
}
split.start();
}
void AudioStream::setSamplerate(double samplerate) {
@ -198,9 +202,11 @@ void AudioStream::setSamplerate(double samplerate) {
this->samplerate = samplerate;
// Stop DSP
split.stop();
for (auto& [id, sink] : sinks) {
sink->stopDSP();
if (running) {
split.stop();
for (auto& [id, sink] : sinks) {
sink->stopDSP();
}
}
// Set samplerate
@ -209,10 +215,12 @@ void AudioStream::setSamplerate(double samplerate) {
}
// Start DSP
for (auto& [id, sink] : sinks) {
sink->startDSP();
if (running) {
for (auto& [id, sink] : sinks) {
sink->startDSP();
}
split.start();
}
split.start();
}
const std::string& AudioStream::getName() const {
@ -246,7 +254,7 @@ SinkID AudioStream::addSink(const std::string& type, SinkID id) {
// Start the sink and DSP
sink->startSink();
sink->startDSP();
if (running) { sink->startDSP(); }
// Bind the sinks's input
split.bindStream(&sink->input);
@ -313,6 +321,36 @@ const std::map<SinkID, std::shared_ptr<SinkEntry>>& AudioStream::getSinks() cons
return sinks;
}
void AudioStream::startDSP() {
// TODO: Maybe add a different mutex for the stream?
std::unique_lock<std::shared_mutex> lck(sinksMtx);
// Check if already running
if (running) { return; }
// Start all DSP
split.start();
for (auto& [id, sink] : sinks) {
sink->startDSP();
}
running = true;
}
void AudioStream::stopDSP() {
// TODO: Maybe add a different mutex for the stream?
std::unique_lock<std::shared_mutex> lck(sinksMtx);
// Check if already running
if (!running) { return; }
// Start all DSP
split.stop();
for (auto& [id, sink] : sinks) {
sink->stopDSP();
}
running = false;
}
std::shared_ptr<AudioStream> StreamManager::createStream(const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) {
std::unique_lock<std::shared_mutex> lck(streamsMtx);

View File

@ -146,7 +146,6 @@ private:
dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
dsp::audio::Volume volumeAdjust;
SinkProvider* provider = NULL;
std::unique_ptr<Sink> sink;
std::string type;
@ -216,6 +215,18 @@ public:
*/
const std::map<SinkID, std::shared_ptr<SinkEntry>>& getSinks() const;
// TODO: This should only be callable by the module that created the stream
/**
* Start the DSP.
*/
void startDSP();
/**
* Stop the DSP.
*/
void stopDSP();
// Emitted when the samplerate of the stream was changed
NewEvent<double> onSamplerateChanged;
// Emitted when a sink was added
@ -228,6 +239,7 @@ private:
const std::string name;
double samplerate;
dsp::routing::Splitter<dsp::stereo_t> split;
bool running = false;
std::map<SinkID, std::shared_ptr<SinkEntry>> sinks;
std::shared_mutex sinksMtx;

View File

@ -24,13 +24,12 @@ namespace demod {
class Demodulator {
public:
virtual ~Demodulator() {}
virtual void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) = 0;
virtual void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) = 0;
virtual void start() = 0;
virtual void stop() = 0;
virtual void showMenu() = 0;
virtual void setBandwidth(double bandwidth) = 0;
virtual void setInput(dsp::stream<dsp::complex_t>* input) = 0;
virtual void AFSampRateChanged(double newSR) = 0;
virtual const char* getName() = 0;
virtual double getIFSampleRate() = 0;
virtual double getAFSampleRate() = 0;

View File

@ -7,13 +7,13 @@ namespace demod {
public:
AM() {}
AM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
AM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~AM() { stop(); }
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
_config = config;
@ -68,8 +68,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "AM"; }

View File

@ -7,15 +7,15 @@ namespace demod {
public:
CW() {}
CW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
CW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~CW() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
this->_config = config;
this->afbwChangeHandler = afbwChangeHandler;
@ -74,8 +74,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "CW"; }

View File

@ -7,15 +7,15 @@ namespace demod {
public:
DSB() {}
DSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
DSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~DSB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
_config = config;
@ -61,8 +61,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "DSB"; }

View File

@ -7,15 +7,15 @@ namespace demod {
public:
LSB() {}
LSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
LSB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~LSB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
_config = config;
@ -61,8 +61,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "LSB"; }

View File

@ -7,13 +7,13 @@ namespace demod {
public:
NFM() {}
NFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
NFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~NFM() { stop(); }
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
this->_config = config;
@ -57,8 +57,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "FM"; }

View File

@ -7,17 +7,18 @@ namespace demod {
public:
RAW() {}
RAW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
RAW(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~RAW() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
audioSampleRate = audioSR;
audioSampleRate = 48000;
// TODO: This needs to be selectable
// Define structure
c2s.init(input);
@ -39,10 +40,6 @@ namespace demod {
c2s.setInput(input);
}
void AFSampRateChanged(double newSR) {
audioSampleRate = newSR;
}
// ============= INFO =============
const char* getName() { return "RAW"; }

View File

@ -8,15 +8,15 @@ namespace demod {
public:
USB() {}
USB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
USB(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~USB() {
stop();
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
_config = config;
@ -62,8 +62,6 @@ namespace demod {
void setInput(dsp::stream<dsp::complex_t>* input) { demod.setInput(input); }
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "USB"; }

View File

@ -16,8 +16,8 @@ namespace demod {
public:
WFM() {}
WFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
init(name, config, input, bandwidth, audioSR);
WFM(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
init(name, config, input, bandwidth);
}
~WFM() {
@ -25,7 +25,7 @@ namespace demod {
gui::waterfall.onFFTRedraw.unbindHandler(&fftRedrawHandler);
}
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth, double audioSR) {
void init(std::string name, ConfigManager* config, dsp::stream<dsp::complex_t>* input, double bandwidth) {
this->name = name;
_config = config;
@ -112,8 +112,6 @@ namespace demod {
demod.setInput(input);
}
void AFSampRateChanged(double newSR) {}
// ============= INFO =============
const char* getName() { return "WFM"; }

View File

@ -81,30 +81,16 @@ public:
// Initialize audio DSP chain
afChain.init(&dummyAudioStream);
resamp.init(NULL, 250000.0, 48000.0);
deemp.init(NULL, 50e-6, 48000.0);
afChain.addBlock(&resamp, true);
afChain.addBlock(&deemp, false);
// Initialize the sink
srChangeHandler.ctx = this;
srChangeHandler.handler = sampleRateChangeHandler;
stream.init(afChain.out, &srChangeHandler, audioSampleRate);
sigpath::sinkManager.registerStream(name, &stream);
stream = sigpath::streamManager.createStream(name, afChain.out, 48000);
// Select the demodulator
selectDemodByID((DemodID)selectedDemodID);
// Start IF chain
ifChain.start();
// Start AF chain
afChain.start();
// Start stream, the rest was started when selecting the demodulator
stream.start();
// Register the menu
gui::menu.registerEntry(name, menuHandler, this, this);
@ -115,11 +101,10 @@ public:
~RadioModule() {
core::modComManager.unregisterInterface(name);
gui::menu.removeEntry(name);
stream.stop();
if (enabled) {
disable();
}
sigpath::sinkManager.unregisterStream(name);
sigpath::streamManager.destroyStream(stream);
}
void postInit() {}
@ -131,9 +116,7 @@ public:
vfo->wtfVFO->onUserChangedBandwidth.bindHandler(&onUserChangedBandwidthHandler);
}
ifChain.setInput(vfo->output, [=](dsp::stream<dsp::complex_t>* out){ ifChainOutputChangeHandler(out, this); });
ifChain.start();
selectDemodByID((DemodID)selectedDemodID);
afChain.start();
}
void disable() {
@ -141,6 +124,7 @@ public:
ifChain.stop();
if (selectedDemod) { selectedDemod->stop(); }
afChain.stop();
stream->stopDSP();
if (vfo) { sigpath::vfoManager.deleteVFO(vfo); }
vfo = NULL;
}
@ -313,7 +297,7 @@ private:
bw = std::clamp<double>(bw, demod->getMinBandwidth(), demod->getMaxBandwidth());
// Initialize
demod->init(name, &config, ifChain.out, bw, stream.getSampleRate());
demod->init(name, &config, ifChain.out, bw);
return demod;
}
@ -337,22 +321,34 @@ private:
}
void selectDemod(demod::Demodulator* demod) {
// Stopcurrently selected demodulator and select new
afChain.setInput(&dummyAudioStream, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
// Stop the IF chain
ifChain.stop();
// Stop the current demodulator
if (selectedDemod) {
selectedDemod->stop();
}
// Stop AF chain
afChain.stop();
// Stop audio stream's DSP
stream->stopDSP();
// Destroy the old demodulator
afChain.setInput(&dummyAudioStream, [=](dsp::stream<dsp::stereo_t>* out){ stream->setInput(out); });
if (selectedDemod) {
delete selectedDemod;
}
selectedDemod = demod;
// Give the demodulator the most recent audio SR
selectedDemod->AFSampRateChanged(audioSampleRate);
// Select the new demodulator
selectedDemod = demod;
// Set the demodulator's input
selectedDemod->setInput(ifChain.out);
// Set AF chain's input
afChain.setInput(selectedDemod->getOutput(), [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
afChain.setInput(selectedDemod->getOutput(), [=](dsp::stream<dsp::stereo_t>* out){ stream->setInput(out); });
// Load config
bandwidth = selectedDemod->getDefaultBandwidth();
@ -440,21 +436,27 @@ private:
// Configure AF chain
if (postProcEnabled) {
// Configure resampler
afChain.stop();
resamp.setInSamplerate(selectedDemod->getAFSampleRate());
setAudioSampleRate(audioSampleRate);
afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
deemp.setSamplerate(selectedDemod->getAFSampleRate());
// Configure deemphasis
setDeemphasisMode(deempModes[deempId]);
}
else {
// Disable everything if post processing is disabled
afChain.disableAllBlocks([=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
afChain.disableAllBlocks([=](dsp::stream<dsp::stereo_t>* out){ stream->setInput(out); });
}
// Start the IF chain
ifChain.start();
// Start new demodulator
selectedDemod->start();
// Start the AF chain
afChain.start();
// Start the audio stream
stream->startDSP();
}
@ -470,37 +472,12 @@ private:
config.release(true);
}
void setAudioSampleRate(double sr) {
audioSampleRate = sr;
if (!selectedDemod) { return; }
selectedDemod->AFSampRateChanged(audioSampleRate);
if (!postProcEnabled && vfo) {
// If postproc is disabled, IF SR = AF SR
minBandwidth = selectedDemod->getMinBandwidth();
maxBandwidth = selectedDemod->getMaxBandwidth();
bandwidth = selectedDemod->getIFSampleRate();
vfo->setBandwidthLimits(minBandwidth, maxBandwidth, selectedDemod->getBandwidthLocked());
vfo->setSampleRate(selectedDemod->getIFSampleRate(), bandwidth);
return;
}
afChain.stop();
// Configure resampler
resamp.setOutSamplerate(audioSampleRate);
// Configure deemphasis sample rate
deemp.setSamplerate(audioSampleRate);
afChain.start();
}
void setDeemphasisMode(DeemphasisMode mode) {
deempId = deempModes.valueId(mode);
if (!postProcEnabled || !selectedDemod) { return; }
bool deempEnabled = (mode != DEEMP_MODE_NONE);
if (deempEnabled) { deemp.setTau(deempTaus[mode]); }
afChain.setBlockEnabled(&deemp, deempEnabled, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
afChain.setBlockEnabled(&deemp, deempEnabled, [=](dsp::stream<dsp::stereo_t>* out){ stream->setInput(out); });
// Save config
config.acquire();
@ -584,11 +561,6 @@ private:
_this->setBandwidth(newBw);
}
static void sampleRateChangeHandler(float sampleRate, void* ctx) {
RadioModule* _this = (RadioModule*)ctx;
_this->setAudioSampleRate(sampleRate);
}
static void ifChainOutputChangeHandler(dsp::stream<dsp::complex_t>* output, void* ctx) {
RadioModule* _this = (RadioModule*)ctx;
if (!_this->selectedDemod) { return; }
@ -643,7 +615,6 @@ private:
// Handlers
EventHandler<double> onUserChangedBandwidthHandler;
EventHandler<float> srChangeHandler;
EventHandler<dsp::stream<dsp::complex_t>*> ifChainOutputChanged;
EventHandler<dsp::stream<dsp::stereo_t>*> afChainOutputChanged;
@ -658,10 +629,9 @@ private:
// Audio chain
dsp::stream<dsp::stereo_t> dummyAudioStream;
dsp::chain<dsp::stereo_t> afChain;
dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
dsp::filter::Deemphasis<dsp::stereo_t> deemp;
SinkManager::Stream stream;
std::shared_ptr<AudioStream> stream;
demod::Demodulator* selectedDemod = NULL;