| @@ -776,11 +776,12 @@ static void reset_codec(WmallDecodeCtx *s) | |||||
| s->mclms_recent = s->mclms_order * s->num_channels; | 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++) | for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++) | ||||
| s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order - 1; | |||||
| s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order; | |||||
| /* first sample of a seekable subframe is considered as the starting of | /* first sample of a seekable subframe is considered as the starting of | ||||
| a transient area which is samples_per_frame samples long */ | a transient area which is samples_per_frame samples long */ | ||||
| s->channel[ich].transient_counter = s->samples_per_frame; | s->channel[ich].transient_counter = s->samples_per_frame; | ||||
| s->transient[ich] = 1; | s->transient[ich] = 1; | ||||
| s->transient_pos[ich] = 0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -875,7 +876,7 @@ static void revert_mclms(WmallDecodeCtx *s, int tile_size) | |||||
| static int lms_predict(WmallDecodeCtx *s, int ich, int ilms) | static int lms_predict(WmallDecodeCtx *s, int ich, int ilms) | ||||
| { | { | ||||
| int16_t pred = 0; | |||||
| int pred = 0; | |||||
| int icoef; | int icoef; | ||||
| int recent = s->cdlms[ich][ilms].recent; | int recent = s->cdlms[ich][ilms].recent; | ||||
| @@ -883,39 +884,53 @@ static int lms_predict(WmallDecodeCtx *s, int ich, int ilms) | |||||
| pred += s->cdlms[ich][ilms].coefs[icoef] * | pred += s->cdlms[ich][ilms].coefs[icoef] * | ||||
| s->cdlms[ich][ilms].lms_prevvalues[icoef + recent]; | 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: | /* XXX: Table 29 has: | ||||
| iPred >= cdlms[iCh][ilms].scaling; | iPred >= cdlms[iCh][ilms].scaling; | ||||
| seems to me like a missing > */ | seems to me like a missing > */ | ||||
| pred >>= s->cdlms[ich][ilms].scaling; | |||||
| //pred >>= s->cdlms[ich][ilms].scaling; | |||||
| return pred; | return pred; | ||||
| } | } | ||||
| static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int16_t residue, int16_t pred) | |||||
| static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input, int residue) | |||||
| { | { | ||||
| int16_t icoef; | |||||
| int icoef; | |||||
| int recent = s->cdlms[ich][ilms].recent; | int recent = s->cdlms[ich][ilms].recent; | ||||
| int16_t range = (1 << s->bits_per_sample - 1) - 1; | |||||
| int range = 1 << s->bits_per_sample - 1; | |||||
| int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample | int bps = s->bits_per_sample > 16 ? 4 : 2; // bytes per sample | ||||
| int16_t input = residue + pred; | |||||
| if (residue > 0) { | |||||
| if (residue < 0) { | |||||
| for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) | 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]; | s->cdlms[ich][ilms].lms_updates[icoef + recent]; | ||||
| } else { | |||||
| } else if (residue > 0) { | |||||
| for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) | 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]; /* spec mistakenly | s->cdlms[ich][ilms].lms_updates[icoef + recent]; /* spec mistakenly | ||||
| dropped the recent */ | 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]; | 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: | /* XXX: spec says: | ||||
| cdlms[iCh][ilms].updates[iRecent + cdlms[iCh][ilms].order >> 4] >>= 2; | cdlms[iCh][ilms].updates[iRecent + cdlms[iCh][ilms].order >> 4] >>= 2; | ||||
| @@ -925,21 +940,9 @@ static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int16_t residue, in | |||||
| seperate buffers? Here I've assumed that the two are same which makes | seperate buffers? Here I've assumed that the two are same which makes | ||||
| more sense to me. | 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) | static void use_high_update_speed(WmallDecodeCtx *s, int ich) | ||||
| @@ -974,33 +977,23 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich) | |||||
| } | } | ||||
| } | } | ||||
| static void revert_cdlms(WmallDecodeCtx *s, int tile_size) | |||||
| static void revert_cdlms(WmallDecodeCtx *s, int ch, int coef_begin, int coef_end) | |||||
| { | { | ||||
| int icoef, ich; | |||||
| int16_t pred, channel_coeff; | |||||
| int icoef; | |||||
| int pred; | |||||
| int ilms, num_lms; | int ilms, num_lms; | ||||
| for (ich = 0; ich < s->num_channels; ich++) { | |||||
| if (!s->is_channel_coded[ich]) | |||||
| continue; | |||||
| num_lms = s->cdlms_ttl[ich]; | |||||
| for (icoef = 0; icoef < tile_size; icoef++) { | |||||
| channel_coeff = s->channel_residues[ich][icoef]; | |||||
| if (icoef == s->transient_pos[ich]) { | |||||
| s->transient[ich] = 1; | |||||
| use_high_update_speed(s, ich); | |||||
| } | |||||
| for (ilms = num_lms - 1; ilms >= 0; ilms--) { | |||||
| pred = lms_predict(s, ich, ilms); | |||||
| lms_update(s, ich, ilms, channel_coeff, pred); | |||||
| channel_coeff += pred; | |||||
| } | |||||
| if (s->transient[ich]) { | |||||
| --s->channel[ich].transient_counter; | |||||
| if(!s->channel[ich].transient_counter) | |||||
| use_normal_update_speed(s, ich); | |||||
| } | |||||
| s->channel_coeffs[ich][icoef] = channel_coeff; | |||||
| 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; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1130,10 +1123,15 @@ static int decode_subframe(WmallDecodeCtx *s) | |||||
| } | } | ||||
| } else { | } else { | ||||
| for(i = 0; i < s->num_channels; i++) | 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); | |||||
| } | |||||
| } | } | ||||
| revert_cdlms(s, subframe_len); | |||||
| /** handled one subframe */ | /** handled one subframe */ | ||||