mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-02-02 21:04:45 +01:00
Performance improvement to the FFT + code cleanup + Added an option to select the FFT window
This commit is contained in:
parent
6db8251e46
commit
ab376ea1aa
@ -118,6 +118,7 @@ int sdrpp_main(int argc, char *argv[]) {
|
||||
defConfig["fastFFT"] = false;
|
||||
defConfig["fftHeight"] = 300;
|
||||
defConfig["fftSize"] = 65536;
|
||||
defConfig["fftWindow"] = 0;
|
||||
defConfig["frequency"] = 100000000.0;
|
||||
defConfig["fullWaterfallUpdate"] = false;
|
||||
defConfig["max"] = 0.0;
|
||||
|
@ -40,8 +40,8 @@ void MainWindow::init() {
|
||||
gui::waterfall.init();
|
||||
gui::waterfall.setRawFFTSize(fftSize);
|
||||
|
||||
tempFFT = new float[fftSize];
|
||||
FFTdata = new float[fftSize];
|
||||
appliedWindow = new float[fftSize];
|
||||
generateFFTWindow(selectedWindow, fftSize);
|
||||
|
||||
credits::init();
|
||||
|
||||
@ -201,21 +201,23 @@ void MainWindow::fftHandler(dsp::complex_t* samples, int count, void* ctx) {
|
||||
std::lock_guard<std::mutex> lck(_this->fft_mtx);
|
||||
if (count != _this->fftSize) { return; }
|
||||
|
||||
memcpy(_this->fft_in, samples, count * sizeof(dsp::complex_t));
|
||||
fftwf_execute(_this->fftwPlan);
|
||||
int half = count / 2;
|
||||
// Apply window
|
||||
volk_32fc_32f_multiply_32fc((lv_32fc_t*)_this->fft_in, (lv_32fc_t*)samples, _this->appliedWindow, count);
|
||||
|
||||
// Execute FFT
|
||||
fftwf_execute(_this->fftwPlan);
|
||||
|
||||
// Get the FFT buffer
|
||||
float* fftBuf = gui::waterfall.getFFTBuffer();
|
||||
if (fftBuf == NULL) {
|
||||
gui::waterfall.pushFFT();
|
||||
return;
|
||||
}
|
||||
|
||||
volk_32fc_s32f_power_spectrum_32f(_this->tempFFT, (lv_32fc_t*)_this->fft_out, count, count);
|
||||
|
||||
memcpy(fftBuf, &_this->tempFFT[half], half * sizeof(float));
|
||||
memcpy(&fftBuf[half], _this->tempFFT, half * sizeof(float));
|
||||
// Take power of spectrum
|
||||
volk_32fc_s32f_power_spectrum_32f(fftBuf, (lv_32fc_t*)_this->fft_out, count, count);
|
||||
|
||||
// Push back data
|
||||
gui::waterfall.pushFFT();
|
||||
}
|
||||
|
||||
@ -619,6 +621,30 @@ void MainWindow::setFFTSize(int size) {
|
||||
fft_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fft_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fftwPlan = fftwf_plan_dft_1d(fftSize, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
|
||||
delete appliedWindow;
|
||||
|
||||
appliedWindow = new float[fftSize];
|
||||
generateFFTWindow(selectedWindow, fftSize);
|
||||
}
|
||||
|
||||
void MainWindow::setFFTWindow(int win) {
|
||||
std::lock_guard<std::mutex> lck(fft_mtx);
|
||||
selectedWindow = win;
|
||||
generateFFTWindow(selectedWindow, fftSize);
|
||||
}
|
||||
|
||||
void MainWindow::generateFFTWindow(int win, int size) {
|
||||
if (win == FFT_WINDOW_RECTANGULAR) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
appliedWindow[i] = (i%2) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
else if (win == FFT_WINDOW_BLACKMAN) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
appliedWindow[i] = ((i%2) ? dsp::window_function::blackman(i, size) : -dsp::window_function::blackman(i, size))*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::isPlaying() {
|
||||
|
@ -11,6 +11,12 @@
|
||||
|
||||
#define WINDOW_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground
|
||||
|
||||
enum {
|
||||
FFT_WINDOW_RECTANGULAR,
|
||||
FFT_WINDOW_BLACKMAN,
|
||||
_FFT_WINDOW_COUNT
|
||||
};
|
||||
|
||||
class MainWindow {
|
||||
public:
|
||||
void init();
|
||||
@ -18,6 +24,7 @@ public:
|
||||
void setViewBandwidthSlider(float bandwidth);
|
||||
bool sdrIsRunning();
|
||||
void setFFTSize(int size);
|
||||
void setFFTWindow(int win);
|
||||
|
||||
// TODO: Replace with it's own class
|
||||
void setVFO(double freq);
|
||||
@ -27,6 +34,7 @@ public:
|
||||
bool lockWaterfallControls = false;
|
||||
|
||||
private:
|
||||
void generateFFTWindow(int win, int size);
|
||||
static void fftHandler(dsp::complex_t* samples, int count, void* ctx);
|
||||
static void vfoAddedHandler(VFOManager::VFO* vfo, void* ctx);
|
||||
|
||||
@ -35,8 +43,7 @@ private:
|
||||
std::mutex fft_mtx;
|
||||
fftwf_complex *fft_in, *fft_out;
|
||||
fftwf_plan fftwPlan;
|
||||
float* tempFFT;
|
||||
float* FFTdata;
|
||||
float* appliedWindow;
|
||||
|
||||
// GUI Variables
|
||||
bool firstMenuRender = true;
|
||||
@ -56,6 +63,7 @@ private:
|
||||
int tuningMode = tuner::TUNER_MODE_NORMAL;
|
||||
dsp::stream<dsp::complex_t> dummyStream;
|
||||
bool demoWindow = false;
|
||||
int selectedWindow = 0;
|
||||
|
||||
EventHandler<VFOManager::VFO*> vfoCreatedHandler;
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace displaymenu {
|
||||
std::vector<std::string> colorMapNames;
|
||||
std::string colorMapNamesTxt = "";
|
||||
std::string colorMapAuthor = "";
|
||||
int selectedWindow = 0;
|
||||
|
||||
const int FFTSizes[] = {
|
||||
65536,
|
||||
@ -70,6 +71,8 @@ namespace displaymenu {
|
||||
}
|
||||
gui::mainWindow.setFFTSize(FFTSizes[fftSizeId]);
|
||||
|
||||
selectedWindow = std::clamp<int>((int)core::configManager.conf["fftWindow"], 0, _FFT_WINDOW_COUNT-1);
|
||||
gui::mainWindow.setFFTWindow(selectedWindow);
|
||||
}
|
||||
|
||||
void draw(void* ctx) {
|
||||
@ -99,13 +102,23 @@ namespace displaymenu {
|
||||
ImGui::Text("FFT Size");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##test_fft_size", &fftSizeId, FFTSizesStr)) {
|
||||
if (ImGui::Combo("##sdrpp_fft_size", &fftSizeId, FFTSizesStr)) {
|
||||
gui::mainWindow.setFFTSize(FFTSizes[fftSizeId]);
|
||||
core::configManager.aquire();
|
||||
core::configManager.conf["fftSize"] = FFTSizes[fftSizeId];
|
||||
core::configManager.release(true);
|
||||
}
|
||||
|
||||
ImGui::Text("FFT Window");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::Combo("##sdrpp_fft_window", &selectedWindow, "Rectangular\0Blackman\0")) {
|
||||
gui::mainWindow.setFFTWindow(selectedWindow);
|
||||
core::configManager.aquire();
|
||||
core::configManager.conf["fftWindow"] = selectedWindow;
|
||||
core::configManager.release(true);
|
||||
}
|
||||
|
||||
if (colorMapNames.size() > 0) {
|
||||
ImGui::Text("Color Map");
|
||||
ImGui::SameLine();
|
||||
|
@ -15,7 +15,7 @@
|
||||
SDRPP_MOD_INFO {
|
||||
/* Name: */ "frequency_manager",
|
||||
/* Description: */ "Frequency manager module for SDR++",
|
||||
/* Author: */ "Ryzerth;zimm",
|
||||
/* Author: */ "Ryzerth;Zimm",
|
||||
/* Version: */ 0, 3, 0,
|
||||
/* Max instances */ 1
|
||||
};
|
||||
@ -125,8 +125,9 @@ private:
|
||||
if (core::modComManager.interfaceExists(vfoName)) {
|
||||
if (core::modComManager.getModuleName(vfoName) == "radio") {
|
||||
int mode = bm.mode;
|
||||
float bandwidth = bm.bandwidth;
|
||||
core::modComManager.callInterface(vfoName, RADIO_IFACE_CMD_SET_MODE, &mode, NULL);
|
||||
// TODO: Set bandwidth as well
|
||||
core::modComManager.callInterface(vfoName, RADIO_IFACE_CMD_SET_BANDWIDTH, &bandwidth, NULL);
|
||||
}
|
||||
}
|
||||
tuner::tune(tuner::TUNER_MODE_NORMAL, vfoName, bm.frequency);
|
||||
@ -594,6 +595,9 @@ private:
|
||||
}
|
||||
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(hoveredBookmarkName.c_str());
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Frequency: %s", freqToStr(hoveredBookmark.frequency).c_str());
|
||||
ImGui::Text("Bandwidth: %s", freqToStr(hoveredBookmark.bandwidth).c_str());
|
||||
ImGui::Text("Mode: %s", demodModeList[hoveredBookmark.mode]);
|
||||
ImGui::EndTooltip();
|
||||
|
@ -162,8 +162,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
float audioBW = std::min<float>(audioSampRate / 2.0f, bw / 2.0f);
|
||||
@ -173,6 +173,7 @@ private:
|
||||
resamp.updateWindow(&win);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -169,12 +169,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -162,12 +162,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -154,14 +154,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
demod.setDeviation(bw / 2.0f);
|
||||
setAudioSampleRate(audioSampRate);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -161,8 +161,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
demod.setBandWidth(bw);
|
||||
@ -173,6 +173,7 @@ private:
|
||||
resamp.updateWindow(&win);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -174,6 +174,10 @@ private:
|
||||
int* _in = (int*)in;
|
||||
if (*_in != _this->demodId) { _this->selectDemodById(*_in); }
|
||||
}
|
||||
else if (code == RADIO_IFACE_CMD_SET_BANDWIDTH) {
|
||||
float* _in = (float*)in;
|
||||
_this->currentDemod->setBandwidth(*_in, true);
|
||||
}
|
||||
}
|
||||
|
||||
void selectDemod(Demodulator* demod) {
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
virtual VFOManager::VFO* getVFO() = 0;
|
||||
virtual void setAudioSampleRate(float sampleRate) = 0;
|
||||
virtual float getAudioSampleRate() = 0;
|
||||
virtual void setBandwidth(float bandWidth, bool updateWaterfall = true) = 0;
|
||||
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
|
||||
virtual void showMenu() = 0;
|
||||
};
|
@ -118,6 +118,10 @@ public:
|
||||
// TODO: Allow selection of the bandwidth
|
||||
}
|
||||
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
|
@ -161,8 +161,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
demod.setBandWidth(bw);
|
||||
@ -173,6 +173,7 @@ private:
|
||||
resamp.updateWindow(&win);
|
||||
}
|
||||
|
||||
private:
|
||||
void setSnapInterval(float snapInt) {
|
||||
snapInterval = snapInt;
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
|
@ -192,13 +192,15 @@ public:
|
||||
_vfo->setSnapInterval(snapInterval);
|
||||
}
|
||||
|
||||
private:
|
||||
void setBandwidth(float bandWidth, bool updateWaterfall = true) {
|
||||
bandWidth = std::clamp<float>(bandWidth, bwMin, bwMax);
|
||||
bw = bandWidth;
|
||||
_vfo->setBandwidth(bw, updateWaterfall);
|
||||
demod.setDeviation(bw / 2.0f);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const float bwMax = 250000;
|
||||
const float bwMin = 50000;
|
||||
const float bbSampRate = 250000;
|
||||
|
@ -1,6 +1,6 @@
|
||||
# SDR++, The bloat-free SDR software
|
||||
|
||||
![Screenshot](https://i.imgur.com/EFOqwQQ.png)
|
||||
![Screenshot](https://i.imgur.com/Ter2MQJ.png)
|
||||
SDR++ is a cross-platform and open source SDR software with the aim of being bloat free and simple to use.
|
||||
|
||||
![Build](https://github.com/AlexandreRouma/SDRPlusPlus/workflows/Build%20Binaries/badge.svg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user