Thank you for your suggestions!
Please find the updated patch in my next email
[PATCH] ATRAC3+ decoder, 2nd try

Below a couple of comments...

On Thu, Oct 10, 2013 at 9:14 PM, Maxim Polijakowski<max_p...@gmx.de>  wrote:

Hi crews,

the attached patch adds an open-source decoder for Sony's ATRAC3+ format.
There is a partial description of its internals located here:
http://wiki.multimedia.cx/**index.php?title=ATRAC3plus<http://wiki.multimedia.cx/index.php?title=ATRAC3plus>


You could define:

const uint8_t *ff_atrac3p_sf_huff_bits[] = {atrac3p_sf_huff_bits1,
atrac3p_sf_huff_bits2, atrac3p_sf_huff_bits1, ...};

And use one (or three) loops to init it (also valid for the ones
initialized with build_canonical_huff).

This part has been significantly reworked. The VLC initialization uses more loops now...


+static void subtract_sf_weights(Atrac3pChanUnitCtx *ctx,
+                                Atrac3pChanParams *chan, int wtab_idx)
+{
+    int i;
+    const int8_t *weights_tab;
+
+    weights_tab = &ff_atrac3p_sf_weights[wtab_idx - 1][0];
+
+    for (i = 0; i < ctx->used_quant_units; i++)
+        chan->qu_sf_idx[i] -= weights_tab[i];
+}

Please move this function right after add_wordlen_weights(). Even if I
understand the reason for the code duplication, I think grouping them
together improves readability.

Done.

There is a pretty large number of decode_* functions with four different
coding modes, some more or less similar. In the cases where applicable, It
would be nice to have some comments like:

/**
  * This function almost identical to decode_something_else(), but VLC delta
coding use
  *     different coefficients.
  */

Ok, comments will be added/improved later...




+/**
+ * ATRAC3+ uses two different MDCT windows:
+ * - The first one is just the plain sine window of size 256.
+ * - The 2nd one is the plain sine window of size 128
+ *   wrapped into zero (at the start) and one (at the end) regions.
+ *   Both regions are 32 samples long. */
+static float mdct_wind_steep[128]; ///< second MDCT window
+
+av_cold void ff_atrac3p_init_imdct(AVCodecContext *avctx, FFTContext
*mdct_ctx)
+{
+    int i;
+
+    avpriv_float_dsp_init(&atrac3p_dsp, avctx->flags &
CODEC_FLAG_BITEXACT);
+
+    ff_init_ff_sine_windows(7);
+    ff_init_ff_sine_windows(6);
+
+    /* Copy the 2nd sine window and place it between one/zero regions. */
+    memcpy(&mdct_wind_steep[32], ff_sine_64, sizeof(ff_sine_64));
+
+    for (i = 0; i < 32; i++) {
+        mdct_wind_steep[i]       = 0.0f;
+        mdct_wind_steep[127 - i] = 1.0f;
+    }

I think you could use ff_sine_64 directly if you modify ff_atrac3p_imdct()
doing something like

    atrac3p_dsp.vector_fmul(pOut+64, pOut+64, ff_sine_64, 64);

for the steep window case.

Done.

+
+    /* generate amplitude mantissas table */
+    for (i = 0; i < 16; i++)
+        amp_mant_tab[i] = (1.0f / 15.13f) * (i + 1);
+}
+

I think this can be done efficiently without a table.

Indeed. The table has been replaced with direct computation.

+    /* Hann windowing for non-faded wave signals */
+    if (tones_now->num_wavs && tones_next->num_wavs &&
+        reg1_env_nonzero && reg2_env_nonzero) {
+        for (i = 0; i < 128; i++) {
+            wavreg1[i] *= hann_window[128 - i];
+            wavreg2[i] *= hann_window[i];
+        }
+    } else {
+        if (tones_now->num_wavs && !tones_now->curr_env.has_stop_point)
+            for (i = 0; i < 128; i++)
+                wavreg1[i] *= hann_window[128 - i];
+
+        if (tones_next->num_wavs && !tones_next->curr_env.has_start_point)
+            for (i = 0; i < 128; i++)
+                wavreg2[i] *= hann_window[i];
+    }
+
+    /* Overlap and add to residual */
+    for (i = 0; i < 128; i++)
+        out[i] += wavreg1[i] + wavreg2[i];
+}

I think we have DSP functions for multiplying and adding floats.

Yes, replaced with vector_fmul()...




+void ff_atrac3p_ipqf(FFTContext *dct_ctx, Atrac3pIPQFChannelCtx *hist,
+                     float *in, float *out)
+{
+    int i, s, sb, t, pos_now, pos_next;
+    DECLARE_ALIGNED(32, float, idct_in)[ATRAC3P_SUBBANDS];
+    DECLARE_ALIGNED(32, float, idct_out)[ATRAC3P_SUBBANDS];
+
+    memset(out, 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out));
+
+    for (s = 0; s < ATRAC3P_SUBBAND_SAMPLES; s++) {
+        /* pick up one sample from each subband */
+        for (sb = 0; sb < ATRAC3P_SUBBANDS; sb++)
+            idct_in[sb] = in[sb * ATRAC3P_SUBBAND_SAMPLES + s];
+
+        /* Calculate the sine and cosine part of the PQF using IDCT-IV */
+        dct_ctx->imdct_half(dct_ctx, idct_out, idct_in);

IDCT-IV or IMDCT?

imdct_half = IDCT-IV in this case because there is no overlap...

Best regards
Maxim
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to