1 import audioop
2 import sys
3 import unittest
4 import struct
5 from test.test_support import run_unittest
6 
7 
8 formats = {
9     1: 'b',
10     2: 'h',
11     4: 'i',
12 }
13 
14 def pack(width, data):
15     return struct.pack('=%d%s' % (len(data), formats[width]), *data)
16 
17 packs = {
18     1: lambda *data: pack(1, data),
19     2: lambda *data: pack(2, data),
20     4: lambda *data: pack(4, data),
21 }
22 maxvalues = {w: (1 << (8 * w - 1)) - 1 for w in (1, 2, 4)}
23 minvalues = {w: -1 << (8 * w - 1) for w in (1, 2, 4)}
24 
25 datas = {
26     1: b'\x00\x12\x45\xbb\x7f\x80\xff',
27     2: packs[2](0, 0x1234, 0x4567, -0x4567, 0x7fff, -0x8000, -1),
28     4: packs[4](0, 0x12345678, 0x456789ab, -0x456789ab,
29                 0x7fffffff, -0x80000000, -1),
30 }
31 
32 INVALID_DATA = [
33     (b'abc', 0),
34     (b'abc', 2),
35     (b'abc', 4),
36 ]
37 
38 
39 class TestAudioop(unittest.TestCase):
40 
41     def test_max(self):
42         for w in 1, 2, 4:
43             self.assertEqual(audioop.max(b'', w), 0)
44             p = packs[w]
45             self.assertEqual(audioop.max(p(5), w), 5)
46             self.assertEqual(audioop.max(p(5, -8, -1), w), 8)
47             self.assertEqual(audioop.max(p(maxvalues[w]), w), maxvalues[w])
48             self.assertEqual(audioop.max(p(minvalues[w]), w), -minvalues[w])
49             self.assertEqual(audioop.max(datas[w], w), -minvalues[w])
50 
51     def test_minmax(self):
52         for w in 1, 2, 4:
53             self.assertEqual(audioop.minmax(b'', w),
54                              (0x7fffffff, -0x80000000))
55             p = packs[w]
56             self.assertEqual(audioop.minmax(p(5), w), (5, 5))
57             self.assertEqual(audioop.minmax(p(5, -8, -1), w), (-8, 5))
58             self.assertEqual(audioop.minmax(p(maxvalues[w]), w),
59                              (maxvalues[w], maxvalues[w]))
60             self.assertEqual(audioop.minmax(p(minvalues[w]), w),
61                              (minvalues[w], minvalues[w]))
62             self.assertEqual(audioop.minmax(datas[w], w),
63                              (minvalues[w], maxvalues[w]))
64 
65     def test_maxpp(self):
66         for w in 1, 2, 4:
67             self.assertEqual(audioop.maxpp(b'', w), 0)
68             self.assertEqual(audioop.maxpp(packs[w](*range(100)), w), 0)
69             self.assertEqual(audioop.maxpp(packs[w](9, 10, 5, 5, 0, 1), w), 10)
70             self.assertEqual(audioop.maxpp(datas[w], w),
71                              maxvalues[w] - minvalues[w])
72 
73     def test_avg(self):
74         for w in 1, 2, 4:
75             self.assertEqual(audioop.avg(b'', w), 0)
76             p = packs[w]
77             self.assertEqual(audioop.avg(p(5), w), 5)
78             self .assertEqual(audioop.avg(p(5, 8), w), 6)
79             self.assertEqual(audioop.avg(p(5, -8), w), -2)
80             self.assertEqual(audioop.avg(p(maxvalues[w], maxvalues[w]), w),
81                              maxvalues[w])
82             self.assertEqual(audioop.avg(p(minvalues[w], minvalues[w]), w),
83                              minvalues[w])
84         self.assertEqual(audioop.avg(packs[4](0x50000000, 0x70000000), 4),
85                          0x60000000)
86         self.assertEqual(audioop.avg(packs[4](-0x50000000, -0x70000000), 4),
87                          -0x60000000)
88 
89     def test_avgpp(self):
90         for w in 1, 2, 4:
91             self.assertEqual(audioop.avgpp(b'', w), 0)
92             self.assertEqual(audioop.avgpp(packs[w](*range(100)), w), 0)
93             self.assertEqual(audioop.avgpp(packs[w](9, 10, 5, 5, 0, 1), w), 10)
94         self.assertEqual(audioop.avgpp(datas[1], 1), 196)
95         self.assertEqual(audioop.avgpp(datas[2], 2), 50534)
96         self.assertEqual(audioop.avgpp(datas[4], 4), 3311897002)
97 
98     def test_rms(self):
99         for w in 1, 2, 4:
100             self.assertEqual(audioop.rms(b'', w), 0)
101             p = packs[w]
102             self.assertEqual(audioop.rms(p(*range(100)), w), 57)
103             self.assertAlmostEqual(audioop.rms(p(maxvalues[w]) * 5, w),
104                                    maxvalues[w], delta=1)
105             self.assertAlmostEqual(audioop.rms(p(minvalues[w]) * 5, w),
106                                    -minvalues[w], delta=1)
107         self.assertEqual(audioop.rms(datas[1], 1), 77)
108         self.assertEqual(audioop.rms(datas[2], 2), 20001)
109         self.assertEqual(audioop.rms(datas[4], 4), 1310854152)
110 
111     def test_cross(self):
112         for w in 1, 2, 4:
113             self.assertEqual(audioop.cross(b'', w), -1)
114             p = packs[w]
115             self.assertEqual(audioop.cross(p(0, 1, 2), w), 0)
116             self.assertEqual(audioop.cross(p(1, 2, -3, -4), w), 1)
117             self.assertEqual(audioop.cross(p(-1, -2, 3, 4), w), 1)
118             self.assertEqual(audioop.cross(p(0, minvalues[w]), w), 1)
119             self.assertEqual(audioop.cross(p(minvalues[w], maxvalues[w]), w), 1)
120 
121     def test_add(self):
122         for w in 1, 2, 4:
123             self.assertEqual(audioop.add(b'', b'', w), b'')
124             self.assertEqual(audioop.add(datas[w], b'\0' * len(datas[w]), w),
125                              datas[w])
126         self.assertEqual(audioop.add(datas[1], datas[1], 1),
127                          b'\x00\x24\x7f\x80\x7f\x80\xfe')
128         self.assertEqual(audioop.add(datas[2], datas[2], 2),
129                 packs[2](0, 0x2468, 0x7fff, -0x8000, 0x7fff, -0x8000, -2))
130         self.assertEqual(audioop.add(datas[4], datas[4], 4),
131                 packs[4](0, 0x2468acf0, 0x7fffffff, -0x80000000,
132                        0x7fffffff, -0x80000000, -2))
133 
134     def test_bias(self):
135         for w in 1, 2, 4:
136             for bias in 0, 1, -1, 127, -128, 0x7fffffff, -0x80000000:
137                 self.assertEqual(audioop.bias(b'', w, bias), b'')
138         self.assertEqual(audioop.bias(datas[1], 1, 1),
139                          b'\x01\x13\x46\xbc\x80\x81\x00')
140         self.assertEqual(audioop.bias(datas[1], 1, -1),
141                          b'\xff\x11\x44\xba\x7e\x7f\xfe')
142         self.assertEqual(audioop.bias(datas[1], 1, 0x7fffffff),
143                          b'\xff\x11\x44\xba\x7e\x7f\xfe')
144         self.assertEqual(audioop.bias(datas[1], 1, -0x80000000),
145                          datas[1])
146         self.assertEqual(audioop.bias(datas[2], 2, 1),
147                 packs[2](1, 0x1235, 0x4568, -0x4566, -0x8000, -0x7fff, 0))
148         self.assertEqual(audioop.bias(datas[2], 2, -1),
149                 packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
150         self.assertEqual(audioop.bias(datas[2], 2, 0x7fffffff),
151                 packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
152         self.assertEqual(audioop.bias(datas[2], 2, -0x80000000),
153                 datas[2])
154         self.assertEqual(audioop.bias(datas[4], 4, 1),
155                 packs[4](1, 0x12345679, 0x456789ac, -0x456789aa,
156                          -0x80000000, -0x7fffffff, 0))
157         self.assertEqual(audioop.bias(datas[4], 4, -1),
158                 packs[4](-1, 0x12345677, 0x456789aa, -0x456789ac,
159                          0x7ffffffe, 0x7fffffff, -2))
160         self.assertEqual(audioop.bias(datas[4], 4, 0x7fffffff),
161                 packs[4](0x7fffffff, -0x6dcba989, -0x3a987656, 0x3a987654,
162                          -2, -1, 0x7ffffffe))
163         self.assertEqual(audioop.bias(datas[4], 4, -0x80000000),
164                 packs[4](-0x80000000, -0x6dcba988, -0x3a987655, 0x3a987655,
165                          -1, 0, 0x7fffffff))
166 
167     def test_lin2lin(self):
168         for w in 1, 2, 4:
169             self.assertEqual(audioop.lin2lin(datas[w], w, w), datas[w])
170 
171         self.assertEqual(audioop.lin2lin(datas[1], 1, 2),
172             packs[2](0, 0x1200, 0x4500, -0x4500, 0x7f00, -0x8000, -0x100))
173         self.assertEqual(audioop.lin2lin(datas[1], 1, 4),
174             packs[4](0, 0x12000000, 0x45000000, -0x45000000,
175                      0x7f000000, -0x80000000, -0x1000000))
176         self.assertEqual(audioop.lin2lin(datas[2], 2, 1),
177             b'\x00\x12\x45\xba\x7f\x80\xff')
178         self.assertEqual(audioop.lin2lin(datas[2], 2, 4),
179             packs[4](0, 0x12340000, 0x45670000, -0x45670000,
180                      0x7fff0000, -0x80000000, -0x10000))
181         self.assertEqual(audioop.lin2lin(datas[4], 4, 1),
182             b'\x00\x12\x45\xba\x7f\x80\xff')
183         self.assertEqual(audioop.lin2lin(datas[4], 4, 2),
184             packs[2](0, 0x1234, 0x4567, -0x4568, 0x7fff, -0x8000, -1))
185 
186     def test_adpcm2lin(self):
187         self.assertEqual(audioop.adpcm2lin(b'\x07\x7f\x7f', 1, None),
188                          (b'\x00\x00\x00\xff\x00\xff', (-179, 40)))
189         self.assertEqual(audioop.adpcm2lin(b'\x07\x7f\x7f', 2, None),
190                          (packs[2](0, 0xb, 0x29, -0x16, 0x72, -0xb3), (-179, 40)))
191         self.assertEqual(audioop.adpcm2lin(b'\x07\x7f\x7f', 4, None),
192                          (packs[4](0, 0xb0000, 0x290000, -0x160000, 0x720000,
193                                    -0xb30000), (-179, 40)))
194 
195         # Very cursory test
196         for w in 1, 2, 4:
197             self.assertEqual(audioop.adpcm2lin(b'\0' * 5, w, None),
198                              (b'\0' * w * 10, (0, 0)))
199 
200     def test_lin2adpcm(self):
201         self.assertEqual(audioop.lin2adpcm(datas[1], 1, None),
202                          (b'\x07\x7f\x7f', (-221, 39)))
203         self.assertEqual(audioop.lin2adpcm(datas[2], 2, None),
204                          (b'\x07\x7f\x7f', (31, 39)))
205         self.assertEqual(audioop.lin2adpcm(datas[4], 4, None),
206                          (b'\x07\x7f\x7f', (31, 39)))
207 
208         # Very cursory test
209         for w in 1, 2, 4:
210             self.assertEqual(audioop.lin2adpcm(b'\0' * w * 10, w, None),
211                              (b'\0' * 5, (0, 0)))
212 
213     def test_invalid_adpcm_state(self):
214         # state must be a tuple or None, not an integer
215         self.assertRaises(TypeError, audioop.adpcm2lin, b'\0', 1, 555)
216         self.assertRaises(TypeError, audioop.lin2adpcm, b'\0', 1, 555)
217         # Issues #24456, #24457: index out of range
218         self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, -1))
219         self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0, 89))
220         self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, -1))
221         self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0, 89))
222         # value out of range
223         self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (-0x8001, 0))
224         self.assertRaises(ValueError, audioop.adpcm2lin, b'\0', 1, (0x8000, 0))
225         self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (-0x8001, 0))
226         self.assertRaises(ValueError, audioop.lin2adpcm, b'\0', 1, (0x8000, 0))
227 
228     def test_lin2alaw(self):
229         self.assertEqual(audioop.lin2alaw(datas[1], 1),
230                          b'\xd5\x87\xa4\x24\xaa\x2a\x5a')
231         self.assertEqual(audioop.lin2alaw(datas[2], 2),
232                          b'\xd5\x87\xa4\x24\xaa\x2a\x55')
233         self.assertEqual(audioop.lin2alaw(datas[4], 4),
234                          b'\xd5\x87\xa4\x24\xaa\x2a\x55')
235 
236     def test_alaw2lin(self):
237         encoded = b'\x00\x03\x24\x2a\x51\x54\x55\x58\x6b\x71\x7f'\
238                   b'\x80\x83\xa4\xaa\xd1\xd4\xd5\xd8\xeb\xf1\xff'
239         src = [-688, -720, -2240, -4032, -9, -3, -1, -27, -244, -82, -106,
240                688, 720, 2240, 4032, 9, 3, 1, 27, 244, 82, 106]
241         for w in 1, 2, 4:
242             self.assertEqual(audioop.alaw2lin(encoded, w),
243                              packs[w](*(x << (w * 8) >> 13 for x in src)))
244 
245         encoded = ''.join(chr(x) for x in xrange(256))
246         for w in 2, 4:
247             decoded = audioop.alaw2lin(encoded, w)
248             self.assertEqual(audioop.lin2alaw(decoded, w), encoded)
249 
250     def test_lin2ulaw(self):
251         self.assertEqual(audioop.lin2ulaw(datas[1], 1),
252                          b'\xff\xad\x8e\x0e\x80\x00\x67')
253         self.assertEqual(audioop.lin2ulaw(datas[2], 2),
254                          b'\xff\xad\x8e\x0e\x80\x00\x7e')
255         self.assertEqual(audioop.lin2ulaw(datas[4], 4),
256                          b'\xff\xad\x8e\x0e\x80\x00\x7e')
257 
258     def test_ulaw2lin(self):
259         encoded = b'\x00\x0e\x28\x3f\x57\x6a\x76\x7c\x7e\x7f'\
260                   b'\x80\x8e\xa8\xbf\xd7\xea\xf6\xfc\xfe\xff'
261         src = [-8031, -4447, -1471, -495, -163, -53, -18, -6, -2, 0,
262                8031, 4447, 1471, 495, 163, 53, 18, 6, 2, 0]
263         for w in 1, 2, 4:
264             self.assertEqual(audioop.ulaw2lin(encoded, w),
265                              packs[w](*(x << (w * 8) >> 14 for x in src)))
266 
267         # Current u-law implementation has two codes fo 0: 0x7f and 0xff.
268         encoded = ''.join(chr(x) for x in range(127) + range(128, 256))
269         for w in 2, 4:
270             decoded = audioop.ulaw2lin(encoded, w)
271             self.assertEqual(audioop.lin2ulaw(decoded, w), encoded)
272 
273     def test_mul(self):
274         for w in 1, 2, 4:
275             self.assertEqual(audioop.mul(b'', w, 2), b'')
276             self.assertEqual(audioop.mul(datas[w], w, 0),
277                              b'\0' * len(datas[w]))
278             self.assertEqual(audioop.mul(datas[w], w, 1),
279                              datas[w])
280         self.assertEqual(audioop.mul(datas[1], 1, 2),
281                          b'\x00\x24\x7f\x80\x7f\x80\xfe')
282         self.assertEqual(audioop.mul(datas[2], 2, 2),
283                 packs[2](0, 0x2468, 0x7fff, -0x8000, 0x7fff, -0x8000, -2))
284         self.assertEqual(audioop.mul(datas[4], 4, 2),
285                 packs[4](0, 0x2468acf0, 0x7fffffff, -0x80000000,
286                          0x7fffffff, -0x80000000, -2))
287 
288     def test_ratecv(self):
289         for w in 1, 2, 4:
290             self.assertEqual(audioop.ratecv(b'', w, 1, 8000, 8000, None),
291                              (b'', (-1, ((0, 0),))))
292             self.assertEqual(audioop.ratecv(b'', w, 5, 8000, 8000, None),
293                              (b'', (-1, ((0, 0),) * 5)))
294             self.assertEqual(audioop.ratecv(b'', w, 1, 8000, 16000, None),
295                              (b'', (-2, ((0, 0),))))
296             self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None)[0],
297                              datas[w])
298             self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 1, 0)[0],
299                              datas[w])
300 
301         state = None
302         d1, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state)
303         d2, state = audioop.ratecv(b'\x00\x01\x02', 1, 1, 8000, 16000, state)
304         self.assertEqual(d1 + d2, b'\000\000\001\001\002\001\000\000\001\001\002')
305 
306         for w in 1, 2, 4:
307             d0, state0 = audioop.ratecv(datas[w], w, 1, 8000, 16000, None)
308             d, state = b'', None
309             for i in range(0, len(datas[w]), w):
310                 d1, state = audioop.ratecv(datas[w][i:i + w], w, 1,
311                                            8000, 16000, state)
312                 d += d1
313             self.assertEqual(d, d0)
314             self.assertEqual(state, state0)
315 
316         expected = {
317             1: packs[1](0, 0x0d, 0x37, -0x26, 0x55, -0x4b, -0x14),
318             2: packs[2](0, 0x0da7, 0x3777, -0x2630, 0x5673, -0x4a64, -0x129a),
319             4: packs[4](0, 0x0da740da, 0x37777776, -0x262fc962,
320                         0x56740da6, -0x4a62fc96, -0x1298bf26),
321         }
322         for w in 1, 2, 4:
323             self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 3, 1)[0],
324                              expected[w])
325             self.assertEqual(audioop.ratecv(datas[w], w, 1, 8000, 8000, None, 30, 10)[0],
326                              expected[w])
327 
328         self.assertRaises(TypeError, audioop.ratecv, b'', 1, 1, 8000, 8000, 42)
329         self.assertRaises(TypeError, audioop.ratecv,
330                           b'', 1, 1, 8000, 8000, (1, (42,)))
331 
332     def test_reverse(self):
333         for w in 1, 2, 4:
334             self.assertEqual(audioop.reverse(b'', w), b'')
335             self.assertEqual(audioop.reverse(packs[w](0, 1, 2), w),
336                              packs[w](2, 1, 0))
337 
338     def test_tomono(self):
339         for w in 1, 2, 4:
340             data1 = datas[w]
341             data2 = bytearray(2 * len(data1))
342             for k in range(w):
343                 data2[k::2*w] = data1[k::w]
344             self.assertEqual(audioop.tomono(str(data2), w, 1, 0), data1)
345             self.assertEqual(audioop.tomono(str(data2), w, 0, 1), b'\0' * len(data1))
346             for k in range(w):
347                 data2[k+w::2*w] = data1[k::w]
348             self.assertEqual(audioop.tomono(str(data2), w, 0.5, 0.5), data1)
349 
350     def test_tostereo(self):
351         for w in 1, 2, 4:
352             data1 = datas[w]
353             data2 = bytearray(2 * len(data1))
354             for k in range(w):
355                 data2[k::2*w] = data1[k::w]
356             self.assertEqual(audioop.tostereo(data1, w, 1, 0), data2)
357             self.assertEqual(audioop.tostereo(data1, w, 0, 0), b'\0' * len(data2))
358             for k in range(w):
359                 data2[k+w::2*w] = data1[k::w]
360             self.assertEqual(audioop.tostereo(data1, w, 1, 1), data2)
361 
362     def test_findfactor(self):
363         self.assertEqual(audioop.findfactor(datas[2], datas[2]), 1.0)
364         self.assertEqual(audioop.findfactor(b'\0' * len(datas[2]), datas[2]),
365                          0.0)
366 
367     def test_findfit(self):
368         self.assertEqual(audioop.findfit(datas[2], datas[2]), (0, 1.0))
369         self.assertEqual(audioop.findfit(datas[2], packs[2](1, 2, 0)),
370                          (1, 8038.8))
371         self.assertEqual(audioop.findfit(datas[2][:-2] * 5 + datas[2], datas[2]),
372                          (30, 1.0))
373 
374     def test_findmax(self):
375         self.assertEqual(audioop.findmax(datas[2], 1), 5)
376 
377     def test_getsample(self):
378         for w in 1, 2, 4:
379             data = packs[w](0, 1, -1, maxvalues[w], minvalues[w])
380             self.assertEqual(audioop.getsample(data, w, 0), 0)
381             self.assertEqual(audioop.getsample(data, w, 1), 1)
382             self.assertEqual(audioop.getsample(data, w, 2), -1)
383             self.assertEqual(audioop.getsample(data, w, 3), maxvalues[w])
384             self.assertEqual(audioop.getsample(data, w, 4), minvalues[w])
385 
386     def test_negativelen(self):
387         # from issue 3306, previously it segfaulted
388         self.assertRaises(audioop.error,
389             audioop.findmax, ''.join( chr(x) for x in xrange(256)), -2392392)
390 
391     def test_issue7673(self):
392         state = None
393         for data, size in INVALID_DATA:
394             size2 = size
395             self.assertRaises(audioop.error, audioop.getsample, data, size, 0)
396             self.assertRaises(audioop.error, audioop.max, data, size)
397             self.assertRaises(audioop.error, audioop.minmax, data, size)
398             self.assertRaises(audioop.error, audioop.avg, data, size)
399             self.assertRaises(audioop.error, audioop.rms, data, size)
400             self.assertRaises(audioop.error, audioop.avgpp, data, size)
401             self.assertRaises(audioop.error, audioop.maxpp, data, size)
402             self.assertRaises(audioop.error, audioop.cross, data, size)
403             self.assertRaises(audioop.error, audioop.mul, data, size, 1.0)
404             self.assertRaises(audioop.error, audioop.tomono, data, size, 0.5, 0.5)
405             self.assertRaises(audioop.error, audioop.tostereo, data, size, 0.5, 0.5)
406             self.assertRaises(audioop.error, audioop.add, data, data, size)
407             self.assertRaises(audioop.error, audioop.bias, data, size, 0)
408             self.assertRaises(audioop.error, audioop.reverse, data, size)
409             self.assertRaises(audioop.error, audioop.lin2lin, data, size, size2)
410             self.assertRaises(audioop.error, audioop.ratecv, data, size, 1, 1, 1, state)
411             self.assertRaises(audioop.error, audioop.lin2ulaw, data, size)
412             self.assertRaises(audioop.error, audioop.lin2alaw, data, size)
413             self.assertRaises(audioop.error, audioop.lin2adpcm, data, size, state)
414 
415     def test_wrongsize(self):
416         data = b'abcdefgh'
417         state = None
418         for size in (-1, 0, 3, 5, 1024):
419             self.assertRaises(audioop.error, audioop.ulaw2lin, data, size)
420             self.assertRaises(audioop.error, audioop.alaw2lin, data, size)
421             self.assertRaises(audioop.error, audioop.adpcm2lin, data, size, state)
422 
423 def test_main():
424     run_unittest(TestAudioop)
425 
426 if __name__ == '__main__':
427     test_main()
428