[FFmpeg-devel] [PATCH] Separate window function from autocorrelation.

Måns Rullgård mans
Wed Jan 19 21:12:15 CET 2011


Justin Ruggles <justin.ruggles at gmail.com> writes:

> This will allow the use of different window functions and also removes
> variable-length arrays in autocorrelation functions.
> ---
>  libavcodec/dsputil.c            |    1 +
>  libavcodec/dsputil.h            |    7 ++++++-
>  libavcodec/lpc.c                |   30 ++++++++++++++----------------
>  libavcodec/lpc.h                |    4 +++-
>  libavcodec/x86/dsputil_mmx.h    |    3 ++-
>  libavcodec/x86/dsputilenc_mmx.c |    1 +
>  libavcodec/x86/lpc_mmx.c        |   20 ++++++--------------
>  7 files changed, 33 insertions(+), 33 deletions(-)
>
>
> diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
> index cc60524..3b2d421 100644
> --- a/libavcodec/dsputil.c
> +++ b/libavcodec/dsputil.c
> @@ -4432,6 +4432,7 @@ av_cold void dsputil_init(DSPContext* c, AVCodecContext *avctx)
>      c->ac3_downmix = ff_ac3_downmix_c;
>  #endif
>  #if CONFIG_LPC
> +    c->lpc_apply_welch_window = ff_lpc_apply_welch_window;
>      c->lpc_compute_autocorr = ff_lpc_compute_autocorr;
>  #endif

Maybe we should move the LPC functions out of DSPContext.  This is as
good a time as any to do that.

>      c->vector_fmul = vector_fmul_c;
> diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
> index 1571491..ad61188 100644
> --- a/libavcodec/dsputil.h
> +++ b/libavcodec/dsputil.h
> @@ -376,7 +376,12 @@ typedef struct DSPContext {
>      void (*vorbis_inverse_coupling)(float *mag, float *ang, int blocksize);
>      void (*ac3_downmix)(float (*samples)[256], float (*matrix)[2], int out_ch, int in_ch, int len);
>      /* no alignment needed */
> -    void (*lpc_compute_autocorr)(const int32_t *data, int len, int lag, double *autoc);
> +    void (*lpc_apply_welch_window)(const int32_t *data, int len, double *w_data);
> +    /* no alignment needed.
> +       data must have have at least lag*sizeof(double) valid bytes preceeding it.
> +       data must be at least (len+1)*sizeof(double) in length if data is
> +       16-byte aligned or (len+2)*sizeof(double) if data is unaligned. */
> +    void (*lpc_compute_autocorr)(const double *data, int len, int lag, double *autoc);

A brief doxygen description of the function would be nice.

> @@ -179,12 +170,19 @@ int ff_lpc_calc_coefs(DSPContext *s,
>             lpc_type > AV_LPC_TYPE_FIXED);
>  
>      if (lpc_type == AV_LPC_TYPE_LEVINSON) {
> -        s->lpc_compute_autocorr(samples, blocksize, max_order, autoc);
> +        double *ws = av_mallocz((blocksize + max_order + 2) * sizeof(double));

Unchecked malloc.  Is it feasible to have this buffer allocate once
per codec instance instead of for each call?

> +        double *windowed_samples = ws + max_order;
> +
> +        s->lpc_apply_welch_window(samples, blocksize, windowed_samples);
> +
> +        s->lpc_compute_autocorr(windowed_samples, blocksize, max_order, autoc);
>  
>          compute_lpc_coefs(autoc, max_order, &lpc[0][0], MAX_LPC_ORDER, 0, 1);
>  
>          for(i=0; i<max_order; i++)
>              ref[i] = fabs(lpc[i][i]);
> +
> +        av_freep(&ws);
>      } else if (lpc_type == AV_LPC_TYPE_CHOLESKY) {
>          LLSModel m[2];
>          double var[MAX_LPC_ORDER+1], av_uninit(weight);
> diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h
> index 1c595f6..4673fc4 100644
> --- a/libavcodec/lpc.h
> +++ b/libavcodec/lpc.h
> @@ -46,7 +46,9 @@ int ff_lpc_calc_coefs(DSPContext *s,
>                        enum AVLPCType lpc_type, int lpc_passes,
>                        int omethod, int max_shift, int zero_shift);
>  
> -void ff_lpc_compute_autocorr(const int32_t *data, int len, int lag,
> +void ff_lpc_apply_welch_window(const int32_t *data, int len, double *w_data);
> +
> +void ff_lpc_compute_autocorr(const double *data, int len, int lag,
>                               double *autoc);
>  
>  #ifdef LPC_USE_DOUBLE
> diff --git a/libavcodec/x86/dsputil_mmx.h b/libavcodec/x86/dsputil_mmx.h
> index c57bbbf..52cd810 100644
> --- a/libavcodec/x86/dsputil_mmx.h
> +++ b/libavcodec/x86/dsputil_mmx.h
> @@ -200,7 +200,8 @@ void ff_vc1dsp_init_mmx(DSPContext* dsp, AVCodecContext *avctx);
>  void ff_put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, int stride, int rnd);
>  void ff_avg_vc1_mspel_mc00_mmx2(uint8_t *dst, const uint8_t *src, int stride, int rnd);
>  
> -void ff_lpc_compute_autocorr_sse2(const int32_t *data, int len, int lag,
> +void ff_lpc_apply_welch_window_sse2(const int32_t *data, int len, double *w_data);
> +void ff_lpc_compute_autocorr_sse2(const double *data, int len, int lag,
>                                     double *autoc);
>  
>  void ff_mmx_idct(DCTELEM *block);
> diff --git a/libavcodec/x86/dsputilenc_mmx.c b/libavcodec/x86/dsputilenc_mmx.c
> index f02d1ca..18a10c8 100644
> --- a/libavcodec/x86/dsputilenc_mmx.c
> +++ b/libavcodec/x86/dsputilenc_mmx.c
> @@ -1167,6 +1167,7 @@ void dsputilenc_init_mmx(DSPContext* c, AVCodecContext *avctx)
>          }
>  
>          if (CONFIG_LPC && mm_flags & (AV_CPU_FLAG_SSE2|AV_CPU_FLAG_SSE2SLOW)) {
> +            c->lpc_apply_welch_window = ff_lpc_apply_welch_window_sse2;
>              c->lpc_compute_autocorr = ff_lpc_compute_autocorr_sse2;
>          }
>  
> diff --git a/libavcodec/x86/lpc_mmx.c b/libavcodec/x86/lpc_mmx.c
> index 49eb569..3e740c6 100644
> --- a/libavcodec/x86/lpc_mmx.c
> +++ b/libavcodec/x86/lpc_mmx.c
> @@ -22,7 +22,7 @@
>  #include "libavutil/x86_cpu.h"
>  #include "dsputil_mmx.h"
>  
> -static void apply_welch_window_sse2(const int32_t *data, int len, double *w_data)
> +void ff_lpc_apply_welch_window_sse2(const int32_t *data, int len, double *w_data)
>  {
>      double c = 2.0 / (len-1.0);
>      int n2 = len>>1;
> @@ -68,21 +68,13 @@ static void apply_welch_window_sse2(const int32_t *data, int len, double *w_data
>  #undef WELCH
>  }
>  
> -void ff_lpc_compute_autocorr_sse2(const int32_t *data, int len, int lag,
> +void ff_lpc_compute_autocorr_sse2(const double *data, int len, int lag,
>                                     double *autoc)
>  {
> -    double tmp[len + lag + 2];
> -    double *data1 = tmp + lag;
>      int j;
>  
> -    if((x86_reg)data1 & 15)
> -        data1++;
> -
> -    apply_welch_window_sse2(data, len, data1);
> -
> -    for(j=0; j<lag; j++)
> -        data1[j-lag]= 0.0;
> -    data1[len] = 0.0;
> +    if((x86_reg)data & 15)
> +        data++;
>  
>      for(j=0; j<lag; j+=2){
>          x86_reg i = -len*sizeof(double);
> @@ -113,7 +105,7 @@ void ff_lpc_compute_autocorr_sse2(const int32_t *data, int len, int lag,
>                  "movsd     %%xmm1,  8(%1)           \n\t"
>                  "movsd     %%xmm2, 16(%1)           \n\t"
>                  :"+&r"(i)
> -                :"r"(autoc+j), "r"(data1+len), "r"(data1+len-j)
> +                :"r"(autoc+j), "r"(data+len), "r"(data+len-j)
>                  :"memory"
>              );
>          } else {
> @@ -136,7 +128,7 @@ void ff_lpc_compute_autocorr_sse2(const int32_t *data, int len, int lag,
>                  "movsd     %%xmm0, %1               \n\t"
>                  "movsd     %%xmm1, %2               \n\t"
>                  :"+&r"(i), "=m"(autoc[j]), "=m"(autoc[j+1])
> -                :"r"(data1+len), "r"(data1+len-j)
> +                :"r"(data+len), "r"(data+len-j)
>              );
>          }
>      }

The rest looks good.

-- 
M?ns Rullg?rd
mans at mansr.com



More information about the ffmpeg-devel mailing list