summaryrefslogtreecommitdiff
path: root/src/libfaad/filtbank.c
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-07-14 23:43:01 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2002-07-14 23:43:01 +0000
commit53c5ec96b87ef2bb61c7d3188d549623495d4500 (patch)
treea1b4904418281d23a2ab750b70be88db40062aa3 /src/libfaad/filtbank.c
parent0ee981a355115c35cc9b6aa5066d6b7271c4b28a (diff)
downloadxine-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.c442
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