📄 cook.c
字号:
/* * COOK compatible decoder * Copyright (c) 2003 Sascha Sommer * Copyright (c) 2005 Benjamin Larsson * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file cook.c * Cook compatible decoder. Bastardization of the G.722.1 standard. * This decoder handles RealNetworks, RealAudio G2 data. * Cook is identified by the codec name cook in RM files. * * To use this decoder, a calling application must supply the extradata * bytes provided from the RM container; 8+ bytes for mono streams and * 16+ for stereo streams (maybe more). * * Codec technicalities (all this assume a buffer length of 1024): * Cook works with several different techniques to achieve its compression. * In the timedomain the buffer is divided into 8 pieces and quantized. If * two neighboring pieces have different quantization index a smooth * quantization curve is used to get a smooth overlap between the different * pieces. * To get to the transformdomain Cook uses a modulated lapped transform. * The transform domain has 50 subbands with 20 elements each. This * means only a maximum of 50*20=1000 coefficients are used out of the 1024 * available. */#include <math.h>#include <stddef.h>#include <mplaylib.h>#include "avcodec.h"#include "bitstream.h"#include "dsputil.h"#include "bytestream.h"#include "random.h"#include "cookdata.h"#undef memcpy#define memcpy uc_memcpy/* the different Cook versions */#define MONO 0x1000001#define STEREO 0x1000002#define JOINT_STEREO 0x1000003#define MC_COOK 0x2000000 //multichannel Cook, not supported#define SUBBAND_SIZE 20#if 1#define COOKFIXED31(a) ( (a) * (1 << 26))//#define COOKFIXED31(a) ( (a) * 0x7fffffff)#define FIXEDSAMPLE(a) ( (a) * (1 << 8))#define FLOATSAMPLE(a) (((float)(a))/(1<<8))#define FIX_31_SQRT2 94906265 /* FFT computation *//* NOTE: soon integer code will be added, so you must use the FFTSample type */typedef int CookFFTSample;typedef int CookLevel;typedef struct CookFFTComplex { CookFFTSample re, im;} CookFFTComplex;struct CookMDCTContext;typedef struct CookFFTContext { int nbits; int inverse; uint16_t *revtab; CookFFTComplex *exptab;} CookFFTContext;/* MDCT computation */typedef struct CookMDCTContext { int n; /* size of MDCT (i.e. number of input data * 2) */ int nbits; /* n = 2^nbits */ /* pre/post rotation tables */ CookFFTSample *tcos; CookFFTSample *tsin; CookFFTContext fft;} CookMDCTContext;/** * The size of the FFT is 2^nbits. If inverse is TRUE, inverse FFT is * done */int Cook_fft_init(CookFFTContext *s, int nbits, int inverse){ int i, j, m, n; float alpha, c1, s1, s2; s->nbits = nbits; n = 1 << nbits; s->exptab = av_malloc((n / 2) * sizeof(CookFFTComplex)); if (!s->exptab) goto fail; s->revtab = av_malloc(n * sizeof(uint16_t)); if (!s->revtab) goto fail; s->inverse = inverse; s2 = inverse ? 1.0 : -1.0; for(i=0;i<(n/2);i++) { alpha = 2 * M_PI * (float)i / (float)n; c1 = cos(alpha); s1 = sin(alpha) * s2; s->exptab[i].re = COOKFIXED31(c1); s->exptab[i].im = COOKFIXED31(s1); } /* compute bit reverse table */ for(i=0;i<n;i++) { m=0; for(j=0;j<nbits;j++) { m |= ((i >> j) & 1) << (nbits-j-1); } s->revtab[i]=m; } return 0; fail: av_freep(&s->revtab); av_freep(&s->exptab); return -1;}/** * init MDCT or IMDCT computation. */int Cook_mdct_init(CookMDCTContext *s, int nbits, int inverse){ int n, n4, i; float alpha; memset(s, 0, sizeof(*s)); n = 1 << nbits; s->nbits = nbits; s->n = n; n4 = n >> 2; s->tcos = av_malloc(n4 * sizeof(CookFFTSample)); if (!s->tcos) goto fail; s->tsin = av_malloc(n4 * sizeof(CookFFTSample)); if (!s->tsin) goto fail; for(i=0;i<n4;i++) { alpha = 2 * M_PI * (i + 1.0 / 8.0) / n; s->tcos[i] = COOKFIXED31(-cos(alpha)); s->tsin[i] = COOKFIXED31(-sin(alpha)); } if (Cook_fft_init(&s->fft, s->nbits - 2, inverse) < 0) goto fail; return 0; fail: av_freep(&s->tcos); av_freep(&s->tsin); return -1;}void Cook_fft_end(CookFFTContext *s){ av_freep(&s->revtab); av_freep(&s->exptab);}void Cook_mdct_end(CookMDCTContext *s){ av_freep(&s->tcos); av_freep(&s->tsin); Cook_fft_end(&s->fft);}/* butter fly op */#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \{\ CookFFTSample ax, ay, bx, by;\ bx=pre1;\ by=pim1;\ ax=qre1;\ ay=qim1;\ pre = (bx + ax);\ pim = (by + ay);\ qre = (bx - ax);\ qim = (by - ay);\}//#define MUL(a,b) ((a) * (b))//#define MUL(a,b) (((long long)(a) * (b))>>26)#define MUL(a,b) \ ({\ long hi, lo;\ __asm__ __volatile__("mult %2, %3"\ :"=l" (lo), "=h" (hi)\ :"%r" (a), "r" (b));\ hi << 6;\ })#define CMUL(pre, pim, are, aim, bre, bim) \{\ pre = (MUL(are, bre) - MUL(aim, bim));\ pim = (MUL(are, bim) + MUL(aim, bre));\}/** * Do a complex FFT with the parameters defined in ff_fft_init(). The * input data must be permuted before with s->revtab table. No * 1.0/sqrt(n) normalization is done. */void Cook_fft_calc(CookFFTContext *s, CookFFTComplex *z){ int ln = s->nbits; int j, np, np2; int nblocks, nloops; register CookFFTComplex *p, *q; CookFFTComplex *exptab = s->exptab; int l; CookFFTSample tmp_re, tmp_im; np = 1 << ln; /* pass 0 */ p=&z[0]; j=(np >> 1); do { BF(p[0].re, p[0].im, p[1].re, p[1].im, p[0].re, p[0].im, p[1].re, p[1].im); p+=2; } while (--j != 0); /* pass 1 */ p=&z[0]; j=np >> 2; if (s->inverse) { do { BF(p[0].re, p[0].im, p[2].re, p[2].im, p[0].re, p[0].im, p[2].re, p[2].im); BF(p[1].re, p[1].im, p[3].re, p[3].im, p[1].re, p[1].im, -p[3].im, p[3].re); p+=4; } while (--j != 0); } else { do { BF(p[0].re, p[0].im, p[2].re, p[2].im, p[0].re, p[0].im, p[2].re, p[2].im); BF(p[1].re, p[1].im, p[3].re, p[3].im, p[1].re, p[1].im, p[3].im, -p[3].re); p+=4; } while (--j != 0); } /* pass 2 .. ln-1 */ nblocks = np >> 3; nloops = 1 << 2; np2 = np >> 1; do { p = z; q = z + nloops; for (j = 0; j < nblocks; ++j) { BF(p->re, p->im, q->re, q->im, p->re, p->im, q->re, q->im); p++; q++; for(l = nblocks; l < np2; l += nblocks) { CMUL(tmp_re, tmp_im, exptab[l].re, exptab[l].im, q->re, q->im); BF(p->re, p->im, q->re, q->im, p->re, p->im, tmp_re, tmp_im); p++; q++; } p += nloops; q += nloops; } nblocks = nblocks >> 1; nloops = nloops << 1; } while (nblocks != 0);}/** * Compute inverse MDCT of size N = 2^nbits * @param output N samples * @param input N/2 samples * @param tmp N/2 samples */void cook_imdct_calc(CookMDCTContext *s, CookFFTSample *output, const CookFFTSample *input, CookFFTSample *tmp){ int k, n8, n4, n2, n, j; const uint16_t *revtab = s->fft.revtab; const CookFFTSample *tcos = s->tcos; const CookFFTSample *tsin = s->tsin; const CookFFTSample *in1, *in2; CookFFTSample tmp_in1, tmp_in2; CookFFTComplex *z = (CookFFTComplex *)tmp; n = 1 << s->nbits; n2 = n >> 1; n4 = n >> 2; n8 = n >> 3; /* pre rotation */ in1 = input; in2 = input + n2 - 1; for(k = 0; k < n4; k++) { j=revtab[k]; CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]); in1 += 2; in2 -= 2; } Cook_fft_calc(&s->fft, z); /* post rotation + reordering */ /* XXX: optimize */ for(k = 0; k < n4; k++) { tmp_in1 = z[k].re; tmp_in2 = z[k].im; CMUL(z[k].re, z[k].im, tmp_in1, tmp_in2, tcos[k], tsin[k]); } for(k = 0; k < n8; k++) { output[2*k] = -z[n8 + k].im; output[n2-1-2*k] = z[n8 + k].im; output[2*k+1] = z[n8-1-k].re; output[n2-1-2*k-1] = -z[n8-1-k].re; output[n2 + 2*k]=-z[k+n8].re; output[n-1- 2*k]=-z[k+n8].re; output[n2 + 2*k+1]=z[n8-k-1].im; output[n-2 - 2 * k] = z[n8-k-1].im; }}#endiftypedef struct { int *now; int *previous;} cook_gains;typedef struct cook { /* * The following 5 functions provide the lowlevel arithmetic on * the internal audio buffers. */ void (* scalar_dequant)(struct cook *q, int index, int quant_index, int* subband_coef_index, int* subband_coef_sign, CookFFTSample * mlt_p); void (* decouple) (struct cook *q, int subband, CookFFTSample f1, CookFFTSample f2, CookFFTSample *decode_buffer, CookFFTSample *mlt_buffer1, CookFFTSample *mlt_buffer2); void (* imlt_window) (struct cook *q, CookFFTSample *buffer1, cook_gains *gains_ptr, CookFFTSample *previous_buffer); void (* interpolate) (struct cook *q,CookFFTSample * buffer, int gain_index, int gain_index_next);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -