diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-07-14 23:43:01 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2002-07-14 23:43:01 +0000 |
commit | 53c5ec96b87ef2bb61c7d3188d549623495d4500 (patch) | |
tree | a1b4904418281d23a2ab750b70be88db40062aa3 /src/libfaad/filtbank.c | |
parent | 0ee981a355115c35cc9b6aa5066d6b7271c4b28a (diff) | |
download | xine-lib-53c5ec96b87ef2bb61c7d3188d549623495d4500.tar.gz xine-lib-53c5ec96b87ef2bb61c7d3188d549623495d4500.tar.bz2 |
merge FAAD2 - the GPL AAC decoder library.
xine_decoder.c is working, but demux_qt must send some needed
initialization data. currently it's hardcoded to play my test stream, so
it's not usable yet.
CVS patchset: 2267
CVS date: 2002/07/14 23:43:01
Diffstat (limited to 'src/libfaad/filtbank.c')
-rw-r--r-- | src/libfaad/filtbank.c | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/src/libfaad/filtbank.c b/src/libfaad/filtbank.c new file mode 100644 index 000000000..092c17600 --- /dev/null +++ b/src/libfaad/filtbank.c @@ -0,0 +1,442 @@ +/* +** FAAD - Freeware Advanced Audio Decoder +** Copyright (C) 2002 M. Bakker +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** 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 General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** $Id: filtbank.c,v 1.1 2002/07/14 23:43:01 miguelfreitas Exp $ +**/ + +#include "common.h" + +#include <stdlib.h> +#include <assert.h> +#include "filtbank.h" +#include "syntax.h" +#include "kbd_win.h" +#include "mdct.h" + + +void filter_bank_init(fb_info *fb, uint16_t frame_len) +{ + uint16_t i; + uint16_t nshort = frame_len/8; +#ifdef LD_DEC + uint16_t frame_len_ld = frame_len/2; +#endif + + /* normal */ + faad_mdct_init(&(fb->mdct256), 2*nshort); + faad_mdct_init(&(fb->mdct2048), 2*frame_len); + + fb->long_window[0] = malloc(frame_len*sizeof(real_t)); + fb->short_window[0] = malloc(nshort*sizeof(real_t)); + fb->long_window[1] = kbd_long; + fb->short_window[1] = kbd_short; + + /* calculate the sine windows */ + for (i = 0; i < frame_len; i++) + fb->long_window[0][i] = (real_t)sin(M_PI / (2.0 * frame_len) * (i + 0.5)); + for (i = 0; i < nshort; i++) + fb->short_window[0][i] = (real_t)sin(M_PI / (2.0 * nshort) * (i + 0.5)); + +#ifdef LD_DEC + /* LD */ + faad_mdct_init(&(fb->mdct1024), frame_len_ld); + + fb->ld_window[0] = malloc(frame_len_ld*sizeof(real_t)); + fb->ld_window[1] = malloc(frame_len_ld*sizeof(real_t)); + + /* calculate the sine windows */ + for (i = 0; i < frame_len_ld; i++) + fb->ld_window[0][i] = (real_t)sin(M_PI / (2.0 * frame_len_ld) * (i + 0.5)); + + /* low overlap window */ + for (i = 0; i < 3*(frame_len_ld>>3); i++) + fb->ld_window[1][i] = 0.0; + for (; i < 5*(frame_len_ld>>3); i++) + fb->ld_window[1][i] = (real_t)sin((i-3*(frame_len_ld>>3)+0.5) * M_PI / (frame_len_ld>>1)); + for (; i < frame_len_ld; i++) + fb->ld_window[1][i] = 1.0; +#endif +} + +void filter_bank_end(fb_info *fb) +{ + faad_mdct_end(&(fb->mdct256)); + faad_mdct_end(&(fb->mdct2048)); + + if (fb->long_window[0]) free(fb->long_window[0]); + if (fb->short_window[0]) free(fb->short_window[0]); + +#ifdef LD_DEC + faad_mdct_end(&(fb->mdct1024)); + + if (fb->ld_window[0]) free(fb->ld_window[0]); + if (fb->ld_window[1]) free(fb->ld_window[1]); +#endif +} + +static INLINE void vcopy(real_t *src, real_t *dest, uint16_t vlen) +{ + int16_t i; + + assert(vlen % 4 == 0); + + for (i = vlen/4-1; i >= 0; --i) + { + *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; *dest++ = *src++; + } +} + +static INLINE void vzero(real_t *dest, uint16_t vlen) +{ + int16_t i; + + assert(vlen % 4 == 0); + + for (i = vlen/4-1; i >= 0; --i) + { + *dest-- = 0; *dest-- = 0; *dest-- = 0; *dest-- = 0; + } +} + +static INLINE void vmult1(real_t *src1, real_t *src2, real_t *dest, uint16_t vlen) +{ + int16_t i; + + assert(vlen % 4 == 0); + + for (i = vlen/4-1; i >= 0 ; --i) + { + *dest++ = MUL(*src1++, *src2++); *dest++ = MUL(*src1++, *src2++); + *dest++ = MUL(*src1++, *src2++); *dest++ = MUL(*src1++, *src2++); + } +} + +static INLINE void vmult2(real_t *src1, real_t *src2, real_t *dest, uint16_t vlen) +{ + int16_t i; + + assert(vlen % 4 == 0); + + for (i = vlen/4-1; i >= 0 ; --i) + { + *dest++ = MUL(*src1++, *src2--); *dest++ = MUL(*src1++, *src2--); + *dest++ = MUL(*src1++, *src2--); *dest++ = MUL(*src1++, *src2--); + } +} + +static INLINE void vadd(real_t *src1, real_t *src2, real_t *dest, uint16_t vlen) +{ + int16_t i; + + assert(vlen % 4 == 0); + + for (i = vlen/4-1; i >= 0; --i) + { + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; +/* + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; + *dest++ = *src1++ + *src2++; *dest++ = *src1++ + *src2++; +*/ + } +} + +static INLINE void imdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) +{ + mdct_info *mdct; + + switch (len) + { + case 2048: + case 1920: + mdct = &(fb->mdct2048); + break; + case 256: + case 240: + mdct = &(fb->mdct256); + break; +#ifdef LD_DEC + case 1024: + case 960: + mdct = &(fb->mdct1024); + break; +#endif + } + + faad_imdct(mdct, in_data, out_data); +} + +#ifdef LTP_DEC +static INLINE void mdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) +{ + mdct_info *mdct; + + switch (len) + { + case 2048: + case 1920: + mdct = &(fb->mdct2048); + break; + case 256: + case 120: + mdct = &(fb->mdct256); + break; +#ifdef LD_DEC + case 1024: + case 960: + mdct = &(fb->mdct1024); + break; +#endif + } + + faad_mdct(mdct, in_data, out_data); +} +#endif + +void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *freq_in, real_t *time_buff, + real_t *time_out, uint8_t object_type, uint16_t frame_len) +{ + real_t *o_buf, *transf_buf; + real_t *obuf_temp; + + real_t *window_long; + real_t *window_long_prev; + real_t *window_short; + real_t *window_short_prev; + real_t *window_short_prev_ptr; + + real_t *fp; + int8_t win; + uint16_t nlong = frame_len; + uint16_t nshort = frame_len/8; + + uint16_t nflat_ls = (nlong-nshort)/2; + + transf_buf = malloc(2*nlong*sizeof(real_t)); + +#ifdef LD_DEC + if (object_type == LD) + { + window_long = fb->ld_window[window_shape]; + window_long_prev = fb->ld_window[window_shape_prev]; + } else { +#endif + window_long = fb->long_window[window_shape]; + window_long_prev = fb->long_window[window_shape_prev]; + window_short = fb->short_window[window_shape]; + window_short_prev = fb->short_window[window_shape_prev]; +#ifdef LD_DEC + } +#endif + + /* pointer to previous window function */ + window_short_prev_ptr = window_short_prev; + + vcopy(time_buff, time_out, nlong); + o_buf = time_out; + + switch (window_sequence) + { + case ONLY_LONG_SEQUENCE: + /* inverse transform */ + imdct(fb, freq_in, transf_buf, 2*nlong); + + /* window function (previous) on first half of the new data */ + vmult1(transf_buf, window_long_prev, transf_buf, nlong); + + /* overlap and add second half of the old data with first half + of the new data */ + vadd(transf_buf, o_buf, o_buf, nlong); + + /* reversed window function on second half of the new data */ + vmult2(transf_buf+nlong, window_long+nlong-1, o_buf+nlong, nlong); + break; + + case LONG_START_SEQUENCE: + /* inverse transform */ + imdct(fb, freq_in, transf_buf, 2*nlong); + + /* window function (previous) on first half of the new data */ + vmult1(transf_buf, window_long_prev, transf_buf, nlong); + + /* overlap and add second half of the old data with first half + of the new data */ + vadd(transf_buf, o_buf, o_buf, nlong); + + /* copy data from nlong upto (3*nlong-nshort)/4; (window function = 1.0) */ + vcopy(transf_buf+nlong, o_buf+nlong, nflat_ls); + + /* reversed window function on part of second half of the new data */ + vmult2(transf_buf+nlong+nflat_ls, window_short+nshort-1, + o_buf+nlong+nflat_ls, nshort); + + /* zero rest of the data; (window function = 0.0) */ + vzero(o_buf+2*nlong-1, nflat_ls); + break; + + case EIGHT_SHORT_SEQUENCE: + obuf_temp = malloc(2*nlong*sizeof(real_t)); + vzero(obuf_temp+2*nlong-1, 2*nlong); + + fp = obuf_temp; + vcopy(time_buff+nflat_ls, fp, nshort); + + for (win = 8-1; win >= 0; --win) + { + /* inverse transform */ + imdct(fb, freq_in, transf_buf, 2*nshort); + + /* window function (previous) on first half of the new data */ + vmult1(transf_buf, window_short_prev_ptr, transf_buf, nshort); + + /* overlap and add second half of the old data with first half + of the new data */ + vadd(transf_buf, fp, fp, nshort); + + /* reversed window function on second half of the new data */ + vmult2(transf_buf+nshort, window_short+nshort-1, fp+nshort, nshort); + + /* shift to next short block */ + freq_in += nshort; + fp += nshort; + window_short_prev_ptr = window_short; + } + + vcopy(obuf_temp, o_buf + 448, nlong*2-nflat_ls); + vzero(o_buf+2*nlong-1, nflat_ls); + + free(obuf_temp); + break; + + case LONG_STOP_SEQUENCE: + /* inverse transform */ + imdct(fb, freq_in, transf_buf, 2*nlong); + + /* zero first part of first half of the data (window function = 0.0) */ + vzero(transf_buf+nflat_ls-1, nflat_ls); + + /* window function (previous) on part of the first half of + the new data */ + vmult1(transf_buf+nflat_ls, window_short_prev_ptr, + transf_buf+nflat_ls, nshort); + + /* third part of the stop sequence window is window function = 1, + so no need to actually apply that */ + + /* overlap and add second half of the old data with first half + of the new data */ + vadd(transf_buf, o_buf, o_buf, nlong); + + /* reversed window function on second half of the new data */ + vmult2(transf_buf+nlong, window_long+nlong-1, o_buf+nlong, nlong); + break; + } + + /* save second half of data */ + vcopy(o_buf+nlong, time_buff, nlong); + + free(transf_buf); +} + +#ifdef LTP_DEC +/* only works for LTP -> no overlapping */ +void filter_bank_ltp(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *in_data, real_t *out_mdct, + uint8_t object_type, uint16_t frame_len) +{ + int8_t win; + real_t *windowed_buf; + real_t *p_o_buf; + + real_t *window_long; + real_t *window_long_prev; + real_t *window_short; + real_t *window_short_prev; + real_t *window_short_prev_ptr; + + uint16_t nlong = frame_len; + uint16_t nshort = frame_len/8; + uint16_t nflat_ls = (nlong-nshort)/2; + + windowed_buf = malloc(nlong*2*sizeof(real_t)); + +#ifdef LD_DEC + if (object_type == LD) + { + window_long = fb->ld_window[window_shape]; + window_long_prev = fb->ld_window[window_shape_prev]; + } else { +#endif + window_long = fb->long_window[window_shape]; + window_long_prev = fb->long_window[window_shape_prev]; + window_short = fb->short_window[window_shape]; + window_short_prev = fb->short_window[window_shape_prev]; +#ifdef LD_DEC + } +#endif + + window_short_prev_ptr = window_short_prev; + + p_o_buf = in_data; + + switch(window_sequence) + { + case ONLY_LONG_SEQUENCE: + vmult1(p_o_buf, window_long_prev, windowed_buf, nlong); + vmult2(p_o_buf+nlong, window_long+nlong-1, windowed_buf+nlong, nlong); + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + + case LONG_START_SEQUENCE: + vmult1(p_o_buf, window_long_prev, windowed_buf, nlong); + vcopy(p_o_buf+nlong, windowed_buf+nlong, nflat_ls); + vmult2(p_o_buf+nlong+nflat_ls, window_short+nshort-1, windowed_buf+nlong+nflat_ls, nshort); + vzero(windowed_buf+2*nlong-1, nflat_ls); + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + + case EIGHT_SHORT_SEQUENCE: + for (win = 8-1; win >= 0; --win) + { + vmult1(p_o_buf, window_short_prev_ptr, windowed_buf, nshort); + vmult2(p_o_buf+nshort, window_short+nshort-1, windowed_buf+nshort, nshort); + mdct(fb, windowed_buf, out_mdct, 2*nshort); + + out_mdct += nshort; + p_o_buf += 2*nshort; + window_short_prev_ptr = window_short; + } + break; + + case LONG_STOP_SEQUENCE: + vzero(windowed_buf+nflat_ls-1, nflat_ls); + vmult1(p_o_buf+nflat_ls, window_short_prev_ptr, windowed_buf+nflat_ls, nshort); + vcopy(p_o_buf+nflat_ls+nshort, windowed_buf+nflat_ls+nshort, nflat_ls); + vmult2(p_o_buf+nlong, window_long+nlong-1, windowed_buf+nlong, nlong); + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + } + + free(windowed_buf); +} +#endif |