Skip to content

Commit 92338f8

Browse files
gh-77171 Support WAVE_FORMAT_EXTENSIBLE in the wave module (GH-96777)
The test file, a modified version of Lib/test/audiodata/pluck-pcm24.wav, was provided by Andrea Celletti on the bug tracker. Co-authored-by: Zackery Spytz <[email protected]>
1 parent 4781535 commit 92338f8

File tree

4 files changed

+46
-8
lines changed

4 files changed

+46
-8
lines changed
19.5 KB
Binary file not shown.

Lib/test/test_wave.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,33 @@ class WavePCM24Test(WaveTest, unittest.TestCase):
7777
frames = wave._byteswap(frames, 3)
7878

7979

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

107134
class MiscTestCase(unittest.TestCase):
108135
def test__all__(self):
109-
support.check__all__(self, wave, not_exported={'WAVE_FORMAT_PCM'})
136+
not_exported = {'WAVE_FORMAT_PCM', 'WAVE_FORMAT_EXTENSIBLE'}
137+
support.check__all__(self, wave, not_exported=not_exported)
110138

111139

112140
class WaveLowLevelTest(unittest.TestCase):

Lib/wave.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class Error(Exception):
8383
pass
8484

8585
WAVE_FORMAT_PCM = 0x0001
86+
WAVE_FORMAT_EXTENSIBLE = 0xFFFE
8687

8788
_array_fmts = None, 'b', 'h', None, 'i'
8889

@@ -377,16 +378,23 @@ def _read_fmt_chunk(self, chunk):
377378
wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
378379
except struct.error:
379380
raise EOFError from None
380-
if wFormatTag == WAVE_FORMAT_PCM:
381+
if wFormatTag != WAVE_FORMAT_PCM and wFormatTag != WAVE_FORMAT_EXTENSIBLE:
382+
raise Error('unknown format: %r' % (wFormatTag,))
383+
try:
384+
sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
385+
except struct.error:
386+
raise EOFError from None
387+
if wFormatTag == WAVE_FORMAT_EXTENSIBLE:
381388
try:
382-
sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
389+
# Only the first 2 bytes (of 16) of SubFormat are needed.
390+
cbSize, wValidBitsPerSample, dwChannelMask, SubFormatFmt = struct.unpack_from('<HHLH', chunk.read(10))
383391
except struct.error:
384392
raise EOFError from None
385-
self._sampwidth = (sampwidth + 7) // 8
386-
if not self._sampwidth:
387-
raise Error('bad sample width')
388-
else:
389-
raise Error('unknown format: %r' % (wFormatTag,))
393+
if SubFormatFmt != WAVE_FORMAT_PCM:
394+
raise Error(f'unknown format: {SubFormatFmt}')
395+
self._sampwidth = (sampwidth + 7) // 8
396+
if not self._sampwidth:
397+
raise Error('bad sample width')
390398
if not self._nchannels:
391399
raise Error('bad # of channels')
392400
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)