It's only optional for now as a commented-out #ifdef while I decide how best to 
handle selecting fixed vs. float.
---
 configure           |    1 +
 libavcodec/ac3enc.c |  153 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 109 insertions(+), 45 deletions(-)

diff --git configure configure
index 7dcb50f..6d29f7d 100755
--- configure
+++ configure
@@ -1190,6 +1190,7 @@ aac_decoder_select="mdct rdft"
 aac_encoder_select="mdct"
 aac_latm_decoder_select="aac_decoder aac_latm_parser"
 ac3_decoder_select="mdct ac3_parser"
+ac3_encode_select="mdct"
 alac_encoder_select="lpc"
 amrnb_decoder_select="lsp"
 atrac1_decoder_select="mdct"
diff --git libavcodec/ac3enc.c libavcodec/ac3enc.c
index 5d92b46..f25bdbc 100644
--- libavcodec/ac3enc.c
+++ libavcodec/ac3enc.c
@@ -36,24 +36,57 @@
 #include "ac3.h"
 #include "audioconvert.h"
 
+//#define CONFIG_FLOAT 1
+
+#ifndef CONFIG_FLOAT
+#define CONFIG_FLOAT 0
+#endif
+
+#if CONFIG_FLOAT
+#include "fft.h"
+#endif
+
+#define SCALE_FLOAT(a, bits) (lrintf(a * (float)(1 << (bits))))
+
+#if CONFIG_FLOAT
+    typedef float SampleType;
+    typedef float CoefType;
+#   define FIX(a) (a)
+#   define MULFUNC(a, b) ((a) * (b))
+#   define FIX_SHIFT(a) (a)
+#   define RSHIFT1(a) ((a) * 0.5f)
+#   define SCALE_COEF(a) SCALE_FLOAT((a), 24)
+#   define INPUT_SAMPLE_FMT SAMPLE_FMT_FLT
+#else
+    typedef int16_t SampleType;
+    typedef int32_t CoefType;
+#   define FIX(a) (av_clip_int16(SCALE_FLOAT(a, 15)))
+#   define MULFUNC MUL16
+#   define FIX_SHIFT(a) ((a) >> 15)
+#   define RSHIFT1(a) ((a) >> 1)
+#   define SCALE_COEF(a) (a)
+#   define INPUT_SAMPLE_FMT SAMPLE_FMT_S16
+#endif
+
 typedef struct IComplex {
-    int16_t re,im;
+    SampleType re,im;
 } IComplex;
 
 typedef struct AC3MDCTContext {
+    const SampleType *window;               ///< MDCT window function
     AVCodecContext *avctx;                  ///< parent context for av_log()
     int nbits;                              ///< log2(transform size)
-    int16_t  *costab;                       ///< FFT cos table
-    int16_t  *sintab;                       ///< FFT sin table
-    int16_t  *xcos1;                        ///< MDCT cos table
-    int16_t  *xsin1;                        ///< MDCT sin table
-    int16_t  *rot_tmp;                      ///< temp buffer for pre-rotated samples
+    SampleType *costab;                     ///< FFT cos table
+    SampleType *sintab;                     ///< FFT sin table
+    SampleType *xcos1;                      ///< MDCT cos table
+    SampleType *xsin1;                      ///< MDCT sin table
+    SampleType *rot_tmp;                    ///< temp buffer for pre-rotated samples
     IComplex *cplx_tmp;                     ///< temp buffer for complex pre-rotated samples
 } AC3MDCTContext;
 
 typedef struct AC3Block {
     uint8_t **bap;                          ///< bap for each channel in this block
-    int32_t **mdct_coef;                    ///< MDCT coefficients for each channel in this block
+    CoefType **mdct_coef;                   ///< MDCT coefficients for each channel in this block
     uint8_t **exp;                          ///< exponents for each channel in this block
     int16_t **psd;                          ///< PSD for each channel in this block
     int16_t **mask;                         ///< masking curve for each channel in this block
@@ -108,11 +141,11 @@ typedef struct AC3EncodeContext {
     /* mantissa encoding */
     int mant1_cnt, mant2_cnt, mant4_cnt;    ///< matissa counts for bap=1,2,4
 
-    int16_t *windowed_samples;                  ///< windowed samples for the current block
-    int16_t *planar_samples[AC3_MAX_CHANNELS];  ///< full input frame, deinterleaved
+    SampleType *windowed_samples;                   ///< windowed samples for the current block
+    SampleType *planar_samples[AC3_MAX_CHANNELS];   ///< full input frame, deinterleaved
     uint8_t *bap_buffer;
     uint8_t *bap1_buffer;
-    int32_t *mdct_coef_buffer;
+    CoefType *mdct_coef_buffer;
     uint8_t *exp_buffer;
     int16_t *psd_buffer;
     int16_t *mask_buffer;
@@ -124,9 +157,6 @@ typedef struct AC3EncodeContext {
  */
 int exponent_group_tab[3][256];
 
-/** convert float in range [-1..1] to int16_t in range [-32768..32767] */
-#define FIX15(a) (av_clip_int16(lrintf(a * (float)(1 << 15))))
-
 static av_cold void mdct_end(AC3MDCTContext *mdct)
 {
     mdct->nbits  = 0;
@@ -136,6 +166,9 @@ static av_cold void mdct_end(AC3MDCTContext *mdct)
     av_freep(&mdct->xsin1);
     av_freep(&mdct->rot_tmp);
     av_freep(&mdct->cplx_tmp);
+#if CONFIG_FLOAT
+    av_freep(&mdct->window);
+#endif
 }
 
 static av_cold int fft_init(AC3MDCTContext *mdct, int ln)
@@ -153,8 +186,8 @@ static av_cold int fft_init(AC3MDCTContext *mdct, int ln)
 
     for (i = 0; i < n2; i++) {
         alpha = 2 * M_PI * (float)i / (float)n;
-        mdct->costab[i] = FIX15(cos(alpha));
-        mdct->sintab[i] = FIX15(sin(alpha));
+        mdct->costab[i] = FIX(cos(alpha));
+        mdct->sintab[i] = FIX(sin(alpha));
     }
 
     return 0;
@@ -164,9 +197,26 @@ fft_alloc_fail:
     return AVERROR(ENOMEM);
 }
 
+static av_cold int window_init(AC3MDCTContext *mdct)
+{
+#if CONFIG_FLOAT
+    SampleType *window;
+    int n2 = (1 << mdct->nbits) >> 1;
+
+    window = av_malloc(n2 * sizeof(*window));
+    if (!window)
+        return AVERROR(ENOMEM);
+    ff_kbd_window_init(window, 5.0, n2);
+    mdct->window = window;
+#else
+    mdct->window = ff_ac3_window;
+#endif
+    return 0;
+}
+
 static av_cold int mdct_init(AC3MDCTContext *mdct, int nbits)
 {
-    int i, n, n4;
+    int i, n, n2, n4;
     int ret;
 
     mdct->nbits = nbits;
@@ -175,7 +225,12 @@ static av_cold int mdct_init(AC3MDCTContext *mdct, int nbits)
     if (ret)
         return ret;
 
+    ret = window_init(mdct);
+    if (ret)
+        return ret;
+
     n  = 1 << nbits;
+    n2 = n >> 1;
     n4 = n >> 2;
 
     FF_ALLOC_OR_GOTO(mdct->avctx, mdct->xcos1,    n4 * sizeof(*mdct->xcos1),
@@ -189,8 +244,8 @@ static av_cold int mdct_init(AC3MDCTContext *mdct, int nbits)
 
     for (i = 0; i < n4; i++) {
         float alpha = 2.0 * M_PI * (i + 1.0 / 8.0) / n;
-        mdct->xcos1[i] = FIX15(-cos(alpha));
-        mdct->xsin1[i] = FIX15(-sin(alpha));
+        mdct->xcos1[i] = FIX(-cos(alpha));
+        mdct->xsin1[i] = FIX(-sin(alpha));
     }
 
     return 0;
@@ -203,21 +258,21 @@ mdct_alloc_fail:
 /* butter fly op */
 #define BF(pre, pim, qre, qim, pre1, pim1, qre1, qim1) \
 {\
-  int ax, ay, bx, by;\
+  CoefType 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;\
+  pre = RSHIFT1(bx + ax);\
+  pim = RSHIFT1(by + ay);\
+  qre = RSHIFT1(bx - ax);\
+  qim = RSHIFT1(by - ay);\
 }
 
 #define CMUL(pre, pim, are, aim, bre, bim) \
 {\
-   pre = (MUL16(are, bre) - MUL16(aim, bim)) >> 15;\
-   pim = (MUL16(are, bim) + MUL16(bre, aim)) >> 15;\
+   pre = FIX_SHIFT(MULFUNC(are, bre) - MULFUNC(aim, bim));\
+   pim = FIX_SHIFT(MULFUNC(are, bim) + MULFUNC(bre, aim));\
 }
 
 
@@ -227,7 +282,7 @@ static void calc_fft(AC3MDCTContext *mdct, IComplex *z, int ln)
     int j, l, np, np2;
     int nblocks, nloops;
     register IComplex *p,*q;
-    int tmp_re, tmp_im;
+    CoefType tmp_re, tmp_im;
 
     np = 1 << ln;
 
@@ -290,11 +345,12 @@ static void calc_fft(AC3MDCTContext *mdct, IComplex *z, int ln)
 }
 
 /* do a 512 point mdct */
-static void calc_mdct(AC3MDCTContext *mdct, int32_t *out, int16_t *in)
+static void calc_mdct(AC3MDCTContext *mdct, CoefType *out, SampleType *in)
 {
-    int i, re, im;
+    int i;
+    CoefType re, im;
     int n, n2, n4;
-    int16_t *rot = mdct->rot_tmp;
+    SampleType *rot = mdct->rot_tmp;
     IComplex *x  = mdct->cplx_tmp;
 
     n  = 1 << mdct->nbits;
@@ -308,8 +364,8 @@ static void calc_mdct(AC3MDCTContext *mdct, int32_t *out, int16_t *in)
 
     /* pre rotation */
     for (i = 0; i < n4; i++) {
-        re =  ((int)rot[   2*i] - (int)rot[ n-1-2*i]) >> 1;
-        im = -((int)rot[n2+2*i] - (int)rot[n2-1-2*i]) >> 1;
+        re = RSHIFT1( ((CoefType)rot[   2*i] - (CoefType)rot[ n-1-2*i]));
+        im = RSHIFT1(-((CoefType)rot[n2+2*i] - (CoefType)rot[n2-1-2*i]));
         CMUL(x[i].re, x[i].im, re, im, -mdct->xcos1[i], mdct->xsin1[i]);
     }
 
@@ -323,6 +379,7 @@ static void calc_mdct(AC3MDCTContext *mdct, int32_t *out, int16_t *in)
     }
 }
 
+#if !CONFIG_FLOAT
 /* compute log2(max(abs(tab[]))) */
 static int log2_tab(int16_t *tab, int n)
 {
@@ -362,9 +419,10 @@ static int normalize_samples(AC3EncodeContext *s)
     lshift_tab(s->windowed_samples, AC3_WINDOW_SIZE, v);
     return v - 9;
 }
+#endif /* !CONFIG_FLOAT */
 
-static void apply_window(int16_t *output, const int16_t *input,
-                         const int16_t *window, int n)
+static void apply_window(SampleType *output, const SampleType *input,
+                         const SampleType *window, int n)
 {
     int i;
     int n2 = n >> 1;
@@ -374,9 +432,9 @@ static void apply_window(int16_t *output, const int16_t *input,
     output += n2;
 
     for (i = 0; i < n2; i++) {
-        int16_t w    = window[-i-1];
-        output[-i-1] = MUL16(input[-i-1], w) >> 15;
-        output[ i  ] = MUL16(input[ i  ], w) >> 15;
+        SampleType w    = window[-i-1];
+        output[-i-1] = FIX_SHIFT(MULFUNC(input[-i-1], w));
+        output[ i  ] = FIX_SHIFT(MULFUNC(input[ i  ], w));
     }
 }
 
@@ -386,12 +444,15 @@ static void apply_mdct(AC3EncodeContext *s)
 
     for (ch = 0; ch < s->channels; ch++) {
         for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
-            int16_t *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
+            SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
 
-            apply_window(s->windowed_samples, input_samples, ff_ac3_window,
+            apply_window(s->windowed_samples, input_samples, s->mdct.window,
                          AC3_WINDOW_SIZE);
-
+#if CONFIG_FLOAT
+            s->blocks[blk].exp_shift[ch] = 0;
+#else
             s->blocks[blk].exp_shift[ch] = normalize_samples(s);
+#endif
 
             calc_mdct(&s->mdct, s->blocks[blk].mdct_coef[ch], s->windowed_samples);
         }
@@ -410,7 +471,7 @@ static void calculate_exponents(AC3EncodeContext *s)
             AC3Block *block = &s->blocks[blk];
             for (i = 0; i < AC3_MAX_COEFS; i++) {
                 int e;
-                v = abs(block->mdct_coef[ch][i]);
+                v = abs(SCALE_COEF(block->mdct_coef[ch][i]));
                 if (v == 0)
                     e = 24;
                 else {
@@ -1346,7 +1407,7 @@ static void output_audio_block(AC3EncodeContext *s,
         int b, c, e, v;
 
         for (i = 0; i < s->nb_coefs[ch]; i++) {
-            c = block->mdct_coef[ch][i];
+            c = SCALE_COEF(block->mdct_coef[ch][i]);
             e = block->exp[ch][i] - block->exp_shift[ch];
             b = block->bap[ch][i];
             switch(b) {
@@ -1480,15 +1541,15 @@ static void output_frame_end(AC3EncodeContext *s)
     AV_WB16(frame+frame_size-2, crc2);
 }
 
-static void deinterleave_samples(AC3EncodeContext *s, const int16_t *samples)
+static void deinterleave_samples(AC3EncodeContext *s, const SampleType *samples)
 {
     int ch, i;
-    const int16_t *smp;
+    const SampleType *smp;
 
     /* copy last 256 samples of previous frame to the start of the current frame */
     for (ch = 0; ch < s->channels; ch++) {
         memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_FRAME_SIZE],
-               AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0]));
+               AC3_BLOCK_SIZE * sizeof(*s->planar_samples[0]));
     }
 
     /* deinterleave and remap input samples */
@@ -1619,6 +1680,7 @@ static int AC3_encode_frame(AVCodecContext *avctx,
     return s->frame_size;
 }
 
+#if !CONFIG_FLOAT
 #ifdef TEST
 /*************************************************************************/
 /* TEST */
@@ -1741,6 +1803,7 @@ int main(void)
     return 0;
 }
 #endif /* TEST */
+#endif /* !CONFIG_FLOAT */
 
 AVCodec ac3_encoder = {
     "ac3",
@@ -1751,7 +1814,7 @@ AVCodec ac3_encoder = {
     AC3_encode_frame,
     AC3_encode_close,
     NULL,
-    .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
+    .sample_fmts = (const enum SampleFormat[]){INPUT_SAMPLE_FMT,SAMPLE_FMT_NONE},
     .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
     .channel_layouts = (const int64_t[]){
         CH_LAYOUT_MONO,
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to