satdump/src-core/common/dsp/rational_resampler.cpp
2021-10-22 15:26:17 +02:00

85 lines
No EOL
2.5 KiB
C++

#include "rational_resampler.h"
#include <numeric>
#include "firdes.h"
namespace dsp
{
CCRationalResamplerBlock::CCRationalResamplerBlock(std::shared_ptr<dsp::stream<complex_t>> input, unsigned interpolation, unsigned decimation)
: Block(input),
d_interpolation(interpolation),
d_decimation(decimation),
d_ctr(0)
{
// Get alignement parameters
int align = volk_get_alignment();
// Buffer
in_buffer = 0;
int size = 2 * STREAM_BUFFER_SIZE;
buffer = (complex_t *)volk_malloc(size * sizeof(complex_t), align);
std::fill(buffer, &buffer[size], 0);
// Start by reducing the interp and decim by their GCD
int gcd = std::gcd(interpolation, decimation);
d_interpolation /= gcd;
d_decimation /= gcd;
// Generate taps
std::vector rtaps = firdes::design_resampler_filter_float(d_interpolation, d_decimation, 0.4); // 0.4 = Fractional BW
// Filter number & tap number
nfilt = d_interpolation;
ntaps = rtaps.size() / nfilt;
// Init tap buffers
taps = (float **)volk_malloc(nfilt * sizeof(float *), align);
for (int i = 0; i < nfilt; i++)
{
this->taps[i] = (float *)volk_malloc(ntaps * sizeof(float), align);
memset(this->taps[i], 0, ntaps);
}
// Setup taps
for (int i = 0; i < (int)rtaps.size(); i++)
taps[i % nfilt][i / nfilt] = rtaps[i];
}
CCRationalResamplerBlock::~CCRationalResamplerBlock()
{
for (int i = 0; i < nfilt; i++)
volk_free(taps[i]);
volk_free(taps);
volk_free(buffer);
}
void CCRationalResamplerBlock::work()
{
int nsamples = input_stream->read();
if (nsamples <= 0)
{
input_stream->flush();
return;
}
memcpy(&buffer[in_buffer], input_stream->readBuf, nsamples * sizeof(complex_t));
in_buffer += nsamples;
input_stream->flush();
int outc = 0;
for (int i = 0; i < in_buffer - ntaps;)
{
volk_32fc_32f_dot_prod_32fc((lv_32fc_t *)&output_stream->writeBuf[outc++], (lv_32fc_t *)&buffer[i], taps[d_ctr], ntaps);
d_ctr += this->d_decimation;
while (d_ctr >= d_interpolation)
{
d_ctr -= d_interpolation;
i++;
}
}
memmove(&buffer[0], &buffer[in_buffer - ntaps], ntaps * sizeof(complex_t));
in_buffer = ntaps;
output_stream->swap(outc);
}
}