?? wmadeci.c
字號:
/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: $ * * Copyright (C) 2005 Dave Chapman * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************//* * WMA decoder : Fixed (16.16) point decoding based originally on the ffmpeg * WMA decoder source : http://ffmpeg.sourceforge.net. * This version 01/04/06 Marsdaddy <pajojo@gmail.com> */#include "malloc.h"#include "memory.h"/* size of blocks */#define BLOCK_MIN_BITS 7#define BLOCK_MAX_BITS 11#define BLOCK_MAX_SIZE (1 << BLOCK_MAX_BITS)#define BLOCK_NB_SIZES (BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1)#define HIGH_BAND_MAX_SIZE 16#define NB_LSP_COEFS 10#define MAX_CODED_SUPERFRAME_SIZE 16384#define M_PI_F 0x3243f /* in fixed 32 format */#define MAX_CHANNELS 2#define NOISE_TAB_SIZE 8192#define LSP_POW_BITS 7#define VLC_TYPE int16_ttypedef unsigned char uint8_t;typedef char int8_t;typedef unsigned short uint16_t;typedef short int16_t;typedef long long int64_t;typedef int int32_t;typedef unsigned int uint32_t;typedef unsigned long long uint64_t;#define fixed32 int32_t#define fixed64 int64_t#include "codeccontext.h"#include "wmadeci.h"#define IGNORE_OVERFLOW#define FAST_FILTERS#define PRECISION 16#define PRECISION64 16static fixed64 IntTo64(int x){ fixed64 res = 0; unsigned char *p = (unsigned char *)&res; p[2] = x & 0xff; p[3] = (x & 0xff00)>>8; p[4] = (x & 0xff0000)>>16; p[5] = (x & 0xff000000)>>24; return res;}static int IntFrom64(fixed64 x){ int res = 0; unsigned char *p = (unsigned char *)&x; res = p[2] | (p[3]<<8) | (p[4]<<16) | (p[5]<<24); return res;}static fixed32 Fixed32From64(fixed64 x){ return x & 0xFFFFFFFF;}static fixed64 Fixed32To64(fixed32 x){ return (fixed64)x;}#define itofix64(x) (IntTo64(x))#define itofix32(x) ((x) << PRECISION)#define fixtoi32(x) ((x) >> PRECISION)#define fixtoi64(x) (IntFrom64(x))static fixed64 fixmul64byfixed(fixed64 x, fixed32 y){ return x * y;}/* Portions of this 32 bit fixed code modified from the GPL Hawksoftsource <http://www.hawkfost.com> by Phil Frisbie, Jr. <phil@hawksoft.com> */static fixed32 fixmul32(fixed32 x, fixed32 y){ fixed64 temp; temp = x; temp *= y; temp >>= PRECISION;#ifndef IGNORE_OVERFLOW if(temp > 0x7fffffff) { return 0x7fffffff; } else if(temp < -0x7ffffffe) { return -0x7ffffffe; }#endif return (fixed32)temp;}static fixed32 fixdiv32(fixed32 x, fixed32 y){ fixed64 temp; if(x == 0) return 0; if(y == 0) return 0x7fffffff; temp = x; temp <<= PRECISION; return (fixed32)(temp / y);}static fixed64 fixdiv64(fixed64 x, fixed64 y){ fixed64 temp; if(x == 0) return 0; if(y == 0) return 0x07ffffffffffffffLL; temp = x; temp <<= PRECISION64; return (fixed64)(temp / y);}static fixed32 fixsqrt32(fixed32 x){ unsigned long r = 0, s, v = (unsigned long)x;#define STEP(k) s = r + (1 << k * 2); r >>= 1; \ if (s <= v) { v -= s; r |= (1 << k * 2); } STEP(15); STEP(14); STEP(13); STEP(12); STEP(11); STEP(10); STEP(9); STEP(8); STEP(7); STEP(6); STEP(5); STEP(4); STEP(3); STEP(2); STEP(1); STEP(0); return (fixed32)(r << (PRECISION / 2));}__inline fixed32 fixsin32(fixed32 x){ fixed64 x2, temp; int sign = 1; if(x < 0) { sign = -1; x = -x; } while (x > 0x19220) { x -= M_PI_F; sign = -sign; } if (x > 0x19220) { x = M_PI_F - x; } x2 = (fixed64)x * x; x2 >>= PRECISION; if(sign != 1) { x = -x; } /** temp = ftofix32(-.0000000239f) * x2; temp >>= PRECISION; **/ temp = 0; /* PJJ */ temp = (temp + 0x0) * x2; temp >>= PRECISION; temp = (temp - 0xd) * x2; temp >>= PRECISION; temp = (temp + 0x222) * x2; temp >>= PRECISION; temp = (temp - 0x2aab) * x2; temp >>= PRECISION; temp += 0x10000; temp = temp * x; temp >>= PRECISION; return (fixed32)(temp);}__inline fixed32 fixcos32(fixed32 x){ return fixsin32(x - (M_PI_F>>1))*-1;}__inline fixed32 fixasin32(fixed32 x){ fixed64 temp; int sign = 1; if(x > 0x10000 || x < 0xffff0000) { return 0; } if(x < 0) { sign = -1; x = -x; } temp = 0xffffffad * (fixed64)x; temp >>= PRECISION; temp = (temp + 0x1b5) * x; temp >>= PRECISION; temp = (temp - 0x460) * x; temp >>= PRECISION; temp = (temp + 0x7e9) * x; temp >>= PRECISION; temp = (temp - 0xcd8) * x; temp >>= PRECISION; temp = (temp + 0x16c7) * x; temp >>= PRECISION; temp = (temp - 0x36f0) * x; temp >>= PRECISION; temp = (temp + 0x19220) * fixsqrt32(0x10000 - x); temp >>= PRECISION; return sign * ((M_PI_F>>1) - (fixed32)temp);}#define ALT_BITSTREAM_READER#define unaligned32(a) (*(uint32_t*)(a))uint16_t bswap_16(uint16_t x){ uint16_t hi = x & 0xff00; uint16_t lo = x & 0x00ff; return (hi >> 8) | (lo << 8);}uint32_t bswap_32(uint32_t x){ uint32_t b1 = x & 0xff000000; uint32_t b2 = x & 0x00ff0000; uint32_t b3 = x & 0x0000ff00; uint32_t b4 = x & 0x000000ff; return (b1 >> 24) | (b2 >> 8) | (b3 << 8) | (b4 << 24);}/* PJJ : reinstate macro */void CMUL(fixed32 *pre, fixed32 *pim, fixed32 are, fixed32 aim, fixed32 bre, fixed32 bim){ fixed32 _aref = are; fixed32 _aimf = aim; fixed32 _bref = bre; fixed32 _bimf = bim; fixed32 _r1 = fixmul32(_aref, _bref); fixed32 _r2 = fixmul32(_aimf, _bimf); fixed32 _r3 = fixmul32(_aref, _bimf); fixed32 _r4 = fixmul32(_aimf, _bref); *pre = _r1 - _r2; *pim = _r3 + _r4;}#ifdef WORDS_BIGENDIAN#define be2me_16(x) (x)#define be2me_32(x) (x)#define be2me_64(x) (x)#define le2me_16(x) bswap_16(x)#define le2me_32(x) bswap_32(x)#define le2me_64(x) bswap_64(x)#else#define be2me_16(x) bswap_16(x)#define be2me_32(x) bswap_32(x)#define be2me_64(x) bswap_64(x)#define le2me_16(x) (x)#define le2me_32(x) (x)#define le2me_64(x) (x)#endif#define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s)))#define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))static inline int unaligned32_be(const void *v){#ifdef CONFIG_ALIGN const uint8_t *p=v; return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]);#else return be2me_32( unaligned32(v)); /* original */#endif}typedef struct GetBitContext{ const uint8_t *buffer, *buffer_end;#ifdef ALT_BITSTREAM_READER int index;#elif defined LIBMPEG2_BITSTREAM_READER uint8_t *buffer_ptr; uint32_t cache; int bit_count;#elif defined A32_BITSTREAM_READER uint32_t *buffer_ptr; uint32_t cache0; uint32_t cache1; int bit_count;#endif int size_in_bits;}GetBitContext;typedef struct VLC{ int bits; VLC_TYPE (*table)[2]; int table_size, table_allocated;}VLC;typedef struct FFTComplex{ fixed32 re, im;}FFTComplex;typedef struct FFTContext{ int nbits; int inverse; uint16_t *revtab; FFTComplex *exptab; FFTComplex *exptab1; /* only used by SSE code */ void (*fft_calc)(struct FFTContext *s, FFTComplex *z);}FFTContext;typedef struct MDCTContext{ int n; /* size of MDCT (i.e. number of input data * 2) */ int nbits; /* n = 2^nbits */ /* pre/post rotation tables */ fixed32 *tcos; fixed32 *tsin; FFTContext fft;}MDCTContext;typedef struct WMADecodeContext{ GetBitContext gb; int sample_rate; int nb_channels; int bit_rate; int version; /* 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) */ int block_align; int use_bit_reservoir; int use_variable_block_len; int use_exp_vlc; /* exponent coding: 0 = lsp, 1 = vlc + delta */ int use_noise_coding; /* true if perceptual noise is added */ int byte_offset_bits; VLC exp_vlc; int exponent_sizes[BLOCK_NB_SIZES]; uint16_t exponent_bands[BLOCK_NB_SIZES][25]; int high_band_start[BLOCK_NB_SIZES]; /* index of first coef in high band */ int coefs_start; /* first coded coef */ int coefs_end[BLOCK_NB_SIZES]; /* max number of coded coefficients */ int exponent_high_sizes[BLOCK_NB_SIZES]; int exponent_high_bands[BLOCK_NB_SIZES][HIGH_BAND_MAX_SIZE]; VLC hgain_vlc; /* coded values in high bands */ int high_band_coded[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; int high_band_values[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; /* there are two possible tables for spectral coefficients */ VLC coef_vlc[2]; uint16_t *run_table[2]; uint16_t *level_table[2]; /* frame info */ int frame_len; /* frame length in samples */ int frame_len_bits; /* frame_len = 1 << frame_len_bits */ int nb_block_sizes; /* number of block sizes */ /* block info */ int reset_block_lengths; int block_len_bits; /* log2 of current block length */ int next_block_len_bits; /* log2 of next block length */ int prev_block_len_bits; /* log2 of prev block length */ int block_len; /* block length in samples */ int block_num; /* block number in current frame */ int block_pos; /* current position in frame */ uint8_t ms_stereo; /* true if mid/side stereo mode */ uint8_t channel_coded[MAX_CHANNELS]; /* true if channel is coded */ fixed32 exponents[MAX_CHANNELS][BLOCK_MAX_SIZE]; fixed32 max_exponent[MAX_CHANNELS]; int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; fixed32 coefs[MAX_CHANNELS][BLOCK_MAX_SIZE]; MDCTContext mdct_ctx[BLOCK_NB_SIZES]; fixed32 *windows[BLOCK_NB_SIZES]; FFTComplex mdct_tmp[BLOCK_MAX_SIZE]; /* temporary storage for imdct */ /* output buffer for one frame and the last for IMDCT windowing */ fixed32 frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]; /* last frame info */ uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */ int last_bitoffset; int last_superframe_len; fixed32 noise_table[NOISE_TAB_SIZE]; int noise_index; fixed32 noise_mult; /* XXX: suppress that and integrate it in the noise array */ /* lsp_to_curve tables */ fixed32 lsp_cos_table[BLOCK_MAX_SIZE]; fixed64 lsp_pow_e_table[256]; fixed64 lsp_pow_m_table1[(1 << LSP_POW_BITS)]; fixed64 lsp_pow_m_table2[(1 << LSP_POW_BITS)];#ifdef TRACE int frame_count;#endif} WMADecodeContext;/*** Prototypes ***/static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len);void fft_calc(FFTContext *s, FFTComplex *z);void av_free(void *ptr); /* PJJ found below */static inline int av_log2(unsigned int v){ int n; n = 0; if (v & 0xffff0000) { v >>= 16; n += 16; } if (v & 0xff00) { v >>= 8; n += 8; } n += ff_log2_tab[v]; return n;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -