From 747ef70faa8637ccf6dd896323fa84aee8f14513 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 13 Mar 2026 18:51:23 +0100 Subject: [PATCH] GH-60729: Revert "Add IEEE format wave audio support (GH-145384)" (GH-145928) Revert "GH-60729: Add IEEE format wave audio support (GH-145384)" This reverts commit 61f2a1a5993967ed4b97ba93a4477c37fe68cf59 for now; as tests fail on big-endian machines. --- Doc/library/wave.rst | 69 +------ Doc/whatsnew/3.15.rst | 15 -- Lib/test/audiodata/pluck-float32.wav | Bin 26514 -> 0 bytes Lib/test/audiotests.py | 16 +- Lib/test/test_wave.py | 188 +----------------- Lib/wave.py | 88 ++------ ...3-03-10-13-10-06.gh-issue-60729.KCCHTe.rst | 1 - 7 files changed, 25 insertions(+), 352 deletions(-) delete mode 100644 Lib/test/audiodata/pluck-float32.wav delete mode 100644 Misc/NEWS.d/next/Library/2023-03-10-13-10-06.gh-issue-60729.KCCHTe.rst diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 9d30a14f1129..ff020b52da3f 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -9,19 +9,14 @@ -------------- The :mod:`!wave` module provides a convenient interface to the Waveform Audio -"WAVE" (or "WAV") file format. - -The module supports uncompressed PCM and IEEE floating-point WAV formats. +"WAVE" (or "WAV") file format. Only uncompressed PCM encoded wave files are +supported. .. versionchanged:: 3.12 Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the extended format is ``KSDATAFORMAT_SUBTYPE_PCM``. -.. versionchanged:: next - - Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added. - The :mod:`!wave` module defines the following function and exception: @@ -65,21 +60,6 @@ The :mod:`!wave` module defines the following function and exception: specification or hits an implementation deficiency. -.. data:: WAVE_FORMAT_PCM - - Format code for uncompressed PCM audio. - - -.. data:: WAVE_FORMAT_IEEE_FLOAT - - Format code for IEEE floating-point audio. - - -.. data:: WAVE_FORMAT_EXTENSIBLE - - Format code for WAVE extensible headers. - - .. _wave-read-objects: Wave_read Objects @@ -118,14 +98,6 @@ Wave_read Objects Returns number of audio frames. - .. method:: getformat() - - Returns the frame format code. - - This is one of :data:`WAVE_FORMAT_PCM`, - :data:`WAVE_FORMAT_IEEE_FLOAT`, or :data:`WAVE_FORMAT_EXTENSIBLE`. - - .. method:: getcomptype() Returns compression type (``'NONE'`` is the only supported type). @@ -140,8 +112,8 @@ Wave_read Objects .. method:: getparams() Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth, - framerate, nframes, comptype, compname)``, equivalent to output - of the ``get*()`` methods. + framerate, nframes, comptype, compname)``, equivalent to output of the + ``get*()`` methods. .. method:: readframes(n) @@ -218,9 +190,6 @@ Wave_write Objects Set the sample width to *n* bytes. - For :data:`WAVE_FORMAT_IEEE_FLOAT`, only 4-byte (32-bit) and - 8-byte (64-bit) sample widths are supported. - .. method:: getsampwidth() @@ -269,32 +238,11 @@ Wave_write Objects Return the human-readable compression type name. - .. method:: setformat(format) - - Set the frame format code. - - Supported values are :data:`WAVE_FORMAT_PCM` and - :data:`WAVE_FORMAT_IEEE_FLOAT`. - - When setting :data:`WAVE_FORMAT_IEEE_FLOAT`, the sample width must be - 4 or 8 bytes. - - - .. method:: getformat() - - Return the current frame format code. - - .. method:: setparams(tuple) - The *tuple* should be - ``(nchannels, sampwidth, framerate, nframes, comptype, compname, format)``, - with values valid for the ``set*()`` methods. Sets all parameters. - - For backwards compatibility, a 6-item tuple without *format* is also - accepted and defaults to :data:`WAVE_FORMAT_PCM`. - - For ``format=WAVE_FORMAT_IEEE_FLOAT``, *sampwidth* must be 4 or 8. + The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype, + compname)``, with values valid for the ``set*()`` methods. Sets all + parameters. .. method:: getparams() @@ -331,6 +279,3 @@ Wave_write Objects Note that it is invalid to set any parameters after calling :meth:`writeframes` or :meth:`writeframesraw`, and any attempt to do so will raise :exc:`wave.Error`. - - For :data:`WAVE_FORMAT_IEEE_FLOAT` output, a ``fact`` chunk is written as - required by the WAVE specification for non-PCM formats. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index d5b142167709..459846e55ccf 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -1518,21 +1518,6 @@ typing wave ---- -* Added support for IEEE floating-point WAVE audio - (``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`. - -* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`, - and :meth:`wave.Wave_write.setformat` for explicit frame format handling. - -* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including - ``format`` and 6-item tuples for backwards compatibility (defaulting to - ``WAVE_FORMAT_PCM``). - -* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk, - as required for non-PCM WAVE formats. - -(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.) - * Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes, which were deprecated since Python 3.13. diff --git a/Lib/test/audiodata/pluck-float32.wav b/Lib/test/audiodata/pluck-float32.wav deleted file mode 100644 index 2030fb16d6e3bd797523605091ff1d732b432b88..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 26514 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 diff --git a/Lib/test/audiotests.py b/Lib/test/audiotests.py index 394097df17dc..9d6c4cc2b4b0 100644 --- a/Lib/test/audiotests.py +++ b/Lib/test/audiotests.py @@ -27,18 +27,17 @@ class AudioTests: unlink(TESTFN) def check_params(self, f, nchannels, sampwidth, framerate, nframes, - comptype, compname, format): + comptype, compname): self.assertEqual(f.getnchannels(), nchannels) self.assertEqual(f.getsampwidth(), sampwidth) self.assertEqual(f.getframerate(), framerate) self.assertEqual(f.getnframes(), nframes) self.assertEqual(f.getcomptype(), comptype) self.assertEqual(f.getcompname(), compname) - self.assertEqual(f.getformat(), format) params = f.getparams() self.assertEqual(params, - (nchannels, sampwidth, framerate, nframes, comptype, compname)) + (nchannels, sampwidth, framerate, nframes, comptype, compname)) self.assertEqual(params.nchannels, nchannels) self.assertEqual(params.sampwidth, sampwidth) self.assertEqual(params.framerate, framerate) @@ -52,17 +51,13 @@ class AudioTests: class AudioWriteTests(AudioTests): - readonly = False def create_file(self, testfile): - if self.readonly: - self.skipTest('Read only file format') f = self.fout = self.module.open(testfile, 'wb') f.setnchannels(self.nchannels) f.setsampwidth(self.sampwidth) f.setframerate(self.framerate) f.setcomptype(self.comptype, self.compname) - f.setformat(self.format) return f def check_file(self, testfile, nframes, frames): @@ -72,14 +67,13 @@ class AudioWriteTests(AudioTests): self.assertEqual(f.getframerate(), self.framerate) self.assertEqual(f.getnframes(), nframes) self.assertEqual(f.readframes(nframes), frames) - self.assertEqual(f.getformat(), self.format) def test_write_params(self): f = self.create_file(TESTFN) f.setnframes(self.nframes) f.writeframes(self.frames) self.check_params(f, self.nchannels, self.sampwidth, self.framerate, - self.nframes, self.comptype, self.compname, self.format) + self.nframes, self.comptype, self.compname) f.close() def test_write_context_manager_calls_close(self): @@ -263,7 +257,7 @@ class AudioTestsWithSourceFile(AudioTests): f = self.f = self.module.open(self.sndfilepath) #self.assertEqual(f.getfp().name, self.sndfilepath) self.check_params(f, self.nchannels, self.sampwidth, self.framerate, - self.sndfilenframes, self.comptype, self.compname, self.format) + self.sndfilenframes, self.comptype, self.compname) def test_close(self): with open(self.sndfilepath, 'rb') as testfile: @@ -304,8 +298,6 @@ class AudioTestsWithSourceFile(AudioTests): f.setpos(f.getnframes() + 1) def test_copy(self): - if self.readonly: - self.skipTest('Read only file format') f = self.f = self.module.open(self.sndfilepath) fout = self.fout = self.module.open(TESTFN, 'wb') fout.setparams(f.getparams()) diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index a1afe91e3774..4c21f1655377 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -1,7 +1,7 @@ import unittest from test import audiotests from test import support -from test.support.os_helper import FakePath, unlink +from test.support.os_helper import FakePath import io import os import struct @@ -22,7 +22,6 @@ class WavePCM8Test(WaveTest, unittest.TestCase): sampwidth = 1 framerate = 11025 nframes = 48 - format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -40,7 +39,6 @@ class WavePCM16Test(WaveTest, unittest.TestCase): sampwidth = 2 framerate = 11025 nframes = 48 - format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -62,7 +60,6 @@ class WavePCM24Test(WaveTest, unittest.TestCase): sampwidth = 3 framerate = 11025 nframes = 48 - format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -90,8 +87,6 @@ class WavePCM24ExtTest(WaveTest, unittest.TestCase): sampwidth = 3 framerate = 11025 nframes = 48 - format = wave.WAVE_FORMAT_EXTENSIBLE - readonly = True # Writing EXTENSIBLE wave format is not supported. comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -119,7 +114,6 @@ class WavePCM32Test(WaveTest, unittest.TestCase): sampwidth = 4 framerate = 11025 nframes = 48 - format = wave.WAVE_FORMAT_PCM comptype = 'NONE' compname = 'not compressed' frames = bytes.fromhex("""\ @@ -140,140 +134,14 @@ class WavePCM32Test(WaveTest, unittest.TestCase): frames = wave._byteswap(frames, 4) -class WaveIeeeFloatingPointTest(WaveTest, unittest.TestCase): - sndfilename = 'pluck-float32.wav' - sndfilenframes = 3307 - nchannels = 2 - sampwidth = 4 - framerate = 11025 - nframes = 48 - format = wave.WAVE_FORMAT_IEEE_FLOAT - comptype = 'NONE' - compname = 'not compressed' - frames = bytes.fromhex("""\ - 60598B3C001423BA 1FB4163F8054FA3B 0E4FC43E80C51D3D 53467EBF4030843D \ - FC84D0BE304C563D 3053113F40BEFC3C B72F00BFC03E583C E0FEDA3C805142BC \ - 54510FBFE02638BD 569F16BF40FDCABD C060A63EECA421BE 3CE5523E2C3349BE \ - 0C2E10BE14725BBE 5268E7BEDC3B6CBE 985AE03D80497ABE B4B606BEECB67EBE \ - B0B12E3FC87C6CBE 005519BD4C0F3EBE F8BD1B3EECDF03BE 924E9FBE588D8DBD \ - D4E150BF501711BD B079A0BD20FBFBBC 5863863D40760CBD 0E3C83BE40E217BD \ - 04FF0B3EF07839BD E29AFB3E80A714BD B91007BFE042D3BC B5AD4D3F80CDA0BB \ - 1AB1C3BEB04E023D D33A063FC0A8973D 8012F9BEE074EC3D 7341223FD415153E \ - D80409BE04A63A3E 00F27BBFBC25333E 0000803FFC29223E 000080BF38A7143E \ - 3638133F283BEB3D 7C6E253F00CADB3D 686A02BE88FDF53D 920CC7BE28E1FB3D \ - 185B5ABED8A2CE3D 5189463FC8A7A53D E88F8C3DF0FFA13D 1CE6AE3EE0A0B03D \ - DF90223F184EE43D 376768BF2CD8093E 281612BF60B3EE3D 2F26083F88B4A53D \ - """) - class MiscTestCase(unittest.TestCase): def test__all__(self): - not_exported = {'KSDATAFORMAT_SUBTYPE_PCM'} + not_exported = {'WAVE_FORMAT_PCM', 'WAVE_FORMAT_EXTENSIBLE', 'KSDATAFORMAT_SUBTYPE_PCM'} support.check__all__(self, wave, not_exported=not_exported) class WaveLowLevelTest(unittest.TestCase): - def test_setparams_6_tuple_defaults_to_pcm(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) - w.setparams((1, 2, 22050, 0, 'NONE', 'not compressed')) - self.assertEqual(w.getformat(), wave.WAVE_FORMAT_PCM) - - def test_setparams_7_tuple_uses_format(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setparams((1, 4, 22050, 0, 'NONE', 'not compressed', - wave.WAVE_FORMAT_IEEE_FLOAT)) - self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) - - def test_setparams_7_tuple_ieee_64bit_sampwidth(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setparams((1, 8, 22050, 0, 'NONE', 'not compressed', - wave.WAVE_FORMAT_IEEE_FLOAT)) - self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) - self.assertEqual(w.getsampwidth(), 8) - - def test_getparams_backward_compatible_shape(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setparams((1, 4, 22050, 0, 'NONE', 'not compressed', - wave.WAVE_FORMAT_IEEE_FLOAT)) - params = w.getparams() - self.assertEqual(params, (1, 4, 22050, 0, 'NONE', 'not compressed')) - - def test_getformat_setformat(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setnchannels(1) - w.setsampwidth(4) - w.setframerate(22050) - self.assertEqual(w.getformat(), wave.WAVE_FORMAT_PCM) - w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) - self.assertEqual(w.getformat(), wave.WAVE_FORMAT_IEEE_FLOAT) - - def test_setformat_ieee_requires_32_or_64_bit_sampwidth(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setnchannels(1) - w.setsampwidth(2) - w.setframerate(22050) - with self.assertRaisesRegex(wave.Error, - 'unsupported sample width for IEEE float format'): - w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) - - def test_setsampwidth_ieee_requires_32_or_64_bit(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setnchannels(1) - w.setframerate(22050) - w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) - with self.assertRaisesRegex(wave.Error, - 'unsupported sample width for IEEE float format'): - w.setsampwidth(2) - w.setsampwidth(4) - - def test_setsampwidth_ieee_accepts_64_bit(self): - with tempfile.NamedTemporaryFile(delete_on_close=False) as fp: - filename = fp.name - self.addCleanup(unlink, filename) - - with wave.open(filename, 'wb') as w: - w.setnchannels(1) - w.setframerate(22050) - w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT) - w.setsampwidth(8) - self.assertEqual(w.getsampwidth(), 8) - - def test_read_getformat(self): - b = b'RIFF' + struct.pack(' 4: + if sampwidth < 1 or sampwidth > 4: raise Error('bad sample width') self._sampwidth = sampwidth @@ -546,18 +518,6 @@ class Wave_write: self._comptype = comptype self._compname = compname - def setformat(self, format): - if self._datawritten: - raise Error('cannot change parameters after starting to write') - if format not in (WAVE_FORMAT_IEEE_FLOAT, WAVE_FORMAT_PCM): - raise Error('unsupported wave format') - if format == WAVE_FORMAT_IEEE_FLOAT and self._sampwidth and self._sampwidth not in (4, 8): - raise Error('unsupported sample width for IEEE float format') - self._format = format - - def getformat(self): - return self._format - def getcomptype(self): return self._comptype @@ -565,15 +525,10 @@ class Wave_write: return self._compname def setparams(self, params): + nchannels, sampwidth, framerate, nframes, comptype, compname = params if self._datawritten: raise Error('cannot change parameters after starting to write') - if len(params) == 6: - nchannels, sampwidth, framerate, nframes, comptype, compname = params - format = WAVE_FORMAT_PCM - else: - nchannels, sampwidth, framerate, nframes, comptype, compname, format = params self.setnchannels(nchannels) - self.setformat(format) self.setsampwidth(sampwidth) self.setframerate(framerate) self.setnframes(nframes) @@ -634,9 +589,6 @@ class Wave_write: raise Error('sampling rate not specified') self._write_header(datasize) - def _needs_fact_chunk(self): - return self._format == WAVE_FORMAT_IEEE_FLOAT - def _write_header(self, initlength): assert not self._headerwritten self._file.write(b'RIFF') @@ -647,23 +599,12 @@ class Wave_write: self._form_length_pos = self._file.tell() except (AttributeError, OSError): self._form_length_pos = None - has_fact = self._needs_fact_chunk() - header_overhead = 36 + (12 if has_fact else 0) - self._file.write(struct.pack('