[FFmpeg-devel] [PATCH] Common ACELP routines (3/3) - LPC decoding routines

Vladimir Voroshilov voroshil
Fri Apr 25 05:24:25 CEST 2008


Michael Niedermayer wrote: 
> On Fri, Apr 25, 2008 at 08:26:35AM +0700, Vladimir Voroshilov wrote:
> [...]
> > +void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, int lsfq_max)
> > +{
> > +    int i, j;
> > +
> > +    /* sort lsfq in ascending order. float bubble agorithm, O(n)*/
> 
> > +    for(i=9; i<9; i++)
> 
> i do not think that will work

It passed all tests what means that data were already ordered.
Anyway since there is nothing in spec about LSFs ordering I'd
prefer keep sorting there.

> 
> 
> [...]
> -- 
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> 
> Why not whip the teacher when the pupil misbehaves? -- Diogenes of Sinope



-- 
Regards,
Vladimir Voroshilov mailto:voroshil at gmail.com
Omsk State University
JID: voroshil at jabber.ru
ICQ: 95587719
-------------- next part --------------
diff --git a/libavcodec/lsp.c b/libavcodec/lsp.c
new file mode 100644
index 0000000..550bd85
--- /dev/null
+++ b/libavcodec/lsp.c
@@ -0,0 +1,123 @@
+/*
+ * LSP routines for ACELP-based codecs
+ *
+ * Copyright (c) 2008 Vladimir Voroshilov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <inttypes.h>
+
+#include "avcodec.h"
+#include "mathops.h"
+#include "lsp.h"
+#include "acelp_math.h"
+
+void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, int lsfq_max)
+{
+    int i, j;
+
+    /* sort lsfq in ascending order. float bubble agorithm, O(n)*/
+    for(i=0; i<9; i++)
+        for(j=i; j>=0 && lsfq[j] > lsfq[j+1]; j--)
+            FFSWAP(int16_t, lsfq[j], lsfq[j+1]);
+
+    for(i=0;i<10; i++)
+    {
+        lsfq[i] = FFMAX(lsfq[i], lsfq_min);
+        lsfq_min = lsfq[i] + lsfq_min_distance;
+    }
+    lsfq[9] = FFMIN(lsfq[9], lsfq_max);//Is warning required ?
+}
+
+void ff_acelp_lsf2lsp(int16_t *lsp, const int16_t *lsf)
+{
+    int i;
+
+    /* Convert LSF to LSP, lsp=cos(lsf) */
+    for(i=0;i<10; i++)
+        // 20861 = (1<<16) / PI
+        lsp[i] = ff_cos(lsf[i] * 20861 >> 15);
+}
+
+/**
+ * \brief decodes polynomial coefficients from LSP
+ * \param f [out] (Q24) decoded polynomial coefficients
+ * \param lsp (Q15) LSP coefficients
+ */
+static void lsp2poly(int* f, const int16_t* lsp)
+{
+    int i, j;
+
+    f[0] = 0x1000000;          // 1.0 in Q24
+    f[1] = -lsp[0] << 10;      // *2 and Q15 -> Q24
+
+    for(i=2; i<=5; i++)
+    {
+        f[i] = f[i-2];
+
+        for(j=i; j>1; j--)
+#ifdef G729_BITEXACT
+            f[j] -= (mul_32_16(f[j-1]>>1, lsp[2*i-2])<<2) - f[j-2];
+#else
+            f[j] -= (mul_32_16(f[j-1], lsp[2*i-2])<<1) - f[j-2];
+#endif
+
+        f[1] -= lsp[2*i-2]  << 10;
+    }
+}
+
+void ff_acelp_lsp2lpc(int16_t* lp, const int16_t* lsp)
+{
+    int i;
+    int f1[6]; // Q24
+    int f2[6]; // Q24
+
+    lsp2poly(f1, lsp  );
+    lsp2poly(f2, lsp+1);
+
+    /* 3.2.6 of G.729, Equations 25 and  26*/
+    lp[0] = 4096;
+    for(i=1; i<6; i++)
+    {
+        int ff1 = f1[i] + f1[i-1]; // Q24
+        int ff2 = f2[i] - f2[i-1]; // Q24
+
+        ff1 += 1 << 12;
+        lp[i]    = (ff1 + ff2) >> 13;
+        lp[11-i] = (ff1 - ff2) >> 13;
+    }
+}
+
+void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd, const int16_t* lsp_prev)
+{
+    int16_t lsp_1st[10]; // Q15
+    int i;
+
+    /* LSP values for first subframe (3.2.5 of G.729, Equation 24)*/
+    for(i=0;i<10;i++)
+#ifdef G729_BITEXACT
+        lsp_1st[i] = (lsp_2nd[i] >> 1) + (lsp_prev[i] >> 1);
+#else
+        lsp_1st[i] = (lsp_2nd[i] + lsp_prev[i]) >> 1;
+#endif
+
+    ff_acelp_lsp2lpc(lp_1st, lsp_1st);
+
+    /* LSP values for second subframe (3.2.5 of G.729)*/
+    ff_acelp_lsp2lpc(lp_2nd, lsp_2nd);
+}
diff --git a/libavcodec/lsp.h b/libavcodec/lsp.h
new file mode 100644
index 0000000..06e9231
--- /dev/null
+++ b/libavcodec/lsp.h
@@ -0,0 +1,60 @@
+/*
+ * LSP computing for ACELP-based codecs
+ *
+ * Copyright (c) 2008 Vladimir Voroshilov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFMPEG_ACELP_LPC_H
+#define FFMPEG_ACELP_LPC_H
+
+/**
+ * \brief keep distance between LSFs.
+ * \param lsfq [in/out] LSF to check and adjust
+ * \param lsfq_min_distance minimum distance between LSFs
+ * \param lsfq_min minimum allowed LSF value
+ * \param lsfq_max maximum allowed LSF value
+ */
+void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsqf_min, int lsfq_max);
+
+/**
+ * \brief Convert LSF to LSP
+ * \param lsp [out] LSP coefficients (-(1<<15) <= lsp < (1<<15))
+ * \param lsf LSF coefficients (0 <= lsf < PI * (1<<13))
+ *
+ * \remark It is safe to pass the same array in lsf and lsp parameters
+ */
+void ff_acelp_lsp2lpc(int16_t* lp, const int16_t* lsp);
+
+/**
+ * \brief LSP to LP conversion (3.2.6 of G.729)
+ * \param lp [out] (Q12) decoded LP coefficients
+ * \param lsp (Q15) LSP coefficients
+ */
+void ff_acelp_lsf2lsp(int16_t *lsp, const int16_t *lsf);
+
+/**
+ * \brief Interpolate LSP for the first subframe and convert LSP -> LP for both subframes (3.2.5 and 3.2.6 of G.729)
+ * \param lp_1st [out] (Q12) decoded LP coefficients for 1st subframe
+ * \param lp_2nd [out] (Q12) decoded LP coefficients for second subframe
+ * \param lsp_2nd (Q15) LSP coefficients of the second subframe
+ * \param lsp_prev (Q15) past LSP coefficients
+ */
+void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd, const int16_t* lsp_prev);
+
+#endif // FFMPEG_ACELP_LPC_H



More information about the ffmpeg-devel mailing list