📄 ac3enc.c
字号:
/* * The simplest AC3 encoder * Copyright (c) 2000 Fabrice Bellard. * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//** * @file ac3enc.c * The simplest AC3 encoder. *///#define DEBUG//#define DEBUG_BITALLOC#include "avcodec.h"#include "ac3.h"typedef struct AC3EncodeContext { PutBitContext pb; int nb_channels; int nb_all_channels; int lfe_channel; int bit_rate; unsigned int sample_rate; unsigned int bsid; unsigned int frame_size_min; /* minimum frame size in case rounding is necessary */ unsigned int frame_size; /* current frame size in words */ int halfratecod; unsigned int frmsizecod; unsigned int fscod; /* frequency */ unsigned int acmod; int lfe; unsigned int bsmod; short last_samples[AC3_MAX_CHANNELS][256]; unsigned int chbwcod[AC3_MAX_CHANNELS]; int nb_coefs[AC3_MAX_CHANNELS]; /* bitrate allocation control */ int sgaincod, sdecaycod, fdecaycod, dbkneecod, floorcod; AC3BitAllocParameters bit_alloc; int csnroffst; int fgaincod[AC3_MAX_CHANNELS]; int fsnroffst[AC3_MAX_CHANNELS]; /* mantissa encoding */ int mant1_cnt, mant2_cnt, mant4_cnt;} AC3EncodeContext;#include "ac3tab.h"#define MDCT_NBITS 9#define N (1 << MDCT_NBITS)/* new exponents are sent if their Norm 1 exceed this number */#define EXP_DIFF_THRESHOLD 1000static void fft_init(int ln);static void ac3_crc_init(void);static inline int16_t fix15(float a){ int v; v = (int)(a * (float)(1 << 15)); if (v < -32767) v = -32767; else if (v > 32767) v = 32767; return v;}static inline int calc_lowcomp1(int a, int b0, int b1){ if ((b0 + 256) == b1) { a = 384 ; } else if (b0 > b1) { a = a - 64; if (a < 0) a=0; } return a;}static inline int calc_lowcomp(int a, int b0, int b1, int bin){ if (bin < 7) { if ((b0 + 256) == b1) { a = 384 ; } else if (b0 > b1) { a = a - 64; if (a < 0) a=0; } } else if (bin < 20) { if ((b0 + 256) == b1) { a = 320 ; } else if (b0 > b1) { a= a - 64; if (a < 0) a=0; } } else { a = a - 128; if (a < 0) a=0; } return a;}/* AC3 bit allocation. The algorithm is the one described in the AC3 spec. */void ac3_parametric_bit_allocation(AC3BitAllocParameters *s, uint8_t *bap, int8_t *exp, int start, int end, int snroffset, int fgain, int is_lfe, int deltbae,int deltnseg, uint8_t *deltoffst, uint8_t *deltlen, uint8_t *deltba){ int bin,i,j,k,end1,v,v1,bndstrt,bndend,lowcomp,begin; int fastleak,slowleak,address,tmp; int16_t psd[256]; /* scaled exponents */ int16_t bndpsd[50]; /* interpolated exponents */ int16_t excite[50]; /* excitation */ int16_t mask[50]; /* masking value */ /* exponent mapping to PSD */ for(bin=start;bin<end;bin++) { psd[bin]=(3072 - (exp[bin] << 7)); } /* PSD integration */ j=start; k=masktab[start]; do { v=psd[j]; j++; end1=bndtab[k+1]; if (end1 > end) end1=end; for(i=j;i<end1;i++) { int c,adr; /* logadd */ v1=psd[j]; c=v-v1; if (c >= 0) { adr=c >> 1; if (adr > 255) adr=255; v=v + latab[adr]; } else { adr=(-c) >> 1; if (adr > 255) adr=255; v=v1 + latab[adr]; } j++; } bndpsd[k]=v; k++; } while (end > bndtab[k]); /* excitation function */ bndstrt = masktab[start]; bndend = masktab[end-1] + 1; if (bndstrt == 0) { lowcomp = 0; lowcomp = calc_lowcomp1(lowcomp, bndpsd[0], bndpsd[1]) ; excite[0] = bndpsd[0] - fgain - lowcomp ; lowcomp = calc_lowcomp1(lowcomp, bndpsd[1], bndpsd[2]) ; excite[1] = bndpsd[1] - fgain - lowcomp ; begin = 7 ; for (bin = 2; bin < 7; bin++) { if (!(is_lfe && bin == 6)) lowcomp = calc_lowcomp1(lowcomp, bndpsd[bin], bndpsd[bin+1]) ; fastleak = bndpsd[bin] - fgain ; slowleak = bndpsd[bin] - s->sgain ; excite[bin] = fastleak - lowcomp ; if (!(is_lfe && bin == 6)) { if (bndpsd[bin] <= bndpsd[bin+1]) { begin = bin + 1 ; break ; } } } end1=bndend; if (end1 > 22) end1=22; for (bin = begin; bin < end1; bin++) { if (!(is_lfe && bin == 6)) lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin) ; fastleak -= s->fdecay ; v = bndpsd[bin] - fgain; if (fastleak < v) fastleak = v; slowleak -= s->sdecay ; v = bndpsd[bin] - s->sgain; if (slowleak < v) slowleak = v; v=fastleak - lowcomp; if (slowleak > v) v=slowleak; excite[bin] = v; } begin = 22; } else { /* coupling channel */ begin = bndstrt; fastleak = (s->cplfleak << 8) + 768; slowleak = (s->cplsleak << 8) + 768; } for (bin = begin; bin < bndend; bin++) { fastleak -= s->fdecay ; v = bndpsd[bin] - fgain; if (fastleak < v) fastleak = v; slowleak -= s->sdecay ; v = bndpsd[bin] - s->sgain; if (slowleak < v) slowleak = v; v=fastleak; if (slowleak > v) v = slowleak; excite[bin] = v; } /* compute masking curve */ for (bin = bndstrt; bin < bndend; bin++) { v1 = excite[bin]; tmp = s->dbknee - bndpsd[bin]; if (tmp > 0) { v1 += tmp >> 2; } v=hth[bin >> s->halfratecod][s->fscod]; if (v1 > v) v=v1; mask[bin] = v; } /* delta bit allocation */ if (deltbae == 0 || deltbae == 1) { int band, seg, delta; band = 0 ; for (seg = 0; seg < deltnseg; seg++) { band += deltoffst[seg] ; if (deltba[seg] >= 4) { delta = (deltba[seg] - 3) << 7; } else { delta = (deltba[seg] - 4) << 7; } for (k = 0; k < deltlen[seg]; k++) { mask[band] += delta ; band++ ; } } } /* compute bit allocation */ i = start ; j = masktab[start] ; do { v=mask[j]; v -= snroffset ; v -= s->floor ; if (v < 0) v = 0; v &= 0x1fe0 ; v += s->floor ; end1=bndtab[j] + bndsz[j]; if (end1 > end) end1=end; for (k = i; k < end1; k++) { address = (psd[i] - v) >> 5 ; if (address < 0) address=0; else if (address > 63) address=63; bap[i] = baptab[address]; i++; } } while (end > bndtab[j++]) ;}typedef struct IComplex { short re,im;} IComplex;static void fft_init(int ln){ int i, j, m, n; float alpha; n = 1 << ln; for(i=0;i<(n/2);i++) { alpha = 2 * M_PI * (float)i / (float)n; costab[i] = fix15(cos(alpha)); sintab[i] = fix15(sin(alpha)); } for(i=0;i<n;i++) { m=0; for(j=0;j<ln;j++) { m |= ((i >> j) & 1) << (ln-j-1); } fft_rev[i]=m; }}/* butter fly op */#define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \{\ int ax, ay, bx, by;\ bx=pre1;\ by=pim1;\ ax=qre1;\ ay=qim1;\ pre = (bx + ax) >> 1;\ pim = (by + ay) >> 1;\ qre = (bx - ax) >> 1;\ qim = (by - ay) >> 1;\}#define MUL16(a,b) ((a) * (b))#define CMUL(pre, pim, are, aim, bre, bim) \{\ pre = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;\ pim = (MUL16(are, bim) + MUL16(bre, aim)) >> 15;\}/* do a 2^n point complex fft on 2^ln points. */static void fft(IComplex *z, int ln){ int j, l, np, np2; int nblocks, nloops; register IComplex *p,*q; int tmp_re, tmp_im; np = 1 << ln; /* reverse */ for(j=0;j<np;j++) { int k; IComplex tmp; k = fft_rev[j]; if (k < j) { tmp = z[k]; z[k] = z[j]; z[j] = tmp; } } /* 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; 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, costab[l], -sintab[l], 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);}/* do a 512 point mdct */static void mdct512(int32_t *out, int16_t *in){ int i, re, im, re1, im1; int16_t rot[N]; IComplex x[N/4]; /* shift to simplify computations */ for(i=0;i<N/4;i++) rot[i] = -in[i + 3*N/4]; for(i=N/4;i<N;i++) rot[i] = in[i - N/4]; /* pre rotation */ for(i=0;i<N/4;i++) { re = ((int)rot[2*i] - (int)rot[N-1-2*i]) >> 1; im = -((int)rot[N/2+2*i] - (int)rot[N/2-1-2*i]) >> 1; CMUL(x[i].re, x[i].im, re, im, -xcos1[i], xsin1[i]); } fft(x, MDCT_NBITS - 2); /* post rotation */ for(i=0;i<N/4;i++) { re = x[i].re; im = x[i].im; CMUL(re1, im1, re, im, xsin1[i], xcos1[i]); out[2*i] = im1; out[N/2-1-2*i] = re1; }}/* XXX: use another norm ? */static int calc_exp_diff(uint8_t *exp1, uint8_t *exp2, int n){ int sum, i; sum = 0; for(i=0;i<n;i++) { sum += abs(exp1[i] - exp2[i]); } return sum;}static void compute_exp_strategy(uint8_t exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS], uint8_t exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2], int ch, int is_lfe){ int i, j; int exp_diff; /* estimate if the exponent variation & decide if they should be reused in the next frame */ exp_strategy[0][ch] = EXP_NEW; for(i=1;i<NB_BLOCKS;i++) { exp_diff = calc_exp_diff(exp[i][ch], exp[i-1][ch], N/2);#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "exp_diff=%d\n", exp_diff);#endif if (exp_diff > EXP_DIFF_THRESHOLD) exp_strategy[i][ch] = EXP_NEW; else exp_strategy[i][ch] = EXP_REUSE; } if (is_lfe) return; /* now select the encoding strategy type : if exponents are often recoded, we use a coarse encoding */ i = 0; while (i < NB_BLOCKS) { j = i + 1; while (j < NB_BLOCKS && exp_strategy[j][ch] == EXP_REUSE) j++; switch(j - i) { case 1: exp_strategy[i][ch] = EXP_D45; break; case 2: case 3: exp_strategy[i][ch] = EXP_D25; break; default: exp_strategy[i][ch] = EXP_D15; break; } i = j; }}/* set exp[i] to min(exp[i], exp1[i]) */static void exponent_min(uint8_t exp[N/2], uint8_t exp1[N/2], int n){ int i; for(i=0;i<n;i++) { if (exp1[i] < exp[i]) exp[i] = exp1[i]; }} /* update the exponents so that they are the ones the decoder will decode. Return the number of bits used to code the exponents */static int encode_exp(uint8_t encoded_exp[N/2], uint8_t exp[N/2], int nb_exps, int exp_strategy){ int group_size, nb_groups, i, j, k, recurse, exp_min, delta; uint8_t exp1[N/2]; switch(exp_strategy) { case EXP_D15: group_size = 1; break; case EXP_D25: group_size = 2; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -