New DSP code

This commit is contained in:
Ryzerth 2020-07-09 16:02:58 +02:00
parent b78c2cf415
commit 30f1b423a6
9 changed files with 399 additions and 133 deletions

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.9)
project(sdrpp)
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
# Compiler config
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")

View File

@ -31,8 +31,8 @@ namespace dsp {
}
DecimatingFIRFilter(stream<complex_t>* input, std::vector<float> taps, int blockSize, float decim) : output(blockSize * 2) {
output.init(blockSize * 2);
DecimatingFIRFilter(stream<complex_t>* input, std::vector<float> taps, int blockSize, float decim) {
output.init((blockSize * 2) / decim);
_in = input;
_blockSize = blockSize;
_tapCount = taps.size();
@ -54,7 +54,7 @@ namespace dsp {
}
void init(stream<complex_t>* input, std::vector<float>& taps, int blockSize, float decim) {
output.init(blockSize * 2);
output.init((blockSize * 2) / decim);
_in = input;
_blockSize = blockSize;
_tapCount = taps.size();
@ -107,6 +107,8 @@ namespace dsp {
delayBuf = new complex_t[_tapCount];
for (int i = 0; i < _tapCount; i++) {
_taps[i] = taps[i];
delayBuf[i].i = 0;
delayBuf[i].q = 0;
}
}
@ -201,8 +203,8 @@ namespace dsp {
}
FloatDecimatingFIRFilter(stream<float>* input, std::vector<float> taps, int blockSize, float decim) : output(blockSize * 2) {
output.init(blockSize * 2);
FloatDecimatingFIRFilter(stream<float>* input, std::vector<float> taps, int blockSize, float decim) {
output.init((blockSize * 2) / decim);
_in = input;
_blockSize = blockSize;
_tapCount = taps.size();
@ -223,7 +225,7 @@ namespace dsp {
}
void init(stream<float>* input, std::vector<float>& taps, int blockSize, float decim) {
output.init(blockSize * 2);
output.init((blockSize * 2) / decim);
_in = input;
_blockSize = blockSize;
_tapCount = taps.size();
@ -274,6 +276,7 @@ namespace dsp {
delayBuf = new float[_tapCount];
for (int i = 0; i < _tapCount; i++) {
_taps[i] = taps[i];
delayBuf[i] = 0;
}
}

221
src/dsp/legacy_stream.h Normal file
View File

@ -0,0 +1,221 @@
#pragma once
#include <condition_variable>
#include <algorithm>
#include <math.h>
#define STREAM_BUF_SZ 1000000
namespace dsp {
template <class T>
class stream {
public:
stream() {
}
stream(int maxLatency) {
size = STREAM_BUF_SZ;
_buffer = new T[size];
_stopReader = false;
_stopWriter = false;
this->maxLatency = maxLatency;
writec = 0;
readc = size - 1;
}
void init(int maxLatency) {
size = STREAM_BUF_SZ;
_buffer = new T[size];
_stopReader = false;
_stopWriter = false;
this->maxLatency = maxLatency;
writec = 0;
readc = size - 1;
}
int read(T* data, int len) {
int dataRead = 0;
while (dataRead < len) {
int canRead = waitUntilReadable();
if (canRead < 0) {
printf("Reader stopped\n");
clearReadStop();
return -1;
}
int toRead = std::min(canRead, len - dataRead);
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
if (len1 < toRead) {
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
}
dataRead += toRead;
readc_mtx.lock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
return len;
}
int readAndSkip(T* data, int len, int skip) {
int dataRead = 0;
while (dataRead < len) {
int canRead = waitUntilReadable();
if (canRead < 0) {
printf("reader stopped (read and skip)\n");
clearReadStop();
return -1;
}
int toRead = std::min(canRead, len - dataRead);
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
if (len1 < toRead) {
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
}
dataRead += toRead;
readc_mtx.lock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
// Skip
dataRead = 0;
while (dataRead < skip) {
int canRead = waitUntilReadable();
int toRead = std::min(canRead, skip - dataRead);
dataRead += toRead;
readc_mtx.lock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
return len;
}
int waitUntilReadable() {
int canRead = readable();
if (canRead > 0) {
return canRead;
}
std::unique_lock<std::mutex> lck(writec_mtx);
canReadVar.wait(lck, [=](){ return ((this->readable(false) > 0) || this->getReadStop()); });
if (this->getReadStop()) {
return -1;
}
return this->readable(false);
}
int readable(bool lock = true) {
if (lock) { writec_mtx.lock(); }
int _wc = writec;
if (lock) { writec_mtx.unlock(); }
int readable = (_wc - readc) % this->size;
if (_wc < readc) {
readable = (this->size + readable);
}
return readable - 1;
}
int write(T* data, int len) {
int dataWrite = 0;
while (dataWrite < len) {
int canWrite = waitUntilWriteable();
if (canWrite < 0) {
printf("Writer stopped\n");
clearWriteStop();
return -1;
}
int toWrite = std::min(canWrite, len - dataWrite);
int len1 = (toWrite >= (size - writec) ? (size - writec) : (toWrite));
memcpy(&_buffer[writec], &data[dataWrite], len1 * sizeof(T));
if (len1 < toWrite) {
memcpy(_buffer, &data[dataWrite + len1], (toWrite - len1) * sizeof(T));
}
dataWrite += toWrite;
writec_mtx.lock();
writec = (writec + toWrite) % size;
writec_mtx.unlock();
canReadVar.notify_one();
}
return len;
}
int waitUntilWriteable() {
int canWrite = writeable();
if (canWrite > 0) {
return canWrite;
}
std::unique_lock<std::mutex> lck(readc_mtx);
canWriteVar.wait(lck, [=](){ return ((this->writeable(false) > 0) || this->getWriteStop()); });
if (this->getWriteStop()) {
return -1;
}
return this->writeable(false);
}
int writeable(bool lock = true) {
if (lock) { readc_mtx.lock(); }
int _rc = readc;
if (lock) { readc_mtx.unlock(); }
int writeable = (_rc - writec) % this->size;
if (_rc < writec) {
writeable = (this->size + writeable);
}
return std::min<float>(writeable - 1, maxLatency - readable(false) - 1);
}
void stopReader() {
_stopReader = true;
canReadVar.notify_one();
}
void stopWriter() {
_stopWriter = true;
canWriteVar.notify_one();
}
bool getReadStop() {
return _stopReader;
}
bool getWriteStop() {
return _stopWriter;
}
void clearReadStop() {
_stopReader = false;
}
void clearWriteStop() {
_stopWriter = false;
}
void setMaxLatency(int maxLatency) {
this->maxLatency = maxLatency;
}
private:
T* _buffer;
int size;
int readc;
int writec;
int maxLatency;
bool _stopReader;
bool _stopWriter;
std::mutex readc_mtx;
std::mutex writec_mtx;
std::condition_variable canReadVar;
std::condition_variable canWriteVar;
};
};

View File

@ -5,6 +5,8 @@
#include <dsp/types.h>
#include <numeric>
#include <Windows.h>
namespace dsp {
template <class T>
@ -21,7 +23,7 @@ namespace dsp {
}
void init(stream<T>* in, float interpolation, int blockSize) {
output.init(blockSize * 2);
output.init(blockSize * 2 * interpolation);
_input = in;
_interpolation = interpolation;
_blockSize = blockSize;
@ -194,6 +196,9 @@ namespace dsp {
}
void start() {
if (running) {
return;
}
if (_interp != 1) {
interp.start();
}
@ -202,6 +207,9 @@ namespace dsp {
}
void stop() {
if (!running) {
return;
}
interp.stop();
decim.stop();
running = false;
@ -323,6 +331,9 @@ namespace dsp {
}
void start() {
if (running) {
return;
}
if (_interp != 1) {
interp.start();
}
@ -331,8 +342,12 @@ namespace dsp {
}
void stop() {
if (!running) {
return;
}
interp.stop();
decim.stop();
//decim.stop();
Sleep(200);
running = false;
}

View File

@ -26,7 +26,25 @@ namespace dsp {
}
void start() {
if (running) {
return;
}
_workerThread = std::thread(_worker, this);
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;
}
stream<complex_t> output_a;
@ -36,14 +54,16 @@ namespace dsp {
static void _worker(Splitter* _this) {
complex_t* buf = new complex_t[_this->_bufferSize];
while (true) {
_this->_in->read(buf, _this->_bufferSize);
_this->output_a.write(buf, _this->_bufferSize);
_this->output_b.write(buf, _this->_bufferSize);
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; };
}
delete[] buf;
}
stream<complex_t>* _in;
int _bufferSize;
std::thread _workerThread;
bool running = false;
};
};

View File

@ -20,7 +20,10 @@ namespace dsp {
_stopWriter = false;
this->maxLatency = maxLatency;
writec = 0;
readc = size - 1;
readc = 0;
readable = 0;
writable = size;
memset(_buffer, 0, size * sizeof(T));
}
void init(int maxLatency) {
@ -30,35 +33,36 @@ namespace dsp {
_stopWriter = false;
this->maxLatency = maxLatency;
writec = 0;
readc = size - 1;
readc = 0;
readable = 0;
writable = size;
memset(_buffer, 0, size * sizeof(T));
}
int read(T* data, int len) {
int dataRead = 0;
int toRead = 0;
while (dataRead < len) {
int canRead = waitUntilReadable();
if (canRead < 0) {
if (_stopReader) {
printf("Stop reader set");
}
else {
printf("Stop not set");
}
clearReadStop();
return -1;
}
int toRead = std::min(canRead, len - dataRead);
toRead = std::min<int>(waitUntilReadable(), len - dataRead);
if (toRead < 0) { return -1; };
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
if (len1 < toRead) {
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
if ((toRead + readc) > size) {
memcpy(&data[dataRead], &_buffer[readc], (size - readc) * sizeof(T));
memcpy(&data[dataRead + (size - readc)], &_buffer[0], (toRead - (size - readc)) * sizeof(T));
}
else {
memcpy(&data[dataRead], &_buffer[readc], toRead * sizeof(T));
}
dataRead += toRead;
readc_mtx.lock();
_readable_mtx.lock();
readable -= toRead;
_readable_mtx.unlock();
_writable_mtx.lock();
writable += toRead;
_writable_mtx.unlock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
return len;
@ -66,114 +70,113 @@ namespace dsp {
int readAndSkip(T* data, int len, int skip) {
int dataRead = 0;
int toRead = 0;
while (dataRead < len) {
int canRead = waitUntilReadable();
if (canRead < 0) {
clearReadStop();
return -1;
}
int toRead = std::min(canRead, len - dataRead);
toRead = std::min<int>(waitUntilReadable(), len - dataRead);
if (toRead < 0) { return -1; };
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
if (len1 < toRead) {
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
if ((toRead + readc) > size) {
memcpy(&data[dataRead], &_buffer[readc], (size - readc) * sizeof(T));
memcpy(&data[dataRead + (size - readc)], &_buffer[0], (toRead - (size - readc)) * sizeof(T));
}
else {
memcpy(&data[dataRead], &_buffer[readc], toRead * sizeof(T));
}
dataRead += toRead;
readc_mtx.lock();
_readable_mtx.lock();
readable -= toRead;
_readable_mtx.unlock();
_writable_mtx.lock();
writable += toRead;
_writable_mtx.unlock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
// Skip
dataRead = 0;
while (dataRead < skip) {
int canRead = waitUntilReadable();
int toRead = std::min(canRead, skip - dataRead);
toRead = std::min<int>(waitUntilReadable(), skip - dataRead);
if (toRead < 0) { return -1; };
dataRead += toRead;
readc_mtx.lock();
_readable_mtx.lock();
readable -= toRead;
_readable_mtx.unlock();
_writable_mtx.lock();
writable += toRead;
_writable_mtx.unlock();
readc = (readc + toRead) % size;
readc_mtx.unlock();
canWriteVar.notify_one();
}
return len;
}
int waitUntilReadable() {
int canRead = readable();
if (canRead > 0) {
return canRead;
}
std::unique_lock<std::mutex> lck(writec_mtx);
canReadVar.wait(lck, [=](){ return ((this->readable(false) > 0) || this->getReadStop()); });
if (this->getReadStop()) {
return -1;
}
return this->readable(false);
if (_stopReader) { return -1; }
int _r = getReadable();
if (_r != 0) { return _r; }
std::unique_lock<std::mutex> lck(_readable_mtx);
canReadVar.wait(lck, [=](){ return ((this->getReadable(false) > 0) || this->getReadStop()); });
if (_stopReader) { return -1; }
return getReadable(false);
}
int readable(bool lock = true) {
if (lock) { writec_mtx.lock(); }
int _wc = writec;
if (lock) { writec_mtx.unlock(); }
int readable = (_wc - readc) % this->size;
if (_wc < readc) {
readable = (this->size + readable);
}
return readable - 1;
int getReadable(bool lock = true) {
if (lock) { _readable_mtx.lock(); };
int _r = readable;
if (lock) { _readable_mtx.unlock(); };
return _r;
}
int write(T* data, int len) {
int dataWrite = 0;
while (dataWrite < len) {
int canWrite = waitUntilWriteable();
if (canWrite < 0) {
clearWriteStop();
return -1;
}
int toWrite = std::min(canWrite, len - dataWrite);
int dataWritten = 0;
int toWrite = 0;
while (dataWritten < len) {
toWrite = std::min<int>(waitUntilwritable(), len - dataWritten);
if (toWrite < 0) { return -1; };
int len1 = (toWrite >= (size - writec) ? (size - writec) : (toWrite));
memcpy(&_buffer[writec], &data[dataWrite], len1 * sizeof(T));
if (len1 < toWrite) {
memcpy(_buffer, &data[dataWrite + len1], (toWrite - len1) * sizeof(T));
if ((toWrite + writec) > size) {
memcpy(&_buffer[writec], &data[dataWritten], (size - writec) * sizeof(T));
memcpy(&_buffer[0], &data[dataWritten + (size - writec)], (toWrite - (size - writec)) * sizeof(T));
}
else {
memcpy(&_buffer[writec], &data[dataWritten], toWrite * sizeof(T));
}
dataWrite += toWrite;
writec_mtx.lock();
dataWritten += toWrite;
_readable_mtx.lock();
readable += toWrite;
_readable_mtx.unlock();
_writable_mtx.lock();
writable -= toWrite;
_writable_mtx.unlock();
writec = (writec + toWrite) % size;
writec_mtx.unlock();
canReadVar.notify_one();
}
return len;
}
int waitUntilWriteable() {
int canWrite = writeable();
if (canWrite > 0) {
return canWrite;
}
std::unique_lock<std::mutex> lck(readc_mtx);
canWriteVar.wait(lck, [=](){ return ((this->writeable(false) > 0) || this->getWriteStop()); });
if (this->getWriteStop()) {
return -1;
}
return this->writeable(false);
int waitUntilwritable() {
if (_stopWriter) { return -1; }
int _w = getWritable();
if (_w != 0) { return _w; }
std::unique_lock<std::mutex> lck(_writable_mtx);
canWriteVar.wait(lck, [=](){ return ((this->getWritable(false) > 0) || this->getWriteStop()); });
if (_stopWriter) { return -1; }
return getWritable(false);
}
int writeable(bool lock = true) {
if (lock) { readc_mtx.lock(); }
int _rc = readc;
if (lock) { readc_mtx.unlock(); }
int writeable = (_rc - writec) % this->size;
if (_rc < writec) {
writeable = (this->size + writeable);
}
return std::min<float>(writeable - 1, maxLatency - readable(false) - 1);
int getWritable(bool lock = true) {
if (lock) { _writable_mtx.lock(); };
int _w = writable;
if (lock) { _writable_mtx.unlock(); _readable_mtx.lock(); };
int _r = readable;
if (lock) { _readable_mtx.unlock(); };
return std::max<int>(std::min<int>(_w, maxLatency - _r), 0);
}
void stopReader() {
@ -211,11 +214,13 @@ namespace dsp {
int size;
int readc;
int writec;
int readable;
int writable;
int maxLatency;
bool _stopReader;
bool _stopWriter;
std::mutex readc_mtx;
std::mutex writec_mtx;
std::mutex _readable_mtx;
std::mutex _writable_mtx;
std::condition_variable canReadVar;
std::condition_variable canWriteVar;
};

View File

@ -33,7 +33,7 @@ int main() {
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
// Create window with graphics context
GLFWwindow* window = glfwCreateWindow(1280, 720, "SDR++ v0.1.0", NULL, NULL);
GLFWwindow* window = glfwCreateWindow(1280, 720, "SDR++ v0.1.0 (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL);
if (window == NULL)
return 1;
glfwMakeContextCurrent(window);

View File

@ -49,7 +49,7 @@ void fftHandler(dsp::complex_t* samples) {
}
void windowInit() {
int sampleRate = 2000000;
int sampleRate = 8000000;
wtf.bandWidth = sampleRate;
wtf.range = 500000;
wtf.centerFrequency = 90500000;

View File

@ -49,31 +49,31 @@ void SignalPath::setDemodulator(int demId) {
audioResamp.stop();
// Stop current demodulator
if (_demod == DEMOD_FM) {
printf("Stopping FM demodulator\n");
demod.stop();
}
else if (_demod == DEMOD_AM) {
printf("Stopping AM demodulator\n");
amDemod.stop();
}
_demod = demId;
// if (_demod == DEMOD_FM) {
// printf("Stopping FM demodulator\n");
// demod.stop();
// }
// else if (_demod == DEMOD_AM) {
// printf("Stopping AM demodulator\n");
// amDemod.stop();
// }
// _demod = demId;
// Set input of the audio resampler
if (demId == DEMOD_FM) {
printf("Starting FM demodulator\n");
mainVFO.setOutputSampleRate(200000, 200000);
audioResamp.setInput(&demod.output);
audioResamp.setInputSampleRate(200000, 800);
demod.start();
}
else if (demId == DEMOD_AM) {
printf("Starting AM demodulator\n");
mainVFO.setOutputSampleRate(12500, 12500);
audioResamp.setInput(&amDemod.output);
audioResamp.setInputSampleRate(12500, 50);
amDemod.start();
}
// // Set input of the audio resampler
// if (demId == DEMOD_FM) {
// printf("Starting FM demodulator\n");
// // mainVFO.setOutputSampleRate(200000, 200000);
// // audioResamp.setInput(&demod.output);
// // audioResamp.setInputSampleRate(200000, 800);
// demod.start();
// }
// else if (demId == DEMOD_AM) {
// printf("Starting AM demodulator\n");
// mainVFO.setOutputSampleRate(12500, 12500);
// audioResamp.setInput(&amDemod.output);
// audioResamp.setInputSampleRate(12500, 50);
// amDemod.start();
// }
audioResamp.start();
}