mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-24 18:08:27 +01:00
Bugfixed + performance improvements to the waterfall
This commit is contained in:
parent
774663d70d
commit
e3db19b16a
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ build/
|
||||
*.wav
|
||||
.DS_Store
|
||||
sdrpp_v0.2.5_beta_x64
|
||||
sdrpp_v0.2.5_beta_x64_new_wf
|
@ -16,7 +16,7 @@ add_subdirectory("plutosdr_source")
|
||||
#add_subdirectory("demo")
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(audio_sink)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -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")
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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,35 +281,40 @@ namespace ImGui {
|
||||
|
||||
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0);
|
||||
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0);
|
||||
|
||||
if (viewBandwidth != wholeBandwidth) {
|
||||
updateAllVFOs();
|
||||
updateWaterfallFb();
|
||||
}
|
||||
}
|
||||
else {
|
||||
lastDrag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
int count = std::min<float>(waterfallHeight, fftLines);
|
||||
if (rawFFTs != NULL) {
|
||||
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);
|
||||
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;
|
||||
waterfallUpdate = true;
|
||||
}
|
||||
@ -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,18 +527,24 @@ 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();
|
||||
double offsetRatio = viewOffset / (wholeBandwidth / 2.0);
|
||||
int drawDataSize = (viewBandwidth / wholeBandwidth) * data.size();
|
||||
int drawDataStart = (((double)data.size() / 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);
|
||||
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) * rawFFTSize;
|
||||
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
|
||||
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
|
||||
|
||||
if (waterfallVisible) {
|
||||
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
|
||||
float pixel;
|
||||
@ -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) {
|
||||
|
@ -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;
|
||||
@ -157,7 +160,7 @@ namespace ImGui {
|
||||
|
||||
int dataWidth; // Width of the FFT and waterfall
|
||||
int fftHeight; // Height of the fft graph
|
||||
int waterfallHeight; // Height of the waterfall
|
||||
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;
|
||||
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(demo)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(file_source)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(plutosdr_source)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(radio)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(recorder)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -3,7 +3,7 @@
|
||||
"bandPlanEnabled": true,
|
||||
"centerTuning": false,
|
||||
"fftHeight": 300,
|
||||
"frequency": 103600000,
|
||||
"frequency": 99000000,
|
||||
"max": 0.0,
|
||||
"maximized": false,
|
||||
"menuOrder": [
|
||||
@ -17,7 +17,7 @@
|
||||
"Display"
|
||||
],
|
||||
"menuWidth": 300,
|
||||
"min": -66.17647552490234,
|
||||
"min": -55.147056579589844,
|
||||
"moduleInstances": {
|
||||
"Audio Sink": "audio_sink",
|
||||
"PlutoSDR Source": "plutosdr_source",
|
||||
@ -36,12 +36,12 @@
|
||||
],
|
||||
"offset": 0.0,
|
||||
"showWaterfall": true,
|
||||
"source": "PlutoSDR",
|
||||
"source": "SoapySDR",
|
||||
"streams": {
|
||||
"Radio": {
|
||||
"muted": false,
|
||||
"sink": "Audio",
|
||||
"volume": 0.6785714030265808
|
||||
"volume": 0.545918345451355
|
||||
},
|
||||
"Radio 1": {
|
||||
"muted": false,
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"device": "AirSpy HF+ [c852435de0224af7]",
|
||||
"device": "HackRF One #0 901868dc282c8f8b",
|
||||
"devices": {
|
||||
"": {
|
||||
"agc": false,
|
||||
@ -32,10 +32,10 @@
|
||||
"HackRF One #0 901868dc282c8f8b": {
|
||||
"gains": {
|
||||
"AMP": 0.0,
|
||||
"LNA": 23.415000915527344,
|
||||
"LNA": 24.503000259399414,
|
||||
"VGA": 16.332000732421875
|
||||
},
|
||||
"sampleRate": 8000000.0
|
||||
"sampleRate": 2000000.0
|
||||
},
|
||||
"Microphone (Realtek High Definition Audio)": {
|
||||
"sampleRate": 96000.0
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(rtl_tcp_source)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(rx888_source)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(soapy_source)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
|
||||
project(soapy)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
Loading…
Reference in New Issue
Block a user