]> granicus.if.org Git - python/commitdiff
SF [ 1231053 ] audioop - alaw encoding/decoding added, code updated
authorAnthony Baxter <anthonybaxter@gmail.com>
Mon, 20 Mar 2006 05:21:58 +0000 (05:21 +0000)
committerAnthony Baxter <anthonybaxter@gmail.com>
Mon, 20 Mar 2006 05:21:58 +0000 (05:21 +0000)
 This patch adds a-LAW encoding to audioop and replaces the old
u-LAW encoding/decoding code with the current code from sox.

Possible issues: the code from sox uses int16_t.

Code by Lars Immisch

Doc/lib/libaudioop.tex
Lib/test/test_audioop.py
Misc/NEWS
Modules/audioop.c

index 76bcdbfbccdb562bfd09c5fa88953094df5c5b1c..52c6f3d798432371cb70df5fbeebcab3647170e5 100644 (file)
@@ -12,9 +12,10 @@ is the same format as used by the \refmodule{al} and \refmodule{sunaudiodev}
 modules.  All scalar items are integers, unless specified otherwise.
 
 % This para is mostly here to provide an excuse for the index entries...
-This module provides support for u-LAW and Intel/DVI ADPCM encodings.
+This module provides support for a-LAW, u-LAW and Intel/DVI ADPCM encodings.
 \index{Intel/DVI ADPCM}
 \index{ADPCM, Intel/DVI}
+\index{a-LAW}
 \index{u-LAW}
 
 A few of the more complicated operations only take 16-bit samples,
@@ -42,6 +43,13 @@ Return a tuple \code{(\var{sample}, \var{newstate})} where the sample
 has the width specified in \var{width}.
 \end{funcdesc}
 
+\begin{funcdesc}{alaw2lin}{fragment, width}
+Convert sound fragments in a-LAW encoding to linearly encoded sound
+fragments.  a-LAW encoding always uses 8 bits samples, so \var{width}
+refers only to the sample width of the output fragment here.
+\versionadded{2.5}
+\end{funcdesc}
+
 \begin{funcdesc}{avg}{fragment, width}
 Return the average over all samples in the fragment.
 \end{funcdesc}
@@ -98,10 +106,6 @@ The routine takes time proportional to \code{len(\var{fragment})}.
 Return the value of sample \var{index} from the fragment.
 \end{funcdesc}
 
-\begin{funcdesc}{lin2lin}{fragment, width, newwidth}
-Convert samples between 1-, 2- and 4-byte formats.
-\end{funcdesc}
-
 \begin{funcdesc}{lin2adpcm}{fragment, width, state}
 Convert samples to 4 bit Intel/DVI ADPCM encoding.  ADPCM coding is an
 adaptive coding scheme, whereby each 4 bit number is the difference
@@ -117,6 +121,18 @@ passed as the state.  \var{adpcmfrag} is the ADPCM coded fragment
 packed 2 4-bit values per byte.
 \end{funcdesc}
 
+\begin{funcdesc}{lin2alaw}{fragment, width}
+Convert samples in the audio fragment to a-LAW encoding and return
+this as a Python string.  a-LAW is an audio encoding format whereby
+you get a dynamic range of about 13 bits using only 8 bit samples.  It
+is used by the Sun audio hardware, among others.
+\versionadded{2.5}
+\end{funcdesc}
+
+\begin{funcdesc}{lin2lin}{fragment, width, newwidth}
+Convert samples between 1-, 2- and 4-byte formats.
+\end{funcdesc}
+
 \begin{funcdesc}{lin2ulaw}{fragment, width}
 Convert samples in the audio fragment to u-LAW encoding and return
 this as a Python string.  u-LAW is an audio encoding format whereby
index 440adabd57f4708f2d6b951845a54af878aa4a16..f585733eacc9438ef6232e6873cd42ce4287feca 100644 (file)
@@ -136,12 +136,30 @@ def testlin2adpcm(data):
         return 0
     return 1
 
+def testlin2alaw(data):
+    if verbose:
+        print 'lin2alaw'
+    if audioop.lin2alaw(data[0], 1) != '\xd5\xc5\xf5' or \
+              audioop.lin2alaw(data[1], 2) != '\xd5\xd5\xd5' or \
+              audioop.lin2alaw(data[2], 4) != '\xd5\xd5\xd5':
+        return 0
+    return 1
+
+def testalaw2lin(data):
+    if verbose:
+        print 'alaw2lin'
+    # Cursory
+    d = audioop.lin2alaw(data[0], 1)
+    if audioop.alaw2lin(d, 1) != data[0]:
+        return 0
+    return 1
+
 def testlin2ulaw(data):
     if verbose:
         print 'lin2ulaw'
-    if audioop.lin2ulaw(data[0], 1) != '\377\347\333' or \
-              audioop.lin2ulaw(data[1], 2) != '\377\377\377' or \
-              audioop.lin2ulaw(data[2], 4) != '\377\377\377':
+    if audioop.lin2ulaw(data[0], 1) != '\xff\xe7\xdb' or \
+              audioop.lin2ulaw(data[1], 2) != '\xff\xff\xff' or \
+              audioop.lin2ulaw(data[2], 4) != '\xff\xff\xff':
         return 0
     return 1
 
index a9667e3b5bab8ff368b4b3394402afb4bbb50672..80691421cafed4ebc27f0b1c7f8bb612f47e8b66 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -295,6 +295,9 @@ Core and builtins
 Extension Modules
 -----------------
 
+- Patch #1231053: The audioop module now supports encoding/decoding of alaw.
+  In addition, the existing ulaw code was updated.
+
 - RFE #567972: Socket objects' family, type and proto properties are
   now exposed via new get...() methods.
 
index beeacd3491a346b50ac5c9a255efae3e85b69dfa..75b38f104f5f298c270021c2324def3b11d80d09 100644 (file)
@@ -22,103 +22,247 @@ typedef unsigned long Py_UInt32;
 #endif
 #endif
 
-/* Code shamelessly stolen from sox,
+/* Code shamelessly stolen from sox, 12.17.7, g711.c
 ** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
 
-#define MINLIN -32768
-#define MAXLIN 32767
-#define LINCLIP(x) do { if ( x < MINLIN ) x = MINLIN ; \
-                        else if ( x > MAXLIN ) x = MAXLIN; \
-                      } while ( 0 )
+/* From g711.c:
+ *
+ * December 30, 1994:
+ * Functions linear2alaw, linear2ulaw have been updated to correctly
+ * convert unquantized 16 bit values.
+ * Tables for direct u- to A-law and A- to u-law conversions have been
+ * corrected.
+ * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
+ * bli@cpk.auc.dk
+ *
+ */
+#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+#define        SIGN_BIT        (0x80)          /* Sign bit for a A-law byte. */
+#define        QUANT_MASK      (0xf)           /* Quantization field mask. */
+#define        SEG_SHIFT       (4)             /* Left shift for segment number. */
+#define        SEG_MASK        (0x70)          /* Segment field mask. */
+
+static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
+                                                         0x1FF, 0x3FF, 0x7FF, 0xFFF};
+static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
+                                                         0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+static int16_t search(int16_t val, int16_t *table, int size)
+{
+       int i;
 
-static unsigned char st_linear_to_ulaw(int sample);
+       for (i = 0; i < size; i++) {
+               if (val <= *table++)
+                       return (i);
+       }
+       return (size);
+}
+#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
+#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
+
+int16_t _st_ulaw2linear16[256] = {
+    -32124,  -31100,  -30076,  -29052,  -28028,  -27004,  -25980,
+    -24956,  -23932,  -22908,  -21884,  -20860,  -19836,  -18812,
+    -17788,  -16764,  -15996,  -15484,  -14972,  -14460,  -13948,
+    -13436,  -12924,  -12412,  -11900,  -11388,  -10876,  -10364,
+     -9852,   -9340,   -8828,   -8316,   -7932,   -7676,   -7420,
+     -7164,   -6908,   -6652,   -6396,   -6140,   -5884,   -5628,
+     -5372,   -5116,   -4860,   -4604,   -4348,   -4092,   -3900,
+     -3772,   -3644,   -3516,   -3388,   -3260,   -3132,   -3004,
+     -2876,   -2748,   -2620,   -2492,   -2364,   -2236,   -2108,
+     -1980,   -1884,   -1820,   -1756,   -1692,   -1628,   -1564,
+     -1500,   -1436,   -1372,   -1308,   -1244,   -1180,   -1116,
+     -1052,    -988,    -924,    -876,    -844,    -812,    -780,
+      -748,    -716,    -684,    -652,    -620,    -588,    -556,
+      -524,    -492,    -460,    -428,    -396,    -372,    -356,
+      -340,    -324,    -308,    -292,    -276,    -260,    -244,
+      -228,    -212,    -196,    -180,    -164,    -148,    -132,
+      -120,    -112,    -104,     -96,     -88,     -80,     -72,
+       -64,     -56,     -48,     -40,     -32,     -24,     -16,
+        -8,       0,   32124,   31100,   30076,   29052,   28028,
+     27004,   25980,   24956,   23932,   22908,   21884,   20860,
+     19836,   18812,   17788,   16764,   15996,   15484,   14972,
+     14460,   13948,   13436,   12924,   12412,   11900,   11388,
+     10876,   10364,    9852,    9340,    8828,    8316,    7932,
+      7676,    7420,    7164,    6908,    6652,    6396,    6140,
+      5884,    5628,    5372,    5116,    4860,    4604,    4348,
+      4092,    3900,    3772,    3644,    3516,    3388,    3260,
+      3132,    3004,    2876,    2748,    2620,    2492,    2364,
+      2236,    2108,    1980,    1884,    1820,    1756,    1692,
+      1628,    1564,    1500,    1436,    1372,    1308,    1244,
+      1180,    1116,    1052,     988,     924,     876,     844,
+       812,     780,     748,     716,     684,     652,     620,
+       588,     556,     524,     492,     460,     428,     396,
+       372,     356,     340,     324,     308,     292,     276,
+       260,     244,     228,     212,     196,     180,     164,
+       148,     132,     120,     112,     104,      96,      88,
+        80,      72,      64,      56,      48,      40,      32,
+        24,      16,       8,       0
+};
 
 /*
-** This macro converts from ulaw to 16 bit linear, faster.
-**
-** Jef Poskanzer
-** 23 October 1989
-**
-** Input: 8 bit ulaw sample
-** Output: signed 16 bit linear sample
-*/
-#define st_ulaw_to_linear(ulawbyte) ulaw_table[ulawbyte]
-
-static int ulaw_table[256] = {
-       -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
-       -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
-       -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
-       -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
-       -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
-       -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
-       -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
-       -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
-       -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
-       -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
-       -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
-       -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
-       -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
-       -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
-       -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
-       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
-       32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
-       23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
-       15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
-       11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
-       7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
-       5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
-       3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
-       2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
-       1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
-       1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
-       876,    844,    812,    780,    748,    716,    684,    652,
-       620,    588,    556,    524,    492,    460,    428,    396,
-       372,    356,    340,    324,    308,    292,    276,    260,
-       244,    228,    212,    196,    180,    164,    148,    132,
-       120,    112,    104,     96,     88,     80,     72,     64,
-       56,     48,     40,     32,     24,     16,      8,      0 };
-
-/* #define ZEROTRAP */   /* turn on the trap as per the MIL-STD */
-#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
-#define CLIP 32635
+ * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 14-bits.
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ *     Biased Linear Input Code        Compressed Code
+ *     ------------------------        ---------------
+ *     00000001wxyza                   000wxyz
+ *     0000001wxyzab                   001wxyz
+ *     000001wxyzabc                   010wxyz
+ *     00001wxyzabcd                   011wxyz
+ *     0001wxyzabcde                   100wxyz
+ *     001wxyzabcdef                   101wxyz
+ *     01wxyzabcdefg                   110wxyz
+ *     1wxyzabcdefgh                   111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char st_14linear2ulaw(
+       int16_t         pcm_val)        /* 2's complement (14-bit range) */
+{
+       int16_t         mask;
+       int16_t         seg;
+       unsigned char   uval;
+
+       /* The original sox code does this in the calling function, not here */
+       pcm_val = pcm_val >> 2;
+
+       /* u-law inverts all bits */
+       /* Get the sign and the magnitude of the value. */
+       if (pcm_val < 0) {
+               pcm_val = -pcm_val;
+               mask = 0x7F;
+       } else {
+               mask = 0xFF;
+       }
+        if ( pcm_val > CLIP ) pcm_val = CLIP;          /* clip the magnitude */
+       pcm_val += (BIAS >> 2);
+
+       /* Convert the scaled magnitude to segment number. */
+       seg = search(pcm_val, seg_uend, 8);
+
+       /*
+        * Combine the sign, segment, quantization bits;
+        * and complement the code word.
+        */
+       if (seg >= 8)           /* out of range, return maximum value. */
+               return (unsigned char) (0x7F ^ mask);
+       else {
+               uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+               return (uval ^ mask);
+       }
 
-static unsigned char
-st_linear_to_ulaw(int sample)
+}
+
+int16_t _st_alaw2linear16[256] = {
+     -5504,   -5248,   -6016,   -5760,   -4480,   -4224,   -4992,
+     -4736,   -7552,   -7296,   -8064,   -7808,   -6528,   -6272,
+     -7040,   -6784,   -2752,   -2624,   -3008,   -2880,   -2240,
+     -2112,   -2496,   -2368,   -3776,   -3648,   -4032,   -3904,
+     -3264,   -3136,   -3520,   -3392,  -22016,  -20992,  -24064,
+    -23040,  -17920,  -16896,  -19968,  -18944,  -30208,  -29184,
+    -32256,  -31232,  -26112,  -25088,  -28160,  -27136,  -11008,
+    -10496,  -12032,  -11520,   -8960,   -8448,   -9984,   -9472,
+    -15104,  -14592,  -16128,  -15616,  -13056,  -12544,  -14080,
+    -13568,    -344,    -328,    -376,    -360,    -280,    -264,
+      -312,    -296,    -472,    -456,    -504,    -488,    -408,
+      -392,    -440,    -424,     -88,     -72,    -120,    -104,
+       -24,      -8,     -56,     -40,    -216,    -200,    -248,
+      -232,    -152,    -136,    -184,    -168,   -1376,   -1312,
+     -1504,   -1440,   -1120,   -1056,   -1248,   -1184,   -1888,
+     -1824,   -2016,   -1952,   -1632,   -1568,   -1760,   -1696,
+      -688,    -656,    -752,    -720,    -560,    -528,    -624,
+      -592,    -944,    -912,   -1008,    -976,    -816,    -784,
+      -880,    -848,    5504,    5248,    6016,    5760,    4480,
+      4224,    4992,    4736,    7552,    7296,    8064,    7808,
+      6528,    6272,    7040,    6784,    2752,    2624,    3008,
+      2880,    2240,    2112,    2496,    2368,    3776,    3648,
+      4032,    3904,    3264,    3136,    3520,    3392,   22016,
+     20992,   24064,   23040,   17920,   16896,   19968,   18944,
+     30208,   29184,   32256,   31232,   26112,   25088,   28160,
+     27136,   11008,   10496,   12032,   11520,    8960,    8448,
+      9984,    9472,   15104,   14592,   16128,   15616,   13056,
+     12544,   14080,   13568,     344,     328,     376,     360,
+       280,     264,     312,     296,     472,     456,     504,
+       488,     408,     392,     440,     424,      88,      72,
+       120,     104,      24,       8,      56,      40,     216,
+       200,     248,     232,     152,     136,     184,     168,
+      1376,    1312,    1504,    1440,    1120,    1056,    1248,
+      1184,    1888,    1824,    2016,    1952,    1632,    1568,
+      1760,    1696,     688,     656,     752,     720,     560,
+       528,     624,     592,     944,     912,    1008,     976,
+       816,     784,     880,     848
+};
+
+/*
+ * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 13-bits.
+ *
+ *             Linear Input Code       Compressed Code
+ *     ------------------------        ---------------
+ *     0000000wxyza                    000wxyz
+ *     0000001wxyza                    001wxyz
+ *     000001wxyzab                    010wxyz
+ *     00001wxyzabc                    011wxyz
+ *     0001wxyzabcd                    100wxyz
+ *     001wxyzabcde                    101wxyz
+ *     01wxyzabcdef                    110wxyz
+ *     1wxyzabcdefg                    111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char st_linear2alaw(
+       int16_t         pcm_val)        /* 2's complement (13-bit range) */
 {
-       static int exp_lut[256] = {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};
-       int sign, exponent, mantissa;
-       unsigned char ulawbyte;
-
-       /* Get the sample into sign-magnitude. */
-       sign = (sample >> 8) & 0x80;            /* set aside the sign */
-       if ( sign != 0 ) sample = -sample;      /* get magnitude */
-       if ( sample > CLIP ) sample = CLIP;     /* clip the magnitude */
-
-       /* Convert from 16 bit linear to ulaw. */
-       sample = sample + BIAS;
-       exponent = exp_lut[( sample >> 7 ) & 0xFF];
-       mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
-       ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
-#ifdef ZEROTRAP
-       if ( ulawbyte == 0 ) ulawbyte = 0x02;   /* optional CCITT trap */
-#endif
+       int16_t         mask;
+       short           seg;
+       unsigned char   aval;
+
+       /* The original sox code does this in the calling function, not here */
+       pcm_val = pcm_val >> 3;
+
+       /* A-law using even bit inversion */
+       if (pcm_val >= 0) {
+               mask = 0xD5;            /* sign (7th) bit = 1 */
+       } else {
+               mask = 0x55;            /* sign bit = 0 */
+               pcm_val = -pcm_val - 1;
+       }
+
+       /* Convert the scaled magnitude to segment number. */
+       seg = search(pcm_val, seg_aend, 8);
+
+       /* Combine the sign, segment, and quantization bits. */
 
-       return ulawbyte;
+       if (seg >= 8)           /* out of range, return maximum value. */
+               return (unsigned char) (0x7F ^ mask);
+       else {
+               aval = (unsigned char) seg << SEG_SHIFT;
+               if (seg < 2)
+                       aval |= (pcm_val >> 1) & QUANT_MASK;
+               else
+                       aval |= (pcm_val >> seg) & QUANT_MASK;
+               return (aval ^ mask);
+       }
 }
 /* End of code taken from sox */
 
@@ -1107,7 +1251,7 @@ audioop_lin2ulaw(PyObject *self, PyObject *args)
                else if ( size == 2 ) val = (int)*SHORTP(cp, i);
                else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
 
-               *ncp++ = st_linear_to_ulaw(val);
+               *ncp++ = st_14linear2ulaw(val);
        }
        return rv;
 }
@@ -1138,7 +1282,75 @@ audioop_ulaw2lin(PyObject *self, PyObject *args)
     
        for ( i=0; i < len*size; i += size ) {
                cval = *cp++;
-               val = st_ulaw_to_linear(cval);
+               val = st_ulaw2linear16(cval);
+       
+               if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val >> 8);
+               else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
+               else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(val<<16);
+       }
+       return rv;
+}
+
+static PyObject *
+audioop_lin2alaw(PyObject *self, PyObject *args)
+{
+       signed char *cp;
+       unsigned char *ncp;
+       int len, size, val = 0;
+       PyObject *rv;
+       int i;
+
+       if ( !PyArg_Parse(args, "(s#i)",
+                         &cp, &len, &size) )
+               return 0;
+
+       if ( size != 1 && size != 2 && size != 4) {
+               PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+               return 0;
+       }
+    
+       rv = PyString_FromStringAndSize(NULL, len/size);
+       if ( rv == 0 )
+               return 0;
+       ncp = (unsigned char *)PyString_AsString(rv);
+    
+       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 == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+
+               *ncp++ = st_linear2alaw(val);
+       }
+       return rv;
+}
+
+static PyObject *
+audioop_alaw2lin(PyObject *self, PyObject *args)
+{
+       unsigned char *cp;
+       unsigned char cval;
+       signed char *ncp;
+       int len, size, val;
+       PyObject *rv;
+       int i;
+
+       if ( !PyArg_Parse(args, "(s#i)",
+                         &cp, &len, &size) )
+               return 0;
+
+       if ( size != 1 && size != 2 && size != 4) {
+               PyErr_SetString(AudioopError, "Size should be 1, 2 or 4");
+               return 0;
+       }
+    
+       rv = PyString_FromStringAndSize(NULL, len*size);
+       if ( rv == 0 )
+               return 0;
+       ncp = (signed char *)PyString_AsString(rv);
+    
+       for ( i=0; i < len*size; i += size ) {
+               cval = *cp++;
+               val = st_alaw2linear16(cval);
        
                if ( size == 1 )      *CHARP(ncp, i) = (signed char)(val >> 8);
                else if ( size == 2 ) *SHORTP(ncp, i) = (short)(val);
@@ -1362,6 +1574,8 @@ static PyMethodDef audioop_methods[] = {
        { "bias", audioop_bias, METH_OLDARGS },
        { "ulaw2lin", audioop_ulaw2lin, METH_OLDARGS },
        { "lin2ulaw", audioop_lin2ulaw, METH_OLDARGS },
+       { "alaw2lin", audioop_alaw2lin, METH_OLDARGS },
+       { "lin2alaw", audioop_lin2alaw, METH_OLDARGS },
        { "lin2lin", audioop_lin2lin, METH_OLDARGS },
        { "adpcm2lin", audioop_adpcm2lin, METH_OLDARGS },
        { "lin2adpcm", audioop_lin2adpcm, METH_OLDARGS },