#include "mpeg4audio.h"
#include "bytestream.h"
-#include "als_data.h"
+#include <stdint.h>
+
+/** Rice parameters and corresponding index offsets for decoding the
+ * indices of scaled PARCOR values. The table choosen is set globally
+ * by the encoder and stored in ALSSpecificConfig.
+ */
+static const int8_t parcor_rice_table[3][20][2] = {
+ { {-52, 4}, {-29, 5}, {-31, 4}, { 19, 4}, {-16, 4},
+ { 12, 3}, { -7, 3}, { 9, 3}, { -5, 3}, { 6, 3},
+ { -4, 3}, { 3, 3}, { -3, 2}, { 3, 2}, { -2, 2},
+ { 3, 2}, { -1, 2}, { 2, 2}, { -1, 2}, { 2, 2} },
+ { {-58, 3}, {-42, 4}, {-46, 4}, { 37, 5}, {-36, 4},
+ { 29, 4}, {-29, 4}, { 25, 4}, {-23, 4}, { 20, 4},
+ {-17, 4}, { 16, 4}, {-12, 4}, { 12, 3}, {-10, 4},
+ { 7, 3}, { -4, 4}, { 3, 3}, { -1, 3}, { 1, 3} },
+ { {-59, 3}, {-45, 5}, {-50, 4}, { 38, 4}, {-39, 4},
+ { 32, 4}, {-30, 4}, { 25, 3}, {-23, 3}, { 20, 3},
+ {-20, 3}, { 16, 3}, {-13, 3}, { 10, 3}, { -7, 3},
+ { 3, 3}, { 0, 3}, { -1, 3}, { 2, 3}, { -1, 2} }
+};
+
+
+/** Scaled PARCOR values used for the first two PARCOR coefficients.
+ * To be indexed by the Rice coded indices.
+ * Generated by: parcor_scaled_values[i] = 32 + ((i * (i+1)) << 7) - (1 << 20)
+ * Actual values are divided by 32 in order to be stored in 16 bits.
+ */
+static const int16_t parcor_scaled_values[] = {
+ -1048544 / 32, -1048288 / 32, -1047776 / 32, -1047008 / 32,
+ -1045984 / 32, -1044704 / 32, -1043168 / 32, -1041376 / 32,
+ -1039328 / 32, -1037024 / 32, -1034464 / 32, -1031648 / 32,
+ -1028576 / 32, -1025248 / 32, -1021664 / 32, -1017824 / 32,
+ -1013728 / 32, -1009376 / 32, -1004768 / 32, -999904 / 32,
+ -994784 / 32, -989408 / 32, -983776 / 32, -977888 / 32,
+ -971744 / 32, -965344 / 32, -958688 / 32, -951776 / 32,
+ -944608 / 32, -937184 / 32, -929504 / 32, -921568 / 32,
+ -913376 / 32, -904928 / 32, -896224 / 32, -887264 / 32,
+ -878048 / 32, -868576 / 32, -858848 / 32, -848864 / 32,
+ -838624 / 32, -828128 / 32, -817376 / 32, -806368 / 32,
+ -795104 / 32, -783584 / 32, -771808 / 32, -759776 / 32,
+ -747488 / 32, -734944 / 32, -722144 / 32, -709088 / 32,
+ -695776 / 32, -682208 / 32, -668384 / 32, -654304 / 32,
+ -639968 / 32, -625376 / 32, -610528 / 32, -595424 / 32,
+ -580064 / 32, -564448 / 32, -548576 / 32, -532448 / 32,
+ -516064 / 32, -499424 / 32, -482528 / 32, -465376 / 32,
+ -447968 / 32, -430304 / 32, -412384 / 32, -394208 / 32,
+ -375776 / 32, -357088 / 32, -338144 / 32, -318944 / 32,
+ -299488 / 32, -279776 / 32, -259808 / 32, -239584 / 32,
+ -219104 / 32, -198368 / 32, -177376 / 32, -156128 / 32,
+ -134624 / 32, -112864 / 32, -90848 / 32, -68576 / 32,
+ -46048 / 32, -23264 / 32, -224 / 32, 23072 / 32,
+ 46624 / 32, 70432 / 32, 94496 / 32, 118816 / 32,
+ 143392 / 32, 168224 / 32, 193312 / 32, 218656 / 32,
+ 244256 / 32, 270112 / 32, 296224 / 32, 322592 / 32,
+ 349216 / 32, 376096 / 32, 403232 / 32, 430624 / 32,
+ 458272 / 32, 486176 / 32, 514336 / 32, 542752 / 32,
+ 571424 / 32, 600352 / 32, 629536 / 32, 658976 / 32,
+ 688672 / 32, 718624 / 32, 748832 / 32, 779296 / 32,
+ 810016 / 32, 840992 / 32, 872224 / 32, 903712 / 32,
+ 935456 / 32, 967456 / 32, 999712 / 32, 1032224 / 32
+};
+
+
+/** Gain values of p(0) for long-term prediction.
+ * To be indexed by the Rice coded indices.
+ */
+static const uint8_t ltp_gain_values [4][4] = {
+ { 0, 8, 16, 24},
+ {32, 40, 48, 56},
+ {64, 70, 76, 82},
+ {88, 92, 96, 100}
+};
+
+
+/** Inter-channel weighting factors for multi-channel correlation.
+ * To be indexed by the Rice coded indices.
+ */
+static const int16_t mcc_weightings[] = {
+ 204, 192, 179, 166, 153, 140, 128, 115,
+ 102, 89, 76, 64, 51, 38, 25, 12,
+ 0, -12, -25, -38, -51, -64, -76, -89,
+ -102, -115, -128, -140, -153, -166, -179, -192
+};
+
enum RA_Flag {
RA_FLAG_NONE,
} ALSSpecificConfig;
+typedef struct {
+ int stop_flag;
+ int master_channel;
+ int time_diff_flag;
+ int time_diff_sign;
+ int time_diff_index;
+ int weighting[6];
+} ALSChannelData;
+
+
typedef struct {
AVCodecContext *avctx;
ALSSpecificConfig sconf;
unsigned int frame_id; ///< the frame ID / number of the current frame
unsigned int js_switch; ///< if true, joint-stereo decoding is enforced
unsigned int num_blocks; ///< number of blocks used in the current frame
- int32_t *quant_cof; ///< quantized parcor coefficients
- int32_t *lpc_cof; ///< coefficients of the direct form prediction filter
+ int ltp_lag_length; ///< number of bits used for ltp lag value
+ int *use_ltp; ///< contains use_ltp flags for all channels
+ int *ltp_lag; ///< contains ltp lag values for all channels
+ int **ltp_gain; ///< gain values for ltp 5-tap filter for a channel
+ int *ltp_gain_buffer; ///< contains all gain values for ltp 5-tap filter
+ int32_t **quant_cof; ///< quantized parcor coefficients for a channel
+ int32_t *quant_cof_buffer; ///< contains all quantized parcor coefficients
+ int32_t **lpc_cof; ///< coefficients of the direct form prediction filter for a channel
+ int32_t *lpc_cof_buffer; ///< contains all coefficients of the direct form prediction filter
+ int32_t *lpc_cof_reversed_buffer; ///< temporary buffer to set up a reversed versio of lpc_cof_buffer
+ ALSChannelData **chan_data; ///< channel data for multi-channel correlation
+ ALSChannelData *chan_data_buffer; ///< contains channel data for all channels
+ int *reverted_channels; ///< stores a flag for each reverted channel
int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block
int32_t **raw_samples; ///< decoded raw samples for each channel
int32_t *raw_buffer; ///< contains all decoded raw samples including carryover samples
} ALSDecContext;
+typedef struct {
+ unsigned int block_length; ///< number of samples within the block
+ unsigned int ra_block; ///< if true, this is a random access block
+ int const_block; ///< if true, this is a constant value block
+ int32_t const_val; ///< the sample value of a constant block
+ int js_blocks; ///< true if this block contains a difference signal
+ unsigned int shift_lsbs; ///< shift of values for this block
+ unsigned int opt_order; ///< prediction order of this block
+ int store_prev_samples;///< if true, carryover samples have to be stored
+ int *use_ltp; ///< if true, long-term prediction is used
+ int *ltp_lag; ///< lag value for long-term prediction
+ int *ltp_gain; ///< gain values for ltp 5-tap filter
+ int32_t *quant_cof; ///< quantized parcor coefficients
+ int32_t *lpc_cof; ///< coefficients of the direct form prediction
+ int32_t *raw_samples; ///< decoded raw samples / residuals for this block
+ int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block
+ int32_t *raw_other; ///< decoded raw samples of the other channel of a channel pair
+} ALSBlockData;
+
+
static av_cold void dprint_specific_config(ALSDecContext *ctx)
{
#ifdef DEBUG
ctx->cur_frame_length = sconf->frame_length;
- // allocate quantized parcor coefficient buffer
- if (!(ctx->quant_cof = av_malloc(sizeof(*ctx->quant_cof) * sconf->max_order)) ||
- !(ctx->lpc_cof = av_malloc(sizeof(*ctx->lpc_cof) * sconf->max_order))) {
- av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
- return AVERROR(ENOMEM);
- }
-
// read channel config
if (sconf->chan_config)
sconf->chan_config_info = get_bits(&gb, 16);
}
MISSING_ERR(sconf->floating, "Floating point decoding", -1);
- MISSING_ERR(sconf->long_term_prediction, "Long-term prediction", -1);
MISSING_ERR(sconf->bgmc, "BGMC entropy decoding", -1);
- MISSING_ERR(sconf->mc_coding, "Multi-channel correlation", -1);
MISSING_ERR(sconf->rlslms, "Adaptive RLS-LMS prediction", -1);
MISSING_ERR(sconf->chan_sort, "Channel sorting", 0);
*/
static int32_t decode_rice(GetBitContext *gb, unsigned int k)
{
- int max = gb->size_in_bits - get_bits_count(gb) - k;
+ int max = get_bits_left(gb) - k;
int q = get_unary(gb, 0, max);
int r = k ? get_bits1(gb) : !(q & 1);
/** Reads the block data for a constant block
*/
-static void read_const_block(ALSDecContext *ctx, int32_t *raw_samples,
- unsigned int block_length, unsigned int *js_blocks)
+static void read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd)
{
ALSSpecificConfig *sconf = &ctx->sconf;
AVCodecContext *avctx = ctx->avctx;
GetBitContext *gb = &ctx->gb;
- int32_t const_val = 0;
- unsigned int const_block, k;
- const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence)
- *js_blocks = get_bits1(gb);
+ bd->const_val = 0;
+ bd->const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence)
+ bd->js_blocks = get_bits1(gb);
// skip 5 reserved bits
skip_bits(gb, 5);
- if (const_block) {
+ if (bd->const_block) {
unsigned int const_val_bits = sconf->floating ? 24 : avctx->bits_per_raw_sample;
- const_val = get_sbits_long(gb, const_val_bits);
+ bd->const_val = get_sbits_long(gb, const_val_bits);
}
+ // ensure constant block decoding by reusing this field
+ bd->const_block = 1;
+}
+
+
+/** Decodes the block data for a constant block
+ */
+static void decode_const_block_data(ALSDecContext *ctx, ALSBlockData *bd)
+{
+ int smp = bd->block_length;
+ int32_t val = bd->const_val;
+ int32_t *dst = bd->raw_samples;
+
// write raw samples into buffer
- for (k = 0; k < block_length; k++)
- raw_samples[k] = const_val;
+ for (; smp; smp--)
+ *dst++ = val;
}
/** Reads the block data for a non-constant block
*/
-static int read_var_block(ALSDecContext *ctx, unsigned int ra_block,
- int32_t *raw_samples, unsigned int block_length,
- unsigned int *js_blocks, int32_t *raw_other,
- unsigned int *shift_lsbs)
+static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
{
ALSSpecificConfig *sconf = &ctx->sconf;
AVCodecContext *avctx = ctx->avctx;
unsigned int k;
unsigned int s[8];
unsigned int sub_blocks, log2_sub_blocks, sb_length;
- unsigned int opt_order = 1;
- int32_t *quant_cof = ctx->quant_cof;
- int32_t *lpc_cof = ctx->lpc_cof;
unsigned int start = 0;
- int smp = 0;
- int sb, store_prev_samples;
- int64_t y;
+ unsigned int opt_order;
+ int sb;
+ int32_t *quant_cof = bd->quant_cof;
+
- *js_blocks = get_bits1(gb);
+ // ensure variable block decoding by reusing this field
+ bd->const_block = 0;
+
+ bd->opt_order = 1;
+ bd->js_blocks = get_bits1(gb);
+
+ opt_order = bd->opt_order;
// determine the number of subblocks for entropy decoding
if (!sconf->bgmc && !sconf->sb_part) {
// do not continue in case of a damaged stream since
// block_length must be evenly divisible by sub_blocks
- if (block_length & (sub_blocks - 1)) {
+ if (bd->block_length & (sub_blocks - 1)) {
av_log(avctx, AV_LOG_WARNING,
"Block length is not evenly divisible by the number of subblocks.\n");
return -1;
}
- sb_length = block_length >> log2_sub_blocks;
+ sb_length = bd->block_length >> log2_sub_blocks;
if (sconf->bgmc) {
}
if (get_bits1(gb))
- *shift_lsbs = get_bits(gb, 4) + 1;
+ bd->shift_lsbs = get_bits(gb, 4) + 1;
- store_prev_samples = (*js_blocks && raw_other) || *shift_lsbs;
+ bd->store_prev_samples = (bd->js_blocks && bd->raw_other) || bd->shift_lsbs;
if (!sconf->rlslms) {
if (sconf->adapt_order) {
- int opt_order_length = av_ceil_log2(av_clip((block_length >> 3) - 1,
+ int opt_order_length = av_ceil_log2(av_clip((bd->block_length >> 3) - 1,
2, sconf->max_order + 1));
- opt_order = get_bits(gb, opt_order_length);
+ bd->opt_order = get_bits(gb, opt_order_length);
} else {
- opt_order = sconf->max_order;
+ bd->opt_order = sconf->max_order;
}
+ opt_order = bd->opt_order;
+
if (opt_order) {
int add_base;
}
}
- // TODO: LTP mode
+ // read LTP gain and lag values
+ if (sconf->long_term_prediction) {
+ *bd->use_ltp = get_bits1(gb);
+
+ if (*bd->use_ltp) {
+ bd->ltp_gain[0] = decode_rice(gb, 1) << 3;
+ bd->ltp_gain[1] = decode_rice(gb, 2) << 3;
+
+ bd->ltp_gain[2] = ltp_gain_values[get_unary(gb, 0, 4)][get_bits(gb, 2)];
+
+ bd->ltp_gain[3] = decode_rice(gb, 2) << 3;
+ bd->ltp_gain[4] = decode_rice(gb, 1) << 3;
+
+ *bd->ltp_lag = get_bits(gb, ctx->ltp_lag_length);
+ *bd->ltp_lag += FFMAX(4, opt_order + 1);
+ }
+ }
// read first value and residuals in case of a random access block
- if (ra_block) {
+ if (bd->ra_block) {
if (opt_order)
- raw_samples[0] = decode_rice(gb, avctx->bits_per_raw_sample - 4);
+ bd->raw_samples[0] = decode_rice(gb, avctx->bits_per_raw_sample - 4);
if (opt_order > 1)
- raw_samples[1] = decode_rice(gb, s[0] + 3);
+ bd->raw_samples[1] = decode_rice(gb, s[0] + 3);
if (opt_order > 2)
- raw_samples[2] = decode_rice(gb, s[0] + 1);
+ bd->raw_samples[2] = decode_rice(gb, s[0] + 1);
start = FFMIN(opt_order, 3);
}
if (sconf->bgmc) {
// TODO: BGMC mode
} else {
- int32_t *current_res = raw_samples + start;
+ int32_t *current_res = bd->raw_samples + start;
for (sb = 0; sb < sub_blocks; sb++, start = 0)
for (; start < sb_length; start++)
*current_res++ = decode_rice(gb, s[sb]);
}
+ if (!sconf->mc_coding || ctx->js_switch)
+ align_get_bits(gb);
+
+ return 0;
+}
+
+
+/** Decodes the block data for a non-constant block
+ */
+static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
+{
+ ALSSpecificConfig *sconf = &ctx->sconf;
+ unsigned int block_length = bd->block_length;
+ unsigned int smp = 0;
+ unsigned int k;
+ int opt_order = bd->opt_order;
+ int sb;
+ int64_t y;
+ int32_t *quant_cof = bd->quant_cof;
+ int32_t *lpc_cof = bd->lpc_cof;
+ int32_t *raw_samples = bd->raw_samples;
+ int32_t *raw_samples_end = bd->raw_samples + bd->block_length;
+ int32_t *lpc_cof_reversed = ctx->lpc_cof_reversed_buffer;
+
+ // reverse long-term prediction
+ if (*bd->use_ltp) {
+ int ltp_smp;
+
+ for (ltp_smp = FFMAX(*bd->ltp_lag - 2, 0); ltp_smp < block_length; ltp_smp++) {
+ int center = ltp_smp - *bd->ltp_lag;
+ int begin = FFMAX(0, center - 2);
+ int end = center + 3;
+ int tab = 5 - (end - begin);
+ int base;
+
+ y = 1 << 6;
+
+ for (base = begin; base < end; base++, tab++)
+ y += MUL64(bd->ltp_gain[tab], raw_samples[base]);
+
+ raw_samples[ltp_smp] += y >> 7;
+ }
+ }
+
// reconstruct all samples from residuals
- if (ra_block) {
+ if (bd->ra_block) {
for (smp = 0; smp < opt_order; smp++) {
y = 1 << 19;
for (sb = 0; sb < smp; sb++)
- y += MUL64(lpc_cof[sb],raw_samples[smp - (sb + 1)]);
+ y += MUL64(lpc_cof[sb], raw_samples[-(sb + 1)]);
- raw_samples[smp] -= y >> 20;
+ *raw_samples++ -= y >> 20;
parcor_to_lpc(smp, quant_cof, lpc_cof);
}
} else {
parcor_to_lpc(k, quant_cof, lpc_cof);
// store previous samples in case that they have to be altered
- if (store_prev_samples)
- memcpy(ctx->prev_raw_samples, raw_samples - sconf->max_order,
- sizeof(*ctx->prev_raw_samples) * sconf->max_order);
+ if (bd->store_prev_samples)
+ memcpy(bd->prev_raw_samples, raw_samples - sconf->max_order,
+ sizeof(*bd->prev_raw_samples) * sconf->max_order);
// reconstruct difference signal for prediction (joint-stereo)
- if (*js_blocks && raw_other) {
+ if (bd->js_blocks && bd->raw_other) {
int32_t *left, *right;
- if (raw_other > raw_samples) { // D = R - L
+ if (bd->raw_other > raw_samples) { // D = R - L
left = raw_samples;
- right = raw_other;
+ right = bd->raw_other;
} else { // D = R - L
- left = raw_other;
+ left = bd->raw_other;
right = raw_samples;
}
}
// reconstruct shifted signal
- if (*shift_lsbs)
+ if (bd->shift_lsbs)
for (sb = -1; sb >= -sconf->max_order; sb--)
- raw_samples[sb] >>= *shift_lsbs;
+ raw_samples[sb] >>= bd->shift_lsbs;
}
+ // reverse linear prediction coefficients for efficiency
+ lpc_cof = lpc_cof + opt_order;
+
+ for (sb = 0; sb < opt_order; sb++)
+ lpc_cof_reversed[sb] = lpc_cof[-(sb + 1)];
+
// reconstruct raw samples
- for (; smp < block_length; smp++) {
+ raw_samples = bd->raw_samples + smp;
+ lpc_cof = lpc_cof_reversed + opt_order;
+
+ for (; raw_samples < raw_samples_end; raw_samples++) {
y = 1 << 19;
- for (sb = 0; sb < opt_order; sb++)
- y += MUL64(lpc_cof[sb],raw_samples[smp - (sb + 1)]);
+ for (sb = -opt_order; sb < 0; sb++)
+ y += MUL64(lpc_cof[sb], raw_samples[sb]);
- raw_samples[smp] -= y >> 20;
+ *raw_samples -= y >> 20;
}
+ raw_samples = bd->raw_samples;
+
// restore previous samples in case that they have been altered
- if (store_prev_samples)
- memcpy(raw_samples - sconf->max_order, ctx->prev_raw_samples,
+ if (bd->store_prev_samples)
+ memcpy(raw_samples - sconf->max_order, bd->prev_raw_samples,
sizeof(*raw_samples) * sconf->max_order);
return 0;
/** Reads the block data.
*/
-static int read_block_data(ALSDecContext *ctx, unsigned int ra_block,
- int32_t *raw_samples, unsigned int block_length,
- unsigned int *js_blocks, int32_t *raw_other)
+static int read_block(ALSDecContext *ctx, ALSBlockData *bd)
{
- ALSSpecificConfig *sconf = &ctx->sconf;
GetBitContext *gb = &ctx->gb;
- unsigned int shift_lsbs = 0;
- unsigned int k;
// read block type flag and read the samples accordingly
if (get_bits1(gb)) {
- if (read_var_block(ctx, ra_block, raw_samples, block_length, js_blocks,
- raw_other, &shift_lsbs))
+ if (read_var_block_data(ctx, bd))
return -1;
} else {
- read_const_block(ctx, raw_samples, block_length, js_blocks);
+ read_const_block_data(ctx, bd);
}
- // TODO: read RLSLMS extension data
+ return 0;
+}
- if (!sconf->mc_coding || ctx->js_switch)
- align_get_bits(gb);
- if (shift_lsbs)
- for (k = 0; k < block_length; k++)
- raw_samples[k] <<= shift_lsbs;
+/** Decodes the block data.
+ */
+static int decode_block(ALSDecContext *ctx, ALSBlockData *bd)
+{
+ unsigned int smp;
+
+ // read block type flag and read the samples accordingly
+ if (bd->const_block)
+ decode_const_block_data(ctx, bd);
+ else if (decode_var_block_data(ctx, bd))
+ return -1;
+
+ // TODO: read RLSLMS extension data
+
+ if (bd->shift_lsbs)
+ for (smp = 0; smp < bd->block_length; smp++)
+ bd->raw_samples[smp] <<= bd->shift_lsbs;
return 0;
}
+/** Reads and decodes block data successively.
+ */
+static int read_decode_block(ALSDecContext *ctx, ALSBlockData *bd)
+{
+ int ret;
+
+ ret = read_block(ctx, bd);
+
+ if (ret)
+ return ret;
+
+ ret = decode_block(ctx, bd);
+
+ return ret;
+}
+
+
/** Computes the number of samples left to decode for the current frame and
* sets these samples to zero.
*/
unsigned int c, const unsigned int *div_blocks,
unsigned int *js_blocks)
{
- int32_t *raw_sample;
unsigned int b;
- raw_sample = ctx->raw_samples[c];
+ ALSBlockData bd;
+
+ memset(&bd, 0, sizeof(ALSBlockData));
+
+ bd.ra_block = ra_frame;
+ bd.use_ltp = ctx->use_ltp;
+ bd.ltp_lag = ctx->ltp_lag;
+ bd.ltp_gain = ctx->ltp_gain[0];
+ bd.quant_cof = ctx->quant_cof[0];
+ bd.lpc_cof = ctx->lpc_cof[0];
+ bd.prev_raw_samples = ctx->prev_raw_samples;
+ bd.raw_samples = ctx->raw_samples[c];
+
for (b = 0; b < ctx->num_blocks; b++) {
- if (read_block_data(ctx, ra_frame, raw_sample,
- div_blocks[b], &js_blocks[0], NULL)) {
+ bd.shift_lsbs = 0;
+ bd.block_length = div_blocks[b];
+
+ if (read_decode_block(ctx, &bd)) {
// damaged block, write zero for the rest of the frame
- zero_remaining(b, ctx->num_blocks, div_blocks, raw_sample);
+ zero_remaining(b, ctx->num_blocks, div_blocks, bd.raw_samples);
return -1;
}
- raw_sample += div_blocks[b];
- ra_frame = 0;
+ bd.raw_samples += div_blocks[b];
+ bd.ra_block = 0;
}
return 0;
{
ALSSpecificConfig *sconf = &ctx->sconf;
unsigned int offset = 0;
- int32_t *raw_samples_R;
- int32_t *raw_samples_L;
unsigned int b;
+ ALSBlockData bd[2];
+
+ memset(bd, 0, 2 * sizeof(ALSBlockData));
+
+ bd[0].ra_block = ra_frame;
+ bd[0].use_ltp = ctx->use_ltp;
+ bd[0].ltp_lag = ctx->ltp_lag;
+ bd[0].ltp_gain = ctx->ltp_gain[0];
+ bd[0].quant_cof = ctx->quant_cof[0];
+ bd[0].lpc_cof = ctx->lpc_cof[0];
+ bd[0].prev_raw_samples = ctx->prev_raw_samples;
+ bd[0].js_blocks = *js_blocks;
+
+ bd[1].ra_block = ra_frame;
+ bd[1].use_ltp = ctx->use_ltp;
+ bd[1].ltp_lag = ctx->ltp_lag;
+ bd[1].ltp_gain = ctx->ltp_gain[0];
+ bd[1].quant_cof = ctx->quant_cof[0];
+ bd[1].lpc_cof = ctx->lpc_cof[0];
+ bd[1].prev_raw_samples = ctx->prev_raw_samples;
+ bd[1].js_blocks = *(js_blocks + 1);
// decode all blocks
for (b = 0; b < ctx->num_blocks; b++) {
unsigned int s;
- raw_samples_L = ctx->raw_samples[c ] + offset;
- raw_samples_R = ctx->raw_samples[c + 1] + offset;
- if (read_block_data(ctx, ra_frame, raw_samples_L, div_blocks[b],
- &js_blocks[0], raw_samples_R) ||
- read_block_data(ctx, ra_frame, raw_samples_R, div_blocks[b],
- &js_blocks[1], raw_samples_L)) {
+
+ bd[0].shift_lsbs = 0;
+ bd[1].shift_lsbs = 0;
+
+ bd[0].block_length = div_blocks[b];
+ bd[1].block_length = div_blocks[b];
+
+ bd[0].raw_samples = ctx->raw_samples[c ] + offset;
+ bd[1].raw_samples = ctx->raw_samples[c + 1] + offset;
+
+ bd[0].raw_other = bd[1].raw_samples;
+ bd[1].raw_other = bd[0].raw_samples;
+
+ if(read_decode_block(ctx, &bd[0]) || read_decode_block(ctx, &bd[1])) {
// damaged block, write zero for the rest of the frame
- zero_remaining(b, ctx->num_blocks, div_blocks, raw_samples_L);
- zero_remaining(b, ctx->num_blocks, div_blocks, raw_samples_R);
+ zero_remaining(b, ctx->num_blocks, div_blocks, bd[0].raw_samples);
+ zero_remaining(b, ctx->num_blocks, div_blocks, bd[1].raw_samples);
return -1;
}
// reconstruct joint-stereo blocks
- if (js_blocks[0]) {
- if (js_blocks[1])
+ if (bd[0].js_blocks) {
+ if (bd[1].js_blocks)
av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair!\n");
for (s = 0; s < div_blocks[b]; s++)
- raw_samples_L[s] = raw_samples_R[s] - raw_samples_L[s];
- } else if (js_blocks[1]) {
+ bd[0].raw_samples[s] = bd[1].raw_samples[s] - bd[0].raw_samples[s];
+ } else if (bd[1].js_blocks) {
for (s = 0; s < div_blocks[b]; s++)
- raw_samples_R[s] = raw_samples_R[s] + raw_samples_L[s];
+ bd[1].raw_samples[s] = bd[1].raw_samples[s] + bd[0].raw_samples[s];
}
offset += div_blocks[b];
- ra_frame = 0;
+ bd[0].ra_block = 0;
+ bd[1].ra_block = 0;
}
// store carryover raw samples,
}
+/** Reads the channel data.
+ */
+static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c)
+{
+ GetBitContext *gb = &ctx->gb;
+ ALSChannelData *current = cd;
+ unsigned int channels = ctx->avctx->channels;
+ int entries = 0;
+
+ while (entries < channels && !(current->stop_flag = get_bits1(gb))) {
+ current->master_channel = get_bits_long(gb, av_ceil_log2(channels));
+
+ if (current->master_channel >= channels) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Invalid master channel!\n");
+ return -1;
+ }
+
+ if (current->master_channel != c) {
+ current->time_diff_flag = get_bits1(gb);
+ current->weighting[0] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 32)];
+ current->weighting[1] = mcc_weightings[av_clip(decode_rice(gb, 2) + 14, 0, 32)];
+ current->weighting[2] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 32)];
+
+ if (current->time_diff_flag) {
+ current->weighting[3] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 32)];
+ current->weighting[4] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 32)];
+ current->weighting[5] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 32)];
+
+ current->time_diff_sign = get_bits1(gb);
+ current->time_diff_index = get_bits(gb, ctx->ltp_lag_length - 3) + 3;
+ }
+ }
+
+ current++;
+ entries++;
+ }
+
+ if (entries == channels) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Damaged channel data!\n");
+ return -1;
+ }
+
+ align_get_bits(gb);
+ return 0;
+}
+
+
+/** Recursively reverts the inter-channel correlation for a block.
+ */
+static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd,
+ ALSChannelData **cd, int *reverted,
+ unsigned int offset, int c)
+{
+ ALSChannelData *ch = cd[c];
+ unsigned int dep = 0;
+ unsigned int channels = ctx->avctx->channels;
+
+ if (reverted[c])
+ return 0;
+
+ reverted[c] = 1;
+
+ while (dep < channels && !ch[dep].stop_flag) {
+ revert_channel_correlation(ctx, bd, cd, reverted, offset,
+ ch[dep].master_channel);
+
+ dep++;
+ }
+
+ if (dep == channels) {
+ av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel correlation!\n");
+ return -1;
+ }
+
+ bd->use_ltp = ctx->use_ltp + c;
+ bd->ltp_lag = ctx->ltp_lag + c;
+ bd->ltp_gain = ctx->ltp_gain[c];
+ bd->lpc_cof = ctx->lpc_cof[c];
+ bd->quant_cof = ctx->quant_cof[c];
+ bd->raw_samples = ctx->raw_samples[c] + offset;
+
+ dep = 0;
+ while (!ch[dep].stop_flag) {
+ unsigned int smp;
+ unsigned int begin = 1;
+ unsigned int end = bd->block_length - 1;
+ int64_t y;
+ int32_t *master = ctx->raw_samples[ch[dep].master_channel] + offset;
+
+ if (ch[dep].time_diff_flag) {
+ int t = ch[dep].time_diff_index;
+
+ if (ch[dep].time_diff_sign) {
+ t = -t;
+ begin -= t;
+ } else {
+ end -= t;
+ }
+
+ for (smp = begin; smp < end; smp++) {
+ y = (1 << 6) +
+ MUL64(ch[dep].weighting[0], master[smp - 1 ]) +
+ MUL64(ch[dep].weighting[1], master[smp ]) +
+ MUL64(ch[dep].weighting[2], master[smp + 1 ]) +
+ MUL64(ch[dep].weighting[3], master[smp - 1 + t]) +
+ MUL64(ch[dep].weighting[4], master[smp + t]) +
+ MUL64(ch[dep].weighting[5], master[smp + 1 + t]);
+
+ bd->raw_samples[smp] += y >> 7;
+ }
+ } else {
+ for (smp = begin; smp < end; smp++) {
+ y = (1 << 6) +
+ MUL64(ch[dep].weighting[0], master[smp - 1]) +
+ MUL64(ch[dep].weighting[1], master[smp ]) +
+ MUL64(ch[dep].weighting[2], master[smp + 1]);
+
+ bd->raw_samples[smp] += y >> 7;
+ }
+ }
+
+ dep++;
+ }
+
+ return 0;
+}
+
+
/** Reads the frame data.
*/
static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
sizeof(*ctx->raw_samples[c]) * sconf->max_order);
}
} else { // multi-channel coding
+ ALSBlockData bd;
+ int b;
+ int *reverted_channels = ctx->reverted_channels;
+ unsigned int offset = 0;
+
+ for (c = 0; c < avctx->channels; c++)
+ if (ctx->chan_data[c] < ctx->chan_data_buffer) {
+ av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data!\n");
+ return -1;
+ }
+
+ memset(&bd, 0, sizeof(ALSBlockData));
+ memset(reverted_channels, 0, sizeof(*reverted_channels) * avctx->channels);
+
+ bd.ra_block = ra_frame;
+ bd.prev_raw_samples = ctx->prev_raw_samples;
+
get_block_sizes(ctx, div_blocks, &bs_info);
- // TODO: multi channel coding might use a temporary buffer instead as
- // the actual channel is not known when read_block-data is called
- if (decode_blocks_ind(ctx, ra_frame, 0, div_blocks, js_blocks))
- return -1;
- // TODO: read_channel_data
+ for (b = 0; b < ctx->num_blocks; b++) {
+ bd.shift_lsbs = 0;
+ bd.block_length = div_blocks[b];
+
+ for (c = 0; c < avctx->channels; c++) {
+ bd.use_ltp = ctx->use_ltp + c;
+ bd.ltp_lag = ctx->ltp_lag + c;
+ bd.ltp_gain = ctx->ltp_gain[c];
+ bd.lpc_cof = ctx->lpc_cof[c];
+ bd.quant_cof = ctx->quant_cof[c];
+ bd.raw_samples = ctx->raw_samples[c] + offset;
+ bd.raw_other = NULL;
+
+ read_block(ctx, &bd);
+ if (read_channel_data(ctx, ctx->chan_data[c], c))
+ return -1;
+ }
+
+ for (c = 0; c < avctx->channels; c++)
+ if (revert_channel_correlation(ctx, &bd, ctx->chan_data,
+ reverted_channels, offset, c))
+ return -1;
+
+ for (c = 0; c < avctx->channels; c++) {
+ bd.use_ltp = ctx->use_ltp + c;
+ bd.ltp_lag = ctx->ltp_lag + c;
+ bd.ltp_gain = ctx->ltp_gain[c];
+ bd.lpc_cof = ctx->lpc_cof[c];
+ bd.quant_cof = ctx->quant_cof[c];
+ bd.raw_samples = ctx->raw_samples[c] + offset;
+ decode_block(ctx, &bd);
+ }
+
+ memset(reverted_channels, 0, avctx->channels * sizeof(*reverted_channels));
+ offset += div_blocks[b];
+ bd.ra_block = 0;
+ }
+
+ // store carryover raw samples
+ for (c = 0; c < avctx->channels; c++)
+ memmove(ctx->raw_samples[c] - sconf->max_order,
+ ctx->raw_samples[c] - sconf->max_order + sconf->frame_length,
+ sizeof(*ctx->raw_samples[c]) * sconf->max_order);
}
// TODO: read_diff_float_data
av_freep(&ctx->sconf.chan_pos);
+ av_freep(&ctx->use_ltp);
+ av_freep(&ctx->ltp_lag);
+ av_freep(&ctx->ltp_gain);
+ av_freep(&ctx->ltp_gain_buffer);
av_freep(&ctx->quant_cof);
av_freep(&ctx->lpc_cof);
+ av_freep(&ctx->quant_cof_buffer);
+ av_freep(&ctx->lpc_cof_buffer);
+ av_freep(&ctx->lpc_cof_reversed_buffer);
av_freep(&ctx->prev_raw_samples);
av_freep(&ctx->raw_samples);
av_freep(&ctx->raw_buffer);
+ av_freep(&ctx->chan_data);
+ av_freep(&ctx->chan_data_buffer);
+ av_freep(&ctx->reverted_channels);
return 0;
}
{
unsigned int c;
unsigned int channel_size;
+ int num_buffers;
ALSDecContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
ctx->avctx = avctx;
avctx->bits_per_raw_sample = (sconf->resolution + 1) * 8;
}
+ // set lag value for long-term prediction
+ ctx->ltp_lag_length = 8 + (avctx->sample_rate >= 96000) +
+ (avctx->sample_rate >= 192000);
+
+ // allocate quantized parcor coefficient buffer
+ num_buffers = sconf->mc_coding ? avctx->channels : 1;
+
+ ctx->quant_cof = av_malloc(sizeof(*ctx->quant_cof) * num_buffers);
+ ctx->lpc_cof = av_malloc(sizeof(*ctx->lpc_cof) * num_buffers);
+ ctx->quant_cof_buffer = av_malloc(sizeof(*ctx->quant_cof_buffer) *
+ num_buffers * sconf->max_order);
+ ctx->lpc_cof_buffer = av_malloc(sizeof(*ctx->lpc_cof_buffer) *
+ num_buffers * sconf->max_order);
+ ctx->lpc_cof_reversed_buffer = av_malloc(sizeof(*ctx->lpc_cof_buffer) *
+ sconf->max_order);
+
+ if (!ctx->quant_cof || !ctx->lpc_cof ||
+ !ctx->quant_cof_buffer || !ctx->lpc_cof_buffer ||
+ !ctx->lpc_cof_reversed_buffer) {
+ av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
+ return AVERROR(ENOMEM);
+ }
+
+ // assign quantized parcor coefficient buffers
+ for (c = 0; c < num_buffers; c++) {
+ ctx->quant_cof[c] = ctx->quant_cof_buffer + c * sconf->max_order;
+ ctx->lpc_cof[c] = ctx->lpc_cof_buffer + c * sconf->max_order;
+ }
+
+ // allocate and assign lag and gain data buffer for ltp mode
+ ctx->use_ltp = av_mallocz(sizeof(*ctx->use_ltp) * num_buffers);
+ ctx->ltp_lag = av_malloc (sizeof(*ctx->ltp_lag) * num_buffers);
+ ctx->ltp_gain = av_malloc (sizeof(*ctx->ltp_gain) * num_buffers);
+ ctx->ltp_gain_buffer = av_malloc (sizeof(*ctx->ltp_gain_buffer) *
+ num_buffers * 5);
+
+ if (!ctx->use_ltp || !ctx->ltp_lag ||
+ !ctx->ltp_gain || !ctx->ltp_gain_buffer) {
+ av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
+ decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
+
+ for (c = 0; c < num_buffers; c++)
+ ctx->ltp_gain[c] = ctx->ltp_gain_buffer + c * 5;
+
+ // allocate and assign channel data buffer for mcc mode
+ if (sconf->mc_coding) {
+ ctx->chan_data_buffer = av_malloc(sizeof(*ctx->chan_data_buffer) *
+ num_buffers);
+ ctx->chan_data = av_malloc(sizeof(ALSChannelData) *
+ num_buffers);
+ ctx->reverted_channels = av_malloc(sizeof(*ctx->reverted_channels) *
+ num_buffers);
+
+ if (!ctx->chan_data_buffer || !ctx->chan_data || !ctx->reverted_channels) {
+ av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
+ decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
+
+ for (c = 0; c < num_buffers; c++)
+ ctx->chan_data[c] = ctx->chan_data_buffer + c;
+ } else {
+ ctx->chan_data = NULL;
+ ctx->chan_data_buffer = NULL;
+ ctx->reverted_channels = NULL;
+ }
+
avctx->frame_size = sconf->frame_length;
channel_size = sconf->frame_length + sconf->max_order;