[pypy-commit] pypy py3.5: audioop support size == 3

plan_rich pypy.commits at gmail.com
Wed Feb 22 08:39:15 EST 2017


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5
Changeset: r90292:a4c46e6650b2
Date: 2017-02-22 14:20 +0100
http://bitbucket.org/pypy/pypy/changeset/a4c46e6650b2/

Log:	audioop support size == 3

diff --git a/lib_pypy/_audioop_build.py b/lib_pypy/_audioop_build.py
--- a/lib_pypy/_audioop_build.py
+++ b/lib_pypy/_audioop_build.py
@@ -301,6 +301,32 @@
 #define CHARP(cp, i) ((signed char *)(cp+i))
 #define SHORTP(cp, i) ((short *)(cp+i))
 #define LONGP(cp, i) ((Py_Int32 *)(cp+i))
+
+#if WORDS_BIGENDIAN
+#define GETINT24(cp, i)  (                              \
+        ((unsigned char *)(cp) + (i))[2] +              \
+        (((unsigned char *)(cp) + (i))[1] << 8) +       \
+        (((signed char *)(cp) + (i))[0] << 16) )
+#else
+#define GETINT24(cp, i)  (                              \
+        ((unsigned char *)(cp) + (i))[0] +              \
+        (((unsigned char *)(cp) + (i))[1] << 8) +       \
+        (((signed char *)(cp) + (i))[2] << 16) )
+#endif
+
+#if WORDS_BIGENDIAN
+#define SETINT24(cp, i, val)  do {                              \
+        ((unsigned char *)(cp) + (i))[2] = (int)(val);          \
+        ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8;     \
+        ((signed char *)(cp) + (i))[0] = (int)(val) >> 16;      \
+    } while (0)
+#else
+#define SETINT24(cp, i, val)  do {                              \
+        ((unsigned char *)(cp) + (i))[0] = (int)(val);          \
+        ((unsigned char *)(cp) + (i))[1] = (int)(val) >> 8;     \
+        ((signed char *)(cp) + (i))[2] = (int)(val) >> 16;      \
+    } while (0)
+#endif
 """
 
 C_SOURCE = _AUDIOOP_C_MODULE + r"""
@@ -362,6 +388,8 @@
                     cur_i[chan] = ((int)*CHARP(cp, 0)) << 24;
                 else if (size == 2)
                     cur_i[chan] = ((int)*SHORTP(cp, 0)) << 16;
+                else if (size == 3)
+                    cur_i[chan] = ((int)GETINT24(cp, 0)) << 16;
                 else if (size == 4)
                     cur_i[chan] = (int)*LONGP(cp, 0);
                 cp += size;
@@ -384,6 +412,8 @@
                     *CHARP(ncp, 0) = (signed char)(cur_o >> 24);
                 else if (size == 2)
                     *SHORTP(ncp, 0) = (short)(cur_o >> 16);
+                else if (size == 3)
+                    SETINT24(ncp, 0, cur_o >> 8);
                 else if (size == 4)
                     *LONGP(ncp, 0) = (Py_Int32)(cur_o);
                 ncp += size;
@@ -407,6 +437,7 @@
     for ( i=0; i < len; i += size ) {
         if ( size == 1 )      val = (int)*CHARP(cp, i);
         else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+        else if ( size == 3 ) val = (int)GETINT24(cp, i);
         else if ( size == 4 ) val = (int)*LONGP(cp, i);
 
         fval = (double)val*fac1;
@@ -417,10 +448,12 @@
 
         if ( size == 1 )      *CHARP(ncp, i*2) = (signed char)val1;
         else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
+        else if ( size == 3 ) SETINT24(ncp, i*2, val1);
         else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
 
         if ( size == 1 )      *CHARP(ncp, i*2+1) = (signed char)val2;
         else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
+        else if ( size == 3 ) SETINT24(ncp, i*2, val1);
         else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
     }
 }
@@ -437,10 +470,12 @@
     for ( i=0; i < len1; i += size ) {
         if ( size == 1 )      val1 = (int)*CHARP(cp1, i);
         else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
+        else if ( size == 3 ) val1 = (int)GETINT24(cp1, i);
         else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
 
         if ( size == 1 )      val2 = (int)*CHARP(cp2, i);
         else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
+        else if ( size == 3 ) val2 = (int)GETINT24(cp2, i);
         else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
 
         if (size < 4) {
@@ -459,6 +494,7 @@
 
         if ( size == 1 )      *CHARP(ncp, i) = (signed char)newval;
         else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
+        else if ( size == 3 ) SETINT24(ncp, i, newval);
         else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
     }
 }
@@ -479,6 +515,7 @@
     for ( i=0; i < len; i += size ) {
         if ( size == 1 )      val = ((int)*CHARP(cp, i)) << 8;
         else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+        else if ( size == 3 ) val = ((int)GETINT24(cp, i)) >> 8;
         else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
         /* Step 1 - compute difference with previous value */
@@ -608,6 +645,7 @@
         /* Step 6 - Output value */
         if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
         else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
+        else if ( size == 3 ) SETINT24(ncp, i, valpred << 8);
         else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
     }
     state[0] = valpred;
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
--- a/lib_pypy/audioop.py
+++ b/lib_pypy/audioop.py
@@ -1,10 +1,11 @@
+import sys
 import builtins
 import math
 import struct
-from fractions import gcd
+from math import gcd
 from _audioop_cffi import ffi, lib
 
-
+BIG_ENDIAN = sys.byteorder != 'little'
 _buffer = memoryview
 
 
@@ -47,18 +48,49 @@
         return "b" if signed else "B"
     elif size == 2:
         return "h" if signed else "H"
+    elif size == 3:
+        raise NotImplementedError
     elif size == 4:
         return "i" if signed else "I"
 
+def _unpack_int24(buf):
+    if BIG_ENDIAN:
+        val = (buf[2] & 0xff) | \
+               ((buf[1] & 0xff) << 8) | \
+               ((buf[0] & 0xff) << 16)
+    else:
+        val = (buf[0] & 0xff) | \
+               ((buf[1] & 0xff) << 8) | \
+               ((buf[2] & 0xff) << 16)
+    if val & 0x800000:
+        val = val - 0x1000000
+    return val
+
+def _pack_int24(into, off, val):
+    buf = _buffer(into)
+    if BIG_ENDIAN:
+        buf[off+2] = val & 0xff
+        buf[off+1] = (val >> 8) & 0xff
+        buf[off+0] = (val >> 16) & 0xff
+    else:
+        buf[off+0] = val & 0xff
+        buf[off+1] = (val >> 8) & 0xff
+        buf[off+2] = (val >> 16) & 0xff
 
 def _get_sample(cp, size, i, signed=True):
-    fmt = _struct_format(size, signed)
     start = i * size
     end = start + size
-    return struct.unpack_from(fmt, _buffer(cp)[start:end])[0]
+    chars = _buffer(cp)[start:end]
+    if size == 3:
+        return _unpack_int24(chars)
+    fmt = _struct_format(size, signed)
+    return struct.unpack_from(fmt, chars)[0]
 
 
 def _put_sample(cp, size, i, val, signed=True):
+    if size == 3:
+        _pack_int24(cp, i*size, val)
+        return
     fmt = _struct_format(size, signed)
     struct.pack_into(fmt, cp, i * size, val)
 
@@ -108,8 +140,17 @@
     else:
         return val % (2**bits)
 
+def _check_bytes(cp):
+    # we have no argument clinic
+    try:
+        memoryview(cp)
+    except TypeError:
+        raise TypeError("a bytes-like object is required, not '%s'" % \
+                str(type(cp)))
+
 
 def getsample(cp, size, i):
+    # _check_bytes checked in _get_sample
     _check_params(len(cp), size)
     if not (0 <= i < len(cp) // size):
         raise error("Index out of range")
@@ -249,6 +290,7 @@
 
 
 def avgpp(cp, size):
+    _check_bytes(cp)
     _check_params(len(cp), size)
     sample_count = _sample_count(cp, size)
     if sample_count <= 2:
@@ -415,6 +457,7 @@
 
 
 def lin2lin(cp, size, size2):
+    _check_bytes(cp)
     _check_params(len(cp), size)
     _check_size(size2)
 
@@ -504,6 +547,8 @@
             yield sample << 8
         elif size == 2:
             yield sample
+        elif size == 3:
+            yield sample >> 8
         elif size == 4:
             yield sample >> 16
 
@@ -513,6 +558,8 @@
         sample >>= 8
     elif size == 2:
         pass
+    elif size == 3:
+        sample <<= 8
     elif size == 4:
         sample <<= 16
     _put_sample(result, size, i, sample)


More information about the pypy-commit mailing list