float* coeffs; ///< pointer to the subframe decode buffer
uint16_t num_vec_coeffs; ///< number of vector coded coefficients
DECLARE_ALIGNED(16, float, out)[WMALL_BLOCK_MAX_SIZE + WMALL_BLOCK_MAX_SIZE / 2]; ///< output buffer
+ int transient_counter; ///< number of transient samples from the beginning of transient zone
} WmallChannelCtx;
- /* XXX: probably we don't need subframe_config[],
- WmallChannelCtx holds all the necessary data. */
-
/**
* @brief channel group for channel transformations
*/
int8_t mclms_scaling;
int16_t mclms_coeffs[128];
int16_t mclms_coeffs_cur[4];
- int mclms_prevvalues[64]; // FIXME: should be 32-bit / 16-bit depending on bit-depth
+ int16_t mclms_prevvalues[64]; // FIXME: should be 32-bit / 16-bit depending on bit-depth
int16_t mclms_updates[64];
int mclms_recent;
int coefsend;
int bitsend;
int16_t coefs[256];
- int lms_prevvalues[512]; // FIXME: see above
+ int16_t lms_prevvalues[512]; // FIXME: see above
int16_t lms_updates[512]; // and here too
int recent;
} cdlms[2][9]; /* XXX: Here, 2 is the max. no. of channels allowed,
int lpc_scaling;
int lpc_intbits;
- int channel_coeffs[2][2048];
+ int16_t channel_coeffs[2][2048]; // FIXME: should be 32-bit / 16-bit depending on bit-depth
} WmallDecodeCtx;
static int num_logged_tiles = 0;
+static int num_logged_subframes = 0;
+static int num_lms_update_call = 0;
/**
*@brief helper function to print the most important members of the context
PRINT("num channels", s->num_channels);
}
+static void dump_int_buffer(uint8_t *buffer, int size, int length, int delimiter)
+{
+ int i;
+
+ for (i=0 ; i<length ; i++) {
+ if (!(i%delimiter))
+ av_log(0, 0, "\n[%d] ", i);
+ av_log(0, 0, "%d, ", *(int16_t *)(buffer + i * size));
+ }
+ av_log(0, 0, "\n");
+
+}
+
/**
*@brief Uninitialize the decoder and free all resources.
*@param avctx codec context
if (offset == s->samples_per_frame - s->min_samples_per_subframe)
return s->min_samples_per_subframe;
- len = av_log2(s->max_num_subframes - 1) + 1; // XXX: 5.3.3
- frame_len_ratio = get_bits(&s->gb, len); // XXX: tile_size_ratio
+ len = av_log2(s->max_num_subframes - 1) + 1;
+ frame_len_ratio = get_bits(&s->gb, len);
subframe_len = s->min_samples_per_subframe * (frame_len_ratio + 1);
*@param s context
*@return 0 on success, < 0 in case of an error
*/
-static int decode_tilehdr(WmallDecodeCtx *s) /* XXX: decode_tile_configuration() [Table 9] */
+static int decode_tilehdr(WmallDecodeCtx *s)
{
uint16_t num_samples[WMALL_MAX_CHANNELS]; /**< sum of samples for all currently known subframes of a channel */
uint8_t contains_subframe[WMALL_MAX_CHANNELS]; /**< flag indicating if a channel contains the current subframe */
memset(num_samples, 0, sizeof(num_samples));
- if (s->max_num_subframes == 1 || get_bits1(&s->gb)) // XXX: locate in the spec
- fixed_channel_layout = 1; // XXX: tile_aligned ?
+ if (s->max_num_subframes == 1 || get_bits1(&s->gb))
+ fixed_channel_layout = 1;
/** loop until the frame data is split between the subframes */
do {
contains_subframe[c] = 1;
}
else {
- contains_subframe[c] = get_bits1(&s->gb); // XXX: locate in the spec
+ contains_subframe[c] = get_bits1(&s->gb);
}
} else
contains_subframe[c] = 0;
}
/** get subframe length, subframe_len == 0 is not allowed */
- if ((subframe_len = decode_subframe_length(s, min_channel_len)) <= 0) //XXX: this reads tile_size_ratio
+ if ((subframe_len = decode_subframe_length(s, min_channel_len)) <= 0)
return AVERROR_INVALIDDATA;
/** add subframes to the individual channels and find new min_channel_len */
min_channel_len += subframe_len;
int i = 0;
unsigned int ave_mean;
s->transient[ch] = get_bits1(&s->gb);
- if(s->transient[ch])
- s->transient_pos[ch] = get_bits(&s->gb, av_log2(tile_size));
+ if(s->transient[ch]) {
+ s->transient_pos[ch] = get_bits(&s->gb, av_log2(tile_size));
+ if (s->transient_pos[ch])
+ s->transient[ch] = 0;
+ s->channel[ch].transient_counter =
+ FFMAX(s->channel[ch].transient_counter, s->samples_per_frame / 2);
+ } else if (s->channel[ch].transient_counter)
+ s->transient[ch] = 1;
if(s->seekable_tile) {
ave_mean = get_bits(&s->gb, s->bits_per_sample);
s->channel_residues[ch][0] = get_sbits(&s->gb, s->bits_per_sample);
i++;
}
- av_log(0, 0, "%8d: ", num_logged_tiles++);
+ //av_log(0, 0, "%8d: ", num_logged_tiles++);
for(; i < tile_size; i++) {
int quo = 0, rem, rem_bits, residue;
while(get_bits1(&s->gb))
else
residue = residue >> 1;
s->channel_residues[ch][i] = residue;
-
- //if (num_logged_tiles < 1)
- av_log(0, 0, "%4d ", residue);
-// dprintf(s->avctx, "%5d: %5d %10d %12d %12d %5d %-16d %04x\n",i, quo, ave_mean, s->ave_sum[ch], rem, rem_bits, s->channel_residues[ch][i], show_bits(&s->gb, 16));
}
- av_log(0, 0, "\n Tile size = %d\n", tile_size);
+ dump_int_buffer(s->channel_residues[ch], 4, tile_size, 16);
return 0;
for (ich = 0; ich < s->num_channels; ich++) {
for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++) {
memset(s->cdlms[ich][ilms].coefs , 0, 256 * sizeof(int16_t));
- memset(s->cdlms[ich][ilms].lms_prevvalues, 0, 512 * sizeof(int));
+ memset(s->cdlms[ich][ilms].lms_prevvalues, 0, 512 * sizeof(int16_t));
memset(s->cdlms[ich][ilms].lms_updates , 0, 512 * sizeof(int16_t));
}
s->ave_sum[ich] = 0;
}
}
+/**
+ *@brief Resets filter parameters and transient area at new seekable tile
+ */
static void reset_codec(WmallDecodeCtx *s)
{
int ich, ilms;
s->mclms_recent = s->mclms_order * s->num_channels;
- for (ich = 0; ich < s->num_channels; ich++)
+ for (ich = 0; ich < s->num_channels; ich++) {
for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++)
s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order;
+ /* first sample of a seekable subframe is considered as the starting of
+ a transient area which is samples_per_frame samples long */
+ s->channel[ich].transient_counter = s->samples_per_frame;
+ s->transient[ich] = 1;
+ s->transient_pos[ich] = 0;
+ }
}
+static void mclms_update(WmallDecodeCtx *s, int icoef)
+{
+ int i, j, ich;
+ int16_t pred_error;
+ int order = s->mclms_order;
+ int num_channels = s->num_channels;
+ int16_t range = 1 << (s->bits_per_sample - 1);
+ int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample
+
+ for (ich = 0; ich < num_channels; ich++) {
+ pred_error = s->channel_coeffs[ich][icoef] -
+ s->channel_residues[ich][icoef];
+ if (pred_error > 0) {
+ for (i = 0; i < order * num_channels; i++)
+ s->mclms_coeffs[i + ich * order * num_channels] +=
+ s->mclms_updates[s->mclms_recent + i];
+ for (j = 0; j < i; j++) {
+ if (s->channel_coeffs[ich][icoef] > 0)
+ s->mclms_coeffs_cur[ich * num_channels + j] += 1;
+ else if (s->channel_coeffs[ich][icoef] < 0)
+ s->mclms_coeffs_cur[ich * num_channels + j] -= 1;
+ }
+ } else if (pred_error < 0) {
+ for (i = 0; i < order * num_channels; i++)
+ s->mclms_coeffs[i + ich * order * num_channels] -=
+ s->mclms_updates[s->mclms_recent + i];
+ for (j = 0; j < i; j++) {
+ if (s->channel_coeffs[ich][icoef] > 0)
+ s->mclms_coeffs_cur[ich * num_channels + j] -= 1;
+ else if (s->channel_coeffs[ich][icoef] < 0)
+ s->mclms_coeffs_cur[ich * num_channels + j] += 1;
+ }
+ }
+ }
+
+ for (ich = num_channels - 1; ich >= 0; ich--) {
+ s->mclms_recent--;
+ if (s->channel_coeffs[ich][icoef] > range - 1)
+ s->mclms_prevvalues[s->mclms_recent] = range - 1;
+ else if (s->channel_coeffs[ich][icoef] <= -range)
+ s->mclms_prevvalues[s->mclms_recent] = -range;
+
+ s->mclms_updates[s->mclms_recent] =
+ av_clip(-1, s->channel_coeffs[ich][icoef], 1);
+ }
+
+ if (s->mclms_recent == 0) {
+ memcpy(&s->mclms_prevvalues[order * num_channels],
+ s->mclms_prevvalues,
+ bps * order * num_channels);
+ memcpy(&s->mclms_updates[order * num_channels],
+ s->mclms_updates,
+ bps * order * num_channels);
+ s->mclms_recent = num_channels * order;
+ }
+}
+static void mclms_predict(WmallDecodeCtx *s, int icoef)
+{
+ int ich, i;
+ int16_t pred;
+ int order = s->mclms_order;
+ int num_channels = s->num_channels;
+
+ for (ich = 0; ich < num_channels; ich++) {
+ if (!s->is_channel_coded[ich])
+ continue;
+ pred = 0;
+ for (i = 0; i < order * num_channels; i++)
+ pred += s->mclms_prevvalues[i] *
+ s->mclms_coeffs[i + order * num_channels * ich];
+ for (i = 0; i < ich; i++)
+ pred += s->channel_coeffs[ich][icoef] *
+ s->mclms_coeffs_cur[i + order * num_channels * ich];
+ s->channel_coeffs[ich][icoef] =
+ s->channel_residues[ich][icoef] + pred;
+ }
+}
+
+static void revert_mclms(WmallDecodeCtx *s, int tile_size)
+{
+ int icoef;
+ for (icoef = 0; icoef < tile_size; icoef++) {
+ mclms_predict(s, icoef);
+ mclms_update(s, icoef);
+ }
+}
+
static int lms_predict(WmallDecodeCtx *s, int ich, int ilms)
{
- int32_t pred, icoef;
+ int pred = 0;
+ int icoef;
int recent = s->cdlms[ich][ilms].recent;
for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
pred += s->cdlms[ich][ilms].coefs[icoef] *
s->cdlms[ich][ilms].lms_prevvalues[icoef + recent];
- pred += (1 << (s->cdlms[ich][ilms].scaling - 1));
+ //pred += (1 << (s->cdlms[ich][ilms].scaling - 1));
/* XXX: Table 29 has:
iPred >= cdlms[iCh][ilms].scaling;
seems to me like a missing > */
- pred >>= s->cdlms[ich][ilms].scaling;
+ //pred >>= s->cdlms[ich][ilms].scaling;
return pred;
}
-static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int32_t input, int32_t pred)
+static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input, int residue)
{
int icoef;
int recent = s->cdlms[ich][ilms].recent;
- int range = 1 << (s->bits_per_sample - 1);
+ int range = 1 << s->bits_per_sample - 1;
int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample
- if (input > pred) {
+ if (residue < 0) {
for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
- s->cdlms[ich][ilms].coefs[icoef] +=
+ s->cdlms[ich][ilms].coefs[icoef] -=
s->cdlms[ich][ilms].lms_updates[icoef + recent];
- } else {
+ } else if (residue > 0) {
for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
- s->cdlms[ich][ilms].coefs[icoef] -=
- s->cdlms[ich][ilms].lms_updates[icoef]; // XXX: [icoef + recent] ?
+ s->cdlms[ich][ilms].coefs[icoef] +=
+ s->cdlms[ich][ilms].lms_updates[icoef + recent]; /* spec mistakenly
+ dropped the recent */
}
- s->cdlms[ich][ilms].recent--;
- s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1);
- if (input > pred)
- s->cdlms[ich][ilms].lms_updates[recent] = s->update_speed[ich];
- else if (input < pred)
+ if (recent)
+ recent--;
+ else {
+ /* XXX: This memcpy()s will probably fail if a fixed 32-bit buffer is used.
+ follow kshishkov's suggestion of using a union. */
+ memcpy(&s->cdlms[ich][ilms].lms_prevvalues[s->cdlms[ich][ilms].order],
+ s->cdlms[ich][ilms].lms_prevvalues,
+ bps * s->cdlms[ich][ilms].order);
+ memcpy(&s->cdlms[ich][ilms].lms_updates[s->cdlms[ich][ilms].order],
+ s->cdlms[ich][ilms].lms_updates,
+ bps * s->cdlms[ich][ilms].order);
+ recent = s->cdlms[ich][ilms].order - 1;
+ }
+
+ s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1);
+ if (!input)
+ s->cdlms[ich][ilms].lms_updates[recent] = 0;
+ else if (input < 0)
s->cdlms[ich][ilms].lms_updates[recent] = -s->update_speed[ich];
+ else
+ s->cdlms[ich][ilms].lms_updates[recent] = s->update_speed[ich];
/* XXX: spec says:
cdlms[iCh][ilms].updates[iRecent + cdlms[iCh][ilms].order >> 4] >>= 2;
seperate buffers? Here I've assumed that the two are same which makes
more sense to me.
*/
- s->cdlms[ich][ilms].lms_updates[recent + s->cdlms[ich][ilms].order >> 4] >>= 2;
- s->cdlms[ich][ilms].lms_updates[recent + s->cdlms[ich][ilms].order >> 3] >>= 1;
- /* XXX: recent + (s->cdlms[ich][ilms].order >> 4) ? */
-
- if (s->cdlms[ich][ilms].recent == 0) {
- /* XXX: This memcpy()s will probably fail if a fixed 32-bit buffer is used.
- follow kshishkov's suggestion of using a union. */
- memcpy(s->cdlms[ich][ilms].lms_prevvalues + s->cdlms[ich][ilms].order,
- s->cdlms[ich][ilms].lms_prevvalues,
- bps * s->cdlms[ich][ilms].order);
- memcpy(s->cdlms[ich][ilms].lms_updates + s->cdlms[ich][ilms].order,
- s->cdlms[ich][ilms].lms_updates,
- bps * s->cdlms[ich][ilms].order);
- s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order;
- }
+ s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 4)] >>= 2;
+ s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 3)] >>= 1;
+ s->cdlms[ich][ilms].recent = recent;
}
static void use_high_update_speed(WmallDecodeCtx *s, int ich)
{
int ilms, recent, icoef;
s->update_speed[ich] = 16;
- for (ilms = s->cdlms_ttl[ich]; ilms >= 0; ilms--) {
+ for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) {
recent = s->cdlms[ich][ilms].recent;
if (s->bV3RTM) {
for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
{
int ilms, recent, icoef;
s->update_speed[ich] = 8;
- for (ilms = s->cdlms_ttl[ich]; ilms >= 0; ilms--) {
+ for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) {
recent = s->cdlms[ich][ilms].recent;
if (s->bV3RTM) {
for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++)
}
}
+static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end)
+{
+ int icoef;
+ int pred;
+ int ilms, num_lms;
+ int residue, input;
+
+ num_lms = s->cdlms_ttl[ch];
+ for (ilms = num_lms - 1; ilms >= 0; ilms--) {
+ //s->cdlms[ch][ilms].recent = s->cdlms[ch][ilms].order;
+ for (icoef = coef_begin; icoef < coef_end; icoef++) {
+ pred = 1 << (s->cdlms[ch][ilms].scaling - 1);
+ residue = s->channel_residues[ch][icoef];
+ pred += lms_predict(s, ch, ilms);
+ input = residue + (pred >> s->cdlms[ch][ilms].scaling);
+ lms_update(s, ch, ilms, input, residue);
+ s->channel_residues[ch][icoef] = input;
+ }
+ }
+}
+
+
+
/**
*@brief Decode a single subframe (block).
*@param s codec context
}
} else {
for(i = 0; i < s->num_channels; i++)
- if(s->is_channel_coded[i])
- decode_channel_residues(s, i, subframe_len);
+ if(s->is_channel_coded[i]) {
+ decode_channel_residues(s, i, subframe_len);
+ if (s->seekable_tile)
+ use_high_update_speed(s, i);
+ else
+ use_normal_update_speed(s, i);
+ revert_cdlms(s, i, 0, subframe_len);
+ }
}
/** handled one subframe */
av_log(s->avctx, AV_LOG_ERROR, "broken subframe\n");
return AVERROR_INVALIDDATA;
}
- ++s->channel[c].cur_subframe; // XXX: 6.4
+ ++s->channel[c].cur_subframe;
}
+ num_logged_subframes++;
return 0;
}
/** get frame length */
if (s->len_prefix)
- len = get_bits(gb, s->log2_frame_size); // XXX: compressed_frame_size_bits [Table 8]
+ len = get_bits(gb, s->log2_frame_size);
/** decode tile information */
- if (decode_tilehdr(s)) { // should include decode_tile_configuration() [Table 9]
+ if (decode_tilehdr(s)) {
s->packet_loss = 1;
return 0;
}
/** read drc info */
if (s->dynamic_range_compression) {
- s->drc_gain = get_bits(gb, 8); // XXX: drc_frame_scale_factor [Table 8]
+ s->drc_gain = get_bits(gb, 8);
}
/** no idea what these are for, might be the number of samples