Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 76 additions & 7 deletions Doc/library/wave.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@
--------------

The :mod:`!wave` module provides a convenient interface to the Waveform Audio
"WAVE" (or "WAV") file format. Only uncompressed PCM encoded wave files are
supported.
"WAVE" (or "WAV") file format.

The module supports uncompressed PCM and IEEE floating-point WAV formats.

.. versionchanged:: 3.12

Support for ``WAVE_FORMAT_EXTENSIBLE`` headers was added, provided that the
extended format is ``KSDATAFORMAT_SUBTYPE_PCM``.

.. versionchanged:: 3.15

Support for reading and writing ``WAVE_FORMAT_IEEE_FLOAT`` files was added.

The :mod:`!wave` module defines the following function and exception:


Expand Down Expand Up @@ -98,6 +103,14 @@ Wave_read Objects
Returns number of audio frames.


.. method:: getformat()

Returns the frame format code.

This is one of ``WAVE_FORMAT_PCM``, ``WAVE_FORMAT_IEEE_FLOAT``, or
``WAVE_FORMAT_EXTENSIBLE``.


.. method:: getcomptype()

Returns compression type (``'NONE'`` is the only supported type).
Expand All @@ -112,8 +125,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, format)``, equivalent to output
of the ``get*()`` methods.


.. method:: readframes(n)
Expand Down Expand Up @@ -181,11 +194,21 @@ Wave_write Objects
Set the number of channels.


.. method:: getnchannels()

Return the number of channels.


.. method:: setsampwidth(n)

Set the sample width to *n* bytes.


.. method:: getsampwidth()

Return the sample width in bytes.


.. method:: setframerate(n)

Set the frame rate to *n*.
Expand All @@ -195,24 +218,67 @@ Wave_write Objects
integer.


.. method:: getframerate()

Return the frame rate.


.. method:: setnframes(n)

Set the number of frames to *n*. This will be changed later if the number
of frames actually written is different (this update attempt will
raise an error if the output stream is not seekable).


.. method:: getnframes()

Return the number of audio frames written so far.


.. method:: setcomptype(type, name)

Set the compression type and description. At the moment, only compression type
``NONE`` is supported, meaning no compression.


.. method:: getcomptype()

Return the compression type (``'NONE'``).


.. method:: getcompname()

Return the human-readable compression type name.


.. method:: setformat(format)

Set the frame format code.

Supported values are ``WAVE_FORMAT_PCM`` and
``WAVE_FORMAT_IEEE_FLOAT``.


.. method:: getformat()

Return the current frame format code.


.. method:: setparams(tuple)

The *tuple* should be ``(nchannels, sampwidth, framerate, nframes, comptype,
compname)``, with values valid for the ``set*()`` methods. Sets all
parameters.
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 ``WAVE_FORMAT_PCM``.


.. method:: getparams()

Return a :func:`~collections.namedtuple`
``(nchannels, sampwidth, framerate, nframes, comptype, compname, format)``
containing the current output parameters.


.. method:: tell()
Expand Down Expand Up @@ -242,3 +308,6 @@ 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 ``WAVE_FORMAT_IEEE_FLOAT`` output, a ``fact`` chunk is written as
required by the WAVE specification for non-PCM formats.
17 changes: 17 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,23 @@ 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_read.getparams` and :meth:`wave.Wave_write.getparams` now
include ``format`` as the seventh field in the returned named tuple.
: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.
Expand Down
Binary file added Lib/test/audiodata/pluck-float32.wav
Binary file not shown.
17 changes: 13 additions & 4 deletions Lib/test/audiotests.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,43 @@ def tearDown(self):
unlink(TESTFN)

def check_params(self, f, nchannels, sampwidth, framerate, nframes,
comptype, compname):
comptype, compname, format):
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, format))
self.assertEqual(params.nchannels, nchannels)
self.assertEqual(params.sampwidth, sampwidth)
self.assertEqual(params.framerate, framerate)
self.assertEqual(params.nframes, nframes)
self.assertEqual(params.comptype, comptype)
self.assertEqual(params.compname, compname)
self.assertEqual(params.format, format)

for proto in range(pickle.HIGHEST_PROTOCOL + 1):
dump = pickle.dumps(params, proto)
self.assertEqual(pickle.loads(dump), params)


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):
Expand All @@ -67,13 +73,14 @@ 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.nframes, self.comptype, self.compname, self.format)
f.close()

def test_write_context_manager_calls_close(self):
Expand Down Expand Up @@ -257,7 +264,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.sndfilenframes, self.comptype, self.compname, self.format)

def test_close(self):
with open(self.sndfilepath, 'rb') as testfile:
Expand Down Expand Up @@ -298,6 +305,8 @@ 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())
Expand Down
Loading
Loading