satdump/src-core/common/dsp/fft/fft_pan.cpp

123 lines
3.9 KiB
C++
Raw Permalink Normal View History

2022-08-15 12:38:39 +02:00
#include "fft_pan.h"
2022-04-26 15:07:18 +02:00
#include "logger.h"
2023-01-31 01:12:10 +01:00
#include "common/dsp/window/window.h"
2022-04-26 15:07:18 +02:00
namespace dsp
{
2022-08-15 12:38:39 +02:00
FFTPanBlock::FFTPanBlock(std::shared_ptr<dsp::stream<complex_t>> input)
2022-04-26 15:07:18 +02:00
: Block(input)
{
}
2022-08-15 12:38:39 +02:00
FFTPanBlock::~FFTPanBlock()
2022-04-26 15:07:18 +02:00
{
2022-12-05 12:22:45 +01:00
if (fft_output_buffer != nullptr)
destroy_fft();
2022-04-26 15:07:18 +02:00
}
2022-12-05 12:22:45 +01:00
void FFTPanBlock::set_fft_settings(int size, uint64_t samplerate, int rate)
2022-04-26 15:07:18 +02:00
{
fft_mutex.lock();
2023-02-09 17:51:07 +01:00
if (rate < 1)
rate = 1;
2022-04-26 15:07:18 +02:00
fft_size = size;
2022-11-29 15:25:20 +01:00
if (fft_output_buffer != nullptr)
2022-04-26 15:07:18 +02:00
destroy_fft();
2022-12-09 00:46:40 +01:00
// Compute FFT settings
rbuffer_rate = (samplerate / rate);
rbuffer_size = std::min<int>(rbuffer_rate, fft_size);
rbuffer_skip = rbuffer_rate - rbuffer_size;
2023-05-08 23:08:34 +02:00
logger->trace("FFT Rate %d, Samplerate %d, Final Size %d, Skip %d", rbuffer_rate, samplerate, rbuffer_size, rbuffer_skip);
2022-12-09 00:46:40 +01:00
2022-04-26 15:07:18 +02:00
// Init taps, rectangular window
2022-12-09 00:46:40 +01:00
fft_taps.resize(rbuffer_size);
for (int i = 0; i < rbuffer_size; i++)
2022-12-14 16:47:58 +01:00
fft_taps[i] = window::nuttall(i, rbuffer_size - 1) * ((i % 2) ? 1.0f : -1.0f);
2022-04-26 15:07:18 +02:00
// Init FFTW
fftw_in = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * fft_size);
fftw_out = (fftwf_complex *)fftwf_malloc(sizeof(fftwf_complex) * fft_size);
fftw_plan = fftwf_plan_dft_1d(fft_size, fftw_in, fftw_out, FFTW_FORWARD, FFTW_ESTIMATE);
2022-11-29 23:03:27 +01:00
memset(fftw_in, 0, sizeof(fftwf_complex) * fft_size);
memset(fftw_out, 0, sizeof(fftwf_complex) * fft_size);
2022-04-26 15:07:18 +02:00
// Output buffer
2022-12-05 12:22:45 +01:00
fft_input_buffer = create_volk_buffer<complex_t>(fft_size);
2022-12-04 01:09:54 +01:00
fft_output_buffer = create_volk_buffer<float>(fft_size);
2022-12-05 12:22:45 +01:00
2022-12-05 13:10:29 +01:00
reshape_buffer_size = std::max<int>(STREAM_BUFFER_SIZE, rbuffer_rate * 10);
fft_reshape_buffer = create_volk_buffer<complex_t>(reshape_buffer_size);
2022-12-05 12:22:45 +01:00
in_reshape_buffer = 0;
fft_mutex.unlock();
2022-04-26 15:07:18 +02:00
}
2022-08-15 12:38:39 +02:00
void FFTPanBlock::destroy_fft()
2022-04-26 15:07:18 +02:00
{
fftwf_free(fftw_in);
fftwf_free(fftw_out);
fftwf_destroy_plan(fftw_plan);
2022-12-05 12:22:45 +01:00
volk_free(fft_input_buffer);
2022-12-04 01:09:54 +01:00
volk_free(fft_output_buffer);
2022-12-05 12:22:45 +01:00
volk_free(fft_reshape_buffer);
2022-04-26 15:07:18 +02:00
}
2022-08-15 12:38:39 +02:00
void FFTPanBlock::work()
2022-04-26 15:07:18 +02:00
{
int nsamples = input_stream->read();
if (nsamples <= 0)
{
input_stream->flush();
return;
}
2022-11-28 16:02:52 +01:00
fft_mutex.lock();
2022-12-05 13:10:29 +01:00
if (in_reshape_buffer + nsamples < reshape_buffer_size)
2022-04-26 15:07:18 +02:00
{
2022-12-05 12:22:45 +01:00
memcpy(&fft_reshape_buffer[in_reshape_buffer], input_stream->readBuf, nsamples * sizeof(complex_t));
in_reshape_buffer += nsamples;
2022-04-26 15:07:18 +02:00
}
input_stream->flush();
2022-12-05 12:22:45 +01:00
if (in_reshape_buffer > rbuffer_rate)
2022-04-26 15:07:18 +02:00
{
2022-12-05 12:22:45 +01:00
int pos_in_buffer = 0;
while (in_reshape_buffer - pos_in_buffer > rbuffer_rate)
2022-04-26 15:07:18 +02:00
{
2022-12-05 12:22:45 +01:00
memcpy(fft_input_buffer, &fft_reshape_buffer[pos_in_buffer], rbuffer_size * sizeof(complex_t));
pos_in_buffer += rbuffer_rate;
2022-04-26 15:07:18 +02:00
2022-12-05 12:22:45 +01:00
complex_t *buffer_ptr = fft_input_buffer;
2022-12-09 00:46:40 +01:00
volk_32fc_32f_multiply_32fc((lv_32fc_t *)fftw_in, (lv_32fc_t *)buffer_ptr, fft_taps.data(), rbuffer_size);
2022-04-26 15:07:18 +02:00
fftwf_execute(fftw_plan);
2022-12-09 00:46:40 +01:00
volk_32fc_s32f_power_spectrum_32f(fft_output_buffer, (lv_32fc_t *)fftw_out, fft_size, fft_size);
2022-04-26 15:07:18 +02:00
2023-12-13 15:42:08 +01:00
if (avg_num < 1)
avg_num = 1;
float avg_rate = 1.0 / avg_num;
2022-04-26 15:07:18 +02:00
for (int i = 0; i < fft_size; i++)
2023-12-13 15:42:08 +01:00
output_stream->writeBuf[i] = output_stream->writeBuf[i] * (1.0f - avg_rate) + fft_output_buffer[i] * avg_rate;
2023-02-11 01:07:39 +01:00
on_fft(output_stream->writeBuf);
2022-12-05 12:22:45 +01:00
}
2022-04-26 15:07:18 +02:00
2022-12-05 12:22:45 +01:00
if (pos_in_buffer < in_reshape_buffer)
{
2022-12-20 10:27:37 +01:00
memmove(fft_reshape_buffer, &fft_reshape_buffer[pos_in_buffer], (in_reshape_buffer - pos_in_buffer) * sizeof(complex_t));
2022-12-05 12:22:45 +01:00
in_reshape_buffer -= pos_in_buffer;
2022-04-26 15:07:18 +02:00
}
}
2022-12-05 12:22:45 +01:00
fft_mutex.unlock();
2022-04-26 15:07:18 +02:00
}
}