[FFmpeg-soc] [soc]: r4189 - dcaenc/dcaenc.c
bwolowiec
subversion at mplayerhq.hu
Sat Apr 4 23:00:42 CEST 2009
Author: bwolowiec
Date: Sat Apr 4 23:00:42 2009
New Revision: 4189
Log:
Add support for LFE.
Modified:
dcaenc/dcaenc.c
Modified: dcaenc/dcaenc.c
==============================================================================
--- dcaenc/dcaenc.c Sat Apr 4 22:51:15 2009 (r4188)
+++ dcaenc/dcaenc.c Sat Apr 4 23:00:42 2009 (r4189)
@@ -35,9 +35,11 @@
#define DCA_SUBBANDS 32 ///< Subband activity count
#define QUANTIZER_BITS 16
-#define SUBFRAMES 2
-#define SUBSUBFRAMES 2
+#define SUBFRAMES 1
+#define SUBSUBFRAMES 4
#define PCM_SAMPLES (SUBFRAMES*SUBSUBFRAMES*8)
+#define LFE_BITS 8
+#define LFE_INTERPOLATION 64
typedef struct {
PutBitContext pb;
@@ -45,10 +47,13 @@ typedef struct {
int start[MAX_CHANNELS];
int frame_size;
int prim_channels;
+ int lfe_channel;
int sample_rate_code;
int scale_factor[MAX_CHANNELS][DCA_SUBBANDS_32];
+ int lfe_scale_factor;
+ int lfe_data[SUBFRAMES*SUBSUBFRAMES*4];
- int32_t pcm[DCA_SUBBANDS_32];
+ int32_t pcm[FFMAX(LFE_INTERPOLATION, DCA_SUBBANDS_32)];
int32_t subband[PCM_SAMPLES][MAX_CHANNELS][DCA_SUBBANDS_32]; /* [sample][channel][subband] */
} DCAContext;
@@ -142,6 +147,30 @@ static void qmf_decompose(DCAContext *c,
}
}
+static int32_t lfe_fir_64i[512];
+static int lfe_downsample(DCAContext *c, int32_t in[LFE_INTERPOLATION]){
+ int i, j;
+ int channel = c->prim_channels;
+ int32_t accum = 0;
+
+ add_new_samples(c, in, LFE_INTERPOLATION, channel);
+ for (i = c->start[channel], j = 0; i < 512; i++, j++)
+ accum += mul32(c->history[channel][i], lfe_fir_64i[j]);
+ for (i = 0; i < c->start[channel]; i++, j++)
+ accum += mul32(c->history[channel][i], lfe_fir_64i[j]);
+ return accum;
+}
+
+static void init_lfe_fir(void){
+ static int initialized;
+ int i;
+ if(initialized)
+ return;
+ for(i=0; i<512; i++)
+ lfe_fir_64i[i] = lfe_fir_64[i] * (1<<25); //float -> int32_t
+ initialized = 1;
+}
+
static void put_frame_header(DCAContext *c)
{
/* SYNC */
@@ -196,8 +225,8 @@ static void put_frame_header(DCAContext
/* Audio sync word insertion flag: after each sub-frame */
put_bits(&c->pb, 1, 0);
- /* Low frequency effects flag: not present */
- put_bits(&c->pb, 2, 0);
+ /* Low frequency effects flag: not present or interpolation factor=64 */
+ put_bits(&c->pb, 2, c->lfe_channel?2:0);
/* Predictor history switch flag: on */
put_bits(&c->pb, 1, 1);
@@ -310,9 +339,11 @@ static inline void put_sample7(DCAContex
sample = (sample << 15) / ((int64_t) lossy_quant[bits+3] * scale_factor_quant7[scale_factor]);
put_bits(&c->pb, bits, quantize((int)sample, bits));
}
-static void put_subframe(DCAContext *c, int32_t subband_data[8*SUBSUBFRAMES][MAX_CHANNELS][32])
+
+static void put_subframe(DCAContext *c, int32_t subband_data[8*SUBSUBFRAMES][MAX_CHANNELS][32], int subframe)
{
int i, sub, ss, ch, max_value;
+ int32_t *lfe_data = c->lfe_data + 4*SUBSUBFRAMES*subframe;
/* Subsubframes count */
put_bits(&c->pb, 2, SUBSUBFRAMES -1);
@@ -347,6 +378,13 @@ static void put_subframe(DCAContext *c,
c->scale_factor[ch][sub] = find_scale_factor7(max_value, QUANTIZER_BITS);
}
+ if(c->lfe_channel){
+ max_value = 0;
+ for(i=0; i<4*SUBSUBFRAMES; i++)
+ max_value = FFMAX(max_value, FFABS(lfe_data[i]));
+ c->lfe_scale_factor = find_scale_factor7(max_value, LFE_BITS);
+ }
+
/* Scale factors: the same for each channel and subband,
encoded according to Table D.1.2 */
for (ch = 0; ch < c->prim_channels; ch++)
@@ -359,7 +397,15 @@ static void put_subframe(DCAContext *c,
/* Dynamic range coefficient: not transmitted */
/* Stde information CRC check word: not transmitted */
/* VQ encoded high frequency subbands: not transmitted */
- /* LFE data: none */
+
+ /* LFE data */
+ if(c->lfe_channel){
+ for(i=0; i<4*SUBSUBFRAMES; i++)
+ put_sample7(c, lfe_data[i], LFE_BITS, c->lfe_scale_factor);
+
+ put_bits(&c->pb, 8, c->lfe_scale_factor);
+ }
+
/* Audio data (subsubframes) */
for (ss = 0; ss < SUBSUBFRAMES ; ss++)
@@ -379,7 +425,7 @@ void put_frame(DCAContext *c, int32_t su
put_primary_audio_header(c);
for(i=0; i<SUBFRAMES; i++)
- put_subframe(c, &subband_data[SUBSUBFRAMES * 8 * i]);
+ put_subframe(c, &subband_data[SUBSUBFRAMES * 8 * i], i);
flush_put_bits(&c->pb);
c->frame_size = (put_bits_count(&c->pb)>>3) + DCA_HEADER_SIZE;
@@ -409,6 +455,13 @@ static int DCA_encode_frame(AVCodecConte
qmf_decompose(c, c->pcm, &c->subband[i][channel][0], channel);
}
+ for (i = 0; i < PCM_SAMPLES/2; i++){
+ for (k = 0; k < LFE_INTERPOLATION; k++) { /* k is the sample number in a 32-sample block */
+ c->pcm[k] = samples[avctx->channels * (LFE_INTERPOLATION*i+k) + c->prim_channels-1] << 16;
+ }
+ c->lfe_data[i] = lfe_downsample(c, c->pcm);
+ }
+
put_frame(c, c->subband, frame);
return c->frame_size;
@@ -418,7 +471,18 @@ static int DCA_encode_init(AVCodecContex
DCAContext *c = avctx->priv_data;
int i;
- c->prim_channels = FFMIN(avctx->channels, 5); //XXX only 5 channels
+ c->prim_channels = avctx->channels;
+ c->lfe_channel = (avctx->channels==3 || avctx->channels==6);
+
+ if(c->lfe_channel){
+ init_lfe_fir();
+ c->prim_channels--;
+ }
+
+ if(c->prim_channels != 2 && c->prim_channels != 5) {
+ av_log(avctx, AV_LOG_ERROR, "Only stereo and 5.1 supported at the moment!\n");
+ return -1;
+ }
for(i=0; i<16; i++){
if(dca_sample_rates[i] == avctx->sample_rate)
@@ -430,11 +494,6 @@ static int DCA_encode_init(AVCodecContex
}
c->sample_rate_code = i;
- if(avctx->channels != 2 && avctx->channels != 6) {
- av_log(avctx, AV_LOG_ERROR, "Only stereo and 5.1 supported at the moment!\n");
- return -1;
- }
-
avctx->frame_size = 32 * PCM_SAMPLES;
qmf_init();
More information about the FFmpeg-soc
mailing list