Mercurial > hg > audiostuff
diff spandsp-0.0.6pre17/src/gsm0610_short_term.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/src/gsm0610_short_term.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,363 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * gsm0610_short_term.c - GSM 06.10 full rate speech codec. + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2006 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This code is based on the widely used GSM 06.10 code available from + * http://kbs.cs.tu-berlin.de/~jutta/toast.html + * + * $Id: gsm0610_short_term.c,v 1.19 2009/02/03 16:28:39 steveu Exp $ + */ + +/*! \file */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include <assert.h> +#include <inttypes.h> +#if defined(HAVE_TGMATH_H) +#include <tgmath.h> +#endif +#if defined(HAVE_MATH_H) +#include <math.h> +#endif +#include "floating_fudge.h" +#include <stdlib.h> + +#include "spandsp/telephony.h" +#include "spandsp/fast_convert.h" +#include "spandsp/bitstream.h" +#include "spandsp/saturated.h" +#include "spandsp/gsm0610.h" + +#include "gsm0610_local.h" + +/* SHORT TERM ANALYSIS FILTERING SECTION */ + +/* 4.2.8 */ +static void decode_log_area_ratios(int16_t LARc[8], int16_t *LARpp) +{ + int16_t temp1; + + /* This procedure requires for efficient implementation + two tables. + INVA[1..8] = integer((32768*8)/real_A[1..8]) + MIC[1..8] = minimum value of the LARc[1..8] + */ + + /* Compute the LARpp[1..8] */ + +#undef STEP +#define STEP(B,MIC,INVA) \ + temp1 = saturated_add16(*LARc++, MIC) << 10; \ + temp1 = saturated_sub16(temp1, B << 1); \ + temp1 = gsm_mult_r(INVA, temp1); \ + *LARpp++ = saturated_add16(temp1, temp1); + + STEP( 0, -32, 13107); + STEP( 0, -32, 13107); + STEP( 2048, -16, 13107); + STEP(-2560, -16, 13107); + + STEP( 94, -8, 19223); + STEP(-1792, -8, 17476); + STEP( -341, -4, 31454); + STEP(-1144, -4, 29708); + + /* NOTE: the addition of *MIC is used to restore the sign of *LARc. */ +} +/*- End of function --------------------------------------------------------*/ + +/* 4.2.9 */ + +/* Computation of the quantized reflection coefficients */ + +/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] */ + +/* Within each frame of 160 analyzed speech samples the short term + analysis and synthesis filters operate with four different sets of + coefficients, derived from the previous set of decoded LARs(LARpp(j - 1)) + and the actual set of decoded LARs (LARpp(j)) + + (Initial value: LARpp(j - 1)[1..8] = 0.) +*/ + +static void coefficients_0_12(int16_t *LARpp_j_1, + int16_t *LARpp_j, + int16_t *LARp) +{ + int i; + + for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) + { + *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2); + *LARp = saturated_add16(*LARp, *LARpp_j_1 >> 1); + } + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +static void coefficients_13_26(int16_t *LARpp_j_1, + int16_t *LARpp_j, + int16_t *LARp) +{ + int i; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) + *LARp = saturated_add16(*LARpp_j_1 >> 1, *LARpp_j >> 1); + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +static void coefficients_27_39(int16_t *LARpp_j_1, + int16_t *LARpp_j, + int16_t *LARp) +{ + int i; + + for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) + { + *LARp = saturated_add16(*LARpp_j_1 >> 2, *LARpp_j >> 2); + *LARp = saturated_add16(*LARp, *LARpp_j >> 1); + } + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +static void coefficients_40_159(int16_t *LARpp_j, int16_t *LARp) +{ + int i; + + for (i = 1; i <= 8; i++) + *LARp++ = *LARpp_j++; + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +/* 4.2.9.2 */ +static void larp_to_rp(int16_t LARp[8]) +{ + int i; + int16_t *LARpx; + int16_t temp; + + /* The input to this procedure is the interpolated LARp[0..7] array. + The reflection coefficients, rp[i], are used in the analysis + filter and in the synthesis filter. + */ + + LARpx = LARp; + for (i = 1; i <= 8; i++, LARpx++) + { + temp = *LARpx; + if (temp < 0) + { + if (temp == INT16_MIN) + temp = INT16_MAX; + else + temp = -temp; + /*endif*/ + if (temp < 11059) + temp <<= 1; + else if (temp < 20070) + temp += 11059; + else + temp = saturated_add16(temp >> 2, 26112); + /*endif*/ + *LARpx = -temp; + } + else + { + if (temp < 11059) + temp <<= 1; + else if (temp < 20070) + temp += 11059; + else + temp = saturated_add16(temp >> 2, 26112); + /*endif*/ + *LARpx = temp; + } + /*endif*/ + } + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +/* 4.2.10 */ +static void short_term_analysis_filtering(gsm0610_state_t *s, + int16_t rp[8], + int k_n, // k_end - k_start + int16_t amp[]) // [0..n-1] IN/OUT +{ + /* This procedure computes the short term residual signal d[..] to be fed + to the RPE-LTP loop from the s[..] signal and from the local rp[..] + array (quantized reflection coefficients). As the call of this + procedure can be done in many ways (see the interpolation of the LAR + coefficient), it is assumed that the computation begins with index + k_start (for arrays d[..] and s[..]) and stops with index k_end + (k_start and k_end are defined in 4.2.9.1). This procedure also + needs to keep the array u[0..7] in memory for each call. + */ + int16_t *u0; + int16_t *u_top; + int i; + int16_t *u; + int16_t *rpx; + int32_t di; + int32_t u_out; + + u0 = s->u; + u_top = u0 + 8; + + for (i = 0; i < k_n; i++) + { + di = + u_out = amp[i]; + for (rpx = rp, u = u0; u < u_top; ) + { + int32_t ui; + int32_t rpi; + + ui = *u; + *u++ = (int16_t) u_out; + rpi = *rpx++; + u_out = ui + (((rpi*di) + 0x4000) >> 15); + di = di + (((rpi*ui) + 0x4000) >> 15); + u_out = saturate(u_out); + di = saturate(di); + } + /*endfor*/ + amp[i] = (int16_t) di; + } + /*endfor*/ +} +/*- End of function --------------------------------------------------------*/ + +static void short_term_synthesis_filtering(gsm0610_state_t *s, + int16_t rrp[8], + int k, // k_end - k_start + int16_t *wt, // [0..k - 1] + int16_t *sr) // [0..k - 1] +{ + int16_t *v; + int i; + int16_t sri; + int16_t tmp1; + int16_t tmp2; + + v = s->v; + while (k--) + { + sri = *wt++; + for (i = 8; i--; ) + { + tmp1 = rrp[i]; + tmp2 = v[i]; + tmp2 = ((tmp1 == INT16_MIN && tmp2 == INT16_MIN) + ? + INT16_MAX + : + (int16_t) (((int32_t) tmp1*(int32_t) tmp2 + 16384) >> 15) & 0xFFFF); + + sri = saturated_sub16(sri, tmp2); + + tmp1 = ((tmp1 == INT16_MIN && sri == INT16_MIN) + ? + INT16_MAX + : + (int16_t) (((int32_t) tmp1*(int32_t) sri + 16384) >> 15) & 0xFFFF); + + v[i + 1] = saturated_add16(v[i], tmp1); + } + /*endfor*/ + *sr++ = + v[0] = sri; + } + /*endwhile*/ +} +/*- End of function --------------------------------------------------------*/ + +void gsm0610_short_term_analysis_filter(gsm0610_state_t *s, + int16_t LARc[8], + int16_t amp[GSM0610_FRAME_LEN]) +{ + int16_t *LARpp_j; + int16_t *LARpp_j_1; + int16_t LARp[8]; + + LARpp_j = s->LARpp[s->j]; + LARpp_j_1 = s->LARpp[s->j ^= 1]; + + decode_log_area_ratios(LARc, LARpp_j); + + coefficients_0_12(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_analysis_filtering(s, LARp, 13, amp); + + coefficients_13_26(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_analysis_filtering(s, LARp, 14, amp + 13); + + coefficients_27_39(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_analysis_filtering(s, LARp, 13, amp + 27); + + coefficients_40_159(LARpp_j, LARp); + larp_to_rp(LARp); + short_term_analysis_filtering(s, LARp, 120, amp + 40); +} +/*- End of function --------------------------------------------------------*/ + +void gsm0610_short_term_synthesis_filter(gsm0610_state_t *s, + int16_t LARcr[8], + int16_t wt[GSM0610_FRAME_LEN], + int16_t amp[GSM0610_FRAME_LEN]) +{ + int16_t *LARpp_j; + int16_t *LARpp_j_1; + int16_t LARp[8]; + + LARpp_j = s->LARpp[s->j]; + LARpp_j_1 = s->LARpp[s->j ^= 1]; + + decode_log_area_ratios(LARcr, LARpp_j); + + coefficients_0_12(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_synthesis_filtering(s, LARp, 13, wt, amp); + + coefficients_13_26(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_synthesis_filtering(s, LARp, 14, wt + 13, amp + 13); + + coefficients_27_39(LARpp_j_1, LARpp_j, LARp); + larp_to_rp(LARp); + short_term_synthesis_filtering(s, LARp, 13, wt + 27, amp + 27); + + coefficients_40_159(LARpp_j, LARp); + larp_to_rp(LARp); + short_term_synthesis_filtering(s, LARp, 120, wt + 40, amp + 40); +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/