Bugfixed + performance improvements to the waterfall

This commit is contained in:
Ryzerth
2020-12-12 05:34:58 +01:00
parent 774663d70d
commit e3db19b16a
20 changed files with 122 additions and 67 deletions

View File

@ -3,7 +3,7 @@ project(sdrpp_core)
# Set compiler options
if (MSVC)
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
else()
set(CMAKE_CXX_FLAGS "-g -O3 -std=c++17 -fpermissive")

View File

@ -8,11 +8,8 @@ using nlohmann::json;
#define DEV_BUILD
#define SDRPP_RESOURCE_DIR "/usr/local/"
#ifndef ROOT_DIR
#ifdef DEV_BUILD
#define ROOT_DIR "../root_dev"

View File

@ -79,7 +79,7 @@ int sdrpp_main() {
defConfig["bandColors"]["military"] = "#FFFF00FF";
defConfig["bandPlan"] = "General";
defConfig["bandPlanEnabled"] = true;
defConfig["centerTuning"] = true;
defConfig["centerTuning"] = false;
defConfig["fftHeight"] = 300;
defConfig["frequency"] = 100000000.0;
defConfig["max"] = 0.0;

View File

@ -35,12 +35,12 @@ std::thread worker;
std::mutex fft_mtx;
fftwf_complex *fft_in, *fft_out;
fftwf_plan p;
float* tempFFT;
float* FFTdata;
char buf[1024];
int fftSize = 8192 * 8;
std::vector<float> _data;
std::vector<float> fftTaps;
void fftHandler(dsp::complex_t* samples, int count, void* ctx) {
if (count < fftSize) {
return;
@ -49,19 +49,24 @@ void fftHandler(dsp::complex_t* samples, int count, void* ctx) {
fftwf_execute(p);
int half = fftSize / 2;
for (int i = 0; i < half; i++) {
_data.push_back(log10(std::abs(std::complex<float>(fft_out[half + i][0], fft_out[half + i][1])) / (float)fftSize) * 10.0);
}
for (int i = 0; i < half; i++) {
_data.push_back(log10(std::abs(std::complex<float>(fft_out[i][0], fft_out[i][1])) / (float)fftSize) * 10.0);
}
volk_32fc_s32f_power_spectrum_32f(tempFFT, (lv_32fc_t*)fft_out, fftSize, fftSize);
volk_32f_s32f_multiply_32f(FFTdata, tempFFT, 0.5f, fftSize);
for (int i = 5; i < fftSize; i++) {
_data[i] = (_data[i - 4] + _data[i - 3] + _data[i - 2] + _data[i - 1] + _data[i]) / 5.0;
}
memcpy(tempFFT, &FFTdata[half], half * sizeof(float));
memmove(&FFTdata[half], FFTdata, half * sizeof(float));
memcpy(FFTdata, tempFFT, half * sizeof(float));
gui::waterfall.pushFFT(_data, fftSize);
_data.clear();
float* fftBuf = gui::waterfall.getFFTBuffer();
if (fftBuf == NULL) {
gui::waterfall.pushFFT();
return;
}
float last = FFTdata[0];
for (int i = 0; i < fftSize; i++) {
last = (FFTdata[i] * 0.1f) + (last * 0.9f);
fftBuf[i] = last;
}
gui::waterfall.pushFFT();
}
watcher<uint64_t> freq((uint64_t)90500000);
@ -87,6 +92,10 @@ bool demoWindow = false;
void windowInit() {
LoadingScreen::show("Initializing UI");
gui::waterfall.init();
gui::waterfall.setRawFFTSize(fftSize);
tempFFT = new float[fftSize];
FFTdata = new float[fftSize];
credits::init();
@ -167,7 +176,6 @@ void windowInit() {
// TODO for 0.2.6
// Add a module add/remove/change order menu
// Change the way fft samples are stored to make it less CPU intensive
// Update UI settings
LoadingScreen::show("Loading configuration");

View File

@ -23,7 +23,7 @@ float COLOR_MAP[][3] = {
{0x4A, 0x00, 0x00}
};
void doZoom(int offset, int width, int outWidth, std::vector<float> data, float* out) {
void doZoom(int offset, int width, int outWidth, float* data, float* out) {
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
if (offset < 0) {
offset = 0;
@ -34,7 +34,7 @@ void doZoom(int offset, int width, int outWidth, std::vector<float> data, float*
float factor = (float)width / (float)outWidth;
for (int i = 0; i < outWidth; i++) {
out[i] = data[offset + ((float)i * factor)];
out[i] = data[(int)(offset + ((float)i * factor))];
}
}
@ -281,7 +281,11 @@ namespace ImGui {
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0);
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0);
updateWaterfallFb();
if (viewBandwidth != wholeBandwidth) {
updateAllVFOs();
updateWaterfallFb();
}
}
else {
lastDrag = 0;
@ -289,25 +293,26 @@ namespace ImGui {
}
void WaterFall::updateWaterfallFb() {
if (!waterfallVisible) {
if (!waterfallVisible || rawFFTs == NULL) {
return;
}
double offsetRatio = viewOffset / (wholeBandwidth / 2.0);
int drawDataSize;
int drawDataStart;
int count = std::min<int>(waterfallHeight, rawFFTs.size());
// TODO: Maybe put on the stack for faster alloc?
float* tempData = new float[dataWidth];
float pixel;
float dataRange = waterfallMax - waterfallMin;
int size;
for (int i = 0; i < count; i++) {
size = rawFFTs[i].size();
drawDataSize = (viewBandwidth / wholeBandwidth) * size;
drawDataStart = (((double)size / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs[i], tempData);
for (int j = 0; j < dataWidth; j++) {
pixel = (std::clamp<float>(tempData[j], waterfallMin, waterfallMax) - waterfallMin) / dataRange;
waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))];
int count = std::min<float>(waterfallHeight, fftLines);
if (rawFFTs != NULL) {
for (int i = 0; i < count; i++) {
drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
for (int j = 0; j < dataWidth; j++) {
pixel = (std::clamp<float>(tempData[j], waterfallMin, waterfallMax) - waterfallMin) / dataRange;
waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))];
}
}
}
delete[] tempData;
@ -391,6 +396,8 @@ namespace ImGui {
return;
}
int lastWaterfallHeight = waterfallHeight;
if (waterfallVisible) {
FFTAreaHeight = std::min<int>(FFTAreaHeight, widgetSize.y - 50);
fftHeight = FFTAreaHeight - 50;
@ -402,12 +409,28 @@ namespace ImGui {
dataWidth = widgetSize.x - 60.0;
delete[] latestFFT;
if (waterfallVisible) {
delete[] waterfallFb;
// Raw FFT resize
fftLines = std::min<int>(fftLines, waterfallHeight);
if (rawFFTs != NULL) {
if (currentFFTLine != 0) {
float* tempWF = new float[currentFFTLine * rawFFTSize];
int moveCount = lastWaterfallHeight - currentFFTLine;
memcpy(tempWF, rawFFTs, currentFFTLine * rawFFTSize * sizeof(float));
memmove(rawFFTs, &rawFFTs[currentFFTLine * rawFFTSize], moveCount * rawFFTSize * sizeof(float));
memcpy(&rawFFTs[moveCount * rawFFTSize], tempWF, currentFFTLine * rawFFTSize * sizeof(float));
delete[] tempWF;
}
currentFFTLine = 0;
rawFFTs = (float*)realloc(rawFFTs, waterfallHeight * rawFFTSize * sizeof(float));
}
else {
rawFFTs = (float*)malloc(waterfallHeight * rawFFTSize * sizeof(float));
}
// ==============
latestFFT = new float[dataWidth];
if (waterfallVisible) {
delete[] waterfallFb;
waterfallFb = new uint32_t[dataWidth * waterfallHeight];
memset(waterfallFb, 0, dataWidth * waterfallHeight * sizeof(uint32_t));
}
@ -504,17 +527,23 @@ namespace ImGui {
buf_mtx.unlock();
}
void WaterFall::pushFFT(std::vector<float> data, int n) {
float* WaterFall::getFFTBuffer() {
if (rawFFTs == NULL) { return NULL; }
buf_mtx.lock();
currentFFTLine--;
fftLines++;
currentFFTLine = ((currentFFTLine + waterfallHeight) % waterfallHeight);
fftLines = std::min<float>(fftLines, waterfallHeight);
return &rawFFTs[currentFFTLine * rawFFTSize];
}
void WaterFall::pushFFT() {
if (rawFFTs == NULL) { return; }
double offsetRatio = viewOffset / (wholeBandwidth / 2.0);
int drawDataSize = (viewBandwidth / wholeBandwidth) * data.size();
int drawDataStart = (((double)data.size() / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
int drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
doZoom(drawDataStart, drawDataSize, dataWidth, data, latestFFT);
rawFFTs.insert(rawFFTs.begin(), data);
if (rawFFTs.size() > waterfallHeight + 300) {
rawFFTs.resize(waterfallHeight);
}
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
if (waterfallVisible) {
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
@ -683,6 +712,19 @@ namespace ImGui {
}
}
void WaterFall::setRawFFTSize(int size, bool lock) {
if (lock) { buf_mtx.lock(); }
rawFFTSize = size;
if (rawFFTs != NULL) {
rawFFTs = (float*)realloc(rawFFTs, rawFFTSize * waterfallHeight * sizeof(float));
}
else {
rawFFTs = (float*)malloc(rawFFTSize * waterfallHeight * sizeof(float));
}
memset(rawFFTs, 0, rawFFTSize * waterfallHeight * sizeof(float));
if (lock) { buf_mtx.unlock(); }
}
void WaterfallVFO::setOffset(double offset) {
generalOffset = offset;
if (reference == REF_CENTER) {

View File

@ -53,7 +53,8 @@ namespace ImGui {
void init();
void draw();
void pushFFT(std::vector<float> data, int n);
float* getFFTBuffer();
void pushFFT();
void updatePallette(float colors[][3], int colorCount);
@ -97,6 +98,8 @@ namespace ImGui {
void setFFTHeight(int height);
int getFFTHeight();
void setRawFFTSize(int size, bool lock = true);
bool centerFreqMoved = false;
bool vfoFreqChanged = false;
bool bandplanEnabled = false;
@ -155,9 +158,9 @@ namespace ImGui {
int maxVSteps;
int maxHSteps;
int dataWidth; // Width of the FFT and waterfall
int fftHeight; // Height of the fft graph
int waterfallHeight; // Height of the waterfall
int dataWidth; // Width of the FFT and waterfall
int fftHeight; // Height of the fft graph
int waterfallHeight = 0; // Height of the waterfall
double viewBandwidth;
double viewOffset;
@ -180,8 +183,12 @@ namespace ImGui {
float waterfallMin;
float waterfallMax;
std::vector<std::vector<float>> rawFFTs;
//std::vector<std::vector<float>> rawFFTs;
int rawFFTSize;
float* rawFFTs = NULL;
float* latestFFT;
int currentFFTLine = 0;
int fftLines = 0;
uint32_t* waterfallFb;