mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-11 18:57:11 +01:00
New DSP code
This commit is contained in:
parent
b78c2cf415
commit
30f1b423a6
@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
project(sdrpp)
|
project(sdrpp)
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||||
|
|
||||||
# Compiler config
|
# Compiler config
|
||||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ namespace dsp {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DecimatingFIRFilter(stream<complex_t>* input, std::vector<float> taps, int blockSize, float decim) : output(blockSize * 2) {
|
DecimatingFIRFilter(stream<complex_t>* input, std::vector<float> taps, int blockSize, float decim) {
|
||||||
output.init(blockSize * 2);
|
output.init((blockSize * 2) / decim);
|
||||||
_in = input;
|
_in = input;
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_tapCount = taps.size();
|
_tapCount = taps.size();
|
||||||
@ -54,7 +54,7 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init(stream<complex_t>* input, std::vector<float>& taps, int blockSize, float decim) {
|
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;
|
_in = input;
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_tapCount = taps.size();
|
_tapCount = taps.size();
|
||||||
@ -107,6 +107,8 @@ namespace dsp {
|
|||||||
delayBuf = new complex_t[_tapCount];
|
delayBuf = new complex_t[_tapCount];
|
||||||
for (int i = 0; i < _tapCount; i++) {
|
for (int i = 0; i < _tapCount; i++) {
|
||||||
_taps[i] = taps[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) {
|
FloatDecimatingFIRFilter(stream<float>* input, std::vector<float> taps, int blockSize, float decim) {
|
||||||
output.init(blockSize * 2);
|
output.init((blockSize * 2) / decim);
|
||||||
_in = input;
|
_in = input;
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_tapCount = taps.size();
|
_tapCount = taps.size();
|
||||||
@ -223,7 +225,7 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init(stream<float>* input, std::vector<float>& taps, int blockSize, float decim) {
|
void init(stream<float>* input, std::vector<float>& taps, int blockSize, float decim) {
|
||||||
output.init(blockSize * 2);
|
output.init((blockSize * 2) / decim);
|
||||||
_in = input;
|
_in = input;
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
_tapCount = taps.size();
|
_tapCount = taps.size();
|
||||||
@ -274,6 +276,7 @@ namespace dsp {
|
|||||||
delayBuf = new float[_tapCount];
|
delayBuf = new float[_tapCount];
|
||||||
for (int i = 0; i < _tapCount; i++) {
|
for (int i = 0; i < _tapCount; i++) {
|
||||||
_taps[i] = taps[i];
|
_taps[i] = taps[i];
|
||||||
|
delayBuf[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
221
src/dsp/legacy_stream.h
Normal file
221
src/dsp/legacy_stream.h
Normal 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;
|
||||||
|
};
|
||||||
|
};
|
@ -5,6 +5,8 @@
|
|||||||
#include <dsp/types.h>
|
#include <dsp/types.h>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -21,7 +23,7 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init(stream<T>* in, float interpolation, int blockSize) {
|
void init(stream<T>* in, float interpolation, int blockSize) {
|
||||||
output.init(blockSize * 2);
|
output.init(blockSize * 2 * interpolation);
|
||||||
_input = in;
|
_input = in;
|
||||||
_interpolation = interpolation;
|
_interpolation = interpolation;
|
||||||
_blockSize = blockSize;
|
_blockSize = blockSize;
|
||||||
@ -194,6 +196,9 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_interp != 1) {
|
if (_interp != 1) {
|
||||||
interp.start();
|
interp.start();
|
||||||
}
|
}
|
||||||
@ -202,6 +207,9 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
interp.stop();
|
interp.stop();
|
||||||
decim.stop();
|
decim.stop();
|
||||||
running = false;
|
running = false;
|
||||||
@ -323,6 +331,9 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_interp != 1) {
|
if (_interp != 1) {
|
||||||
interp.start();
|
interp.start();
|
||||||
}
|
}
|
||||||
@ -331,8 +342,12 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
|
if (!running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
interp.stop();
|
interp.stop();
|
||||||
decim.stop();
|
//decim.stop();
|
||||||
|
Sleep(200);
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,25 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_workerThread = std::thread(_worker, this);
|
_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;
|
stream<complex_t> output_a;
|
||||||
@ -36,14 +54,16 @@ namespace dsp {
|
|||||||
static void _worker(Splitter* _this) {
|
static void _worker(Splitter* _this) {
|
||||||
complex_t* buf = new complex_t[_this->_bufferSize];
|
complex_t* buf = new complex_t[_this->_bufferSize];
|
||||||
while (true) {
|
while (true) {
|
||||||
_this->_in->read(buf, _this->_bufferSize);
|
if (_this->_in->read(buf, _this->_bufferSize) < 0) { break; };
|
||||||
_this->output_a.write(buf, _this->_bufferSize);
|
if (_this->output_a.write(buf, _this->_bufferSize) < 0) { break; };
|
||||||
_this->output_b.write(buf, _this->_bufferSize);
|
if (_this->output_b.write(buf, _this->_bufferSize) < 0) { break; };
|
||||||
}
|
}
|
||||||
|
delete[] buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream<complex_t>* _in;
|
stream<complex_t>* _in;
|
||||||
int _bufferSize;
|
int _bufferSize;
|
||||||
std::thread _workerThread;
|
std::thread _workerThread;
|
||||||
|
bool running = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
195
src/dsp/stream.h
195
src/dsp/stream.h
@ -20,7 +20,10 @@ namespace dsp {
|
|||||||
_stopWriter = false;
|
_stopWriter = false;
|
||||||
this->maxLatency = maxLatency;
|
this->maxLatency = maxLatency;
|
||||||
writec = 0;
|
writec = 0;
|
||||||
readc = size - 1;
|
readc = 0;
|
||||||
|
readable = 0;
|
||||||
|
writable = size;
|
||||||
|
memset(_buffer, 0, size * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(int maxLatency) {
|
void init(int maxLatency) {
|
||||||
@ -30,35 +33,36 @@ namespace dsp {
|
|||||||
_stopWriter = false;
|
_stopWriter = false;
|
||||||
this->maxLatency = maxLatency;
|
this->maxLatency = maxLatency;
|
||||||
writec = 0;
|
writec = 0;
|
||||||
readc = size - 1;
|
readc = 0;
|
||||||
|
readable = 0;
|
||||||
|
writable = size;
|
||||||
|
memset(_buffer, 0, size * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
int read(T* data, int len) {
|
int read(T* data, int len) {
|
||||||
int dataRead = 0;
|
int dataRead = 0;
|
||||||
|
int toRead = 0;
|
||||||
while (dataRead < len) {
|
while (dataRead < len) {
|
||||||
int canRead = waitUntilReadable();
|
toRead = std::min<int>(waitUntilReadable(), len - dataRead);
|
||||||
if (canRead < 0) {
|
if (toRead < 0) { return -1; };
|
||||||
if (_stopReader) {
|
|
||||||
printf("Stop reader set");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("Stop not set");
|
|
||||||
}
|
|
||||||
clearReadStop();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int toRead = std::min(canRead, len - dataRead);
|
|
||||||
|
|
||||||
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
|
if ((toRead + readc) > size) {
|
||||||
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
|
memcpy(&data[dataRead], &_buffer[readc], (size - readc) * sizeof(T));
|
||||||
if (len1 < toRead) {
|
memcpy(&data[dataRead + (size - readc)], &_buffer[0], (toRead - (size - readc)) * sizeof(T));
|
||||||
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
|
}
|
||||||
|
else {
|
||||||
|
memcpy(&data[dataRead], &_buffer[readc], toRead * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
dataRead += toRead;
|
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 = (readc + toRead) % size;
|
||||||
readc_mtx.unlock();
|
|
||||||
canWriteVar.notify_one();
|
canWriteVar.notify_one();
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
@ -66,114 +70,113 @@ namespace dsp {
|
|||||||
|
|
||||||
int readAndSkip(T* data, int len, int skip) {
|
int readAndSkip(T* data, int len, int skip) {
|
||||||
int dataRead = 0;
|
int dataRead = 0;
|
||||||
|
int toRead = 0;
|
||||||
while (dataRead < len) {
|
while (dataRead < len) {
|
||||||
int canRead = waitUntilReadable();
|
toRead = std::min<int>(waitUntilReadable(), len - dataRead);
|
||||||
if (canRead < 0) {
|
if (toRead < 0) { return -1; };
|
||||||
clearReadStop();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int toRead = std::min(canRead, len - dataRead);
|
|
||||||
|
|
||||||
int len1 = (toRead >= (size - readc) ? (size - readc) : (toRead));
|
if ((toRead + readc) > size) {
|
||||||
memcpy(&data[dataRead], &_buffer[readc], len1 * sizeof(T));
|
memcpy(&data[dataRead], &_buffer[readc], (size - readc) * sizeof(T));
|
||||||
if (len1 < toRead) {
|
memcpy(&data[dataRead + (size - readc)], &_buffer[0], (toRead - (size - readc)) * sizeof(T));
|
||||||
memcpy(&data[dataRead + len1], _buffer, (toRead - len1) * sizeof(T));
|
}
|
||||||
|
else {
|
||||||
|
memcpy(&data[dataRead], &_buffer[readc], toRead * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
dataRead += toRead;
|
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 = (readc + toRead) % size;
|
||||||
readc_mtx.unlock();
|
|
||||||
canWriteVar.notify_one();
|
canWriteVar.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip
|
|
||||||
|
|
||||||
dataRead = 0;
|
dataRead = 0;
|
||||||
while (dataRead < skip) {
|
while (dataRead < skip) {
|
||||||
int canRead = waitUntilReadable();
|
toRead = std::min<int>(waitUntilReadable(), skip - dataRead);
|
||||||
int toRead = std::min(canRead, skip - dataRead);
|
if (toRead < 0) { return -1; };
|
||||||
|
|
||||||
dataRead += toRead;
|
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 = (readc + toRead) % size;
|
||||||
readc_mtx.unlock();
|
|
||||||
canWriteVar.notify_one();
|
canWriteVar.notify_one();
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int waitUntilReadable() {
|
int waitUntilReadable() {
|
||||||
int canRead = readable();
|
if (_stopReader) { return -1; }
|
||||||
if (canRead > 0) {
|
int _r = getReadable();
|
||||||
return canRead;
|
if (_r != 0) { return _r; }
|
||||||
}
|
std::unique_lock<std::mutex> lck(_readable_mtx);
|
||||||
std::unique_lock<std::mutex> lck(writec_mtx);
|
canReadVar.wait(lck, [=](){ return ((this->getReadable(false) > 0) || this->getReadStop()); });
|
||||||
canReadVar.wait(lck, [=](){ return ((this->readable(false) > 0) || this->getReadStop()); });
|
if (_stopReader) { return -1; }
|
||||||
if (this->getReadStop()) {
|
return getReadable(false);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return this->readable(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int readable(bool lock = true) {
|
int getReadable(bool lock = true) {
|
||||||
if (lock) { writec_mtx.lock(); }
|
if (lock) { _readable_mtx.lock(); };
|
||||||
int _wc = writec;
|
int _r = readable;
|
||||||
if (lock) { writec_mtx.unlock(); }
|
if (lock) { _readable_mtx.unlock(); };
|
||||||
int readable = (_wc - readc) % this->size;
|
return _r;
|
||||||
if (_wc < readc) {
|
|
||||||
readable = (this->size + readable);
|
|
||||||
}
|
|
||||||
return readable - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int write(T* data, int len) {
|
int write(T* data, int len) {
|
||||||
int dataWrite = 0;
|
int dataWritten = 0;
|
||||||
while (dataWrite < len) {
|
int toWrite = 0;
|
||||||
int canWrite = waitUntilWriteable();
|
while (dataWritten < len) {
|
||||||
if (canWrite < 0) {
|
toWrite = std::min<int>(waitUntilwritable(), len - dataWritten);
|
||||||
clearWriteStop();
|
if (toWrite < 0) { return -1; };
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int toWrite = std::min(canWrite, len - dataWrite);
|
|
||||||
|
|
||||||
int len1 = (toWrite >= (size - writec) ? (size - writec) : (toWrite));
|
if ((toWrite + writec) > size) {
|
||||||
memcpy(&_buffer[writec], &data[dataWrite], len1 * sizeof(T));
|
memcpy(&_buffer[writec], &data[dataWritten], (size - writec) * sizeof(T));
|
||||||
if (len1 < toWrite) {
|
memcpy(&_buffer[0], &data[dataWritten + (size - writec)], (toWrite - (size - writec)) * sizeof(T));
|
||||||
memcpy(_buffer, &data[dataWrite + len1], (toWrite - len1) * sizeof(T));
|
}
|
||||||
|
else {
|
||||||
|
memcpy(&_buffer[writec], &data[dataWritten], toWrite * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
dataWrite += toWrite;
|
dataWritten += toWrite;
|
||||||
writec_mtx.lock();
|
|
||||||
|
_readable_mtx.lock();
|
||||||
|
readable += toWrite;
|
||||||
|
_readable_mtx.unlock();
|
||||||
|
_writable_mtx.lock();
|
||||||
|
writable -= toWrite;
|
||||||
|
_writable_mtx.unlock();
|
||||||
writec = (writec + toWrite) % size;
|
writec = (writec + toWrite) % size;
|
||||||
writec_mtx.unlock();
|
|
||||||
canReadVar.notify_one();
|
canReadVar.notify_one();
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int waitUntilWriteable() {
|
int waitUntilwritable() {
|
||||||
int canWrite = writeable();
|
if (_stopWriter) { return -1; }
|
||||||
if (canWrite > 0) {
|
int _w = getWritable();
|
||||||
return canWrite;
|
if (_w != 0) { return _w; }
|
||||||
}
|
std::unique_lock<std::mutex> lck(_writable_mtx);
|
||||||
std::unique_lock<std::mutex> lck(readc_mtx);
|
canWriteVar.wait(lck, [=](){ return ((this->getWritable(false) > 0) || this->getWriteStop()); });
|
||||||
canWriteVar.wait(lck, [=](){ return ((this->writeable(false) > 0) || this->getWriteStop()); });
|
if (_stopWriter) { return -1; }
|
||||||
if (this->getWriteStop()) {
|
return getWritable(false);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return this->writeable(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int writeable(bool lock = true) {
|
int getWritable(bool lock = true) {
|
||||||
if (lock) { readc_mtx.lock(); }
|
if (lock) { _writable_mtx.lock(); };
|
||||||
int _rc = readc;
|
int _w = writable;
|
||||||
if (lock) { readc_mtx.unlock(); }
|
if (lock) { _writable_mtx.unlock(); _readable_mtx.lock(); };
|
||||||
int writeable = (_rc - writec) % this->size;
|
int _r = readable;
|
||||||
if (_rc < writec) {
|
if (lock) { _readable_mtx.unlock(); };
|
||||||
writeable = (this->size + writeable);
|
return std::max<int>(std::min<int>(_w, maxLatency - _r), 0);
|
||||||
}
|
|
||||||
return std::min<float>(writeable - 1, maxLatency - readable(false) - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopReader() {
|
void stopReader() {
|
||||||
@ -211,11 +214,13 @@ namespace dsp {
|
|||||||
int size;
|
int size;
|
||||||
int readc;
|
int readc;
|
||||||
int writec;
|
int writec;
|
||||||
|
int readable;
|
||||||
|
int writable;
|
||||||
int maxLatency;
|
int maxLatency;
|
||||||
bool _stopReader;
|
bool _stopReader;
|
||||||
bool _stopWriter;
|
bool _stopWriter;
|
||||||
std::mutex readc_mtx;
|
std::mutex _readable_mtx;
|
||||||
std::mutex writec_mtx;
|
std::mutex _writable_mtx;
|
||||||
std::condition_variable canReadVar;
|
std::condition_variable canReadVar;
|
||||||
std::condition_variable canWriteVar;
|
std::condition_variable canWriteVar;
|
||||||
};
|
};
|
||||||
|
@ -33,7 +33,7 @@ int main() {
|
|||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
||||||
|
|
||||||
// Create window with graphics context
|
// 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)
|
if (window == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
@ -49,7 +49,7 @@ void fftHandler(dsp::complex_t* samples) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void windowInit() {
|
void windowInit() {
|
||||||
int sampleRate = 2000000;
|
int sampleRate = 8000000;
|
||||||
wtf.bandWidth = sampleRate;
|
wtf.bandWidth = sampleRate;
|
||||||
wtf.range = 500000;
|
wtf.range = 500000;
|
||||||
wtf.centerFrequency = 90500000;
|
wtf.centerFrequency = 90500000;
|
||||||
|
@ -49,31 +49,31 @@ void SignalPath::setDemodulator(int demId) {
|
|||||||
audioResamp.stop();
|
audioResamp.stop();
|
||||||
|
|
||||||
// Stop current demodulator
|
// Stop current demodulator
|
||||||
if (_demod == DEMOD_FM) {
|
// if (_demod == DEMOD_FM) {
|
||||||
printf("Stopping FM demodulator\n");
|
// printf("Stopping FM demodulator\n");
|
||||||
demod.stop();
|
// demod.stop();
|
||||||
}
|
// }
|
||||||
else if (_demod == DEMOD_AM) {
|
// else if (_demod == DEMOD_AM) {
|
||||||
printf("Stopping AM demodulator\n");
|
// printf("Stopping AM demodulator\n");
|
||||||
amDemod.stop();
|
// amDemod.stop();
|
||||||
}
|
// }
|
||||||
_demod = demId;
|
// _demod = demId;
|
||||||
|
|
||||||
// Set input of the audio resampler
|
// // Set input of the audio resampler
|
||||||
if (demId == DEMOD_FM) {
|
// if (demId == DEMOD_FM) {
|
||||||
printf("Starting FM demodulator\n");
|
// printf("Starting FM demodulator\n");
|
||||||
mainVFO.setOutputSampleRate(200000, 200000);
|
// // mainVFO.setOutputSampleRate(200000, 200000);
|
||||||
audioResamp.setInput(&demod.output);
|
// // audioResamp.setInput(&demod.output);
|
||||||
audioResamp.setInputSampleRate(200000, 800);
|
// // audioResamp.setInputSampleRate(200000, 800);
|
||||||
demod.start();
|
// demod.start();
|
||||||
}
|
// }
|
||||||
else if (demId == DEMOD_AM) {
|
// else if (demId == DEMOD_AM) {
|
||||||
printf("Starting AM demodulator\n");
|
// printf("Starting AM demodulator\n");
|
||||||
mainVFO.setOutputSampleRate(12500, 12500);
|
// mainVFO.setOutputSampleRate(12500, 12500);
|
||||||
audioResamp.setInput(&amDemod.output);
|
// audioResamp.setInput(&amDemod.output);
|
||||||
audioResamp.setInputSampleRate(12500, 50);
|
// audioResamp.setInputSampleRate(12500, 50);
|
||||||
amDemod.start();
|
// amDemod.start();
|
||||||
}
|
// }
|
||||||
|
|
||||||
audioResamp.start();
|
audioResamp.start();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user