|
|
@ -56,6 +56,10 @@ int srslte_resampler_fft_init(srslte_resampler_fft_t* q, srslte_resampler_mode_t
|
|
|
|
return SRSLTE_ERROR_OUT_OF_BOUNDS;
|
|
|
|
return SRSLTE_ERROR_OUT_OF_BOUNDS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (q->mode == mode && q->ratio == ratio) {
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure interpolator is freed
|
|
|
|
// Make sure interpolator is freed
|
|
|
|
srslte_resampler_fft_free(q);
|
|
|
|
srslte_resampler_fft_free(q);
|
|
|
|
|
|
|
|
|
|
|
@ -142,26 +146,32 @@ int srslte_resampler_fft_init(srslte_resampler_fft_t* q, srslte_resampler_mode_t
|
|
|
|
float norm = 1.0f / (cabsf(q->out_buffer[0]) * (float)input_fft_size);
|
|
|
|
float norm = 1.0f / (cabsf(q->out_buffer[0]) * (float)input_fft_size);
|
|
|
|
srslte_vec_sc_prod_cfc(q->out_buffer, norm, q->filter, high_size);
|
|
|
|
srslte_vec_sc_prod_cfc(q->out_buffer, norm, q->filter, high_size);
|
|
|
|
|
|
|
|
|
|
|
|
// Zero state
|
|
|
|
// reset state
|
|
|
|
q->state_len = 0;
|
|
|
|
srslte_resampler_fft_reset_state(q);
|
|
|
|
srslte_vec_cf_zero(q->state, output_fft_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void srslte_resampler_fft_reset_state(srslte_resampler_fft_t* q)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
q->state_len = 0;
|
|
|
|
|
|
|
|
srslte_vec_cf_zero(q->state, q->ifft.size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void resampler_fft_interpolate(srslte_resampler_fft_t* q, const cf_t* input, cf_t* output, uint32_t nsamples)
|
|
|
|
static void resampler_fft_interpolate(srslte_resampler_fft_t* q, const cf_t* input, cf_t* output, uint32_t nsamples)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (q == NULL || input == NULL || output == NULL) {
|
|
|
|
if (q == NULL) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (count < nsamples) {
|
|
|
|
while (count < nsamples) {
|
|
|
|
uint32_t n = SRSLTE_MIN(q->window_sz, nsamples - count);
|
|
|
|
uint32_t n = SRSLTE_MIN(q->window_sz, nsamples - count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (input) {
|
|
|
|
// Copy input samples
|
|
|
|
// Copy input samples
|
|
|
|
srslte_vec_cf_copy(q->in_buffer, &input[count], q->window_sz);
|
|
|
|
srslte_vec_cf_copy(q->in_buffer, &input[count], n);
|
|
|
|
|
|
|
|
|
|
|
|
// Pad zeroes
|
|
|
|
// Pad zeroes
|
|
|
|
srslte_vec_cf_zero(&q->in_buffer[n], q->fft.size - n);
|
|
|
|
srslte_vec_cf_zero(&q->in_buffer[n], q->fft.size - n);
|
|
|
@ -179,12 +189,18 @@ static void resampler_fft_interpolate(srslte_resampler_fft_t* q, const cf_t* inp
|
|
|
|
|
|
|
|
|
|
|
|
// Execute iFFT
|
|
|
|
// Execute iFFT
|
|
|
|
srslte_dft_run_guru_c(&q->ifft);
|
|
|
|
srslte_dft_run_guru_c(&q->ifft);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Equivalent IFFT output of feeding zeroes
|
|
|
|
|
|
|
|
srslte_vec_cf_zero(q->out_buffer, q->ifft.size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add previous state
|
|
|
|
// Add previous state
|
|
|
|
srslte_vec_sum_ccc(q->out_buffer, q->state, q->out_buffer, q->state_len);
|
|
|
|
srslte_vec_sum_ccc(q->out_buffer, q->state, q->out_buffer, q->state_len);
|
|
|
|
|
|
|
|
|
|
|
|
// Copy output
|
|
|
|
// Copy output
|
|
|
|
|
|
|
|
if (output) {
|
|
|
|
srslte_vec_cf_copy(&output[count * q->ratio], q->out_buffer, n * q->ratio);
|
|
|
|
srslte_vec_cf_copy(&output[count * q->ratio], q->out_buffer, n * q->ratio);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Save current state
|
|
|
|
// Save current state
|
|
|
|
q->state_len = q->ifft.size - n * q->ratio;
|
|
|
|
q->state_len = q->ifft.size - n * q->ratio;
|
|
|
@ -206,6 +222,7 @@ static void resampler_fft_decimate(srslte_resampler_fft_t* q, const cf_t* input,
|
|
|
|
while (count < nsamples) {
|
|
|
|
while (count < nsamples) {
|
|
|
|
uint32_t n = SRSLTE_MIN(q->window_sz, nsamples - count);
|
|
|
|
uint32_t n = SRSLTE_MIN(q->window_sz, nsamples - count);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (input) {
|
|
|
|
// Copy input samples
|
|
|
|
// Copy input samples
|
|
|
|
srslte_vec_cf_copy(q->in_buffer, &input[count], q->window_sz);
|
|
|
|
srslte_vec_cf_copy(q->in_buffer, &input[count], q->window_sz);
|
|
|
|
|
|
|
|
|
|
|
@ -224,12 +241,17 @@ static void resampler_fft_decimate(srslte_resampler_fft_t* q, const cf_t* input,
|
|
|
|
|
|
|
|
|
|
|
|
// Execute iFFT
|
|
|
|
// Execute iFFT
|
|
|
|
srslte_dft_run_guru_c(&q->ifft);
|
|
|
|
srslte_dft_run_guru_c(&q->ifft);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
srslte_vec_cf_zero(q->out_buffer, q->ifft.size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add previous state
|
|
|
|
// Add previous state
|
|
|
|
srslte_vec_sum_ccc(q->out_buffer, q->state, q->out_buffer, q->state_len);
|
|
|
|
srslte_vec_sum_ccc(q->out_buffer, q->state, q->out_buffer, q->state_len);
|
|
|
|
|
|
|
|
|
|
|
|
// Copy output
|
|
|
|
// Copy output
|
|
|
|
|
|
|
|
if (output) {
|
|
|
|
srslte_vec_cf_copy(&output[count / q->ratio], q->out_buffer, n / q->ratio);
|
|
|
|
srslte_vec_cf_copy(&output[count / q->ratio], q->out_buffer, n / q->ratio);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Save current state
|
|
|
|
// Save current state
|
|
|
|
q->state_len = q->ifft.size - n / q->ratio;
|
|
|
|
q->state_len = q->ifft.size - n / q->ratio;
|
|
|
|