SDRPlusPlus/core/src/dsp/routing.h

310 lines
8.2 KiB
C
Raw Normal View History

2020-06-22 16:45:57 +02:00
#pragma once
#include <thread>
#include <dsp/stream.h>
#include <dsp/types.h>
#include <vector>
2020-08-18 00:56:51 +02:00
#include <spdlog/spdlog.h>
2020-06-22 16:45:57 +02:00
namespace dsp {
class Splitter {
public:
Splitter() {
}
Splitter(stream<complex_t>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
output_a.init(bufferSize);
output_b.init(bufferSize);
}
void init(stream<complex_t>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
output_a.init(bufferSize);
output_b.init(bufferSize);
}
void start() {
2020-07-09 16:02:58 +02:00
if (running) {
return;
}
2020-06-22 16:45:57 +02:00
_workerThread = std::thread(_worker, this);
2020-07-09 16:02:58 +02:00
running = true;
}
void stop() {
if (!running) {
return;
}
_in->stopReader();
output_a.stopWriter();
output_b.stopWriter();
_workerThread.join();
_in->clearReadStop();
output_a.clearWriteStop();
output_b.clearWriteStop();
running = false;
2020-06-22 16:45:57 +02:00
}
2020-07-19 15:59:44 +02:00
void setBlockSize(int blockSize) {
if (running) {
return;
}
_bufferSize = blockSize;
output_a.setMaxLatency(blockSize * 2);
output_b.setMaxLatency(blockSize * 2);
}
2020-06-22 16:45:57 +02:00
stream<complex_t> output_a;
stream<complex_t> output_b;
private:
static void _worker(Splitter* _this) {
complex_t* buf = new complex_t[_this->_bufferSize];
while (true) {
2020-07-09 16:02:58 +02:00
if (_this->_in->read(buf, _this->_bufferSize) < 0) { break; };
if (_this->output_a.write(buf, _this->_bufferSize) < 0) { break; };
if (_this->output_b.write(buf, _this->_bufferSize) < 0) { break; };
2020-06-22 16:45:57 +02:00
}
2020-07-09 16:02:58 +02:00
delete[] buf;
2020-06-22 16:45:57 +02:00
}
stream<complex_t>* _in;
int _bufferSize;
std::thread _workerThread;
2020-07-09 16:02:58 +02:00
bool running = false;
2020-06-22 16:45:57 +02:00
};
2020-08-11 18:33:42 +02:00
2020-08-16 03:39:05 +02:00
template <class T>
2020-08-11 18:33:42 +02:00
class DynamicSplitter {
public:
DynamicSplitter() {
}
2020-08-16 03:39:05 +02:00
DynamicSplitter(stream<T>* input, int bufferSize) {
2020-08-11 18:33:42 +02:00
_in = input;
_bufferSize = bufferSize;
}
2020-08-16 03:39:05 +02:00
void init(stream<T>* input, int bufferSize) {
2020-08-11 18:33:42 +02:00
_in = input;
_bufferSize = bufferSize;
}
void start() {
if (running) {
return;
}
_workerThread = std::thread(_worker, this);
running = true;
}
void stop() {
if (!running) {
return;
}
_in->stopReader();
int outputCount = outputs.size();
for (int i = 0; i < outputCount; i++) {
outputs[i]->stopWriter();
}
_workerThread.join();
_in->clearReadStop();
for (int i = 0; i < outputCount; i++) {
outputs[i]->clearWriteStop();
}
running = false;
}
void setBlockSize(int blockSize) {
if (running) {
return;
}
_bufferSize = blockSize;
int outputCount = outputs.size();
for (int i = 0; i < outputCount; i++) {
outputs[i]->setMaxLatency(blockSize * 2);
}
}
2020-08-16 03:39:05 +02:00
void bind(stream<T>* stream) {
2020-08-11 18:33:42 +02:00
if (running) {
return;
}
outputs.push_back(stream);
}
2020-08-16 03:39:05 +02:00
void unbind(stream<T>* stream) {
2020-08-11 18:33:42 +02:00
if (running) {
return;
}
int outputCount = outputs.size();
for (int i = 0; i < outputCount; i++) {
if (outputs[i] == stream) {
outputs.erase(outputs.begin() + i);
2020-08-18 00:56:51 +02:00
return;
2020-08-11 18:33:42 +02:00
}
}
}
private:
static void _worker(DynamicSplitter* _this) {
2020-08-16 03:39:05 +02:00
T* buf = new T[_this->_bufferSize];
2020-08-11 18:33:42 +02:00
int outputCount = _this->outputs.size();
while (true) {
if (_this->_in->read(buf, _this->_bufferSize) < 0) { break; };
for (int i = 0; i < outputCount; i++) {
if (_this->outputs[i]->write(buf, _this->_bufferSize) < 0) { break; };
}
}
delete[] buf;
}
2020-08-16 03:39:05 +02:00
stream<T>* _in;
int _bufferSize;
std::thread _workerThread;
bool running = false;
std::vector<stream<T>*> outputs;
};
class MonoToStereo {
public:
MonoToStereo() {
}
MonoToStereo(stream<float>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
2020-08-18 00:56:51 +02:00
output.init(bufferSize * 2);
2020-08-16 03:39:05 +02:00
}
void init(stream<float>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
2020-08-18 00:56:51 +02:00
output.init(bufferSize * 2);
2020-08-16 03:39:05 +02:00
}
void start() {
if (running) {
return;
}
_workerThread = std::thread(_worker, this);
running = true;
}
void stop() {
if (!running) {
return;
}
_in->stopReader();
output.stopWriter();
_workerThread.join();
_in->clearReadStop();
output.clearWriteStop();
running = false;
}
void setBlockSize(int blockSize) {
if (running) {
return;
}
_bufferSize = blockSize;
output.setMaxLatency(blockSize * 2);
}
stream<StereoFloat_t> output;
private:
static void _worker(MonoToStereo* _this) {
float* inBuf = new float[_this->_bufferSize];
StereoFloat_t* outBuf = new StereoFloat_t[_this->_bufferSize];
while (true) {
if (_this->_in->read(inBuf, _this->_bufferSize) < 0) { break; };
for (int i = 0; i < _this->_bufferSize; i++) {
outBuf[i].l = inBuf[i];
outBuf[i].r = inBuf[i];
}
if (_this->output.write(outBuf, _this->_bufferSize) < 0) { break; };
}
delete[] inBuf;
delete[] outBuf;
}
stream<float>* _in;
int _bufferSize;
std::thread _workerThread;
bool running = false;
};
class StereoToMono {
public:
StereoToMono() {
}
StereoToMono(stream<StereoFloat_t>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
}
void init(stream<StereoFloat_t>* input, int bufferSize) {
_in = input;
_bufferSize = bufferSize;
}
void start() {
if (running) {
return;
}
_workerThread = std::thread(_worker, this);
running = true;
}
void stop() {
if (!running) {
return;
}
_in->stopReader();
output.stopWriter();
_workerThread.join();
_in->clearReadStop();
output.clearWriteStop();
running = false;
}
void setBlockSize(int blockSize) {
if (running) {
return;
}
_bufferSize = blockSize;
output.setMaxLatency(blockSize * 2);
}
stream<float> output;
private:
static void _worker(StereoToMono* _this) {
StereoFloat_t* inBuf = new StereoFloat_t[_this->_bufferSize];
float* outBuf = new float[_this->_bufferSize];
while (true) {
if (_this->_in->read(inBuf, _this->_bufferSize) < 0) { break; };
for (int i = 0; i < _this->_bufferSize; i++) {
outBuf[i] = (inBuf[i].l + inBuf[i].r) / 2.0f;
}
if (_this->output.write(outBuf, _this->_bufferSize) < 0) { break; };
}
delete[] inBuf;
delete[] outBuf;
}
stream<StereoFloat_t>* _in;
2020-08-11 18:33:42 +02:00
int _bufferSize;
std::thread _workerThread;
bool running = false;
};
2020-06-22 16:45:57 +02:00
};