diff options
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/acelp_filters.c | 33 | ||||
-rw-r--r-- | libavcodec/acelp_filters.h | 19 | ||||
-rw-r--r-- | libavcodec/acelp_vectors.c | 22 | ||||
-rw-r--r-- | libavcodec/acelp_vectors.h | 12 | ||||
-rw-r--r-- | libavcodec/lsp.c | 8 | ||||
-rw-r--r-- | libavcodec/lsp.h | 13 |
6 files changed, 107 insertions, 0 deletions
diff --git a/libavcodec/acelp_filters.c b/libavcodec/acelp_filters.c index 2db69d595d..9f720a5b96 100644 --- a/libavcodec/acelp_filters.c +++ b/libavcodec/acelp_filters.c @@ -73,6 +73,26 @@ void ff_acelp_interpolate(int16_t* out, const int16_t* in, } } +void ff_acelp_interpolatef(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length) +{ + int n, i; + + for (n = 0; n < length; n++) { + int idx = 0; + float v = 0; + + for (i = 0; i < filter_length;) { + v += in[n + i] * filter_coeffs[idx + frac_pos]; + idx += precision; + i++; + v += in[n - i] * filter_coeffs[idx - frac_pos]; + } + out[n] = v; + } +} + void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2], const int16_t* in, int length) @@ -110,3 +130,16 @@ void ff_acelp_apply_order_2_transfer_function(float *buf, mem[0] = tmp; } } + +void ff_tilt_compensation(float *mem, float tilt, float *samples, int size) +{ + float new_tilt_mem = samples[size - 1]; + int i; + + for (i = size - 1; i > 0; i--) + samples[i] -= tilt * samples[i - 1]; + + samples[0] -= tilt * *mem; + *mem = new_tilt_mem; +} + diff --git a/libavcodec/acelp_filters.h b/libavcodec/acelp_filters.h index 2cbe9bb17d..c5be5a6cb1 100644 --- a/libavcodec/acelp_filters.h +++ b/libavcodec/acelp_filters.h @@ -56,6 +56,14 @@ void ff_acelp_interpolate(int16_t* out, const int16_t* in, int frac_pos, int filter_length, int length); /** + * Floating point version of ff_acelp_interpolate() + */ +void ff_acelp_interpolatef(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length); + + +/** * high-pass filtering and upscaling (4.2.5 of G.729). * @param out [out] output buffer for filtered speech data * @param hpf_f [in/out] past filtered data from previous (2 items long) @@ -97,4 +105,15 @@ void ff_acelp_apply_order_2_transfer_function(float *samples, float gain, float mem[2], int n); +/** + * Apply tilt compensation filter, 1 - tilt * z-1. + * + * @param mem pointer to the filter's state (one single float) + * @param tilt tilt factor + * @param samples array where the filter is applied + * @param size the size of the samples array + */ +void ff_tilt_compensation(float *mem, float tilt, float *samples, int size); + + #endif /* AVCODEC_ACELP_FILTERS_H */ diff --git a/libavcodec/acelp_vectors.c b/libavcodec/acelp_vectors.c index 5443006718..2d9aa1ad79 100644 --- a/libavcodec/acelp_vectors.c +++ b/libavcodec/acelp_vectors.c @@ -23,6 +23,7 @@ #include <inttypes.h> #include "avcodec.h" #include "acelp_vectors.h" +#include "celp_math.h" const uint8_t ff_fc_2pulses_9bits_track1[16] = { @@ -155,3 +156,24 @@ void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b, out[i] = weight_coeff_a * in_a[i] + weight_coeff_b * in_b[i]; } + +void ff_adaptative_gain_control(float *buf_out, float speech_energ, + int size, float alpha, float *gain_mem) +{ + int i; + float postfilter_energ = ff_dot_productf(buf_out, buf_out, size); + float gain_scale_factor = 1.0; + float mem = *gain_mem; + + if (postfilter_energ) + gain_scale_factor = sqrt(speech_energ / postfilter_energ); + + gain_scale_factor *= 1.0 - alpha; + + for (i = 0; i < size; i++) { + mem = alpha * mem + gain_scale_factor; + buf_out[i] *= mem; + } + + *gain_mem = mem; +} diff --git a/libavcodec/acelp_vectors.h b/libavcodec/acelp_vectors.h index 3a47a7b61c..58cd84c841 100644 --- a/libavcodec/acelp_vectors.h +++ b/libavcodec/acelp_vectors.h @@ -164,4 +164,16 @@ void ff_acelp_weighted_vector_sum( void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b, float weight_coeff_a, float weight_coeff_b, int length); +/** + * Adaptative gain control (as used in AMR postfiltering) + * + * @param buf_out the input speech buffer + * @param speech_energ input energy + * @param size the input buffer size + * @param alpha exponential filter factor + * @param gain_mem a pointer to the filter memory (single float of size) + */ +void ff_adaptative_gain_control(float *buf_out, float speech_energ, + int size, float alpha, float *gain_mem); + #endif /* AVCODEC_ACELP_VECTORS_H */ diff --git a/libavcodec/lsp.c b/libavcodec/lsp.c index 5b5fc1c50e..09c9259c70 100644 --- a/libavcodec/lsp.c +++ b/libavcodec/lsp.c @@ -47,6 +47,14 @@ void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, in lsfq[lp_order-1] = FFMIN(lsfq[lp_order-1], lsfq_max);//Is warning required ? } +void ff_set_min_dist_lsf(float *lsf, float min_spacing, int size) +{ + int i; + float prev = 0.0; + for (i = 0; i < size; i++) + prev = lsf[i] = FFMAX(lsf[i], prev + min_spacing); +} + void ff_acelp_lsf2lsp(int16_t *lsp, const int16_t *lsf, int lp_order) { int i; diff --git a/libavcodec/lsp.h b/libavcodec/lsp.h index 0fa585016a..9aee5fad7d 100644 --- a/libavcodec/lsp.h +++ b/libavcodec/lsp.h @@ -40,6 +40,19 @@ void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, int lsfq_max, int lp_order); /** + * Adjust the quantized LSFs so they are increasing and not too close. + * + * This step is not mentioned in the AMR spec but is in the reference C decoder. + * Omitting this step creates audible distortion on the sinusoidal sweep + * test vectors in 3GPP TS 26.074. + * + * @param[in,out] lsf LSFs in Hertz + * @param min_spacing minimum distance between two consecutive lsf values + * @param size size of the lsf vector + */ +void ff_set_min_dist_lsf(float *lsf, float min_spacing, int order); + +/** * \brief Convert LSF to LSP * \param lsp [out] LSP coefficients (-0x8000 <= (0.15) < 0x8000) * \param lsf normalized LSF coefficients (0 <= (2.13) < 0x2000 * PI) |