This patch is broken for upsamle (96kHz XLL). It was not intended. On Fri, Jan 1, 2016 at 4:01 PM, Alexandra Hájková <[email protected]> wrote: > Add bit-exact QMF and LFE filters, which makes it possible for XLL > streams to be decoded losslessly. The new -force_lossy option allows > to keep lossy mode for the XLL streams. This option was added to the > fate-dca-xll test to keep its decoded output the same as the refference. > --- > This patch was tested with libdcadec (by foo86) used as refference decoder. > > doc/decoders.texi | 11 ++ > libavcodec/dca.h | 9 +- > libavcodec/dca_exss.c | 9 + > libavcodec/dcadec.c | 159 +++++++++++++--- > libavcodec/dcadsp.c | 487 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > libavcodec/dcadsp.h | 15 +- > tests/fate/audio.mak | 2 +- > 7 files changed, 660 insertions(+), 32 deletions(-) > > diff --git a/doc/decoders.texi b/doc/decoders.texi > index 99d2008..9de3243 100644 > --- a/doc/decoders.texi > +++ b/doc/decoders.texi > @@ -53,4 +53,15 @@ Loud sounds are fully compressed. Soft sounds are > enhanced. > > @end table > > +@section dca > +Fixed-point reconstruction for any kind of input might be > +forced by using @code{-request_sample_fmt @var{s32p}} option. > + > +@table @option > + > +@item -force_lossy 1 > +Force lossy mode for the XLL streams. > + > +@end table > + > @c man end AUDIO DECODERS > diff --git a/libavcodec/dca.h b/libavcodec/dca.h > index 787a9c7..67945d5 100644 > --- a/libavcodec/dca.h > +++ b/libavcodec/dca.h > @@ -156,6 +156,7 @@ typedef struct DCAChan { > /* Half size is sufficient for core decoding, but for 96 kHz data > * we need QMF with 64 subbands and 1024 samples. */ > DECLARE_ALIGNED(32, float, subband_fir_hist)[1024]; > + DECLARE_ALIGNED(32, int, subband_hist)[1024]; > DECLARE_ALIGNED(32, float, subband_fir_noidea)[64]; > > /* Primary audio coding side information */ > @@ -220,7 +221,8 @@ typedef struct DCAContext { > uint16_t core_downmix_codes[DCA_PRIM_CHANNELS_MAX + 1][4]; ///< > embedded downmix coefficients (9-bit codes) > > > - float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low > frequency effect data > + int lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low > frequency effect data > + float lfe_data_flt[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; > int lfe_scale_factor; > > /* Subband samples history (for ADPCM) */ > @@ -230,7 +232,7 @@ typedef struct DCAContext { > > int output; ///< type of output > > - float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1]; > + void *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1]; > float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1]; > uint8_t *extra_channels_buffer; > unsigned int extra_channels_buffer_size; > @@ -247,6 +249,9 @@ typedef struct DCAContext { > int core_ext_mask; ///< present extensions in the core substream > int exss_ext_mask; ///< Non-core extensions > > + int fixed; ///< force using fixedpoint QMF > + int lossy; ///< force lossy decoding for the XLL stream > + > /* XCh extension information */ > int xch_present; ///< XCh extension present and valid > int xch_base_channel; ///< index of first (only) channel > containing XCH data > diff --git a/libavcodec/dca_exss.c b/libavcodec/dca_exss.c > index 2895e20..648c126 100644 > --- a/libavcodec/dca_exss.c > +++ b/libavcodec/dca_exss.c > @@ -22,6 +22,7 @@ > #include "libavutil/log.h" > > #include "dca.h" > +#include "dcadata.h" > #include "dca_syncwords.h" > #include "get_bits.h" > > @@ -343,6 +344,14 @@ void ff_dca_exss_parse_header(DCAContext *s) > "DTS-XLL: ignoring XLL extension\n"); > break; > } > + av_log(s->avctx, AV_LOG_ERROR, > + "bps = %d\n", > ff_dca_bits_per_sample[s->source_pcm_res]); > + > + /* Do not change the sample format for the case XLL stream > is decoded > + * in a lossy mode. */ > + if (!s->lossy) > + s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P; > + s->avctx->bits_per_raw_sample = > ff_dca_bits_per_sample[s->source_pcm_res]; > av_log(s->avctx, AV_LOG_DEBUG, > "DTS-XLL: decoding XLL extension\n"); > if (ff_dca_xll_decode_header(s) == 0 && > diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c > index 43992dd..da0ae90 100644 > --- a/libavcodec/dcadec.c > +++ b/libavcodec/dcadec.c > @@ -44,6 +44,7 @@ > #include "dcadata.h" > #include "dcadsp.h" > #include "dcahuff.h" > +#include "dcamath.h" > #include "fft.h" > #include "fmtconvert.h" > #include "get_bits.h" > @@ -520,7 +521,8 @@ static int dca_subframe_header(DCAContext *s, int > base_channel, int block_index) > /* LFE samples */ > int lfe_samples = 2 * s->lfe * (4 + block_index); > int lfe_end_sample = 2 * s->lfe * (4 + block_index + > s->subsubframes[s->current_subframe]); > - float lfe_scale; > + float lfe_scale_flt; > + int lfe_scale; > > for (j = lfe_samples; j < lfe_end_sample; j++) { > /* Signed 8 bits int */ > @@ -532,10 +534,14 @@ static int dca_subframe_header(DCAContext *s, int > base_channel, int block_index) > s->lfe_scale_factor = ff_dca_scale_factor_quant7[get_bits(&s->gb, > 7)]; > > /* Quantization step size * scale factor */ > - lfe_scale = 0.035 * s->lfe_scale_factor; > + lfe_scale_flt = 0.035 * s->lfe_scale_factor; > + /* 4697620 is 24-bit fixedpoint representation of 0.035 */ > + lfe_scale = dca_norm((int64_t)4697620 * s->lfe_scale_factor, 23); > > - for (j = lfe_samples; j < lfe_end_sample; j++) > - s->lfe_data[j] *= lfe_scale; > + for (j = lfe_samples; j < lfe_end_sample; j++) { > + s->lfe_data_flt[j] = lfe_scale_flt * s->lfe_data[j]; > + s->lfe_data[j] = dca_clip23((s->lfe_data[j] * lfe_scale) >> > 4); > + } > } > > return 0; > @@ -932,11 +938,24 @@ static int dca_subsubframe(DCAContext *s, int > base_channel, int block_index) > return 0; > } > > -static int dca_filter_channels(DCAContext *s, int block_index, int upsample) > +static int dca_qmf_filters(DCAContext *s, int block_index, int upsample) > { > int k; > > - if (upsample) { > + // for the 96 kHz lossless > + if (s->fixed && upsample) { > + int **subband_samples_hi = NULL; > + > + for (k = 0; k < s->audio_header.prim_channels; k++) { > + int (*subband_samples)[SAMPLES_PER_SUBBAND] = > + s->dca_chan[k].subband_samples[block_index]; > + int *samples_out = s->samples_chanptr[s->channel_order_tab[k]]; > + > + qmf_64_subbands_fixed(subband_samples, subband_samples_hi, > + s->dca_chan[k].subband_hist, samples_out, > 8); > + } > + // for the 96 kHz lossy > + } else if (upsample) { > LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS_X96K], > [SAMPLES_PER_SUBBAND]); > > if (!s->qmf64_table) { > @@ -945,7 +964,6 @@ static int dca_filter_channels(DCAContext *s, int > block_index, int upsample) > return AVERROR(ENOMEM); > } > > - /* 64 subbands QMF */ > for (k = 0; k < s->audio_header.prim_channels; k++) { > int32_t (*subband_samples)[SAMPLES_PER_SUBBAND] = > s->dca_chan[k].subband_samples[block_index]; > @@ -959,6 +977,20 @@ static int dca_filter_channels(DCAContext *s, int > block_index, int upsample) > /* Upsampling needs a factor 2 here. */ > M_SQRT2 / 32768.0); > } > + // for the 48 kHz lossless > + } else if (s->fixed) { > + for (k = 0; k < s->audio_header.prim_channels; k++) { > + int (*subband_samples)[SAMPLES_PER_SUBBAND] = > + s->dca_chan[k].subband_samples[block_index]; > + int **subband_samples_hi = NULL; > + int *samples_out = s->samples_chanptr[s->channel_order_tab[k]]; > + > + qmf_32_subbands_fixed(subband_samples, subband_samples_hi, > + s->dca_chan[k].subband_hist, > + samples_out, SAMPLES_PER_SUBBAND, > + s->multirate_inter); > + } > + // for the 48 kHz lossy > } else { > /* 32 subbands QMF */ > LOCAL_ALIGNED(32, float, samples, [DCA_SUBBANDS], > [SAMPLES_PER_SUBBAND]); > @@ -977,11 +1009,21 @@ static int dca_filter_channels(DCAContext *s, int > block_index, int upsample) > } > } > > - /* Generate LFE samples for this subsubframe FIXME!!! */ > - if (s->lfe) { > + return 0; > +} > + > +static void dca_generate_lfe(DCAContext *s, int block_index, int upsample) > +{ > + if (s->fixed) { > + int *samples = s->samples_chanptr[ff_dca_lfe_index[s->amode]]; > + int synth_x96 = 0; // X96 synthesis flag should be set if X96 would > be implemented > + int *lfe = s->lfe_data + 2 * s->lfe * (block_index + 4); > + > + lfe_interpolation_fir_fixed(samples, lfe, 2 * s->lfe, synth_x96); > + } else { > float *samples = s->samples_chanptr[ff_dca_lfe_index[s->amode]]; > lfe_interpolation_fir(s, > - s->lfe_data + 2 * s->lfe * (block_index + 4), > + s->lfe_data_flt + 2 * s->lfe * (block_index + > 4), > samples); > if (upsample) { > unsigned i; > @@ -994,13 +1036,45 @@ static int dca_filter_channels(DCAContext *s, int > block_index, int upsample) > samples[1] = samples[0]; > } > } > +} > + > +static int dca_filter_channels(DCAContext *s, int block_index, int upsample) > +{ > + int ret, k; > + > + /* Choose suitable QMF filter. */ > + ret = dca_qmf_filters(s, block_index, upsample); > + if (ret < 0) > + return ret; > + > + /* Generate LFE samples for this subsubframe FIXME!!! */ > + if (s->lfe) > + dca_generate_lfe(s, block_index, upsample); > + > + /* Fixed-point QMF outputs 24-bit samples but libavcodec > + * supports 32-bit */ > + if (s->fixed) { > + int nb_chans = s->lfe ? s->audio_header.prim_channels + 1 : > + s->audio_header.prim_channels; > + int subbands = upsample ? DCA_SUBBANDS_X96K : DCA_SUBBANDS; > + int nb_samples = SAMPLES_PER_SUBBAND * subbands; > + > + for (k = 0; k < nb_chans; k++) { > + int *samples = s->samples_chanptr[k]; > + int i; > + > + for (i = 0; i < nb_samples; i++) > + samples[i] <<= 8; > + } > + } > > /* FIXME: This downmixing is probably broken with upsample. > - * Probably totally broken also with XLL in general. */ > - /* Downmixing to Stereo */ > - if (s->audio_header.prim_channels + !!s->lfe > 2 && > - s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { > - dca_downmix(s->samples_chanptr, s->amode, !!s->lfe, s->downmix_coef, > + * Downmixing to Stereo. */ > + if ((!s->fixed && s->audio_header.prim_channels + !!s->lfe > 2 && > + s->avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)) { > + float **samples = (float **)s->samples_chanptr; > + > + dca_downmix(samples, s->amode, !!s->lfe, s->downmix_coef, > s->channel_order_tab); > } > > @@ -1355,6 +1429,15 @@ static int set_channel_layout(AVCodecContext *avctx, > int channels, int num_core_ > return 0; > } > > +/* Multiply int vector src with scalar mul and add it to destination vector > dst. */ > +static void vector_by_scalar(int *dst, const int *src, int mul, int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + dst[i] += src[i] * (int64_t)mul + 0x8000 >> 16; > +} > + > /** > * Main frame decoding function > * FIXME add arguments > @@ -1369,7 +1452,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void > *data, > int lfe_samples; > int num_core_channels = 0; > int i, ret; > - float **samples_flt; > DCAContext *s = avctx->priv_data; > int channels, full_channels; > int upsample = 0; > @@ -1437,6 +1519,8 @@ static int dca_decode_frame(AVCodecContext *avctx, void > *data, > xll_nb_samples, frame->nb_samples); > s->exss_ext_mask &= ~DCA_EXT_EXSS_XLL; > } else { > + if (!s->lossy) > + s->fixed = 1; > if (2 * frame->nb_samples == xll_nb_samples) { > av_log(s->avctx, AV_LOG_INFO, > "XLL: upsampling core channels by a factor of 2\n"); > @@ -1463,7 +1547,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void > *data, > av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); > return ret; > } > - samples_flt = (float **) frame->extended_data; > > /* allocate buffer for extra channels if downmixing */ > if (avctx->channels < full_channels) { > @@ -1477,7 +1560,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void > *data, > &s->extra_channels_buffer_size, ret); > if (!s->extra_channels_buffer) > return AVERROR(ENOMEM); > - > ret = av_samples_fill_arrays((uint8_t **) s->extra_channels, NULL, > s->extra_channels_buffer, > full_channels - channels, > @@ -1491,27 +1573,40 @@ static int dca_decode_frame(AVCodecContext *avctx, > void *data, > int ch; > unsigned block = upsample ? 512 : 256; > for (ch = 0; ch < channels; ch++) > - s->samples_chanptr[ch] = samples_flt[ch] + i * block; > - for (; ch < full_channels; ch++) > + s->samples_chanptr[ch] = (int *)frame->extended_data[ch] + i * > block; > + for (; ch < full_channels; ch++) { > s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * > block; > + } > > dca_filter_channels(s, i, upsample); > > /* If this was marked as a DTS-ES stream we need to subtract back- */ > /* channel from SL & SR to remove matrixed back-channel signal */ > if ((s->source_pcm_res & 1) && s->xch_present) { > - float *back_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]]; > - float *lt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]]; > - float *rt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]]; > - s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256); > - s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256); > + if (s->fixed) { > + int *back_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]]; > + int *lt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]]; > + int *rt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]]; > + vector_by_scalar(lt_chan, back_chan, > + (int)(M_SQRT1_2 * -0x10000), 256); > + vector_by_scalar(rt_chan, back_chan, > + (int)(M_SQRT1_2 * -0x10000), 256); > + } else { > + float *back_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]]; > + float *lt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]]; > + float *rt_chan = > s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]]; > + s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, > 256); > + s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, > 256); > + } > } > } > > /* update lfe history */ > lfe_samples = 2 * s->lfe * (s->sample_blocks / SAMPLES_PER_SUBBAND); > - for (i = 0; i < 2 * s->lfe * 4; i++) > - s->lfe_data[i] = s->lfe_data[i + lfe_samples]; > + for (i = 0; i < 2 * s->lfe * 4; i++) { > + s->lfe_data_flt[i] = s->lfe_data_flt[i + lfe_samples]; > + s->lfe_data[i] = s->lfe_data[i + lfe_samples]; > + } > > if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) { > ret = ff_dca_xll_decode_audio(s, frame); > @@ -1551,7 +1646,13 @@ static av_cold int dca_decode_init(AVCodecContext > *avctx) > ff_dcadsp_init(&s->dcadsp); > ff_fmt_convert_init(&s->fmt_conv, avctx); > > - avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; > + if (avctx->request_sample_fmt == AV_SAMPLE_FMT_S32P) { > + s->fixed = 1; > + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; > + } else { > + s->fixed = 0; > + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; > + } > > /* allow downmixing to stereo */ > if (avctx->channels > 2 && > @@ -1574,6 +1675,7 @@ static av_cold int dca_decode_end(AVCodecContext *avctx) > static const AVOption options[] = { > { "disable_xch", "disable decoding of the XCh extension", > offsetof(DCAContext, xch_disable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, > AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM }, > { "disable_xll", "disable decoding of the XLL extension", > offsetof(DCAContext, xll_disable), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, > AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM }, > + { "force_lossy", "force lossy XLL decoding", > offsetof(DCAContext, lossy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, > AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM }, > { NULL }, > }; > > @@ -1595,6 +1697,7 @@ AVCodec ff_dca_decoder = { > .close = dca_decode_end, > .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, > .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, > + AV_SAMPLE_FMT_S32P, > AV_SAMPLE_FMT_NONE }, > .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), > .priv_class = &dca_decoder_class, > diff --git a/libavcodec/dcadsp.c b/libavcodec/dcadsp.c > index beec200..3bef29f 100644 > --- a/libavcodec/dcadsp.c > +++ b/libavcodec/dcadsp.c > @@ -1,6 +1,7 @@ > /* > * Copyright (c) 2004 Gildas Bazin > * Copyright (c) 2010 Mans Rullgard <[email protected]> > + * Copyright (c) 2015 foo86 > * > * This file is part of Libav. > * > @@ -17,14 +18,21 @@ > * You should have received a copy of the GNU Lesser General Public > * License along with Libav; if not, write to the Free Software > * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + * > + * The functions idct_perform32_fixed, qmf_32_subbands_fixed, > idct_perform64_fixed, > + * qmf_64_subbands_fixed, lfe_interpolation_fir_fixed and the auxiliary > functions > + * they are using (mod*, sub*, clp*) are adapted from libdcadec, > + * https://github.com/foo86/dcadec/tree/master/libdcadec. > */ > > +#include <stdio.h> > #include "config.h" > > #include "libavutil/attributes.h" > #include "libavutil/intreadwrite.h" > > #include "dcadsp.h" > +#include "dcadata.h" > #include "dcamath.h" > > static void decode_hf_c(int32_t dst[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], > @@ -132,3 +140,482 @@ av_cold void ff_dcadsp_init(DCADSPContext *s) > if (ARCH_X86) > ff_dcadsp_init_x86(s); > } > + > +static void sum_a(const int * restrict input, int * restrict output, int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + output[i] = input[2 * i] + input[2 * i + 1]; > +} > + > +static void sum_b(const int * restrict input, int * restrict output, int len) > +{ > + int i; > + > + output[0] = input[0]; > + for (i = 1; i < len; i++) > + output[i] = input[2 * i] + input[2 * i - 1]; > +} > + > +static void sum_c(const int * restrict input, int * restrict output, int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + output[i] = input[2 * i]; > +} > + > +static void sum_d(const int * restrict input, int * restrict output, int len) > +{ > + int i; > + > + output[0] = input[1]; > + for (i = 1; i < len; i++) > + output[i] = input[2 * i - 1] + input[2 * i + 1]; > +} > + > +static void clp_v(int *input, int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + input[i] = dca_clip23(input[i]); > +} > + > +static void dct_a(const int * restrict input, int * restrict output) > +{ > + int i, j; > + static const int cos_mod[8][8] = { > + { 8348215, 8027397, 7398092, 6484482, 5321677, 3954362, > 2435084, 822227 }, > + { 8027397, 5321677, 822227, -3954362, -7398092, -8348215, > -6484482, -2435084 }, > + { 7398092, 822227, -6484482, -8027397, -2435084, 5321677, > 8348215, 3954362 }, > + { 6484482, -3954362, -8027397, 822227, 8348215, 2435084, > -7398092, -5321677 }, > + { 5321677, -7398092, -2435084, 8348215, -822227, -8027397, > 3954362, 6484482 }, > + { 3954362, -8348215, 5321677, 2435084, -8027397, 6484482, > 822227, -7398092 }, > + { 2435084, -6484482, 8348215, -7398092, 3954362, 822227, > -5321677, 8027397 }, > + { 822227, -2435084, 3954362, -5321677, 6484482, -7398092, > 8027397, -8348215 } > + }; > + > + for (i = 0; i < 8; i++) { > + int64_t res = INT64_C(0); > + for (j = 0; j < 8; j++) > + res += (int64_t)cos_mod[i][j] * input[j]; > + output[i] = dca_norm(res, 23); > + } > +} > + > +static void dct_b(const int * restrict input, int * restrict output) > +{ > + int i, j; > + static const int cos_mod[8][7] = { > + { 8227423, 7750063, 6974873, 5931642, 4660461, 3210181, > 1636536 }, > + { 6974873, 3210181, -1636536, -5931642, -8227423, -7750063, > -4660461 }, > + { 4660461, -3210181, -8227423, -5931642, 1636536, 7750063, > 6974873 }, > + { 1636536, -7750063, -4660461, 5931642, 6974873, -3210181, > -8227423 }, > + { -1636536, -7750063, 4660461, 5931642, -6974873, -3210181, > 8227423 }, > + { -4660461, -3210181, 8227423, -5931642, -1636536, 7750063, > -6974873 }, > + { -6974873, 3210181, 1636536, -5931642, 8227423, -7750063, > 4660461 }, > + { -8227423, 7750063, -6974873, 5931642, -4660461, 3210181, > -1636536 } > + }; > + > + for (i = 0; i < 8; i++) { > + int64_t res = (int64_t)input[0] * (1 << 23); > + for (j = 0; j < 7; j++) > + res += (int64_t)cos_mod[i][j] * input[1 + j]; > + output[i] = dca_norm(res, 23); > + } > +} > + > +static void mod_a(const int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[16] = { > + 4199362, 4240198, 4323885, 4454708, > + 4639772, 4890013, 5221943, 5660703, > + -6245623, -7040975, -8158494, -9809974, > + -12450076, -17261920, -28585092, -85479984 > + }; > + > + for (i = 0; i < 8; i++) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[i] + input[8 + > i]), 23); > + > + for (i = 8, k = 7; i < 16; i++, k--) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[k] - input[8 + > k]), 23); > +} > + > +static void mod_b(int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[8] = { > + 4214598, 4383036, 4755871, 5425934, > + 6611520, 8897610, 14448934, 42791536 > + }; > + > + for (i = 0; i < 8; i++) > + input[8 + i] = dca_norm((int64_t)cos_mod[i] * input[8 + i], 23); > + > + for (i = 0; i < 8; i++) > + output[i] = input[i] + input[8 + i]; > + > + for (i = 8, k = 7; i < 16; i++, k--) > + output[i] = input[k] - input[8 + k]; > +} > + > +static void mod_c(const int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[32] = { > + 1048892, 1051425, 1056522, 1064244, > + 1074689, 1087987, 1104313, 1123884, > + 1146975, 1173922, 1205139, 1241133, > + 1282529, 1330095, 1384791, 1447815, > + -1520688, -1605358, -1704360, -1821051, > + -1959964, -2127368, -2332183, -2587535, > + -2913561, -3342802, -3931480, -4785806, > + -6133390, -8566050, -14253820, -42727120 > + }; > + > + for (i = 0; i < 16; i++) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[i] + input[16 + > i]), 23); > + > + for (i = 16, k = 15; i < 32; i++, k--) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[k] - input[16 + > k]), 23); > +} > + > +void idct_perform32_fixed(int * restrict input, int * restrict output) > +{ > + int mag = 0; > + int shift, round; > + int i; > + > + for (i = 0; i < 32; i++) > + mag += abs(input[i]); > + > + shift = mag > 0x400000 ? 2 : 0; > + round = shift > 0 ? 1 << (shift - 1) : 0; > + > + for (i = 0; i < 32; i++) > + input[i] = (input[i] + round) >> shift; > + > + sum_a(input, output + 0, 16); > + sum_b(input, output + 16, 16); > + clp_v(output, 32); > + > + sum_a(output + 0, input + 0, 8); > + sum_b(output + 0, input + 8, 8); > + sum_c(output + 16, input + 16, 8); > + sum_d(output + 16, input + 24, 8); > + clp_v(input, 32); > + > + dct_a(input + 0, output + 0); > + dct_b(input + 8, output + 8); > + dct_b(input + 16, output + 16); > + dct_b(input + 24, output + 24); > + clp_v(output, 32); > + > + mod_a(output + 0, input + 0); > + mod_b(output + 16, input + 16); > + clp_v(input, 32); > + > + mod_c(input, output); > + > + for (i = 0; i < 32; i++) > + output[i] = dca_clip23(output[i] * (1 << shift)); > +} > + > +void qmf_32_subbands_fixed(int subband_samples[32][8], int > **subband_samples_hi, int *history, > + int *pcm_samples, int nb_samples, int swich) > +{ > + const int32_t *filter_coeff; > + int input[32]; > + int output[32]; > + int sample; > + > + // Select filter > + if (!swich) > + filter_coeff = ff_dca_fir_32bands_nonperfect_fixed; > + else > + filter_coeff = ff_dca_fir_32bands_perfect_fixed; > + > + for (sample = 0; sample < nb_samples; sample++) { > + int i, j, k; > + > + // Load in one sample from each subband > + for (i = 0; i < 32; i++) { > + input[i] = subband_samples[i][sample]; > + } > + > + // Inverse DCT > + idct_perform32_fixed(input, output); > + > + // Store history > + for (i = 0, k = 31; i < 16; i++, k--) { > + history[ i] = dca_clip23(output[i] - output[k]); > + history[16 + i] = dca_clip23(output[i] + output[k]); > + } > + > + // One subband sample generates 32 interpolated ones > + for (i = 0; i < 16; i++) { > + // Clear accumulation > + int64_t res = INT64_C(0); > + > + // Accumulate > + for (j = 32; j < 512; j += 64) > + res += (int64_t)history[16 + i + j] * filter_coeff[i + j]; > + res = dca_round(res, 21); > + for (j = 0; j < 512; j += 64) > + res += (int64_t)history[ i + j] * filter_coeff[i + j]; > + > + // Save interpolated samples > + pcm_samples[sample * 32 + i] = dca_clip23(dca_norm(res, 21)); // > * (1.0f / (1 << 24)); > + } > + > + for (i = 16, k = 15; i < 32; i++, k--) { > + // Clear accumulation > + int64_t res = INT64_C(0); > + > + // Accumulate > + for (j = 32; j < 512; j += 64) > + res += (int64_t)history[16 + k + j] * filter_coeff[i + j]; > + res = dca_round(res, 21); > + for (j = 0; j < 512; j += 64) > + res += (int64_t)history[ k + j] * filter_coeff[i + j]; > + > + // Save interpolated samples > + pcm_samples[sample * 32 + i] = dca_clip23(dca_norm(res, 21)); // > * (1.0f / (1 << 24)); > + } > + > + // Shift history > + for (i = 511; i >= 32; i--) > + history[i] = history[i - 32]; > + } > +} > + > +static void mod64_a(const int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[32] = { > + 4195568, 4205700, 4226086, 4256977, > + 4298755, 4351949, 4417251, 4495537, > + 4587901, 4695690, 4820557, 4964534, > + 5130115, 5320382, 5539164, 5791261, > + -6082752, -6421430, -6817439, -7284203, > + -7839855, -8509474, -9328732, -10350140, > + -11654242, -13371208, -15725922, -19143224, > + -24533560, -34264200, -57015280, -170908480 > + }; > + > + for (i = 0; i < 16; i++) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[i] + input[16 + > i]), 23); > + > + for (i = 16, k = 15; i < 32; i++, k--) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[k] - input[16 + > k]), 23); > +} > + > +static void mod64_b(int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[16] = { > + 4199362, 4240198, 4323885, 4454708, > + 4639772, 4890013, 5221943, 5660703, > + 6245623, 7040975, 8158494, 9809974, > + 12450076, 17261920, 28585092, 85479984 > + }; > + > + for (i = 0; i < 16; i++) > + input[16 + i] = dca_norm((int64_t)cos_mod[i] * input[16 + i], 23); > + > + for (i = 0; i < 16; i++) > + output[i] = input[i] + input[16 + i]; > + > + for (i = 16, k = 15; i < 32; i++, k--) > + output[i] = input[k] - input[16 + k]; > +} > + > +static void mod64_c(const int * restrict input, int * restrict output) > +{ > + int i, k; > + static const int cos_mod[64] = { > + 741511, 741958, 742853, 744199, > + 746001, 748262, 750992, 754197, > + 757888, 762077, 766777, 772003, > + 777772, 784105, 791021, 798546, > + 806707, 815532, 825054, 835311, > + 846342, 858193, 870912, 884554, > + 899181, 914860, 931667, 949686, > + 969011, 989747, 1012012, 1035941, > + -1061684, -1089412, -1119320, -1151629, > + -1186595, -1224511, -1265719, -1310613, > + -1359657, -1413400, -1472490, -1537703, > + -1609974, -1690442, -1780506, -1881904, > + -1996824, -2128058, -2279225, -2455101, > + -2662128, -2909200, -3208956, -3579983, > + -4050785, -4667404, -5509372, -6726913, > + -8641940, -12091426, -20144284, -60420720 > + }; > + > + for (i = 0; i < 32; i++) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[i] + input[32 + > i]), 23); > + > + for (i = 32, k = 31; i < 64; i++, k--) > + output[i] = dca_norm((int64_t)cos_mod[i] * (input[k] - input[32 + > k]), 23); > +} > + > +void idct_perform64_fixed(int * restrict input, int * restrict output) > +{ > + int mag = 0; > + int shift; > + int round; > + int i; > + > + for (i = 0; i < 64; i++) > + mag += abs(input[i]); > + > + shift = mag > 0x400000 ? 2 : 0; > + round = shift > 0 ? 1 << (shift - 1) : 0; > + > + for (i = 0; i < 64; i++) > + input[i] = (input[i] + round) >> shift; > + > + sum_a(input, output + 0, 32); > + sum_b(input, output + 32, 32); > + clp_v(output, 64); > + > + sum_a(output + 0, input + 0, 16); > + sum_b(output + 0, input + 16, 16); > + sum_c(output + 32, input + 32, 16); > + sum_d(output + 32, input + 48, 16); > + clp_v(input, 64); > + > + sum_a(input + 0, output + 0, 8); > + sum_b(input + 0, output + 8, 8); > + sum_c(input + 16, output + 16, 8); > + sum_d(input + 16, output + 24, 8); > + sum_c(input + 32, output + 32, 8); > + sum_d(input + 32, output + 40, 8); > + sum_c(input + 48, output + 48, 8); > + sum_d(input + 48, output + 56, 8); > + clp_v(output, 64); > + > + dct_a(output + 0, input + 0); > + dct_b(output + 8, input + 8); > + dct_b(output + 16, input + 16); > + dct_b(output + 24, input + 24); > + dct_b(output + 32, input + 32); > + dct_b(output + 40, input + 40); > + dct_b(output + 48, input + 48); > + dct_b(output + 56, input + 56); > + clp_v(input, 64); > + > + mod_a(input + 0, output + 0); > + mod_b(input + 16, output + 16); > + mod_b(input + 32, output + 32); > + mod_b(input + 48, output + 48); > + clp_v(output, 64); > + > + mod64_a(output + 0, input + 0); > + mod64_b(output + 32, input + 32); > + clp_v(input, 64); > + > + mod64_c(input, output); > + > + for (i = 0; i < 64; i++) > + output[i] = dca_clip23(output[i] * (1 << shift)); > +} > + > +void qmf_64_subbands_fixed(int subband_samples[64][8], int > **subband_samples_hi, int *history, > + int *pcm_samples, int nb_samples) > +{ > + int output[64]; > + int sample; > + > + // Interpolation begins > + for (sample = 0; sample < nb_samples; sample++) { > + int i, j, k; > + > + // Load in one sample from each subband > + int input[64]; > + if (subband_samples_hi) { > + // Full 64 subbands, first 32 are residual coded > + for (i = 0; i < 32; i++) > + input[i] = subband_samples[i][sample] + > subband_samples_hi[i][sample]; > + for (i = 32; i < 64; i++) > + input[i] = subband_samples_hi[i][sample]; > + } else { > + // Only first 32 subbands > + for (i = 0; i < 32; i++) > + input[i] = subband_samples[i][sample]; > + for (i = 32; i < 64; i++) > + input[i] = 0; > + } > + > + // Inverse DCT > + idct_perform64_fixed(input, output); > + > + // Store history > + for (i = 0, k = 63; i < 32; i++, k--) { > + history[ i] = dca_clip23(output[i] - output[k]); > + history[32 + i] = dca_clip23(output[i] + output[k]); > + } > + > + // One subband sample generates 64 interpolated ones > + for (i = 0; i < 32; i++) { > + // Clear accumulation > + int64_t res = INT64_C(0); > + > + // Accumulate > + for (j = 64; j < 1024; j += 128) > + res += (int64_t)history[32 + i + j] * ff_dca_band_fir_x96[i > + j]; > + res = dca_round(res, 20); > + for (j = 0; j < 1024; j += 128) > + res += (int64_t)history[ i + j] * ff_dca_band_fir_x96[i > + j]; > + > + // Save interpolated samples > + pcm_samples[sample * 64 + i] = dca_clip23(dca_norm(res, 20)); > + } > + > + for (i = 32, k = 31; i < 64; i++, k--) { > + // Clear accumulation > + int64_t res = INT64_C(0); > + > + // Accumulate > + for (j = 64; j < 1024; j += 128) > + res += (int64_t)history[32 + k + j] * ff_dca_band_fir_x96[i > + j]; > + res = dca_round(res, 20); > + for (j = 0; j < 1024; j += 128) > + res += (int64_t)history[ k + j] * ff_dca_band_fir_x96[i > + j]; > + > + // Save interpolated samples > + pcm_samples[sample * 64 + i] = dca_clip23(dca_norm(res, 20)); > + } > + > + // Shift history > + for (i = 1023; i >= 64; i--) > + history[i] = history[i - 64]; > + } > +} > + > +void lfe_interpolation_fir_fixed(int *pcm_samples, int *lfe_samples, > + int nb_samples, int synth_x96) > +{ > + int dec_factor = 64; > + int i, j, k; > + > + // Interpolation > + for (i = 0; i < nb_samples; i++) { > + // One decimated sample generates 64 or 128 interpolated ones > + for (j = 0; j < dec_factor; j++) { > + // Clear accumulation > + int64_t res = INT64_C(0); > + > + // Accumulate > + for (k = 0; k < 512 / dec_factor; k++) > + res += (int64_t)ff_dca_lfe_fir_64_fixed[k * dec_factor + j] * > + lfe_samples[i - k]; > + > + // Save interpolated samples > + pcm_samples[(i * dec_factor + j) << synth_x96] = > dca_clip23(dca_norm(res, 23)); > + } > + } > +} > diff --git a/libavcodec/dcadsp.h b/libavcodec/dcadsp.h > index 9ea89ea..0c0e6c8 100644 > --- a/libavcodec/dcadsp.h > +++ b/libavcodec/dcadsp.h > @@ -14,6 +14,10 @@ > * You should have received a copy of the GNU Lesser General Public > * License along with Libav; if not, write to the Free Software > * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + * > + * The functions idct_perform32_fixed, qmf_32_subbands_fixed, > idct_perform64_fixed, > + * qmf_64_subbands_fixed and the auxiliary functions they are using are > adapted > + * from libdcadec, https://github.com/foo86/dcadec/tree/master/libdcadec. > */ > > #ifndef AVCODEC_DCADSP_H > @@ -28,7 +32,7 @@ > > > typedef struct DCADSPContext { > - void (*lfe_fir[2])(float *out, const float *in, const float *coefs); > + void (*lfe_fir[2])(void *out, const float *in, const float *coefs); > void (*qmf_32_subbands)(float > samples_in[DCA_SUBBANDS][SAMPLES_PER_SUBBAND], int sb_act, > SynthFilterContext *synth, FFTContext *imdct, > float synth_buf_ptr[512], > @@ -48,4 +52,13 @@ void ff_dcadsp_init_aarch64(DCADSPContext *s); > void ff_dcadsp_init_arm(DCADSPContext *s); > void ff_dcadsp_init_x86(DCADSPContext *s); > > +void idct_perform32_fixed(int * restrict input, int * restrict output); > +void qmf_32_subbands_fixed(int subband_samples[32][8], int > **subband_samples_hi, > + int *history, int *pcm_samples, int nb_samples, > int swich); > +void idct_perform64_fixed(int * restrict input, int * restrict output); > +void qmf_64_subbands_fixed(int subband_samples[64][8], int > **subband_samples_hi, > + int *history, int *pcm_samples, int nb_samples); > +void lfe_interpolation_fir_fixed(int *pcm_samples, int *lfe_samples, > + int nb_samples, int synth_x96); > + > #endif /* AVCODEC_DCADSP_H */ > diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak > index cf11e9d..5f04418 100644 > --- a/tests/fate/audio.mak > +++ b/tests/fate/audio.mak > @@ -22,7 +22,7 @@ fate-dca-core: CMP = oneoff > fate-dca-core: REF = $(SAMPLES)/dts/dts.pcm > > FATE_DCA-$(CONFIG_DTS_DEMUXER) += fate-dca-xll > -fate-dca-xll: CMD = pcm -disable_xll 0 -i > $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts > +fate-dca-xll: CMD = pcm -disable_xll 0 -force_lossy 1 -i > $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts > fate-dca-xll: CMP = oneoff > fate-dca-xll: REF = $(SAMPLES)/dts/master_audio_7.1_24bit_2.pcm > > -- > 2.1.4 >
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
