[FFmpeg-devel] [PATCH] Make ff_lpc_calc_coefs order estimation?flexible by passing parameters
Michael Niedermayer
michaelni
Sun Aug 17 05:10:39 CEST 2008
On Sat, Aug 16, 2008 at 08:29:34PM -0400, Justin Ruggles wrote:
> Justin Ruggles wrote:
> > Michael Niedermayer wrote:
> >> On Sun, Aug 17, 2008 at 02:10:28AM +0530, Jai Menon wrote:
> >>> Hi,
> >>>
> >>> On Sunday 17 Aug 2008 1:38:51 am Michael Niedermayer wrote:
> >>>> On Sun, Aug 17, 2008 at 01:21:52AM +0530, Jai Menon wrote:
> >>>>> Hi,
> >>>>>
> >>>>> On Sunday 17 Aug 2008 12:42:33 am Jai Menon wrote:
> >>>>>> Hi,
> >>>>>>
> >>>>>> On Sunday 17 Aug 2008 12:36:54 am Jai Menon wrote:
> >>>>>>> Hi,
> >>>>>>>
> >>>>>>> Attached patch allows for order estimation to be varied based on
> >>>>>>> external parameters.
> >>>>>> This will allow for order estimation between a specific range or
> >>>>>> interval, particularly useful for the alac encoder.
> >>>>> Again, based on Ramiro's advice, a more detailed incremental patchset.
> >>>> [...]
> >>>>
> >>>>> @@ -195,10 +195,20 @@ int ff_lpc_calc_coefs(DSPContext *s,
> >>>>> i = opt_order-1;
> >>>>> quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i],
> >>>>> max_shift, zero_shift); } else {
> >>>>> + if(omethod == ORDER_METHOD_RANGE) {
> >>>>> + int i = opt_order = param_list[0];
> >>>>> + while(i < param_list[1]) {
> >>>>> + if(ref[i] > ref[opt_order-1])
> >>>>> + opt_order = i + 1;
> >>>>> + i++;
> >>>>> + }
> >>>>> + quantize_lpc_coefs(lpc[opt_order-1], opt_order, precision,
> >>>>> coefs[opt_order-1], &shift[opt_order-1], max_shift, zero_shift); +
> >>>>> } else {
> >>>>> for(i=0; i<max_order; i++) {
> >>>>> quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i],
> >>>>> &shift[i], max_shift, zero_shift); }
> >>>>> }
> >>>>> + }
> >>>>>
> >>>>> return opt_order;
> >>>>> }
> >>>> As the current omethods (If i understand the code correctly) are not
> >>>> limiting their search range. This is a bug, and it can either be fixed or
> >>>> left but i will not accept the addition of a new omethod because the
> >>>> existing ones are buggy.
> >>>>
> >>>> Besides max_order is passed as parameter already and we do not need a
> >>>> opaque parameter list, that is the addition of such list is rejected.
> >>>>
> >>> So should I just hardcode the selection among 4th and 6th orders (based on
> >>> reflection coeffs) in a new order method solely for alac?
> >> First please explain me again what exactly in lpc_calc_coefs is slowing your
> >> code down when you use omethod != ORDER_METHOD_EST?
> >>
> >> is it quantize_lpc_coefs() ?
> >>
> >> if yes (and you really checked this instead of guessing) then
> >> you can add a min_order and use ORDER_METHOD_2LEVEL with appropriate changes
> >> to lpc_calc_coefs()
> >> I just cannot belive that quantize_lpc_coefs() really makes a big difference ...
> >
> > ORDER_METHOD_EST was tuned for FLAC, so it may not be good for other codecs.
> >
> > I think it might be cleaner to share quantize_lpc_coefs() separately.
> >
> > ff_lpc_calc_coefs() would do either levinson-durbin or cholesky
> > depending on avctx->use_lpc, and it would output lpc and reflection
> > coeffs as doubles.
> >
> > ff_lpc_quantize_coefs() could be a function which quantizes coeffs for a
> > range of orders.
> >
> > estimate_best_order() could be shared separately as well if it proves
> > useful for other codecs.
> >
> > This way codecs which just want the coeffs could do their own
> > quantization or order decision. MP4-ALS, for example, quantizes the
> > reflection coeffs and has a bit-exact transformation in the spec to
> > convert to integer lpc coeffs.
>
> patch attached implementing the above.
>
> Although there is not an "all-in-one" function, I think this is a
> cleaner and more flexible solution.
>
> -Justin
>
> Index: libavcodec/lpc.c
> ===================================================================
> --- libavcodec/lpc.c (revision 14797)
> +++ libavcodec/lpc.c (working copy)
> @@ -117,10 +117,13 @@
> *shift = sh;
> }
>
> -static int estimate_best_order(double *ref, int min_order, int max_order)
> +int ff_lpc_estimate_best_order(double *ref, int min_order, int max_order)
> {
> int i, est;
>
> + assert(min_order >= MIN_LPC_ORDER && min_order <= MAX_LPC_ORDER);
> + assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
assert(min_order <= max_order);
assert(min_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
> +
> est = min_order;
> for(i=max_order-1; i>=min_order-1; i--) {
> if(ref[i] > 0.10) {
> @@ -134,18 +137,15 @@
> /**
> * Calculate LPC coefficients for multiple orders
> */
> -int ff_lpc_calc_coefs(DSPContext *s,
> +void ff_lpc_calc_coefs(DSPContext *s,
> const int32_t *samples, int blocksize, int min_order,
> - int max_order, int precision,
> - int32_t coefs[][MAX_LPC_ORDER], int *shift, int use_lpc,
> - int omethod, int max_shift, int zero_shift)
> + int max_order, int use_lpc, double lpc[][MAX_LPC_ORDER],
> + double ref[MAX_LPC_ORDER])
> {
> double autoc[MAX_LPC_ORDER+1];
> - double ref[MAX_LPC_ORDER];
> - double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
> int i, j, pass;
> - int opt_order;
>
> + assert(min_order >= MIN_LPC_ORDER && min_order <= MAX_LPC_ORDER);
> assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
>
> if(use_lpc == 1){
> @@ -189,17 +189,19 @@
> for(i=max_order-1; i>0; i--)
> ref[i] = ref[i-1] - ref[i];
> }
> - opt_order = max_order;
> +}
ok
>
> - if(omethod == ORDER_METHOD_EST) {
> - opt_order = estimate_best_order(ref, min_order, max_order);
> - i = opt_order-1;
> - quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
> - } else {
> +void ff_lpc_quantize_coefs(double lpc[][MAX_LPC_ORDER], int min_order,
> + int max_order, int precision, int max_shift,
> + int zero_shift, int32_t coefs[][MAX_LPC_ORDER],
> + int *shift)
> +{
> + int i;
> +
> + assert(min_order >= MIN_LPC_ORDER && min_order <= MAX_LPC_ORDER);
> + assert(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER);
> +
> for(i=min_order-1; i<max_order; i++) {
> quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift);
> }
> - }
> -
> - return opt_order;
> }
looks like a silly wraper function over a for loop
> Index: libavcodec/lpc.h
> ===================================================================
> --- libavcodec/lpc.h (revision 14797)
> +++ libavcodec/lpc.h (working copy)
> @@ -36,12 +36,50 @@
>
>
> /**
> - * Calculate LPC coefficients for multiple orders
> + * Calculate LPC coefficients for multiple orders.
> + *
> + * @param[in] s DSPContext used for autocorrelation with welch window.
only true for some use_lpc values ...
> + * @param[in] samples input audio samples for a single channel.
> + * @param[in] blocksize number of input samples.
> + * @param[in] min_order lowest LPC order to generate coefficients for.
> + * @param[in] max_order highest LPC order to generate coefficients for.
> + * @param[in] use_lpc determines which LPC algorithm to use.
it should be a enum (or well documented what is what)
> + * @param[out] lpc LPC coefficients for multiple orders.
> + * @param[out] ref reflection coefficients up to \p max_order.
> */
> -int ff_lpc_calc_coefs(DSPContext *s,
> +void ff_lpc_calc_coefs(DSPContext *s,
> const int32_t *samples, int blocksize, int min_order,
> - int max_order, int precision,
> - int32_t coefs[][MAX_LPC_ORDER], int *shift, int use_lpc,
> - int omethod, int max_shift, int zero_shift);
> + int max_order, int use_lpc, double lpc[][MAX_LPC_ORDER],
> + double ref[MAX_LPC_ORDER]);
>
> +/**
> + * Estimate the best LPC order based on the reflection coefficients.
> + * This does a reverse iteration through the coeffs and compares against a
> + * fixed threshold to estimate a good order.
> + *
> + * @param ref reflection coefficients from 0 to \p max_order.
> + * @param min_order lowest LPC order to choose from.
> + * @param max_order highest LPC order to choose from.
> + * @return estimated best LPC order.
> + */
> +int ff_lpc_estimate_best_order(double *ref, int min_order, int max_order);
why not estimate the bits needed to store LPC coeffs & prediction residual?
> +
> +/**
> + * Quantize the LPC coefficients.
> + *
> + * @param[in] lpc floating-point LPC coefficients for multiple orders.
> + * @param[in] min_order lowest LPC order to quantize.
> + * @param[in] max_order highest LPC order to quantize.
> + * @param[in] precision largest number of bits in the quantized coefficients.
> + * @param[in] max_shift largest left-shift value to apply when quantizing coefficients.
> + * @param[in] zero_shift value to set \p shift to when all coefficients
> + * quantize to zero when using \p max_shift.
> + * @param[out] coefs quantized coefficients for multiple orders.
> + * @param[out] shift left-shift which was applied to coefficients during quantization.
> + */
> +void ff_lpc_quantize_coefs(double lpc[][MAX_LPC_ORDER], int min_order,
> + int max_order, int precision, int max_shift,
> + int zero_shift, int32_t coefs[][MAX_LPC_ORDER],
> + int *shift);
> +
scalar quantization of LPC coeffs is not good, some more sane variant should
be tried, like all that are within a small distance from the correct but not
representable vector.
> #endif /* FFMPEG_LPC_H */
> Index: libavcodec/flacenc.c
> ===================================================================
> --- libavcodec/flacenc.c (revision 14797)
> +++ libavcodec/flacenc.c (working copy)
> @@ -795,6 +795,8 @@
> int min_porder, max_porder;
> FlacFrame *frame;
> FlacSubframe *sub;
> + double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
> + double ref[MAX_LPC_ORDER];
> int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER];
> int shift[MAX_LPC_ORDER];
> int32_t *res, *smp;
> @@ -855,10 +857,17 @@
> }
>
> /* LPC */
> - opt_order = ff_lpc_calc_coefs(&ctx->dsp, smp, n, min_order, max_order,
> - precision, coefs, shift, ctx->options.use_lpc,
> - omethod, MAX_LPC_SHIFT, 0);
> + ff_lpc_calc_coefs(&ctx->dsp, smp, n, min_order, max_order,
> + ctx->options.use_lpc, lpc, ref);
>
> + if(omethod == ORDER_METHOD_EST) {
> + min_order = max_order = ff_lpc_estimate_best_order(ref, min_order, max_order);
> + }
> +
> + ff_lpc_quantize_coefs(lpc, min_order, max_order, precision, MAX_LPC_SHIFT,
> + 0, coefs, shift);
> +
> + opt_order = max_order;
> if(omethod == ORDER_METHOD_2LEVEL ||
> omethod == ORDER_METHOD_4LEVEL ||
> omethod == ORDER_METHOD_8LEVEL) {
ok
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Dictatorship naturally arises out of democracy, and the most aggravated
form of tyranny and slavery out of the most extreme liberty. -- Plato
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080817/474eb62e/attachment.pgp>
More information about the ffmpeg-devel
mailing list