mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-26 12:27:51 +02:00
New optional detailed FFT system
This commit is contained in:
@ -33,25 +33,25 @@
|
||||
#include <options.h>
|
||||
#include <gui/colormaps.h>
|
||||
|
||||
// const int FFTSizes[] = {
|
||||
// 65536,
|
||||
// 32768,
|
||||
// 16384,
|
||||
// 8192,
|
||||
// 4096,
|
||||
// 2048
|
||||
// };
|
||||
const int FFTSizes[] = {
|
||||
65536,
|
||||
32768,
|
||||
16384,
|
||||
8192,
|
||||
4096,
|
||||
2048,
|
||||
1024
|
||||
};
|
||||
|
||||
// const char* FFTSizesStr[] = {
|
||||
// "65536",
|
||||
// "32768",
|
||||
// "16384",
|
||||
// "8192",
|
||||
// "4096",
|
||||
// "2048"
|
||||
// };
|
||||
const char* FFTSizesStr = "65536\0"
|
||||
"32768\0"
|
||||
"16384\0"
|
||||
"8192\0"
|
||||
"4096\0"
|
||||
"2048\0"
|
||||
"1024\0";
|
||||
|
||||
// int fftSizeId = 0;
|
||||
int fftSizeId = 0;
|
||||
int fftSize = 8192 * 8;
|
||||
|
||||
std::mutex fft_mtx;
|
||||
@ -63,26 +63,39 @@ char buf[1024];
|
||||
bool experimentalZoom = false;
|
||||
|
||||
void fftHandler(dsp::complex_t* samples, int count, void* ctx) {
|
||||
std::lock_guard<std::mutex> lck(fft_mtx);
|
||||
|
||||
memcpy(fft_in, samples, count * sizeof(dsp::complex_t));
|
||||
fftwf_execute(p);
|
||||
int half = count / 2;
|
||||
|
||||
volk_32fc_s32f_power_spectrum_32f(FFTdata, (lv_32fc_t*)fft_out, count, count);
|
||||
// volk_32fc_s32f_power_spectrum_32f(FFTdata, (lv_32fc_t*)fft_out, count, count);
|
||||
|
||||
memcpy(tempFFT, &FFTdata[half], half * sizeof(float));
|
||||
memmove(&FFTdata[half], FFTdata, half * sizeof(float));
|
||||
memcpy(FFTdata, tempFFT, half * sizeof(float));
|
||||
// memcpy(tempFFT, &FFTdata[half], half * sizeof(float));
|
||||
// memmove(&FFTdata[half], FFTdata, half * sizeof(float));
|
||||
// memcpy(FFTdata, tempFFT, half * sizeof(float));
|
||||
|
||||
// float* fftBuf = gui::waterfall.getFFTBuffer();
|
||||
// if (fftBuf == NULL) {
|
||||
// gui::waterfall.pushFFT();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// memcpy(fftBuf, FFTdata, count * sizeof(float));
|
||||
|
||||
// gui::waterfall.pushFFT();
|
||||
|
||||
float* fftBuf = gui::waterfall.getFFTBuffer();
|
||||
if (fftBuf == NULL) {
|
||||
gui::waterfall.pushFFT();
|
||||
return;
|
||||
}
|
||||
float last = FFTdata[0];
|
||||
for (int i = 0; i < count; i++) {
|
||||
last = (FFTdata[i] * 0.1f) + (last * 0.9f);
|
||||
fftBuf[i] = last;
|
||||
}
|
||||
|
||||
volk_32fc_s32f_power_spectrum_32f(tempFFT, (lv_32fc_t*)fft_out, count, count);
|
||||
|
||||
memcpy(fftBuf, &tempFFT[half], half * sizeof(float));
|
||||
memcpy(&fftBuf[half], tempFFT, half * sizeof(float));
|
||||
|
||||
gui::waterfall.pushFFT();
|
||||
}
|
||||
|
||||
@ -555,6 +568,22 @@ void drawWindow() {
|
||||
spdlog::error("Will this make the software crash?");
|
||||
}
|
||||
|
||||
if (ImGui::Combo("##test_fft_size", &fftSizeId, FFTSizesStr)) {
|
||||
std::lock_guard<std::mutex> lck(fft_mtx);
|
||||
fftSize = FFTSizes[fftSizeId];
|
||||
|
||||
gui::waterfall.setRawFFTSize(fftSize);
|
||||
sigpath::signalPath.setFFTSize(fftSize);
|
||||
|
||||
fftwf_free(fft_in);
|
||||
fftwf_free(fft_out);
|
||||
fftwf_destroy_plan(p);
|
||||
|
||||
fft_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fft_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
p = fftwf_plan_dft_1d(fftSize, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
namespace displaymenu {
|
||||
bool showWaterfall;
|
||||
bool fastFFT = true;
|
||||
int colorMapId = 0;
|
||||
std::vector<std::string> colorMapNames;
|
||||
std::string colorMapNamesTxt = "";
|
||||
@ -55,5 +56,9 @@ namespace displaymenu {
|
||||
}
|
||||
ImGui::Text("Color map Author: %s", colorMapAuthor.c_str());
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Fast FFT", &fastFFT)) {
|
||||
gui::waterfall.setFastFFT(fastFFT);
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ float DEFAULT_COLOR_MAP[][3] = {
|
||||
{0x4A, 0x00, 0x00}
|
||||
};
|
||||
|
||||
void doZoom(int offset, int width, int outWidth, float* data, float* out) {
|
||||
void doZoom(int offset, int width, int outWidth, float* data, float* out, bool fast) {
|
||||
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
@ -33,8 +33,24 @@ void doZoom(int offset, int width, int outWidth, float* data, float* out) {
|
||||
}
|
||||
|
||||
float factor = (float)width / (float)outWidth;
|
||||
|
||||
if (fast) {
|
||||
for (int i = 0; i < outWidth; i++) {
|
||||
out[i] = data[(int)(offset + ((float)i * factor))];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float id = offset;
|
||||
float val, maxVal;
|
||||
float next;
|
||||
for (int i = 0; i < outWidth; i++) {
|
||||
out[i] = data[(int)(offset + ((float)i * factor))];
|
||||
maxVal = -INFINITY;
|
||||
for (int j = 0; j < factor; j++) {
|
||||
if (data[(int)id + j] > maxVal) { maxVal = data[(int)id + j]; }
|
||||
}
|
||||
out[i] = maxVal;
|
||||
id += factor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,6 +326,11 @@ namespace ImGui {
|
||||
}
|
||||
}
|
||||
|
||||
void WaterFall::setFastFFT(bool fastFFT) {
|
||||
std::lock_guard<std::mutex> lck(buf_mtx);
|
||||
_fastFFT = fastFFT;
|
||||
}
|
||||
|
||||
void WaterFall::updateWaterfallFb() {
|
||||
if (!waterfallVisible || rawFFTs == NULL) {
|
||||
return;
|
||||
@ -326,7 +347,7 @@ namespace ImGui {
|
||||
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);
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData, _fastFFT);
|
||||
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))];
|
||||
@ -571,10 +592,18 @@ namespace ImGui {
|
||||
int drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
|
||||
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
|
||||
|
||||
|
||||
// If in fast mode, apply IIR filtering
|
||||
float* buf = &rawFFTs[currentFFTLine * rawFFTSize];
|
||||
if (_fastFFT) {
|
||||
float last = buf[0];
|
||||
for (int i = 0; i < rawFFTSize; i++) {
|
||||
last = (buf[i] * 0.1f) + (last * 0.9f);
|
||||
buf[i] = last;
|
||||
}
|
||||
}
|
||||
|
||||
if (waterfallVisible) {
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT, _fastFFT);
|
||||
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
|
||||
float pixel;
|
||||
float dataRange = waterfallMax - waterfallMin;
|
||||
@ -586,7 +615,7 @@ namespace ImGui {
|
||||
waterfallUpdate = true;
|
||||
}
|
||||
else {
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT);
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT, _fastFFT);
|
||||
fftLines = 1;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,8 @@ namespace ImGui {
|
||||
|
||||
void setRawFFTSize(int size, bool lock = true);
|
||||
|
||||
void setFastFFT(bool fastFFT);
|
||||
|
||||
bool centerFreqMoved = false;
|
||||
bool vfoFreqChanged = false;
|
||||
bool bandplanEnabled = false;
|
||||
@ -203,5 +205,7 @@ namespace ImGui {
|
||||
|
||||
bool waterfallVisible = true;
|
||||
bool bandplanVisible = false;
|
||||
|
||||
bool _fastFFT = true;
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user