You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Support 24-bit audio, even if running on old versions of Python that don't support 24-bit audio in the audioop module. Remove FLAC support for platforms that don't really work reliably.
Copy file name to clipboardexpand all lines: reference/library-reference.rst
+2
Original file line number
Diff line number
Diff line change
@@ -301,6 +301,8 @@ Writing these bytes directly to a file results in a valid `AIFF-C file <https://
301
301
302
302
Returns a byte string representing the contents of a FLAC file containing the audio represented by the ``AudioData`` instance.
303
303
304
+
Note that 32-bit FLAC is not supported. If the audio data is 32-bit and ``convert_width`` is not specified, then the resulting FLAC will be a 24-bit FLAC.
305
+
304
306
If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.
305
307
306
308
If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.
# 24-bit audio needs some special handling for old Python versions (workaround for https://bugs.python.org/issue12866)
207
+
samples_24_bit_pretending_to_be_32_bit=False
208
+
try: audioop.bias(b"", 3, 0) # test whether this sample width is supported (for example, ``audioop`` in Python 3.3 and below don't support sample width 3, while Python 3.4+ do)
209
+
exceptaudioop.error: # this version of audioop doesn't support 24-bit audio (probably Python 3.3 or less)
210
+
samples_24_bit_pretending_to_be_32_bit=True# while the ``AudioFile`` instance will outwardly appear to be 32-bit, it will actually internally be 24-bit
211
+
self.SAMPLE_WIDTH=4# the ``AudioFile`` instance should present itself as a 32-bit stream now, since we'll be converting into 32-bit on the fly when reading
self.audio_reader=audio_reader# an audio file object (e.g., a `wave.Wave_read` instance)
229
+
self.little_endian=little_endian# whether the audio data is little-endian (when working with big-endian things, we'll have to convert it to little-endian before we process it)
230
+
self.samples_24_bit_pretending_to_be_32_bit=samples_24_bit_pretending_to_be_32_bit# this is true if the audio is 24-bit audio, but 24-bit audio isn't supported, so we have to pretend that this is 32-bit audio and convert it on the fly
ifnotisinstance(buffer, bytes): buffer=b""# workaround for https://bugs.python.org/issue24608
223
235
224
236
sample_width=self.audio_reader.getsampwidth()
225
237
ifnotself.little_endian: # big endian format, convert to little endian on the fly
226
-
ifhasattr(audioop, "byteswap"): # ``audioop.byteswap`` was only added in Python 3.4
238
+
ifhasattr(audioop, "byteswap"): # ``audioop.byteswap`` was only added in Python 3.4 (incidentally, that also means that we don't need to worry about 24-bit audio being unsupported, since Python 3.4+ always has that functionality)
227
239
buffer=audioop.byteswap(buffer, sample_width)
228
240
else: # manually reverse the bytes of each sample, which is slower but works well enough as a fallback
# workaround for https://bugs.python.org/issue12866
244
+
ifself.samples_24_bit_pretending_to_be_32_bit: # we need to convert samples from 24-bit to 32-bit before we can process them with ``audioop`` functions
245
+
buffer=b"".join("\x00"+buffer[i:i+sample_width] foriinrange(0, len(buffer), sample_width)) # since we're in little endian, we prepend a zero byte to each 24-bit sample to get a 32-bit sample
ifconvert_width==3: # we're converting the audio into 24-bit (workaround for https://bugs.python.org/issue12866)
284
+
raw_data=audioop.lin2lin(raw_data, self.sample_width, 4) # convert audio into 32-bit first, which is always supported
285
+
try: audioop.bias(b"", 3, 0) # test whether 24-bit audio is supported (for example, ``audioop`` in Python 3.3 and below don't support sample width 3, while Python 3.4+ do)
286
+
exceptaudioop.error: # this version of audioop doesn't support 24-bit audio (probably Python 3.3 or less)
287
+
raw_data=b"".join(raw_data[i+1:i+4] foriinrange(0, len(raw_data), 4)) # since we're in little endian, we discard the first byte from each 32-bit sample to get a 24-bit sample
288
+
else: # 24-bit audio fully supported, we don't need to shim anything
Returns a byte string representing the contents of a FLAC file containing the audio represented by the ``AudioData`` instance.
339
362
363
+
Note that 32-bit FLAC is not supported. If the audio data is 32-bit and ``convert_width`` is not specified, then the resulting FLAC will be a 24-bit FLAC.
364
+
340
365
If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.
341
366
342
367
If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.
343
368
344
369
Writing these bytes directly to a file results in a valid `FLAC file <https://en.wikipedia.org/wiki/FLAC>`__.
345
370
"""
371
+
assertconvert_widthisNoneor (convert_width%1==0and1<=convert_width<=3), "Sample width to convert to must be between 1 and 3 inclusive"
372
+
373
+
ifself.sample_width>3andconvert_widthisNone: # resulting WAV data would be 32-bit, which is not convertable to FLAC using our encoder
374
+
convert_width=3# the largest supported sample width is 24-bit, so we'll limit the sample width to that
375
+
346
376
# run the FLAC converter with the WAV data to get the FLAC data
0 commit comments