[Ffmpeg-devel] ac3enc.c modifications
Justin Ruggles
jruggle
Sun Apr 24 09:29:42 CEST 2005
Nico Sabbi wrote:
> I'd like to test this patch but patch doesn't accept it, complaining
> it's incorrect.
> Can you update it against current cvs, please?
Sorry...I'm still getting used to posting patches. I've made a couple
more changes now. I changed the bit allocation so that it uses
rematrixing as well. I also added an input high-pass filter. I'm not
sure how this jives with the rest of ffmpeg, but all the info in the
specs and from Dolby recommends filtering the input to remove DC.
Hopefully this patch will work better.
-Justin
P.S. I think I've solved the short-block mdct problem!!! Now all I
need is a fast algorithm for a regular type iv dct. Once I get it
working I'll submit a patch for it as well.
diff -ru ffmpeg-orig/libavcodec/ac3enc.c ffmpeg/libavcodec/ac3enc.c
--- ffmpeg-orig/libavcodec/ac3enc.c 2005-04-24 03:12:22.000000000 -0400
+++ ffmpeg/libavcodec/ac3enc.c 2005-04-24 03:12:40.000000000 -0400
@@ -669,6 +669,7 @@
uint8_t
bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
uint8_t
encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2],
uint8_t
exp_strategy[NB_BLOCKS][AC3_MAX_CHANNELS],
+ uint8_t rematstr[NB_BLOCKS],
int frame_bits)
{
int i, ch;
@@ -704,7 +705,11 @@
for(i=0;i<NB_BLOCKS;i++) {
frame_bits += s->nb_channels * 2 + 2; /* blksw * c, dithflag *
c, dynrnge, cplstre */
if (s->acmod == 2)
+ {
frame_bits++; /* rematstr */
+ if(rematstr[i])
+ frame_bits += 4; /* rematflg[4] */
+ }
frame_bits += 2 * s->nb_channels; /* chexpstr[2] * c */
if (s->lfe)
frame_bits++; /* lfeexpstr */
@@ -967,6 +972,9 @@
uint8_t bap[AC3_MAX_CHANNELS][N/2],
int32_t mdct_coefs[AC3_MAX_CHANNELS][N/2],
int8_t global_exp[AC3_MAX_CHANNELS],
+ uint8_t gainrng[AC3_MAX_CHANNELS],
+ uint8_t rematstr,
+ uint8_t rematflg[4],
int block_num)
{
int ch, nb_groups, group_size, i, baie, rbnd;
@@ -991,23 +999,16 @@
put_bits(&s->pb, 1, 0); /* no new coupling strategy */
}
- if (s->acmod == 2)
- {
- if(block_num==0)
- {
- /* first block must define rematrixing (rematstr) */
- put_bits(&s->pb, 1, 1);
-
- /* dummy rematrixing rematflg(1:4)=0 */
- for (rbnd=0;rbnd<4;rbnd++)
- put_bits(&s->pb, 1, 0);
- }
- else
- {
- /* no matrixing (but should be used in the future) */
- put_bits(&s->pb, 1, 0);
- }
- }
+ if(s->acmod == 2) {
+ // rematrixing strategy
+ put_bits(&s->pb, 1, rematstr);
+
+ // rematrixing flags
+ if(rematstr) {
+ for(rbnd=0; rbnd<4; rbnd++)
+ put_bits(&s->pb, 1, rematflg[rbnd]);
+ }
+ }
#if defined(DEBUG)
{
@@ -1074,7 +1075,7 @@
}
if (ch != s->lfe_channel)
- put_bits(&s->pb, 2, 0); /* no gain range info */
+ put_bits(&s->pb, 2, gainrng[ch]); /* gain range info */
}
/* bit allocation info */
@@ -1355,6 +1356,91 @@
return frame_size * 2;
}
+
+/*
+ * DC removal high-pass IIR filter at 3 Hz
+ */
+static void
+input_highpass(int16_t *xx, int n)
+{
+ int i;
+ int32_t yy[n];
+ yy[0] = xx[0];
+ for(i=1; i<n; i++) {
+ yy[i] = 0.99978633188f*xx[i] + -0.99978633188f*xx[i-1] +
+ 0.999572663762f*yy[i-1];
+ if(yy[i] > 32767) yy[i] = 32767;
+ if(yy[i] < -32767) yy[i] = -32767;
+ }
+ for(i=0; i<n; i++) {
+ xx[i] = yy[i];
+ }
+}
+
+
+/*
+ * channel gain range
+ */
+static uint8_t
+calc_ch_gain_range(int16_t *tab, int n) {
+ int i;
+ int v = 0;
+ for(i=0; i<n; i++) {
+ v |= abs(tab[i]);
+ }
+ uint8_t gain = 0;
+ if(v >= 16384) gain = 0;
+ else if(v >= 8192) gain = 1;
+ else if(v >= 4096) gain = 2;
+ else gain = 3;
+ return gain;
+}
+
+
+/* probably should go in ac3tab.h */
+static uint8_t rematbndtab[4][2] = { {13, 24}, {25, 36}, {37, 60}, {61,
252} };
+
+static void calc_rematrixing(int32_t mdct_coef[AC3_MAX_CHANNELS][N/2],
+ uint8_t *rematstr, uint8_t
rematflg[NB_BLOCKS][4], int blk)
+{
+ uint32_t sum[4][4];
+ int32_t lt, rt, ctmp;
+ int bnd, i, chmin;
+
+ memset(sum, 0, 64);
+ *rematstr = 0;
+ for(bnd=0; bnd<4; bnd++) {
+ for(i=rematbndtab[bnd][0]; i<=rematbndtab[bnd][1]; i++) {
+ lt = mdct_coef[0][i] / 128;
+ rt = mdct_coef[1][i] / 128;
+ sum[bnd][0] += lt*lt;
+ sum[bnd][1] += rt*rt;
+ sum[bnd][2] += (lt+rt)*(lt+rt);
+ sum[bnd][3] += (lt-rt)*(lt-rt);
+ }
+ chmin = 0;
+ if(sum[bnd][1] < sum[bnd][chmin]) chmin = 1;
+ if(sum[bnd][2] < sum[bnd][chmin]) chmin = 2;
+ if(sum[bnd][3] < sum[bnd][chmin]) chmin = 3;
+ if(chmin<2) {
+ rematflg[blk][bnd] = 0;
+ }
+ else {
+ rematflg[blk][bnd] = 1;
+ for(i=rematbndtab[bnd][0]; i<=rematbndtab[bnd][1]; i++) {
+ ctmp = mdct_coef[0][i];
+ mdct_coef[0][i] = (ctmp + mdct_coef[1][i]) / 2;
+ mdct_coef[1][i] = (ctmp - mdct_coef[1][i]) / 2;
+ }
+ }
+ if(blk != 0 && *rematstr == 0 &&
+ rematflg[blk][bnd] != rematflg[blk-1][bnd]) {
+ *rematstr = 1;
+ }
+ }
+ if(blk == 0) *rematstr = 1;
+}
+
static int AC3_encode_frame(AVCodecContext *avctx,
unsigned char *frame, int buf_size, void *data)
{
@@ -1368,6 +1454,9 @@
uint8_t encoded_exp[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
uint8_t bap[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
int8_t exp_samples[NB_BLOCKS][AC3_MAX_CHANNELS];
+ uint8_t gainrng[NB_BLOCKS][AC3_MAX_CHANNELS];
+ uint8_t rematstr[NB_BLOCKS];
+ uint8_t rematflg[NB_BLOCKS][4];
int frame_bits;
frame_bits = 0;
@@ -1388,6 +1477,12 @@
sptr += sinc;
}
+ /* highpass filter to remove DC */
+ input_highpass(input_samples, 512);
+
+ /* calculate channel gain range */
+ gainrng[i][ch] = calc_ch_gain_range(input_samples, 512);
+
/* apply the MDCT window */
for(j=0;j<N/2;j++) {
input_samples[j] = MUL16(input_samples[j],
@@ -1401,12 +1496,23 @@
v = 14 - log2_tab(input_samples, N);
if (v < 0)
v = 0;
- exp_samples[i][ch] = v - 8;
+ exp_samples[i][ch] = v - 9;
lshift_tab(input_samples, N, v);
/* do the MDCT */
mdct512(mdct_coef[i][ch], input_samples);
-
+ }
+ }
+
+ // calculate rematrixing
+ if(s->acmod == 2) {
+ for(i=0;i<NB_BLOCKS;i++) {
+ calc_rematrixing(mdct_coef[i], &rematstr[i], rematflg, i);
+ }
+ }
+
+ for(ch=0;ch<s->nb_all_channels;ch++) {
+ for(i=0;i<NB_BLOCKS;i++) {
/* compute "exponents". We take into account the
normalization there */
for(j=0;j<N/2;j++) {
@@ -1449,13 +1555,15 @@
}
}
- compute_bit_allocation(s, bap, encoded_exp, exp_strategy, frame_bits);
+ compute_bit_allocation(s, bap, encoded_exp, exp_strategy, rematstr,
+ frame_bits);
/* everything is known... let's output the frame */
output_frame_header(s, frame);
for(i=0;i<NB_BLOCKS;i++) {
output_audio_block(s, exp_strategy[i], encoded_exp[i],
- bap[i], mdct_coef[i], exp_samples[i], i);
+ bap[i], mdct_coef[i], exp_samples[i],
+ gainrng[i], rematstr[i], rematflg[i], i);
}
return output_frame_end(s);
}
More information about the ffmpeg-devel
mailing list