ref: f9e3268baa83cbab1acf1575d530ad692e3f1638
parent: 00a8871df8151ba4ce8355fa702c78cc129032a8
author: rrt <rrt>
date: Thu May 10 09:40:25 EDT 2007
Faster ADPCM conversion (patch from Philippe Chaintreuil, patch tracker #1694394).
--- a/src/g72x.c
+++ b/src/g72x.c
@@ -1,4 +1,27 @@
/*
+ * Common routines for G.721 and G.723 conversions.
+ *
+ * (c) SoX Contributors
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library. If not, write to the Free Software
+ * Foundation, Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301,
+ * USA.
+ *
+ *
+ * This code is based on code from Sun, which came with the following
+ * copyright notice:
+ * -----------------------------------------------------------------------
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
@@ -22,21 +45,52 @@
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
+ * -----------------------------------------------------------------------
*/
-/*
- * g72x.c
- *
- * Common routines for G.721 and G.723 conversions.
- */
-
#include "sox_i.h"
#include "g711.h"
#include "g72x.h"
-static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
- 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
+static const char LogTable256[] =
+{
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+static inline int log2plus1(int val)
+{
+ /* From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup */
+ unsigned int v = (unsigned int)val; /* 32-bit word to find the log of */
+ unsigned r; /* r will be lg(v) */
+ register unsigned int t, tt; /* temporaries */
+
+ if ((tt = v >> 16))
+ {
+ r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
+ }
+ else
+ {
+ r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v];
+ }
+
+ return r + 1;
+}
+
/*
* quan()
*
@@ -68,7 +122,7 @@
short retval;
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
- anexp = quan(anmag, power2, 15) - 6;
+ anexp = log2plus1(anmag) - 6;
anmant = (anmag == 0) ? 32 :
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
@@ -185,7 +239,7 @@
* Compute base 2 log of 'd', and store in 'dl'.
*/
dqm = abs(d);
- exp = quan(dqm >> 1, power2, 15);
+ exp = log2plus1(dqm >> 1);
mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */
dl = (exp << 7) + mant;
@@ -375,7 +429,7 @@
if (mag == 0) {
state_ptr->dq[0] = (dq >= 0) ? 0x20 : (short)0xFC20;
} else {
- exp = quan(mag, power2, 15);
+ exp = log2plus1(mag);
state_ptr->dq[0] = (dq >= 0) ?
(exp << 6) + ((mag << 6) >> exp) :
(exp << 6) + ((mag << 6) >> exp) - 0x400;
@@ -386,11 +440,11 @@
if (sr == 0) {
state_ptr->sr[0] = 0x20;
} else if (sr > 0) {
- exp = quan(sr, power2, 15);
+ exp = log2plus1(sr);
state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp);
} else if (sr > -32768) {
mag = -sr;
- exp = quan(mag, power2, 15);
+ exp = log2plus1(mag);
state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400;
} else
state_ptr->sr[0] = (short)(0xFC20);