From a44372fd0b143947b86926d9377f2b4c3a585dca Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 9 Nov 2013 23:12:06 +0200 Subject: [PATCH] Issue #1575020: Fixed support of 24-bit wave files on big-endian platforms. --- Lib/test/test_wave.py | 3 --- Lib/wave.py | 21 +++++++++++++-------- Misc/NEWS | 2 ++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index b4413c665b3..cf069ae7713 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -49,9 +49,6 @@ class WavePCM16Test(audiotests.AudioWriteTests, frames = audiotests.byteswap2(frames) -@unittest.skipIf(sys.byteorder == 'big', - '24-bit wave files are supported only on little-endian ' - 'platforms') class WavePCM24Test(audiotests.AudioWriteTests, audiotests.AudioTestsWithSourceFile, unittest.TestCase): diff --git a/Lib/wave.py b/Lib/wave.py index a1daead8abd..6285c748765 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -82,15 +82,16 @@ WAVE_FORMAT_PCM = 0x0001 _array_fmts = None, 'b', 'h', None, 'i' -# Determine endian-ness import struct -if struct.pack("h", 1) == b"\000\001": - big_endian = 1 -else: - big_endian = 0 - +import sys from chunk import Chunk +def _byteswap3(data): + ba = bytearray(data) + ba[::3] = data[2::3] + ba[2::3] = data[::3] + return bytes(ba) + class Wave_read: """Variables used in this class: @@ -231,7 +232,7 @@ class Wave_read: self._data_seek_needed = 0 if nframes == 0: return b'' - if self._sampwidth > 1 and big_endian: + if self._sampwidth in (2, 4) and sys.byteorder == 'big': # unfortunately the fromfile() method does not take # something that only looks like a file object, so # we have to reach into the innards of the chunk object @@ -252,6 +253,8 @@ class Wave_read: data = data.tobytes() else: data = self._data_chunk.read(nframes * self._framesize) + if self._sampwidth == 3 and sys.byteorder == 'big': + data = _byteswap3(data) if self._convert and data: data = self._convert(data) self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth) @@ -419,7 +422,7 @@ class Wave_write: nframes = len(data) // (self._sampwidth * self._nchannels) if self._convert: data = self._convert(data) - if self._sampwidth > 1 and big_endian: + if self._sampwidth in (2, 4) and sys.byteorder == 'big': import array data = array.array(_array_fmts[self._sampwidth], data) assert data.itemsize == self._sampwidth @@ -427,6 +430,8 @@ class Wave_write: data.tofile(self._file) self._datawritten = self._datawritten + len(data) * self._sampwidth else: + if self._sampwidth == 3 and sys.byteorder == 'big': + data = _byteswap3(data) self._file.write(data) self._datawritten = self._datawritten + len(data) self._nframeswritten = self._nframeswritten + nframes diff --git a/Misc/NEWS b/Misc/NEWS index e4e2e140b4e..e96504e9a10 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Core and Builtins Library ------- +- Issue #1575020: Fixed support of 24-bit wave files on big-endian platforms. + - Issue #19480: HTMLParser now accepts all valid start-tag names as defined by the HTML5 standard.