Skip to content

Commit 80b360a

Browse files
committed
bpo-32990: Support WAVE_FORMAT_EXTENSIBLE in the wave module
The test file, a modified version of Lib/test/audiodata/pluck-pcm24.wav, was provided by Andrea Celletti on the bug tracker.
1 parent c87d9f4 commit 80b360a

File tree

4 files changed

+44
-11
lines changed

4 files changed

+44
-11
lines changed
19.5 KB
Binary file not shown.

Lib/test/test_wave.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,33 @@ class WavePCM24Test(WaveTest, unittest.TestCase):
7878
frames = byteswap(frames, 3)
7979

8080

81+
class WavePCM24ExtTest(WaveTest, unittest.TestCase):
82+
sndfilename = 'pluck-pcm24-ext.wav'
83+
sndfilenframes = 3307
84+
nchannels = 2
85+
sampwidth = 3
86+
framerate = 11025
87+
nframes = 48
88+
comptype = 'NONE'
89+
compname = 'not compressed'
90+
frames = bytes.fromhex("""\
91+
022D65FFEB9D 4B5A0F00FA54 3113C304EE2B 80DCD6084303 \
92+
CBDEC006B261 48A99803F2F8 BFE82401B07D 036BFBFE7B5D \
93+
B85756FA3EC9 B4B055F3502B 299830EBCB62 1A5CA7E6D99A \
94+
EDFA3EE491BD C625EBE27884 0E05A9E0B6CF EF2929E02922 \
95+
5758D8E27067 FB3557E83E16 1377BFEF8402 D82C5BF7272A \
96+
978F16FB7745 F5F865FC1013 086635FB9C4E DF30FCFB40EE \
97+
117FE0FA3438 3EE6B8FB5AC3 BC77A3FCB2F4 66D6DAFF5F32 \
98+
CF13B9041275 431D69097A8C C1BB600EC74E 5120B912A2BA \
99+
EEDF641754C0 8207001664B7 7FFFFF14453F 8000001294E6 \
100+
499C1B0EB3B2 52B73E0DBCA0 EFB2B20F5FD8 CE3CDB0FBE12 \
101+
E4B49C0CEA2D 6344A80A5A7C 08C8FE0A1FFE 2BB9860B0A0E \
102+
51486F0E44E1 8BCC64113B05 B6F4EC0EEB36 4413170A5B48 \
103+
""")
104+
if sys.byteorder != 'big':
105+
frames = byteswap(frames, 3)
106+
107+
81108
class WavePCM32Test(WaveTest, unittest.TestCase):
82109
sndfilename = 'pluck-pcm32.wav'
83110
sndfilenframes = 3307
@@ -109,7 +136,7 @@ class MiscTestCase(audiotests.AudioMiscTests, unittest.TestCase):
109136
module = wave
110137

111138
def test__all__(self):
112-
blacklist = {'WAVE_FORMAT_PCM'}
139+
blacklist = {'WAVE_FORMAT_PCM', 'WAVE_FORMAT_EXTENSIBLE'}
113140
support.check__all__(self, wave, blacklist=blacklist)
114141

115142

Lib/wave.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class Error(Exception):
7979
pass
8080

8181
WAVE_FORMAT_PCM = 0x0001
82+
WAVE_FORMAT_EXTENSIBLE = 0xFFFE
8283

8384
_array_fmts = None, 'b', 'h', None, 'i'
8485

@@ -254,19 +255,22 @@ def readframes(self, nframes):
254255

255256
def _read_fmt_chunk(self, chunk):
256257
try:
257-
wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
258+
wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, \
259+
wBlockAlign, wBitsPerSample = \
260+
struct.unpack_from('<HHLLHH', chunk.read(16))
258261
except struct.error:
259262
raise EOFError from None
260-
if wFormatTag == WAVE_FORMAT_PCM:
261-
try:
262-
sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
263-
except struct.error:
264-
raise EOFError from None
265-
self._sampwidth = (sampwidth + 7) // 8
266-
if not self._sampwidth:
267-
raise Error('bad sample width')
268-
else:
263+
if wFormatTag == WAVE_FORMAT_EXTENSIBLE:
264+
# Only the first 2 bytes (of 16) of SubFormat are needed.
265+
cbSize, wValidBitsPerSample, dwChannelMask, \
266+
SubFormatFmt = struct.unpack_from('<HHLH', chunk.read(10))
267+
if SubFormatFmt != WAVE_FORMAT_PCM:
268+
raise Error(f'unknown format: {SubFormatFmt}')
269+
elif wFormatTag != WAVE_FORMAT_PCM:
269270
raise Error('unknown format: %r' % (wFormatTag,))
271+
self._sampwidth = (wBitsPerSample + 7) // 8
272+
if not self._sampwidth:
273+
raise Error('bad sample width')
270274
if not self._nchannels:
271275
raise Error('bad # of channels')
272276
self._framesize = self._nchannels * self._sampwidth
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Support reading wave files with the ``WAVE_FORMAT_EXTENSIBLE`` format in the
2+
:mod:`wave` module.

0 commit comments

Comments
 (0)