|
6 | 6 | from tempfile import TemporaryFile, NamedTemporaryFile
|
7 | 7 | import wave
|
8 | 8 | import sys
|
| 9 | +import struct |
9 | 10 | from .logging_utils import log_conversion
|
10 | 11 |
|
11 | 12 | try:
|
12 | 13 | from StringIO import StringIO
|
13 | 14 | except:
|
14 |
| - from io import StringIO, BytesIO |
| 15 | + from io import StringIO |
| 16 | + |
| 17 | +from io import BytesIO |
15 | 18 |
|
16 | 19 | try:
|
17 | 20 | from itertools import izip
|
@@ -150,15 +153,24 @@ def __init__(self, data=None, *args, **kwargs):
|
150 | 153 | # Convert 24-bit audio to 32-bit audio.
|
151 | 154 | # (stdlib audioop and array modules do not support 24-bit data)
|
152 | 155 | if self.sample_width == 3:
|
153 |
| - # Pad each triplet of bytes with one more byte, either 0 or 0xFF. |
154 |
| - padding = {False: b'\x00', True: b'\xFF'} |
155 |
| - pad_byte = lambda b: bytes(b) + padding[b[-1] > b'\x7f'[0]] |
| 156 | + byte_buffer = BytesIO() |
| 157 | + |
| 158 | + # Workaround for python 2 vs python 3. _data in 2.x are length-1 strings, |
| 159 | + # And in 3.x are ints. |
| 160 | + pack_fmt = 'BBB' if isinstance(self._data[0], int) else 'ccc' |
156 | 161 |
|
157 |
| - i = iter(self._data) |
158 | 162 | # This conversion maintains the 24 bit values. The values are
|
159 | 163 | # not scaled up to the 32 bit range. Other conversions could be
|
160 | 164 | # implemented.
|
161 |
| - self._data = b''.join(pad_byte(t) for t in izip(i, i, i)) |
| 165 | + i = iter(self._data) |
| 166 | + padding = {False: b'\x00', True: b'\xFF'} |
| 167 | + for b0, b1, b2 in izip(i, i, i): |
| 168 | + byte_buffer.write(padding[b2 > b'\x7f'[0]]) |
| 169 | + old_bytes = struct.pack(pack_fmt, b0, b1, b2) |
| 170 | + byte_buffer.write(old_bytes) |
| 171 | + |
| 172 | + |
| 173 | + self._data = byte_buffer.getvalue() |
162 | 174 | self.sample_width = 4
|
163 | 175 | self.frame_width = self.channels * self.sample_width
|
164 | 176 |
|
|
0 commit comments