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