diff options
Diffstat (limited to 'codecs/mp3/src/dec8.c')
-rwxr-xr-x | codecs/mp3/src/dec8.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/codecs/mp3/src/dec8.c b/codecs/mp3/src/dec8.c new file mode 100755 index 000000000..478bbf1df --- /dev/null +++ b/codecs/mp3/src/dec8.c @@ -0,0 +1,338 @@ +/*____________________________________________________________________________ + + FreeAmp - The Free MP3 Player + + MP3 Decoder originally Copyright (C) 1995-1997 Xing Technology + Corp. http://www.xingtech.com + + Portions Copyright (C) 1998-1999 EMusic.com + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +____________________________________________________________________________*/ + +/**** dec8.c *************************************************** + + +ANSI C +MPEG audio decoder Layer II only mpeg1 and mpeg2 +output sample type and sample rate conversion + decode mpeg to 8000Ks mono + output 16 bit linear, 8 bit linear, or u-law + + +mod 6/29/95 bugfix in u-law table + +mod 11/15/95 for Layer I + +mod 1/7/97 minor mods for warnings + +******************************************************************/ +/***************************************************************** + + MPEG audio software decoder portable ANSI c. + Decodes all Layer II to 8000Ks mono pcm. + Output selectable: 16 bit linear, 8 bit linear, u-law. + +------------------------------------- +int audio_decode8_init(MPEG_HEAD *h, int framebytes_arg, + int reduction_code, int transform_code, int convert_code, + int freq_limit) + +initilize decoder: + return 0 = fail, not 0 = success + +MPEG_HEAD *h input, mpeg header info (returned by call to head_info) +framebytes input, mpeg frame size (returned by call to head_info) +reduction_code input, ignored +transform_code input, ignored +convert_code input, set convert_code = 4*bit_code + chan_code + bit_code: 1 = 16 bit linear pcm + 2 = 8 bit (unsigned) linear pcm + 3 = u-law (8 bits unsigned) + chan_code: 0 = convert two chan to mono + 1 = convert two chan to mono + 2 = convert two chan to left chan + 3 = convert two chan to right chan +freq_limit input, ignored + + +--------------------------------- +void audio_decode8_info( DEC_INFO *info) + +information return: + Call after audio_decode8_init. See mhead.h for + information returned in DEC_INFO structure. + + +--------------------------------- +IN_OUT audio_decode8(unsigned char *bs, void *pcmbuf) + +decode one mpeg audio frame: +bs input, mpeg bitstream, must start with + sync word. Caution: may read up to 3 bytes + beyond end of frame. +pcmbuf output, pcm samples. + +IN_OUT structure returns: + Number bytes conceptually removed from mpeg bitstream. + Returns 0 if sync loss. + Number bytes of pcm output. This may vary from frame + to frame. + +*****************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <float.h> +#include <math.h> +#include "L3.h" +#include "mhead.h" /* mpeg header structure */ + + + + + +/*------------------------------------------*/ +static int output_code; +static int convert(void *mv, unsigned char *pcm); +static int convert_8bit(void *mv, unsigned char *pcm); +static int convert_u(void *mv, unsigned char *pcm); +static CVT_FUNCTION_8 cvt_table[3] = +{ + convert, + convert_8bit, + convert_u, +}; + +void mpeg8_init(MPEG8 *m) +{ + memset(&m->dec, 0, sizeof(m->dec)); + m->dec.ncnt = 8 * 288; + m->dec.ncnt1 = 8 * 287; + m->dec.nlast = 287; + m->dec.ndeci = 11; + m->dec.kdeci = 8 * 288; + m->dec.first_pass = 1; +} + +/*====================================================================*/ +IN_OUT audio_decode8(MPEG8 *m, unsigned char *bs, signed short *pcmbuf) +{ + IN_OUT x; + + x = audio_decode(&m->cupper, bs, m->dec.pcm); + if (x.in_bytes <= 0) + return x; + x.out_bytes = m->dec.convert_routine(m, (void *) pcmbuf); + + return x; +} +/*--------------8Ks 16 bit pcm --------------------------------*/ +static int convert(void *mv, unsigned char y0[]) +{ + MPEG8 *m = mv; + int i, k; + long alpha; + short *y; + + y = (short *) y0; + k = 0; + if (m->dec.kdeci < m->dec.ncnt) + { + alpha = m->dec.kdeci & 7; + y[k++] = (short) (m->dec.xsave + ((alpha * (m->dec.pcm[0] - m->dec.xsave)) >> 3)); + m->dec.kdeci += m->dec.ndeci; + } + m->dec.kdeci -= m->dec.ncnt; + for (; m->dec.kdeci < m->dec.ncnt1; m->dec.kdeci += m->dec.ndeci) + { + i = m->dec.kdeci >> 3; + alpha = m->dec.kdeci & 7; + y[k++] = (short) (m->dec.pcm[i] + ((alpha * (m->dec.pcm[i + 1] - m->dec.pcm[i])) >> 3)); + } + m->dec.xsave = m->dec.pcm[m->dec.nlast]; + +/* printf("\n k out = %4d", k); */ + + return sizeof(short) * k; +} +/*----------------8Ks 8 bit unsigned pcm ---------------------------*/ +static int convert_8bit(void *mv, unsigned char y[]) +{ + MPEG8 *m = mv; + int i, k; + long alpha; + + k = 0; + if (m->dec.kdeci < m->dec.ncnt) + { + alpha = m->dec.kdeci & 7; + y[k++] = (unsigned char) (((m->dec.xsave + ((alpha * (m->dec.pcm[0] - m->dec.xsave)) >> 3)) >> 8) + 128); + m->dec.kdeci += m->dec.ndeci; + } + m->dec.kdeci -= m->dec.ncnt; + for (; m->dec.kdeci < m->dec.ncnt1; m->dec.kdeci += m->dec.ndeci) + { + i = m->dec.kdeci >> 3; + alpha = m->dec.kdeci & 7; + y[k++] = (unsigned char) (((m->dec.pcm[i] + ((alpha * (m->dec.pcm[i + 1] - m->dec.pcm[i])) >> 3)) >> 8) + 128); + } + m->dec.xsave = m->dec.pcm[m->dec.nlast]; + +/* printf("\n k out = %4d", k); */ + + return k; +} +/*--------------8Ks u-law --------------------------------*/ +static int convert_u(void *mv, unsigned char y[]) +{ + MPEG8 *m = mv; + int i, k; + long alpha; + unsigned char *look; + + look = m->dec.look_u + 4096; + + k = 0; + if (m->dec.kdeci < m->dec.ncnt) + { + alpha = m->dec.kdeci & 7; + y[k++] = look[(m->dec.xsave + ((alpha * (m->dec.pcm[0] - m->dec.xsave)) >> 3)) >> 3]; + m->dec.kdeci += m->dec.ndeci; + } + m->dec.kdeci -= m->dec.ncnt; + for (; m->dec.kdeci < m->dec.ncnt1; m->dec.kdeci += m->dec.ndeci) + { + i = m->dec.kdeci >> 3; + alpha = m->dec.kdeci & 7; + y[k++] = look[(m->dec.pcm[i] + ((alpha * (m->dec.pcm[i + 1] - m->dec.pcm[i])) >> 3)) >> 3]; + } + m->dec.xsave = m->dec.pcm[m->dec.nlast]; + +/* printf("\n k out = %4d", k); */ + + return k; +} +/*--------------------------------------------------------------------*/ +static int ucomp3(int x) /* re analog devices CCITT G.711 */ +{ + int s, p, y, t, u, u0, sign; + + sign = 0; + if (x < 0) + { + x = -x; + sign = 0x0080; + } + if (x > 8031) + x = 8031; + x += 33; + t = x; + for (s = 0; s < 15; s++) + { + if (t & 0x4000) + break; + t <<= 1; + } + y = x << s; + p = (y >> 10) & 0x0f; /* position */ + s = 9 - s; /* segment */ + u0 = (((s << 4) | p) & 0x7f) | sign; + u = u0 ^ 0xff; + + return u; +} +/*------------------------------------------------------------------*/ +static void table_init(MPEG8 *m) +{ + int i; + + for (i = -4096; i < 4096; i++) + m->dec.look_u[4096 + i] = (unsigned char) (ucomp3(2 * i)); + +} +/*-------------------------------------------------------------------*/ +int audio_decode8_init(MPEG8 *m, MPEG_HEAD * h, int framebytes_arg, + int reduction_code, int transform_code, int convert_code, + int freq_limit) +{ + int istat; + int outvals; + static int sr_table[2][4] = + {{22, 24, 16, 0}, {44, 48, 32, 0}}; + + if (m->dec.first_pass) + { + table_init(m); + m->dec.first_pass = 0; + } + + if ((h->sync & 1) == 0) + return 0; // fail mpeg 2.5 + + output_code = convert_code >> 2; + if (output_code < 1) + output_code = 1; /* 1= 16bit 2 = 8bit 3 = u */ + if (output_code > 3) + output_code = 3; /* 1= 16bit 2 = 8bit 3 = u */ + + convert_code = convert_code & 3; + if (convert_code <= 0) + convert_code = 1; /* always cvt to mono */ + + reduction_code = 1; + if (h->id) + reduction_code = 2; + +/* select convert routine */ + m->dec.convert_routine = cvt_table[output_code - 1]; + +/* init decimation/convert routine */ +/*-- MPEG-2 layer III --*/ + if ((h->option == 1) && h->id == 0) + outvals = 576 >> reduction_code; + else if (h->option == 3) + outvals = 384 >> reduction_code; +/*-- layer I --*/ + else + outvals = 1152 >> reduction_code; + m->dec.ncnt = 8 * outvals; + m->dec.ncnt1 = 8 * (outvals - 1); + m->dec.nlast = outvals - 1; + m->dec.ndeci = sr_table[h->id][h->sr_index] >> reduction_code; + m->dec.kdeci = 8 * outvals; +/* printf("\n outvals %d", outvals); */ + + freq_limit = 3200; + istat = audio_decode_init(&m->cupper, h, framebytes_arg, + reduction_code, transform_code, convert_code, + freq_limit); + + + return istat; +} +/*-----------------------------------------------------------------*/ +void audio_decode8_info(MPEG8 *m, DEC_INFO * info) +{ + + audio_decode_info(&m->cupper, info); + info->samprate = 8000; + if (output_code != 1) + info->bits = 8; + if (output_code == 3) + info->type = 10; +} |