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 61f2a1a599 for now;
as tests fail on big-endian machines.
This commit is contained in:
Petr Viktorin 2026-03-13 18:51:23 +01:00 committed by GitHub
parent 00a25859a9
commit 747ef70faa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 25 additions and 352 deletions

View file

@ -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.

View file

@ -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.

Binary file not shown.

View file

@ -27,18 +27,17 @@ def tearDown(self):
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 @@ def check_params(self, f, nchannels, sampwidth, framerate, nframes,
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 @@ def check_file(self, testfile, nframes, frames):
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 @@ def test_read_params(self):
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 @@ def test_read(self):
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())

View file

@ -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('<L', 36) + b'WAVE'
b += b'fmt ' + struct.pack('<LHHLLHH', 16, 1, 1, 11025, 11025, 1, 8)
b += b'data' + struct.pack('<L', 0)
with wave.open(io.BytesIO(b), 'rb') as r:
self.assertEqual(r.getformat(), wave.WAVE_FORMAT_PCM)
def test_read_no_chunks(self):
b = b'SPAM'
with self.assertRaises(EOFError):
@ -339,58 +207,6 @@ def test_open_in_write_raises(self):
support.gc_collect()
self.assertIsNone(cm.unraisable)
def test_ieee_float_has_fact_chunk(self):
nframes = 100
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)
w.setformat(wave.WAVE_FORMAT_IEEE_FLOAT)
w.writeframes(b'\x00\x00\x00\x00' * nframes)
with open(filename, 'rb') as f:
f.read(12)
fact_found = False
fact_samples = None
while True:
chunk_id = f.read(4)
if len(chunk_id) < 4:
break
chunk_size = struct.unpack('<L', f.read(4))[0]
if chunk_id == b'fact':
fact_found = True
fact_samples = struct.unpack('<L', f.read(4))[0]
break
f.seek(chunk_size + (chunk_size & 1), 1)
self.assertTrue(fact_found)
self.assertEqual(fact_samples, nframes)
def test_pcm_has_no_fact_chunk(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)
w.writeframes(b'\x00\x00' * 100)
with open(filename, 'rb') as f:
f.read(12)
while True:
chunk_id = f.read(4)
if len(chunk_id) < 4:
break
chunk_size = struct.unpack('<L', f.read(4))[0]
self.assertNotEqual(chunk_id, b'fact')
f.seek(chunk_size + (chunk_size & 1), 1)
class WaveOpen(unittest.TestCase):
def test_open_pathlike(self):

View file

@ -15,8 +15,6 @@
getsampwidth() -- returns sample width in bytes
getframerate() -- returns sampling frequency
getnframes() -- returns number of audio frames
getformat() -- returns frame encoding (WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT
or WAVE_FORMAT_EXTENSIBLE)
getcomptype() -- returns compression type ('NONE' for linear samples)
getcompname() -- returns human-readable version of
compression type ('not compressed' linear samples)
@ -44,9 +42,6 @@
setsampwidth(n) -- set the sample width
setframerate(n) -- set the frame rate
setnframes(n) -- set the number of frames
setformat(format)
-- set the frame format. Only WAVE_FORMAT_PCM and
WAVE_FORMAT_IEEE_FLOAT are supported.
setcomptype(type, name)
-- set the compression type and the
human-readable compression type
@ -79,21 +74,12 @@
import sys
__all__ = [
"open",
"Error",
"Wave_read",
"Wave_write",
"WAVE_FORMAT_PCM",
"WAVE_FORMAT_IEEE_FLOAT",
"WAVE_FORMAT_EXTENSIBLE",
]
__all__ = ["open", "Error", "Wave_read", "Wave_write"]
class Error(Exception):
pass
WAVE_FORMAT_PCM = 0x0001
WAVE_FORMAT_IEEE_FLOAT = 0x0003
WAVE_FORMAT_EXTENSIBLE = 0xFFFE
# Derived from uuid.UUID("00000001-0000-0010-8000-00aa00389b71").bytes_le
KSDATAFORMAT_SUBTYPE_PCM = b'\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x008\x9bq'
@ -240,10 +226,6 @@ class Wave_read:
available through the getsampwidth() method
_framerate -- the sampling frequency
available through the getframerate() method
_format -- frame format
One of WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT
or WAVE_FORMAT_EXTENSIBLE available through
getformat() method
_comptype -- the AIFF-C compression type ('NONE' if AIFF)
available through the getcomptype() method
_compname -- the human-readable AIFF-C compression type
@ -345,9 +327,6 @@ def getsampwidth(self):
def getframerate(self):
return self._framerate
def getformat(self):
return self._format
def getcomptype(self):
return self._comptype
@ -388,16 +367,16 @@ def readframes(self, nframes):
def _read_fmt_chunk(self, chunk):
try:
self._format, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))
except struct.error:
raise EOFError from None
if self._format not in (WAVE_FORMAT_PCM, WAVE_FORMAT_IEEE_FLOAT, WAVE_FORMAT_EXTENSIBLE):
raise Error('unknown format: %r' % (self._format,))
if wFormatTag != WAVE_FORMAT_PCM and wFormatTag != WAVE_FORMAT_EXTENSIBLE:
raise Error('unknown format: %r' % (wFormatTag,))
try:
sampwidth = struct.unpack_from('<H', chunk.read(2))[0]
except struct.error:
raise EOFError from None
if self._format == WAVE_FORMAT_EXTENSIBLE:
if wFormatTag == WAVE_FORMAT_EXTENSIBLE:
try:
cbSize, wValidBitsPerSample, dwChannelMask = struct.unpack_from('<HHL', chunk.read(8))
# Read the entire UUID from the chunk
@ -440,8 +419,6 @@ class Wave_write:
set through the setsampwidth() or setparams() method
_framerate -- the sampling frequency
set through the setframerate() or setparams() method
_format -- frame format
set through setformat() method
_nframes -- the number of audio frames written to the header
set through the setnframes() or setparams() method
@ -469,14 +446,12 @@ def initfp(self, file):
self._file = file
self._convert = None
self._nchannels = 0
self._format = WAVE_FORMAT_PCM
self._sampwidth = 0
self._framerate = 0
self._nframes = 0
self._nframeswritten = 0
self._datawritten = 0
self._datalength = 0
self._fact_sample_count_pos = None
self._headerwritten = False
def __del__(self):
@ -506,10 +481,7 @@ def getnchannels(self):
def setsampwidth(self, sampwidth):
if self._datawritten:
raise Error('cannot change parameters after starting to write')
if self._format == WAVE_FORMAT_IEEE_FLOAT:
if sampwidth not in (4, 8):
raise Error('unsupported sample width for IEEE float format')
elif sampwidth < 1 or sampwidth > 4:
if sampwidth < 1 or sampwidth > 4:
raise Error('bad sample width')
self._sampwidth = sampwidth
@ -546,18 +518,6 @@ def setcomptype(self, comptype, compname):
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 @@ def getcompname(self):
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 @@ def _ensure_header_written(self, datasize):
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 @@ def _write_header(self, initlength):
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('<L4s4sLHHLLHH',
header_overhead + self._datalength, b'WAVE', b'fmt ', 16,
self._format, self._nchannels, self._framerate,
self._file.write(struct.pack('<L4s4sLHHLLHH4s',
36 + self._datalength, b'WAVE', b'fmt ', 16,
WAVE_FORMAT_PCM, self._nchannels, self._framerate,
self._nchannels * self._framerate * self._sampwidth,
self._nchannels * self._sampwidth,
self._sampwidth * 8))
if has_fact:
self._file.write(b'fact')
self._file.write(struct.pack('<L', 4))
try:
self._fact_sample_count_pos = self._file.tell()
except (AttributeError, OSError):
self._fact_sample_count_pos = None
self._file.write(struct.pack('<L', self._nframes))
self._file.write(b'data')
self._sampwidth * 8, b'data'))
if self._form_length_pos is not None:
self._data_length_pos = self._file.tell()
self._file.write(struct.pack('<L', self._datalength))
@ -674,13 +615,8 @@ def _patchheader(self):
if self._datawritten == self._datalength:
return
curpos = self._file.tell()
header_overhead = 36 + (12 if self._needs_fact_chunk() else 0)
self._file.seek(self._form_length_pos, 0)
self._file.write(struct.pack('<L', header_overhead + self._datawritten))
if self._fact_sample_count_pos is not None:
self._file.seek(self._fact_sample_count_pos, 0)
nframes = self._datawritten // (self._nchannels * self._sampwidth)
self._file.write(struct.pack('<L', nframes))
self._file.write(struct.pack('<L', 36 + self._datawritten))
self._file.seek(self._data_length_pos, 0)
self._file.write(struct.pack('<L', self._datawritten))
self._file.seek(curpos, 0)

View file

@ -1 +0,0 @@
Add support for floating point audio wave files in :mod:`wave`.