FFT based Resampler admits NULL inputs/outputs

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 44ae70dcc6
commit 5799100e42

@ -73,6 +73,12 @@ typedef struct {
*/ */
SRSLTE_API int srslte_resampler_fft_init(srslte_resampler_fft_t* q, srslte_resampler_mode_t mode, uint32_t ratio); SRSLTE_API int srslte_resampler_fft_init(srslte_resampler_fft_t* q, srslte_resampler_mode_t mode, uint32_t ratio);
/**
* @brief resets internal re-sampler state
* @param q Object pointer
*/
SRSLTE_API void srslte_resampler_fft_reset_state(srslte_resampler_fft_t* q);
/** /**
* Get delay from the FFT based resampler. * Get delay from the FFT based resampler.
* @param q Object pointer * @param q Object pointer
@ -81,7 +87,11 @@ SRSLTE_API int srslte_resampler_fft_init(srslte_resampler_fft_t* q, srslte_resam
SRSLTE_API uint32_t srslte_resampler_fft_get_delay(srslte_resampler_fft_t* q); SRSLTE_API uint32_t srslte_resampler_fft_get_delay(srslte_resampler_fft_t* q);
/** /**
* Run FFT based resampler in the initiated mode. * @brief Run FFT based resampler in the initiated mode.
*
* @note Setting the input to NULL is equivalent of feeding zeroes
* @note Setting the output to NULL is equivalent of dropping output samples
*
* @param q Object pointer, make sure it has been initialised * @param q Object pointer, make sure it has been initialised
* @param input Points at the input complex buffer * @param input Points at the input complex buffer
* @param output Points at the output complex buffer * @param output Points at the output complex buffer

@ -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;

Loading…
Cancel
Save