mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-104773: PEP 594: Remove the aifc module (#104933)
* Remove .aifc and .aiff test files of Lib/test/audiodata/ * Remove Lib/test/Sine-1000Hz-300ms.aif test file
This commit is contained in:
		
							parent
							
								
									076b6204cb
								
							
						
					
					
						commit
						036da3bd43
					
				
					 25 changed files with 20 additions and 1688 deletions
				
			
		| 
						 | 
					@ -1,247 +0,0 @@
 | 
				
			||||||
:mod:`aifc` --- Read and write AIFF and AIFC files
 | 
					 | 
				
			||||||
==================================================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. module:: aifc
 | 
					 | 
				
			||||||
   :synopsis: Read and write audio files in AIFF or AIFC format.
 | 
					 | 
				
			||||||
   :deprecated:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Source code:** :source:`Lib/aifc.py`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. index::
 | 
					 | 
				
			||||||
   single: Audio Interchange File Format
 | 
					 | 
				
			||||||
   single: AIFF
 | 
					 | 
				
			||||||
   single: AIFF-C
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. deprecated-removed:: 3.11 3.13
 | 
					 | 
				
			||||||
   The :mod:`aifc` module is deprecated
 | 
					 | 
				
			||||||
   (see :pep:`PEP 594 <594#aifc>` for details).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
--------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This module provides support for reading and writing AIFF and AIFF-C files.
 | 
					 | 
				
			||||||
AIFF is Audio Interchange File Format, a format for storing digital audio
 | 
					 | 
				
			||||||
samples in a file.  AIFF-C is a newer version of the format that includes the
 | 
					 | 
				
			||||||
ability to compress the audio data.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Audio files have a number of parameters that describe the audio data. The
 | 
					 | 
				
			||||||
sampling rate or frame rate is the number of times per second the sound is
 | 
					 | 
				
			||||||
sampled.  The number of channels indicate if the audio is mono, stereo, or
 | 
					 | 
				
			||||||
quadro.  Each frame consists of one sample per channel.  The sample size is the
 | 
					 | 
				
			||||||
size in bytes of each sample.  Thus a frame consists of
 | 
					 | 
				
			||||||
``nchannels * samplesize`` bytes, and a second's worth of audio consists of
 | 
					 | 
				
			||||||
``nchannels * samplesize * framerate`` bytes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For example, CD quality audio has a sample size of two bytes (16 bits), uses two
 | 
					 | 
				
			||||||
channels (stereo) and has a frame rate of 44,100 frames/second.  This gives a
 | 
					 | 
				
			||||||
frame size of 4 bytes (2\*2), and a second's worth occupies 2\*2\*44100 bytes
 | 
					 | 
				
			||||||
(176,400 bytes).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Module :mod:`aifc` defines the following function:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. function:: open(file, mode=None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Open an AIFF or AIFF-C file and return an object instance with methods that are
 | 
					 | 
				
			||||||
   described below.  The argument *file* is either a string naming a file or a
 | 
					 | 
				
			||||||
   :term:`file object`.  *mode* must be ``'r'`` or ``'rb'`` when the file must be
 | 
					 | 
				
			||||||
   opened for reading, or ``'w'``  or ``'wb'`` when the file must be opened for writing.
 | 
					 | 
				
			||||||
   If omitted, ``file.mode`` is used if it exists, otherwise ``'rb'`` is used.  When
 | 
					 | 
				
			||||||
   used for writing, the file object should be seekable, unless you know ahead of
 | 
					 | 
				
			||||||
   time how many samples you are going to write in total and use
 | 
					 | 
				
			||||||
   :meth:`writeframesraw` and :meth:`setnframes`.
 | 
					 | 
				
			||||||
   The :func:`.open` function may be used in a :keyword:`with` statement.  When
 | 
					 | 
				
			||||||
   the :keyword:`!with` block completes, the :meth:`~aifc.close` method is called.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   .. versionchanged:: 3.4
 | 
					 | 
				
			||||||
      Support for the :keyword:`with` statement was added.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Objects returned by :func:`.open` when a file is opened for reading have the
 | 
					 | 
				
			||||||
following methods:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getnchannels()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the number of audio channels (1 for mono, 2 for stereo).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getsampwidth()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the size in bytes of individual samples.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getframerate()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the sampling rate (number of audio frames per second).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getnframes()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the number of audio frames in the file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getcomptype()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return a bytes array of length 4 describing the type of compression
 | 
					 | 
				
			||||||
   used in the audio file.  For AIFF files, the returned value is
 | 
					 | 
				
			||||||
   ``b'NONE'``.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getcompname()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return a bytes array convertible to a human-readable description
 | 
					 | 
				
			||||||
   of the type of compression used in the audio file.  For AIFF files,
 | 
					 | 
				
			||||||
   the returned value is ``b'not compressed'``.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getparams()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Returns a :func:`~collections.namedtuple` ``(nchannels, sampwidth,
 | 
					 | 
				
			||||||
   framerate, nframes, comptype, compname)``, equivalent to output of the
 | 
					 | 
				
			||||||
   :meth:`get\*` methods.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getmarkers()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return a list of markers in the audio file.  A marker consists of a tuple of
 | 
					 | 
				
			||||||
   three elements.  The first is the mark ID (an integer), the second is the mark
 | 
					 | 
				
			||||||
   position in frames from the beginning of the data (an integer), the third is the
 | 
					 | 
				
			||||||
   name of the mark (a string).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.getmark(id)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the tuple as described in :meth:`getmarkers` for the mark with the given
 | 
					 | 
				
			||||||
   *id*.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.readframes(nframes)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Read and return the next *nframes* frames from the audio file.  The returned
 | 
					 | 
				
			||||||
   data is a string containing for each frame the uncompressed samples of all
 | 
					 | 
				
			||||||
   channels.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.rewind()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Rewind the read pointer.  The next :meth:`readframes` will start from the
 | 
					 | 
				
			||||||
   beginning.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setpos(pos)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Seek to the specified frame number.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.tell()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the current frame number.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Close the AIFF file.  After calling this method, the object can no longer be
 | 
					 | 
				
			||||||
   used.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Objects returned by :func:`.open` when a file is opened for writing have all the
 | 
					 | 
				
			||||||
above methods, except for :meth:`readframes` and :meth:`setpos`.  In addition
 | 
					 | 
				
			||||||
the following methods exist.  The :meth:`get\*` methods can only be called after
 | 
					 | 
				
			||||||
the corresponding :meth:`set\*` methods have been called.  Before the first
 | 
					 | 
				
			||||||
:meth:`writeframes` or :meth:`writeframesraw`, all parameters except for the
 | 
					 | 
				
			||||||
number of frames must be filled in.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.aiff()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Create an AIFF file.  The default is that an AIFF-C file is created, unless the
 | 
					 | 
				
			||||||
   name of the file ends in ``'.aiff'`` in which case the default is an AIFF file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.aifc()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Create an AIFF-C file.  The default is that an AIFF-C file is created, unless
 | 
					 | 
				
			||||||
   the name of the file ends in ``'.aiff'`` in which case the default is an AIFF
 | 
					 | 
				
			||||||
   file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setnchannels(nchannels)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Specify the number of channels in the audio file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setsampwidth(width)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Specify the size in bytes of audio samples.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setframerate(rate)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Specify the sampling frequency in frames per second.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setnframes(nframes)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Specify the number of frames that are to be written to the audio file. If this
 | 
					 | 
				
			||||||
   parameter is not set, or not set correctly, the file needs to support seeking.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setcomptype(type, name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   .. index::
 | 
					 | 
				
			||||||
      single: u-LAW
 | 
					 | 
				
			||||||
      single: A-LAW
 | 
					 | 
				
			||||||
      single: G.722
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Specify the compression type.  If not specified, the audio data will
 | 
					 | 
				
			||||||
   not be compressed.  In AIFF files, compression is not possible.
 | 
					 | 
				
			||||||
   The name parameter should be a human-readable description of the
 | 
					 | 
				
			||||||
   compression type as a bytes array, the type parameter should be a
 | 
					 | 
				
			||||||
   bytes array of length 4.  Currently the following compression types
 | 
					 | 
				
			||||||
   are supported: ``b'NONE'``, ``b'ULAW'``, ``b'ALAW'``, ``b'G722'``.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setparams(nchannels, sampwidth, framerate, comptype, compname)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Set all the above parameters at once.  The argument is a tuple consisting of the
 | 
					 | 
				
			||||||
   various parameters.  This means that it is possible to use the result of a
 | 
					 | 
				
			||||||
   :meth:`getparams` call as argument to :meth:`setparams`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.setmark(id, pos, name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Add a mark with the given id (larger than 0), and the given name at the given
 | 
					 | 
				
			||||||
   position.  This method can be called at any time before :meth:`close`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.tell()
 | 
					 | 
				
			||||||
   :noindex:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Return the current write position in the output file.  Useful in combination
 | 
					 | 
				
			||||||
   with :meth:`setmark`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.writeframes(data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Write data to the output file.  This method can only be called after the audio
 | 
					 | 
				
			||||||
   file parameters have been set.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   .. versionchanged:: 3.4
 | 
					 | 
				
			||||||
      Any :term:`bytes-like object` is now accepted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.writeframesraw(data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Like :meth:`writeframes`, except that the header of the audio file is not
 | 
					 | 
				
			||||||
   updated.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   .. versionchanged:: 3.4
 | 
					 | 
				
			||||||
      Any :term:`bytes-like object` is now accepted.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. method:: aifc.close()
 | 
					 | 
				
			||||||
   :noindex:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Close the AIFF file.  The header of the file is updated to reflect the actual
 | 
					 | 
				
			||||||
   size of the audio data. After calling this method, the object can no longer be
 | 
					 | 
				
			||||||
   used.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,6 @@ backwards compatibility. They have been superseded by other modules.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. toctree::
 | 
					.. toctree::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   aifc.rst
 | 
					 | 
				
			||||||
   audioop.rst
 | 
					   audioop.rst
 | 
				
			||||||
   chunk.rst
 | 
					   chunk.rst
 | 
				
			||||||
   imghdr.rst
 | 
					   imghdr.rst
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ Wave_read objects, as returned by :func:`.open`, have the following methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   Rewind the file pointer to the beginning of the audio stream.
 | 
					   Rewind the file pointer to the beginning of the audio stream.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following two methods are defined for compatibility with the :mod:`aifc`
 | 
					The following two methods are defined for compatibility with the old :mod:`!aifc`
 | 
				
			||||||
module, and don't do anything interesting.
 | 
					module, and don't do anything interesting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,6 @@ Doc/install/index.rst
 | 
				
			||||||
Doc/library/__future__.rst
 | 
					Doc/library/__future__.rst
 | 
				
			||||||
Doc/library/_thread.rst
 | 
					Doc/library/_thread.rst
 | 
				
			||||||
Doc/library/abc.rst
 | 
					Doc/library/abc.rst
 | 
				
			||||||
Doc/library/aifc.rst
 | 
					 | 
				
			||||||
Doc/library/ast.rst
 | 
					Doc/library/ast.rst
 | 
				
			||||||
Doc/library/asyncio-dev.rst
 | 
					Doc/library/asyncio-dev.rst
 | 
				
			||||||
Doc/library/asyncio-eventloop.rst
 | 
					Doc/library/asyncio-eventloop.rst
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1031,7 +1031,7 @@ Module changes
 | 
				
			||||||
Lots of improvements and bugfixes were made to Python's extensive standard
 | 
					Lots of improvements and bugfixes were made to Python's extensive standard
 | 
				
			||||||
library; some of the affected modules include :mod:`readline`,
 | 
					library; some of the affected modules include :mod:`readline`,
 | 
				
			||||||
:mod:`ConfigParser`, :mod:`!cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`,
 | 
					:mod:`ConfigParser`, :mod:`!cgi`, :mod:`calendar`, :mod:`posix`, :mod:`readline`,
 | 
				
			||||||
:mod:`xmllib`, :mod:`aifc`, :mod:`chunk, wave`, :mod:`random`, :mod:`shelve`,
 | 
					:mod:`xmllib`, :mod:`!aifc`, :mod:`chunk, wave`, :mod:`random`, :mod:`shelve`,
 | 
				
			||||||
and :mod:`!nntplib`.  Consult the CVS logs for the exact patch-by-patch details.
 | 
					and :mod:`!nntplib`.  Consult the CVS logs for the exact patch-by-patch details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Brian Gallew contributed OpenSSL support for the :mod:`socket` module.  OpenSSL
 | 
					Brian Gallew contributed OpenSSL support for the :mod:`socket` module.  OpenSSL
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1731,7 +1731,7 @@ Modules
 | 
				
			||||||
  slated for removal in Python 3.13:
 | 
					  slated for removal in Python 3.13:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
					  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
				
			||||||
  | :mod:`aifc`         | :mod:`chunk`        | :mod:`!msilib`      | :mod:`!pipes`       | :mod:`!telnetlib`   |
 | 
					  | :mod:`!aifc`        | :mod:`chunk`        | :mod:`!msilib`      | :mod:`!pipes`       | :mod:`!telnetlib`   |
 | 
				
			||||||
  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
					  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
				
			||||||
  | :mod:`audioop`      | :mod:`!crypt`       | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`!uu`          |
 | 
					  | :mod:`audioop`      | :mod:`!crypt`       | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`!uu`          |
 | 
				
			||||||
  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
					  +---------------------+---------------------+---------------------+---------------------+---------------------+
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -918,7 +918,7 @@ and will be removed in Python 3.13.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Modules (see :pep:`594`):
 | 
					Modules (see :pep:`594`):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* :mod:`aifc`
 | 
					* :mod:`!aifc`
 | 
				
			||||||
* :mod:`audioop`
 | 
					* :mod:`audioop`
 | 
				
			||||||
* :mod:`!cgi`
 | 
					* :mod:`!cgi`
 | 
				
			||||||
* :mod:`!cgitb`
 | 
					* :mod:`!cgitb`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,6 +221,9 @@ Removed
 | 
				
			||||||
  the :mod:`base64` module is a modern alternative.
 | 
					  the :mod:`base64` module is a modern alternative.
 | 
				
			||||||
  (Contributed by Victor Stinner in :gh:`104773`.)
 | 
					  (Contributed by Victor Stinner in :gh:`104773`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* :pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11.
 | 
				
			||||||
 | 
					  (Contributed by Victor Stinner in :gh:`104773`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Porting to Python 3.13
 | 
					Porting to Python 3.13
 | 
				
			||||||
======================
 | 
					======================
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -605,15 +605,15 @@ Using ``ABC`` as a base class has essentially the same effect as specifying
 | 
				
			||||||
aifc
 | 
					aifc
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The :meth:`~aifc.aifc.getparams` method now returns a namedtuple rather than a
 | 
					The :meth:`~!aifc.aifc.getparams` method now returns a namedtuple rather than a
 | 
				
			||||||
plain tuple.  (Contributed by Claudiu Popa in :issue:`17818`.)
 | 
					plain tuple.  (Contributed by Claudiu Popa in :issue:`17818`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:func:`aifc.open` now supports the context management protocol: when used in a
 | 
					:func:`!aifc.open` now supports the context management protocol: when used in a
 | 
				
			||||||
:keyword:`with` block, the :meth:`~aifc.aifc.close` method of the returned
 | 
					:keyword:`with` block, the :meth:`~!aifc.aifc.close` method of the returned
 | 
				
			||||||
object will be called automatically at the end of the block.  (Contributed by
 | 
					object will be called automatically at the end of the block.  (Contributed by
 | 
				
			||||||
Serhiy Storchacha in :issue:`16486`.)
 | 
					Serhiy Storchacha in :issue:`16486`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The :meth:`~aifc.aifc.writeframesraw` and :meth:`~aifc.aifc.writeframes`
 | 
					The :meth:`~!aifc.aifc.writeframesraw` and :meth:`~!aifc.aifc.writeframes`
 | 
				
			||||||
methods now accept any :term:`bytes-like object`.  (Contributed by Serhiy
 | 
					methods now accept any :term:`bytes-like object`.  (Contributed by Serhiy
 | 
				
			||||||
Storchaka in :issue:`8311`.)
 | 
					Storchaka in :issue:`8311`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1940,8 +1940,8 @@ Deprecated Python modules, functions and methods
 | 
				
			||||||
aifc
 | 
					aifc
 | 
				
			||||||
----
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:func:`aifc.openfp` has been deprecated and will be removed in Python 3.9.
 | 
					:func:`!aifc.openfp` has been deprecated and will be removed in Python 3.9.
 | 
				
			||||||
Use :func:`aifc.open` instead.
 | 
					Use :func:`!aifc.open` instead.
 | 
				
			||||||
(Contributed by Brian Curtin in :issue:`31985`.)
 | 
					(Contributed by Brian Curtin in :issue:`31985`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										984
									
								
								Lib/aifc.py
									
										
									
									
									
								
							
							
						
						
									
										984
									
								
								Lib/aifc.py
									
										
									
									
									
								
							| 
						 | 
					@ -1,984 +0,0 @@
 | 
				
			||||||
"""Stuff to parse AIFF-C and AIFF files.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Unless explicitly stated otherwise, the description below is true
 | 
					 | 
				
			||||||
both for AIFF-C files and AIFF files.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
An AIFF-C file has the following structure.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  +-----------------+
 | 
					 | 
				
			||||||
  | FORM            |
 | 
					 | 
				
			||||||
  +-----------------+
 | 
					 | 
				
			||||||
  | <size>          |
 | 
					 | 
				
			||||||
  +----+------------+
 | 
					 | 
				
			||||||
  |    | AIFC       |
 | 
					 | 
				
			||||||
  |    +------------+
 | 
					 | 
				
			||||||
  |    | <chunks>   |
 | 
					 | 
				
			||||||
  |    |    .       |
 | 
					 | 
				
			||||||
  |    |    .       |
 | 
					 | 
				
			||||||
  |    |    .       |
 | 
					 | 
				
			||||||
  +----+------------+
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
An AIFF file has the string "AIFF" instead of "AIFC".
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A chunk consists of an identifier (4 bytes) followed by a size (4 bytes,
 | 
					 | 
				
			||||||
big endian order), followed by the data.  The size field does not include
 | 
					 | 
				
			||||||
the size of the 8 byte header.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The following chunk types are recognized.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  FVER
 | 
					 | 
				
			||||||
      <version number of AIFF-C defining document> (AIFF-C only).
 | 
					 | 
				
			||||||
  MARK
 | 
					 | 
				
			||||||
      <# of markers> (2 bytes)
 | 
					 | 
				
			||||||
      list of markers:
 | 
					 | 
				
			||||||
          <marker ID> (2 bytes, must be > 0)
 | 
					 | 
				
			||||||
          <position> (4 bytes)
 | 
					 | 
				
			||||||
          <marker name> ("pstring")
 | 
					 | 
				
			||||||
  COMM
 | 
					 | 
				
			||||||
      <# of channels> (2 bytes)
 | 
					 | 
				
			||||||
      <# of sound frames> (4 bytes)
 | 
					 | 
				
			||||||
      <size of the samples> (2 bytes)
 | 
					 | 
				
			||||||
      <sampling frequency> (10 bytes, IEEE 80-bit extended
 | 
					 | 
				
			||||||
          floating point)
 | 
					 | 
				
			||||||
      in AIFF-C files only:
 | 
					 | 
				
			||||||
      <compression type> (4 bytes)
 | 
					 | 
				
			||||||
      <human-readable version of compression type> ("pstring")
 | 
					 | 
				
			||||||
  SSND
 | 
					 | 
				
			||||||
      <offset> (4 bytes, not used by this program)
 | 
					 | 
				
			||||||
      <blocksize> (4 bytes, not used by this program)
 | 
					 | 
				
			||||||
      <sound data>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A pstring consists of 1 byte length, a string of characters, and 0 or 1
 | 
					 | 
				
			||||||
byte pad to make the total length even.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Usage.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Reading AIFF files:
 | 
					 | 
				
			||||||
  f = aifc.open(file, 'r')
 | 
					 | 
				
			||||||
where file is either the name of a file or an open file pointer.
 | 
					 | 
				
			||||||
The open file pointer must have methods read(), seek(), and close().
 | 
					 | 
				
			||||||
In some types of audio files, if the setpos() method is not used,
 | 
					 | 
				
			||||||
the seek() method is not necessary.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This returns an instance of a class with the following public methods:
 | 
					 | 
				
			||||||
  getnchannels()  -- returns number of audio channels (1 for
 | 
					 | 
				
			||||||
             mono, 2 for stereo)
 | 
					 | 
				
			||||||
  getsampwidth()  -- returns sample width in bytes
 | 
					 | 
				
			||||||
  getframerate()  -- returns sampling frequency
 | 
					 | 
				
			||||||
  getnframes()    -- returns number of audio frames
 | 
					 | 
				
			||||||
  getcomptype()   -- returns compression type ('NONE' for AIFF files)
 | 
					 | 
				
			||||||
  getcompname()   -- returns human-readable version of
 | 
					 | 
				
			||||||
             compression type ('not compressed' for AIFF files)
 | 
					 | 
				
			||||||
  getparams() -- returns a namedtuple consisting of all of the
 | 
					 | 
				
			||||||
             above in the above order
 | 
					 | 
				
			||||||
  getmarkers()    -- get the list of marks in the audio file or None
 | 
					 | 
				
			||||||
             if there are no marks
 | 
					 | 
				
			||||||
  getmark(id) -- get mark with the specified id (raises an error
 | 
					 | 
				
			||||||
             if the mark does not exist)
 | 
					 | 
				
			||||||
  readframes(n)   -- returns at most n frames of audio
 | 
					 | 
				
			||||||
  rewind()    -- rewind to the beginning of the audio stream
 | 
					 | 
				
			||||||
  setpos(pos) -- seek to the specified position
 | 
					 | 
				
			||||||
  tell()      -- return the current position
 | 
					 | 
				
			||||||
  close()     -- close the instance (make it unusable)
 | 
					 | 
				
			||||||
The position returned by tell(), the position given to setpos() and
 | 
					 | 
				
			||||||
the position of marks are all compatible and have nothing to do with
 | 
					 | 
				
			||||||
the actual position in the file.
 | 
					 | 
				
			||||||
The close() method is called automatically when the class instance
 | 
					 | 
				
			||||||
is destroyed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Writing AIFF files:
 | 
					 | 
				
			||||||
  f = aifc.open(file, 'w')
 | 
					 | 
				
			||||||
where file is either the name of a file or an open file pointer.
 | 
					 | 
				
			||||||
The open file pointer must have methods write(), tell(), seek(), and
 | 
					 | 
				
			||||||
close().
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This returns an instance of a class with the following public methods:
 | 
					 | 
				
			||||||
  aiff()      -- create an AIFF file (AIFF-C default)
 | 
					 | 
				
			||||||
  aifc()      -- create an AIFF-C file
 | 
					 | 
				
			||||||
  setnchannels(n) -- set the number of channels
 | 
					 | 
				
			||||||
  setsampwidth(n) -- set the sample width
 | 
					 | 
				
			||||||
  setframerate(n) -- set the frame rate
 | 
					 | 
				
			||||||
  setnframes(n)   -- set the number of frames
 | 
					 | 
				
			||||||
  setcomptype(type, name)
 | 
					 | 
				
			||||||
          -- set the compression type and the
 | 
					 | 
				
			||||||
             human-readable compression type
 | 
					 | 
				
			||||||
  setparams(tuple)
 | 
					 | 
				
			||||||
          -- set all parameters at once
 | 
					 | 
				
			||||||
  setmark(id, pos, name)
 | 
					 | 
				
			||||||
          -- add specified mark to the list of marks
 | 
					 | 
				
			||||||
  tell()      -- return current position in output file (useful
 | 
					 | 
				
			||||||
             in combination with setmark())
 | 
					 | 
				
			||||||
  writeframesraw(data)
 | 
					 | 
				
			||||||
          -- write audio frames without pathing up the
 | 
					 | 
				
			||||||
             file header
 | 
					 | 
				
			||||||
  writeframes(data)
 | 
					 | 
				
			||||||
          -- write audio frames and patch up the file header
 | 
					 | 
				
			||||||
  close()     -- patch up the file header and close the
 | 
					 | 
				
			||||||
             output file
 | 
					 | 
				
			||||||
You should set the parameters before the first writeframesraw or
 | 
					 | 
				
			||||||
writeframes.  The total number of frames does not need to be set,
 | 
					 | 
				
			||||||
but when it is set to the correct value, the header does not have to
 | 
					 | 
				
			||||||
be patched up.
 | 
					 | 
				
			||||||
It is best to first set all parameters, perhaps possibly the
 | 
					 | 
				
			||||||
compression type, and then write audio frames using writeframesraw.
 | 
					 | 
				
			||||||
When all frames have been written, either call writeframes(b'') or
 | 
					 | 
				
			||||||
close() to patch up the sizes in the header.
 | 
					 | 
				
			||||||
Marks can be added anytime.  If there are any marks, you must call
 | 
					 | 
				
			||||||
close() after all frames have been written.
 | 
					 | 
				
			||||||
The close() method is called automatically when the class instance
 | 
					 | 
				
			||||||
is destroyed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
When a file is opened with the extension '.aiff', an AIFF file is
 | 
					 | 
				
			||||||
written, otherwise an AIFF-C file is written.  This default can be
 | 
					 | 
				
			||||||
changed by calling aiff() or aifc() before the first writeframes or
 | 
					 | 
				
			||||||
writeframesraw.
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import struct
 | 
					 | 
				
			||||||
import builtins
 | 
					 | 
				
			||||||
import warnings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__all__ = ["Error", "open"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
warnings._deprecated(__name__, remove=(3, 13))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Error(Exception):
 | 
					 | 
				
			||||||
    pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_AIFC_version = 0xA2805140     # Version 1 of AIFF-C
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_long(file):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return struct.unpack('>l', file.read(4))[0]
 | 
					 | 
				
			||||||
    except struct.error:
 | 
					 | 
				
			||||||
        raise EOFError from None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_ulong(file):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return struct.unpack('>L', file.read(4))[0]
 | 
					 | 
				
			||||||
    except struct.error:
 | 
					 | 
				
			||||||
        raise EOFError from None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_short(file):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return struct.unpack('>h', file.read(2))[0]
 | 
					 | 
				
			||||||
    except struct.error:
 | 
					 | 
				
			||||||
        raise EOFError from None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_ushort(file):
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return struct.unpack('>H', file.read(2))[0]
 | 
					 | 
				
			||||||
    except struct.error:
 | 
					 | 
				
			||||||
        raise EOFError from None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_string(file):
 | 
					 | 
				
			||||||
    length = ord(file.read(1))
 | 
					 | 
				
			||||||
    if length == 0:
 | 
					 | 
				
			||||||
        data = b''
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        data = file.read(length)
 | 
					 | 
				
			||||||
    if length & 1 == 0:
 | 
					 | 
				
			||||||
        dummy = file.read(1)
 | 
					 | 
				
			||||||
    return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_HUGE_VAL = 1.79769313486231e+308 # See <limits.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _read_float(f): # 10 bytes
 | 
					 | 
				
			||||||
    expon = _read_short(f) # 2 bytes
 | 
					 | 
				
			||||||
    sign = 1
 | 
					 | 
				
			||||||
    if expon < 0:
 | 
					 | 
				
			||||||
        sign = -1
 | 
					 | 
				
			||||||
        expon = expon + 0x8000
 | 
					 | 
				
			||||||
    himant = _read_ulong(f) # 4 bytes
 | 
					 | 
				
			||||||
    lomant = _read_ulong(f) # 4 bytes
 | 
					 | 
				
			||||||
    if expon == himant == lomant == 0:
 | 
					 | 
				
			||||||
        f = 0.0
 | 
					 | 
				
			||||||
    elif expon == 0x7FFF:
 | 
					 | 
				
			||||||
        f = _HUGE_VAL
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        expon = expon - 16383
 | 
					 | 
				
			||||||
        f = (himant * 0x100000000 + lomant) * pow(2.0, expon - 63)
 | 
					 | 
				
			||||||
    return sign * f
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_short(f, x):
 | 
					 | 
				
			||||||
    f.write(struct.pack('>h', x))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_ushort(f, x):
 | 
					 | 
				
			||||||
    f.write(struct.pack('>H', x))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_long(f, x):
 | 
					 | 
				
			||||||
    f.write(struct.pack('>l', x))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_ulong(f, x):
 | 
					 | 
				
			||||||
    f.write(struct.pack('>L', x))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_string(f, s):
 | 
					 | 
				
			||||||
    if len(s) > 255:
 | 
					 | 
				
			||||||
        raise ValueError("string exceeds maximum pstring length")
 | 
					 | 
				
			||||||
    f.write(struct.pack('B', len(s)))
 | 
					 | 
				
			||||||
    f.write(s)
 | 
					 | 
				
			||||||
    if len(s) & 1 == 0:
 | 
					 | 
				
			||||||
        f.write(b'\x00')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def _write_float(f, x):
 | 
					 | 
				
			||||||
    import math
 | 
					 | 
				
			||||||
    if x < 0:
 | 
					 | 
				
			||||||
        sign = 0x8000
 | 
					 | 
				
			||||||
        x = x * -1
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        sign = 0
 | 
					 | 
				
			||||||
    if x == 0:
 | 
					 | 
				
			||||||
        expon = 0
 | 
					 | 
				
			||||||
        himant = 0
 | 
					 | 
				
			||||||
        lomant = 0
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        fmant, expon = math.frexp(x)
 | 
					 | 
				
			||||||
        if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN
 | 
					 | 
				
			||||||
            expon = sign|0x7FFF
 | 
					 | 
				
			||||||
            himant = 0
 | 
					 | 
				
			||||||
            lomant = 0
 | 
					 | 
				
			||||||
        else:                   # Finite
 | 
					 | 
				
			||||||
            expon = expon + 16382
 | 
					 | 
				
			||||||
            if expon < 0:           # denormalized
 | 
					 | 
				
			||||||
                fmant = math.ldexp(fmant, expon)
 | 
					 | 
				
			||||||
                expon = 0
 | 
					 | 
				
			||||||
            expon = expon | sign
 | 
					 | 
				
			||||||
            fmant = math.ldexp(fmant, 32)
 | 
					 | 
				
			||||||
            fsmant = math.floor(fmant)
 | 
					 | 
				
			||||||
            himant = int(fsmant)
 | 
					 | 
				
			||||||
            fmant = math.ldexp(fmant - fsmant, 32)
 | 
					 | 
				
			||||||
            fsmant = math.floor(fmant)
 | 
					 | 
				
			||||||
            lomant = int(fsmant)
 | 
					 | 
				
			||||||
    _write_ushort(f, expon)
 | 
					 | 
				
			||||||
    _write_ulong(f, himant)
 | 
					 | 
				
			||||||
    _write_ulong(f, lomant)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
with warnings.catch_warnings():
 | 
					 | 
				
			||||||
    warnings.simplefilter("ignore", DeprecationWarning)
 | 
					 | 
				
			||||||
    from chunk import Chunk
 | 
					 | 
				
			||||||
from collections import namedtuple
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_aifc_params = namedtuple('_aifc_params',
 | 
					 | 
				
			||||||
                          'nchannels sampwidth framerate nframes comptype compname')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_aifc_params.nchannels.__doc__ = 'Number of audio channels (1 for mono, 2 for stereo)'
 | 
					 | 
				
			||||||
_aifc_params.sampwidth.__doc__ = 'Sample width in bytes'
 | 
					 | 
				
			||||||
_aifc_params.framerate.__doc__ = 'Sampling frequency'
 | 
					 | 
				
			||||||
_aifc_params.nframes.__doc__ = 'Number of audio frames'
 | 
					 | 
				
			||||||
_aifc_params.comptype.__doc__ = 'Compression type ("NONE" for AIFF files)'
 | 
					 | 
				
			||||||
_aifc_params.compname.__doc__ = ("""\
 | 
					 | 
				
			||||||
A human-readable version of the compression type
 | 
					 | 
				
			||||||
('not compressed' for AIFF files)""")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Aifc_read:
 | 
					 | 
				
			||||||
    # Variables used in this class:
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # These variables are available to the user though appropriate
 | 
					 | 
				
			||||||
    # methods of this class:
 | 
					 | 
				
			||||||
    # _file -- the open file with methods read(), close(), and seek()
 | 
					 | 
				
			||||||
    #       set through the __init__() method
 | 
					 | 
				
			||||||
    # _nchannels -- the number of audio channels
 | 
					 | 
				
			||||||
    #       available through the getnchannels() method
 | 
					 | 
				
			||||||
    # _nframes -- the number of audio frames
 | 
					 | 
				
			||||||
    #       available through the getnframes() method
 | 
					 | 
				
			||||||
    # _sampwidth -- the number of bytes per audio sample
 | 
					 | 
				
			||||||
    #       available through the getsampwidth() method
 | 
					 | 
				
			||||||
    # _framerate -- the sampling frequency
 | 
					 | 
				
			||||||
    #       available through the getframerate() method
 | 
					 | 
				
			||||||
    # _comptype -- the AIFF-C compression type ('NONE' if AIFF)
 | 
					 | 
				
			||||||
    #       available through the getcomptype() method
 | 
					 | 
				
			||||||
    # _compname -- the human-readable AIFF-C compression type
 | 
					 | 
				
			||||||
    #       available through the getcomptype() method
 | 
					 | 
				
			||||||
    # _markers -- the marks in the audio file
 | 
					 | 
				
			||||||
    #       available through the getmarkers() and getmark()
 | 
					 | 
				
			||||||
    #       methods
 | 
					 | 
				
			||||||
    # _soundpos -- the position in the audio stream
 | 
					 | 
				
			||||||
    #       available through the tell() method, set through the
 | 
					 | 
				
			||||||
    #       setpos() method
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # These variables are used internally only:
 | 
					 | 
				
			||||||
    # _version -- the AIFF-C version number
 | 
					 | 
				
			||||||
    # _decomp -- the decompressor from builtin module cl
 | 
					 | 
				
			||||||
    # _comm_chunk_read -- 1 iff the COMM chunk has been read
 | 
					 | 
				
			||||||
    # _aifc -- 1 iff reading an AIFF-C file
 | 
					 | 
				
			||||||
    # _ssnd_seek_needed -- 1 iff positioned correctly in audio
 | 
					 | 
				
			||||||
    #       file for readframes()
 | 
					 | 
				
			||||||
    # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk
 | 
					 | 
				
			||||||
    # _framesize -- size of one frame in the file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _file = None  # Set here since __del__ checks it
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def initfp(self, file):
 | 
					 | 
				
			||||||
        self._version = 0
 | 
					 | 
				
			||||||
        self._convert = None
 | 
					 | 
				
			||||||
        self._markers = []
 | 
					 | 
				
			||||||
        self._soundpos = 0
 | 
					 | 
				
			||||||
        self._file = file
 | 
					 | 
				
			||||||
        chunk = Chunk(file)
 | 
					 | 
				
			||||||
        if chunk.getname() != b'FORM':
 | 
					 | 
				
			||||||
            raise Error('file does not start with FORM id')
 | 
					 | 
				
			||||||
        formdata = chunk.read(4)
 | 
					 | 
				
			||||||
        if formdata == b'AIFF':
 | 
					 | 
				
			||||||
            self._aifc = 0
 | 
					 | 
				
			||||||
        elif formdata == b'AIFC':
 | 
					 | 
				
			||||||
            self._aifc = 1
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise Error('not an AIFF or AIFF-C file')
 | 
					 | 
				
			||||||
        self._comm_chunk_read = 0
 | 
					 | 
				
			||||||
        self._ssnd_chunk = None
 | 
					 | 
				
			||||||
        while 1:
 | 
					 | 
				
			||||||
            self._ssnd_seek_needed = 1
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                chunk = Chunk(self._file)
 | 
					 | 
				
			||||||
            except EOFError:
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
            chunkname = chunk.getname()
 | 
					 | 
				
			||||||
            if chunkname == b'COMM':
 | 
					 | 
				
			||||||
                self._read_comm_chunk(chunk)
 | 
					 | 
				
			||||||
                self._comm_chunk_read = 1
 | 
					 | 
				
			||||||
            elif chunkname == b'SSND':
 | 
					 | 
				
			||||||
                self._ssnd_chunk = chunk
 | 
					 | 
				
			||||||
                dummy = chunk.read(8)
 | 
					 | 
				
			||||||
                self._ssnd_seek_needed = 0
 | 
					 | 
				
			||||||
            elif chunkname == b'FVER':
 | 
					 | 
				
			||||||
                self._version = _read_ulong(chunk)
 | 
					 | 
				
			||||||
            elif chunkname == b'MARK':
 | 
					 | 
				
			||||||
                self._readmark(chunk)
 | 
					 | 
				
			||||||
            chunk.skip()
 | 
					 | 
				
			||||||
        if not self._comm_chunk_read or not self._ssnd_chunk:
 | 
					 | 
				
			||||||
            raise Error('COMM chunk and/or SSND chunk missing')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, f):
 | 
					 | 
				
			||||||
        if isinstance(f, str):
 | 
					 | 
				
			||||||
            file_object = builtins.open(f, 'rb')
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                self.initfp(file_object)
 | 
					 | 
				
			||||||
            except:
 | 
					 | 
				
			||||||
                file_object.close()
 | 
					 | 
				
			||||||
                raise
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # assume it is an open file object already
 | 
					 | 
				
			||||||
            self.initfp(f)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __enter__(self):
 | 
					 | 
				
			||||||
        return self
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __exit__(self, *args):
 | 
					 | 
				
			||||||
        self.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # User visible methods.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    def getfp(self):
 | 
					 | 
				
			||||||
        return self._file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def rewind(self):
 | 
					 | 
				
			||||||
        self._ssnd_seek_needed = 1
 | 
					 | 
				
			||||||
        self._soundpos = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					 | 
				
			||||||
        file = self._file
 | 
					 | 
				
			||||||
        if file is not None:
 | 
					 | 
				
			||||||
            self._file = None
 | 
					 | 
				
			||||||
            file.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def tell(self):
 | 
					 | 
				
			||||||
        return self._soundpos
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getnchannels(self):
 | 
					 | 
				
			||||||
        return self._nchannels
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getnframes(self):
 | 
					 | 
				
			||||||
        return self._nframes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getsampwidth(self):
 | 
					 | 
				
			||||||
        return self._sampwidth
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getframerate(self):
 | 
					 | 
				
			||||||
        return self._framerate
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getcomptype(self):
 | 
					 | 
				
			||||||
        return self._comptype
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getcompname(self):
 | 
					 | 
				
			||||||
        return self._compname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
##  def getversion(self):
 | 
					 | 
				
			||||||
##      return self._version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getparams(self):
 | 
					 | 
				
			||||||
        return _aifc_params(self.getnchannels(), self.getsampwidth(),
 | 
					 | 
				
			||||||
                            self.getframerate(), self.getnframes(),
 | 
					 | 
				
			||||||
                            self.getcomptype(), self.getcompname())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getmarkers(self):
 | 
					 | 
				
			||||||
        if len(self._markers) == 0:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
        return self._markers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getmark(self, id):
 | 
					 | 
				
			||||||
        for marker in self._markers:
 | 
					 | 
				
			||||||
            if id == marker[0]:
 | 
					 | 
				
			||||||
                return marker
 | 
					 | 
				
			||||||
        raise Error('marker {0!r} does not exist'.format(id))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setpos(self, pos):
 | 
					 | 
				
			||||||
        if pos < 0 or pos > self._nframes:
 | 
					 | 
				
			||||||
            raise Error('position not in range')
 | 
					 | 
				
			||||||
        self._soundpos = pos
 | 
					 | 
				
			||||||
        self._ssnd_seek_needed = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def readframes(self, nframes):
 | 
					 | 
				
			||||||
        if self._ssnd_seek_needed:
 | 
					 | 
				
			||||||
            self._ssnd_chunk.seek(0)
 | 
					 | 
				
			||||||
            dummy = self._ssnd_chunk.read(8)
 | 
					 | 
				
			||||||
            pos = self._soundpos * self._framesize
 | 
					 | 
				
			||||||
            if pos:
 | 
					 | 
				
			||||||
                self._ssnd_chunk.seek(pos + 8)
 | 
					 | 
				
			||||||
            self._ssnd_seek_needed = 0
 | 
					 | 
				
			||||||
        if nframes == 0:
 | 
					 | 
				
			||||||
            return b''
 | 
					 | 
				
			||||||
        data = self._ssnd_chunk.read(nframes * self._framesize)
 | 
					 | 
				
			||||||
        if self._convert and data:
 | 
					 | 
				
			||||||
            data = self._convert(data)
 | 
					 | 
				
			||||||
        self._soundpos = self._soundpos + len(data) // (self._nchannels
 | 
					 | 
				
			||||||
                                                        * self._sampwidth)
 | 
					 | 
				
			||||||
        return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # Internal methods.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _alaw2lin(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.alaw2lin(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _ulaw2lin(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.ulaw2lin(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _adpcm2lin(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        if not hasattr(self, '_adpcmstate'):
 | 
					 | 
				
			||||||
            # first time
 | 
					 | 
				
			||||||
            self._adpcmstate = None
 | 
					 | 
				
			||||||
        data, self._adpcmstate = audioop.adpcm2lin(data, 2, self._adpcmstate)
 | 
					 | 
				
			||||||
        return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _sowt2lin(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.byteswap(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _read_comm_chunk(self, chunk):
 | 
					 | 
				
			||||||
        self._nchannels = _read_short(chunk)
 | 
					 | 
				
			||||||
        self._nframes = _read_long(chunk)
 | 
					 | 
				
			||||||
        self._sampwidth = (_read_short(chunk) + 7) // 8
 | 
					 | 
				
			||||||
        self._framerate = int(_read_float(chunk))
 | 
					 | 
				
			||||||
        if self._sampwidth <= 0:
 | 
					 | 
				
			||||||
            raise Error('bad sample width')
 | 
					 | 
				
			||||||
        if self._nchannels <= 0:
 | 
					 | 
				
			||||||
            raise Error('bad # of channels')
 | 
					 | 
				
			||||||
        self._framesize = self._nchannels * self._sampwidth
 | 
					 | 
				
			||||||
        if self._aifc:
 | 
					 | 
				
			||||||
            #DEBUG: SGI's soundeditor produces a bad size :-(
 | 
					 | 
				
			||||||
            kludge = 0
 | 
					 | 
				
			||||||
            if chunk.chunksize == 18:
 | 
					 | 
				
			||||||
                kludge = 1
 | 
					 | 
				
			||||||
                warnings.warn('Warning: bad COMM chunk size')
 | 
					 | 
				
			||||||
                chunk.chunksize = 23
 | 
					 | 
				
			||||||
            #DEBUG end
 | 
					 | 
				
			||||||
            self._comptype = chunk.read(4)
 | 
					 | 
				
			||||||
            #DEBUG start
 | 
					 | 
				
			||||||
            if kludge:
 | 
					 | 
				
			||||||
                length = ord(chunk.file.read(1))
 | 
					 | 
				
			||||||
                if length & 1 == 0:
 | 
					 | 
				
			||||||
                    length = length + 1
 | 
					 | 
				
			||||||
                chunk.chunksize = chunk.chunksize + length
 | 
					 | 
				
			||||||
                chunk.file.seek(-1, 1)
 | 
					 | 
				
			||||||
            #DEBUG end
 | 
					 | 
				
			||||||
            self._compname = _read_string(chunk)
 | 
					 | 
				
			||||||
            if self._comptype != b'NONE':
 | 
					 | 
				
			||||||
                if self._comptype == b'G722':
 | 
					 | 
				
			||||||
                    self._convert = self._adpcm2lin
 | 
					 | 
				
			||||||
                elif self._comptype in (b'ulaw', b'ULAW'):
 | 
					 | 
				
			||||||
                    self._convert = self._ulaw2lin
 | 
					 | 
				
			||||||
                elif self._comptype in (b'alaw', b'ALAW'):
 | 
					 | 
				
			||||||
                    self._convert = self._alaw2lin
 | 
					 | 
				
			||||||
                elif self._comptype in (b'sowt', b'SOWT'):
 | 
					 | 
				
			||||||
                    self._convert = self._sowt2lin
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    raise Error('unsupported compression type')
 | 
					 | 
				
			||||||
                self._sampwidth = 2
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            self._comptype = b'NONE'
 | 
					 | 
				
			||||||
            self._compname = b'not compressed'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _readmark(self, chunk):
 | 
					 | 
				
			||||||
        nmarkers = _read_short(chunk)
 | 
					 | 
				
			||||||
        # Some files appear to contain invalid counts.
 | 
					 | 
				
			||||||
        # Cope with this by testing for EOF.
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            for i in range(nmarkers):
 | 
					 | 
				
			||||||
                id = _read_short(chunk)
 | 
					 | 
				
			||||||
                pos = _read_long(chunk)
 | 
					 | 
				
			||||||
                name = _read_string(chunk)
 | 
					 | 
				
			||||||
                if pos or name:
 | 
					 | 
				
			||||||
                    # some files appear to have
 | 
					 | 
				
			||||||
                    # dummy markers consisting of
 | 
					 | 
				
			||||||
                    # a position 0 and name ''
 | 
					 | 
				
			||||||
                    self._markers.append((id, pos, name))
 | 
					 | 
				
			||||||
        except EOFError:
 | 
					 | 
				
			||||||
            w = ('Warning: MARK chunk contains only %s marker%s instead of %s' %
 | 
					 | 
				
			||||||
                 (len(self._markers), '' if len(self._markers) == 1 else 's',
 | 
					 | 
				
			||||||
                  nmarkers))
 | 
					 | 
				
			||||||
            warnings.warn(w)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Aifc_write:
 | 
					 | 
				
			||||||
    # Variables used in this class:
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # These variables are user settable through appropriate methods
 | 
					 | 
				
			||||||
    # of this class:
 | 
					 | 
				
			||||||
    # _file -- the open file with methods write(), close(), tell(), seek()
 | 
					 | 
				
			||||||
    #       set through the __init__() method
 | 
					 | 
				
			||||||
    # _comptype -- the AIFF-C compression type ('NONE' in AIFF)
 | 
					 | 
				
			||||||
    #       set through the setcomptype() or setparams() method
 | 
					 | 
				
			||||||
    # _compname -- the human-readable AIFF-C compression type
 | 
					 | 
				
			||||||
    #       set through the setcomptype() or setparams() method
 | 
					 | 
				
			||||||
    # _nchannels -- the number of audio channels
 | 
					 | 
				
			||||||
    #       set through the setnchannels() or setparams() method
 | 
					 | 
				
			||||||
    # _sampwidth -- the number of bytes per audio sample
 | 
					 | 
				
			||||||
    #       set through the setsampwidth() or setparams() method
 | 
					 | 
				
			||||||
    # _framerate -- the sampling frequency
 | 
					 | 
				
			||||||
    #       set through the setframerate() or setparams() method
 | 
					 | 
				
			||||||
    # _nframes -- the number of audio frames written to the header
 | 
					 | 
				
			||||||
    #       set through the setnframes() or setparams() method
 | 
					 | 
				
			||||||
    # _aifc -- whether we're writing an AIFF-C file or an AIFF file
 | 
					 | 
				
			||||||
    #       set through the aifc() method, reset through the
 | 
					 | 
				
			||||||
    #       aiff() method
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # These variables are used internally only:
 | 
					 | 
				
			||||||
    # _version -- the AIFF-C version number
 | 
					 | 
				
			||||||
    # _comp -- the compressor from builtin module cl
 | 
					 | 
				
			||||||
    # _nframeswritten -- the number of audio frames actually written
 | 
					 | 
				
			||||||
    # _datalength -- the size of the audio samples written to the header
 | 
					 | 
				
			||||||
    # _datawritten -- the size of the audio samples actually written
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _file = None  # Set here since __del__ checks it
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, f):
 | 
					 | 
				
			||||||
        if isinstance(f, str):
 | 
					 | 
				
			||||||
            file_object = builtins.open(f, 'wb')
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                self.initfp(file_object)
 | 
					 | 
				
			||||||
            except:
 | 
					 | 
				
			||||||
                file_object.close()
 | 
					 | 
				
			||||||
                raise
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # treat .aiff file extensions as non-compressed audio
 | 
					 | 
				
			||||||
            if f.endswith('.aiff'):
 | 
					 | 
				
			||||||
                self._aifc = 0
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            # assume it is an open file object already
 | 
					 | 
				
			||||||
            self.initfp(f)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def initfp(self, file):
 | 
					 | 
				
			||||||
        self._file = file
 | 
					 | 
				
			||||||
        self._version = _AIFC_version
 | 
					 | 
				
			||||||
        self._comptype = b'NONE'
 | 
					 | 
				
			||||||
        self._compname = b'not compressed'
 | 
					 | 
				
			||||||
        self._convert = None
 | 
					 | 
				
			||||||
        self._nchannels = 0
 | 
					 | 
				
			||||||
        self._sampwidth = 0
 | 
					 | 
				
			||||||
        self._framerate = 0
 | 
					 | 
				
			||||||
        self._nframes = 0
 | 
					 | 
				
			||||||
        self._nframeswritten = 0
 | 
					 | 
				
			||||||
        self._datawritten = 0
 | 
					 | 
				
			||||||
        self._datalength = 0
 | 
					 | 
				
			||||||
        self._markers = []
 | 
					 | 
				
			||||||
        self._marklength = 0
 | 
					 | 
				
			||||||
        self._aifc = 1      # AIFF-C is default
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __del__(self):
 | 
					 | 
				
			||||||
        self.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __enter__(self):
 | 
					 | 
				
			||||||
        return self
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __exit__(self, *args):
 | 
					 | 
				
			||||||
        self.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # User visible methods.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    def aiff(self):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        self._aifc = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def aifc(self):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        self._aifc = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setnchannels(self, nchannels):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        if nchannels < 1:
 | 
					 | 
				
			||||||
            raise Error('bad # of channels')
 | 
					 | 
				
			||||||
        self._nchannels = nchannels
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getnchannels(self):
 | 
					 | 
				
			||||||
        if not self._nchannels:
 | 
					 | 
				
			||||||
            raise Error('number of channels not set')
 | 
					 | 
				
			||||||
        return self._nchannels
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setsampwidth(self, sampwidth):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        if sampwidth < 1 or sampwidth > 4:
 | 
					 | 
				
			||||||
            raise Error('bad sample width')
 | 
					 | 
				
			||||||
        self._sampwidth = sampwidth
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getsampwidth(self):
 | 
					 | 
				
			||||||
        if not self._sampwidth:
 | 
					 | 
				
			||||||
            raise Error('sample width not set')
 | 
					 | 
				
			||||||
        return self._sampwidth
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setframerate(self, framerate):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        if framerate <= 0:
 | 
					 | 
				
			||||||
            raise Error('bad frame rate')
 | 
					 | 
				
			||||||
        self._framerate = framerate
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getframerate(self):
 | 
					 | 
				
			||||||
        if not self._framerate:
 | 
					 | 
				
			||||||
            raise Error('frame rate not set')
 | 
					 | 
				
			||||||
        return self._framerate
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setnframes(self, nframes):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        self._nframes = nframes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getnframes(self):
 | 
					 | 
				
			||||||
        return self._nframeswritten
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setcomptype(self, comptype, compname):
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        if comptype not in (b'NONE', b'ulaw', b'ULAW',
 | 
					 | 
				
			||||||
                            b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'):
 | 
					 | 
				
			||||||
            raise Error('unsupported compression type')
 | 
					 | 
				
			||||||
        self._comptype = comptype
 | 
					 | 
				
			||||||
        self._compname = compname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getcomptype(self):
 | 
					 | 
				
			||||||
        return self._comptype
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getcompname(self):
 | 
					 | 
				
			||||||
        return self._compname
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
##  def setversion(self, version):
 | 
					 | 
				
			||||||
##      if self._nframeswritten:
 | 
					 | 
				
			||||||
##          raise Error, 'cannot change parameters after starting to write'
 | 
					 | 
				
			||||||
##      self._version = version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setparams(self, params):
 | 
					 | 
				
			||||||
        nchannels, sampwidth, framerate, nframes, comptype, compname = params
 | 
					 | 
				
			||||||
        if self._nframeswritten:
 | 
					 | 
				
			||||||
            raise Error('cannot change parameters after starting to write')
 | 
					 | 
				
			||||||
        if comptype not in (b'NONE', b'ulaw', b'ULAW',
 | 
					 | 
				
			||||||
                            b'alaw', b'ALAW', b'G722', b'sowt', b'SOWT'):
 | 
					 | 
				
			||||||
            raise Error('unsupported compression type')
 | 
					 | 
				
			||||||
        self.setnchannels(nchannels)
 | 
					 | 
				
			||||||
        self.setsampwidth(sampwidth)
 | 
					 | 
				
			||||||
        self.setframerate(framerate)
 | 
					 | 
				
			||||||
        self.setnframes(nframes)
 | 
					 | 
				
			||||||
        self.setcomptype(comptype, compname)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getparams(self):
 | 
					 | 
				
			||||||
        if not self._nchannels or not self._sampwidth or not self._framerate:
 | 
					 | 
				
			||||||
            raise Error('not all parameters set')
 | 
					 | 
				
			||||||
        return _aifc_params(self._nchannels, self._sampwidth, self._framerate,
 | 
					 | 
				
			||||||
                            self._nframes, self._comptype, self._compname)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setmark(self, id, pos, name):
 | 
					 | 
				
			||||||
        if id <= 0:
 | 
					 | 
				
			||||||
            raise Error('marker ID must be > 0')
 | 
					 | 
				
			||||||
        if pos < 0:
 | 
					 | 
				
			||||||
            raise Error('marker position must be >= 0')
 | 
					 | 
				
			||||||
        if not isinstance(name, bytes):
 | 
					 | 
				
			||||||
            raise Error('marker name must be bytes')
 | 
					 | 
				
			||||||
        for i in range(len(self._markers)):
 | 
					 | 
				
			||||||
            if id == self._markers[i][0]:
 | 
					 | 
				
			||||||
                self._markers[i] = id, pos, name
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
        self._markers.append((id, pos, name))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getmark(self, id):
 | 
					 | 
				
			||||||
        for marker in self._markers:
 | 
					 | 
				
			||||||
            if id == marker[0]:
 | 
					 | 
				
			||||||
                return marker
 | 
					 | 
				
			||||||
        raise Error('marker {0!r} does not exist'.format(id))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getmarkers(self):
 | 
					 | 
				
			||||||
        if len(self._markers) == 0:
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
        return self._markers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def tell(self):
 | 
					 | 
				
			||||||
        return self._nframeswritten
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def writeframesraw(self, data):
 | 
					 | 
				
			||||||
        if not isinstance(data, (bytes, bytearray)):
 | 
					 | 
				
			||||||
            data = memoryview(data).cast('B')
 | 
					 | 
				
			||||||
        self._ensure_header_written(len(data))
 | 
					 | 
				
			||||||
        nframes = len(data) // (self._sampwidth * self._nchannels)
 | 
					 | 
				
			||||||
        if self._convert:
 | 
					 | 
				
			||||||
            data = self._convert(data)
 | 
					 | 
				
			||||||
        self._file.write(data)
 | 
					 | 
				
			||||||
        self._nframeswritten = self._nframeswritten + nframes
 | 
					 | 
				
			||||||
        self._datawritten = self._datawritten + len(data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def writeframes(self, data):
 | 
					 | 
				
			||||||
        self.writeframesraw(data)
 | 
					 | 
				
			||||||
        if self._nframeswritten != self._nframes or \
 | 
					 | 
				
			||||||
              self._datalength != self._datawritten:
 | 
					 | 
				
			||||||
            self._patchheader()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					 | 
				
			||||||
        if self._file is None:
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            self._ensure_header_written(0)
 | 
					 | 
				
			||||||
            if self._datawritten & 1:
 | 
					 | 
				
			||||||
                # quick pad to even size
 | 
					 | 
				
			||||||
                self._file.write(b'\x00')
 | 
					 | 
				
			||||||
                self._datawritten = self._datawritten + 1
 | 
					 | 
				
			||||||
            self._writemarkers()
 | 
					 | 
				
			||||||
            if self._nframeswritten != self._nframes or \
 | 
					 | 
				
			||||||
                  self._datalength != self._datawritten or \
 | 
					 | 
				
			||||||
                  self._marklength:
 | 
					 | 
				
			||||||
                self._patchheader()
 | 
					 | 
				
			||||||
        finally:
 | 
					 | 
				
			||||||
            # Prevent ref cycles
 | 
					 | 
				
			||||||
            self._convert = None
 | 
					 | 
				
			||||||
            f = self._file
 | 
					 | 
				
			||||||
            self._file = None
 | 
					 | 
				
			||||||
            f.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # Internal methods.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _lin2alaw(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.lin2alaw(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _lin2ulaw(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.lin2ulaw(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _lin2adpcm(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        if not hasattr(self, '_adpcmstate'):
 | 
					 | 
				
			||||||
            self._adpcmstate = None
 | 
					 | 
				
			||||||
        data, self._adpcmstate = audioop.lin2adpcm(data, 2, self._adpcmstate)
 | 
					 | 
				
			||||||
        return data
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _lin2sowt(self, data):
 | 
					 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					 | 
				
			||||||
            warnings.simplefilter('ignore', category=DeprecationWarning)
 | 
					 | 
				
			||||||
            import audioop
 | 
					 | 
				
			||||||
        return audioop.byteswap(data, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _ensure_header_written(self, datasize):
 | 
					 | 
				
			||||||
        if not self._nframeswritten:
 | 
					 | 
				
			||||||
            if self._comptype in (b'ULAW', b'ulaw',
 | 
					 | 
				
			||||||
                b'ALAW', b'alaw', b'G722',
 | 
					 | 
				
			||||||
                b'sowt', b'SOWT'):
 | 
					 | 
				
			||||||
                if not self._sampwidth:
 | 
					 | 
				
			||||||
                    self._sampwidth = 2
 | 
					 | 
				
			||||||
                if self._sampwidth != 2:
 | 
					 | 
				
			||||||
                    raise Error('sample width must be 2 when compressing '
 | 
					 | 
				
			||||||
                                'with ulaw/ULAW, alaw/ALAW, sowt/SOWT '
 | 
					 | 
				
			||||||
                                'or G7.22 (ADPCM)')
 | 
					 | 
				
			||||||
            if not self._nchannels:
 | 
					 | 
				
			||||||
                raise Error('# channels not specified')
 | 
					 | 
				
			||||||
            if not self._sampwidth:
 | 
					 | 
				
			||||||
                raise Error('sample width not specified')
 | 
					 | 
				
			||||||
            if not self._framerate:
 | 
					 | 
				
			||||||
                raise Error('sampling rate not specified')
 | 
					 | 
				
			||||||
            self._write_header(datasize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _init_compression(self):
 | 
					 | 
				
			||||||
        if self._comptype == b'G722':
 | 
					 | 
				
			||||||
            self._convert = self._lin2adpcm
 | 
					 | 
				
			||||||
        elif self._comptype in (b'ulaw', b'ULAW'):
 | 
					 | 
				
			||||||
            self._convert = self._lin2ulaw
 | 
					 | 
				
			||||||
        elif self._comptype in (b'alaw', b'ALAW'):
 | 
					 | 
				
			||||||
            self._convert = self._lin2alaw
 | 
					 | 
				
			||||||
        elif self._comptype in (b'sowt', b'SOWT'):
 | 
					 | 
				
			||||||
            self._convert = self._lin2sowt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _write_header(self, initlength):
 | 
					 | 
				
			||||||
        if self._aifc and self._comptype != b'NONE':
 | 
					 | 
				
			||||||
            self._init_compression()
 | 
					 | 
				
			||||||
        self._file.write(b'FORM')
 | 
					 | 
				
			||||||
        if not self._nframes:
 | 
					 | 
				
			||||||
            self._nframes = initlength // (self._nchannels * self._sampwidth)
 | 
					 | 
				
			||||||
        self._datalength = self._nframes * self._nchannels * self._sampwidth
 | 
					 | 
				
			||||||
        if self._datalength & 1:
 | 
					 | 
				
			||||||
            self._datalength = self._datalength + 1
 | 
					 | 
				
			||||||
        if self._aifc:
 | 
					 | 
				
			||||||
            if self._comptype in (b'ulaw', b'ULAW', b'alaw', b'ALAW'):
 | 
					 | 
				
			||||||
                self._datalength = self._datalength // 2
 | 
					 | 
				
			||||||
                if self._datalength & 1:
 | 
					 | 
				
			||||||
                    self._datalength = self._datalength + 1
 | 
					 | 
				
			||||||
            elif self._comptype == b'G722':
 | 
					 | 
				
			||||||
                self._datalength = (self._datalength + 3) // 4
 | 
					 | 
				
			||||||
                if self._datalength & 1:
 | 
					 | 
				
			||||||
                    self._datalength = self._datalength + 1
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            self._form_length_pos = self._file.tell()
 | 
					 | 
				
			||||||
        except (AttributeError, OSError):
 | 
					 | 
				
			||||||
            self._form_length_pos = None
 | 
					 | 
				
			||||||
        commlength = self._write_form_length(self._datalength)
 | 
					 | 
				
			||||||
        if self._aifc:
 | 
					 | 
				
			||||||
            self._file.write(b'AIFC')
 | 
					 | 
				
			||||||
            self._file.write(b'FVER')
 | 
					 | 
				
			||||||
            _write_ulong(self._file, 4)
 | 
					 | 
				
			||||||
            _write_ulong(self._file, self._version)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            self._file.write(b'AIFF')
 | 
					 | 
				
			||||||
        self._file.write(b'COMM')
 | 
					 | 
				
			||||||
        _write_ulong(self._file, commlength)
 | 
					 | 
				
			||||||
        _write_short(self._file, self._nchannels)
 | 
					 | 
				
			||||||
        if self._form_length_pos is not None:
 | 
					 | 
				
			||||||
            self._nframes_pos = self._file.tell()
 | 
					 | 
				
			||||||
        _write_ulong(self._file, self._nframes)
 | 
					 | 
				
			||||||
        if self._comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
 | 
					 | 
				
			||||||
            _write_short(self._file, 8)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            _write_short(self._file, self._sampwidth * 8)
 | 
					 | 
				
			||||||
        _write_float(self._file, self._framerate)
 | 
					 | 
				
			||||||
        if self._aifc:
 | 
					 | 
				
			||||||
            self._file.write(self._comptype)
 | 
					 | 
				
			||||||
            _write_string(self._file, self._compname)
 | 
					 | 
				
			||||||
        self._file.write(b'SSND')
 | 
					 | 
				
			||||||
        if self._form_length_pos is not None:
 | 
					 | 
				
			||||||
            self._ssnd_length_pos = self._file.tell()
 | 
					 | 
				
			||||||
        _write_ulong(self._file, self._datalength + 8)
 | 
					 | 
				
			||||||
        _write_ulong(self._file, 0)
 | 
					 | 
				
			||||||
        _write_ulong(self._file, 0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _write_form_length(self, datalength):
 | 
					 | 
				
			||||||
        if self._aifc:
 | 
					 | 
				
			||||||
            commlength = 18 + 5 + len(self._compname)
 | 
					 | 
				
			||||||
            if commlength & 1:
 | 
					 | 
				
			||||||
                commlength = commlength + 1
 | 
					 | 
				
			||||||
            verslength = 12
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            commlength = 18
 | 
					 | 
				
			||||||
            verslength = 0
 | 
					 | 
				
			||||||
        _write_ulong(self._file, 4 + verslength + self._marklength + \
 | 
					 | 
				
			||||||
                     8 + commlength + 16 + datalength)
 | 
					 | 
				
			||||||
        return commlength
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _patchheader(self):
 | 
					 | 
				
			||||||
        curpos = self._file.tell()
 | 
					 | 
				
			||||||
        if self._datawritten & 1:
 | 
					 | 
				
			||||||
            datalength = self._datawritten + 1
 | 
					 | 
				
			||||||
            self._file.write(b'\x00')
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            datalength = self._datawritten
 | 
					 | 
				
			||||||
        if datalength == self._datalength and \
 | 
					 | 
				
			||||||
              self._nframes == self._nframeswritten and \
 | 
					 | 
				
			||||||
              self._marklength == 0:
 | 
					 | 
				
			||||||
            self._file.seek(curpos, 0)
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        self._file.seek(self._form_length_pos, 0)
 | 
					 | 
				
			||||||
        dummy = self._write_form_length(datalength)
 | 
					 | 
				
			||||||
        self._file.seek(self._nframes_pos, 0)
 | 
					 | 
				
			||||||
        _write_ulong(self._file, self._nframeswritten)
 | 
					 | 
				
			||||||
        self._file.seek(self._ssnd_length_pos, 0)
 | 
					 | 
				
			||||||
        _write_ulong(self._file, datalength + 8)
 | 
					 | 
				
			||||||
        self._file.seek(curpos, 0)
 | 
					 | 
				
			||||||
        self._nframes = self._nframeswritten
 | 
					 | 
				
			||||||
        self._datalength = datalength
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _writemarkers(self):
 | 
					 | 
				
			||||||
        if len(self._markers) == 0:
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        self._file.write(b'MARK')
 | 
					 | 
				
			||||||
        length = 2
 | 
					 | 
				
			||||||
        for marker in self._markers:
 | 
					 | 
				
			||||||
            id, pos, name = marker
 | 
					 | 
				
			||||||
            length = length + len(name) + 1 + 6
 | 
					 | 
				
			||||||
            if len(name) & 1 == 0:
 | 
					 | 
				
			||||||
                length = length + 1
 | 
					 | 
				
			||||||
        _write_ulong(self._file, length)
 | 
					 | 
				
			||||||
        self._marklength = length + 8
 | 
					 | 
				
			||||||
        _write_short(self._file, len(self._markers))
 | 
					 | 
				
			||||||
        for marker in self._markers:
 | 
					 | 
				
			||||||
            id, pos, name = marker
 | 
					 | 
				
			||||||
            _write_short(self._file, id)
 | 
					 | 
				
			||||||
            _write_ulong(self._file, pos)
 | 
					 | 
				
			||||||
            _write_string(self._file, name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def open(f, mode=None):
 | 
					 | 
				
			||||||
    if mode is None:
 | 
					 | 
				
			||||||
        if hasattr(f, 'mode'):
 | 
					 | 
				
			||||||
            mode = f.mode
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            mode = 'rb'
 | 
					 | 
				
			||||||
    if mode in ('r', 'rb'):
 | 
					 | 
				
			||||||
        return Aifc_read(f)
 | 
					 | 
				
			||||||
    elif mode in ('w', 'wb'):
 | 
					 | 
				
			||||||
        return Aifc_write(f)
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        raise Error("mode must be 'r', 'rb', 'w', or 'wb'")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == '__main__':
 | 
					 | 
				
			||||||
    import sys
 | 
					 | 
				
			||||||
    if not sys.argv[1:]:
 | 
					 | 
				
			||||||
        sys.argv.append('/usr/demos/data/audio/bach.aiff')
 | 
					 | 
				
			||||||
    fn = sys.argv[1]
 | 
					 | 
				
			||||||
    with open(fn, 'r') as f:
 | 
					 | 
				
			||||||
        print("Reading", fn)
 | 
					 | 
				
			||||||
        print("nchannels =", f.getnchannels())
 | 
					 | 
				
			||||||
        print("nframes   =", f.getnframes())
 | 
					 | 
				
			||||||
        print("sampwidth =", f.getsampwidth())
 | 
					 | 
				
			||||||
        print("framerate =", f.getframerate())
 | 
					 | 
				
			||||||
        print("comptype  =", f.getcomptype())
 | 
					 | 
				
			||||||
        print("compname  =", f.getcompname())
 | 
					 | 
				
			||||||
        if sys.argv[2:]:
 | 
					 | 
				
			||||||
            gn = sys.argv[2]
 | 
					 | 
				
			||||||
            print("Writing", gn)
 | 
					 | 
				
			||||||
            with open(gn, 'w') as g:
 | 
					 | 
				
			||||||
                g.setparams(f.getparams())
 | 
					 | 
				
			||||||
                while 1:
 | 
					 | 
				
			||||||
                    data = f.readframes(1024)
 | 
					 | 
				
			||||||
                    if not data:
 | 
					 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
                    g.writeframes(data)
 | 
					 | 
				
			||||||
            print("Done.")
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -1,439 +0,0 @@
 | 
				
			||||||
from test.support import findfile
 | 
					 | 
				
			||||||
from test.support.os_helper import TESTFN, unlink
 | 
					 | 
				
			||||||
from test.support.warnings_helper import check_no_resource_warning, import_deprecated
 | 
					 | 
				
			||||||
import unittest
 | 
					 | 
				
			||||||
from unittest import mock
 | 
					 | 
				
			||||||
from test import audiotests
 | 
					 | 
				
			||||||
import io
 | 
					 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import struct
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
aifc = import_deprecated("aifc")
 | 
					 | 
				
			||||||
audioop = import_deprecated("audioop")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcTest(audiotests.AudioWriteTests,
 | 
					 | 
				
			||||||
               audiotests.AudioTestsWithSourceFile):
 | 
					 | 
				
			||||||
    module = aifc
 | 
					 | 
				
			||||||
    close_fd = True
 | 
					 | 
				
			||||||
    test_unseekable_read = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcPCM8Test(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-pcm8.aiff'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 1
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'NONE'
 | 
					 | 
				
			||||||
    compname = b'not compressed'
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      02FF 4B00 3104 8008 CB06 4803 BF01 03FE B8FA B4F3 29EB 1AE6 \
 | 
					 | 
				
			||||||
      EDE4 C6E2 0EE0 EFE0 57E2 FBE8 13EF D8F7 97FB F5FC 08FB DFFB \
 | 
					 | 
				
			||||||
      11FA 3EFB BCFC 66FF CF04 4309 C10E 5112 EE17 8216 7F14 8012 \
 | 
					 | 
				
			||||||
      490E 520D EF0F CE0F E40C 630A 080A 2B0B 510E 8B11 B60E 440A \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcPCM16Test(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-pcm16.aiff'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 2
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'NONE'
 | 
					 | 
				
			||||||
    compname = b'not compressed'
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      022EFFEA 4B5D00F6 311804EA 80E10840 CBE106B1 48A903F5 BFE601B2 036CFE7B \
 | 
					 | 
				
			||||||
      B858FA3E B4B1F34F 299AEBCA 1A5DE6DA EDFAE491 C628E275 0E09E0B5 EF2AE029 \
 | 
					 | 
				
			||||||
      5758E271 FB35E83F 1376EF86 D82BF727 9790FB76 F5FAFC0F 0867FB9C DF30FB43 \
 | 
					 | 
				
			||||||
      117EFA36 3EE5FB5B BC79FCB1 66D9FF5D CF150412 431D097C C1BA0EC8 512112A1 \
 | 
					 | 
				
			||||||
      EEE21753 82071665 7FFF1443 8004128F 49A20EAF 52BB0DBA EFB40F60 CE3C0FBF \
 | 
					 | 
				
			||||||
      E4B30CEC 63430A5C 08C80A20 2BBB0B08 514A0E43 8BCF1139 B6F60EEB 44120A5E \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcPCM24Test(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-pcm24.aiff'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 3
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'NONE'
 | 
					 | 
				
			||||||
    compname = b'not compressed'
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      022D65FFEB9D 4B5A0F00FA54 3113C304EE2B 80DCD6084303 \
 | 
					 | 
				
			||||||
      CBDEC006B261 48A99803F2F8 BFE82401B07D 036BFBFE7B5D \
 | 
					 | 
				
			||||||
      B85756FA3EC9 B4B055F3502B 299830EBCB62 1A5CA7E6D99A \
 | 
					 | 
				
			||||||
      EDFA3EE491BD C625EBE27884 0E05A9E0B6CF EF2929E02922 \
 | 
					 | 
				
			||||||
      5758D8E27067 FB3557E83E16 1377BFEF8402 D82C5BF7272A \
 | 
					 | 
				
			||||||
      978F16FB7745 F5F865FC1013 086635FB9C4E DF30FCFB40EE \
 | 
					 | 
				
			||||||
      117FE0FA3438 3EE6B8FB5AC3 BC77A3FCB2F4 66D6DAFF5F32 \
 | 
					 | 
				
			||||||
      CF13B9041275 431D69097A8C C1BB600EC74E 5120B912A2BA \
 | 
					 | 
				
			||||||
      EEDF641754C0 8207001664B7 7FFFFF14453F 8000001294E6 \
 | 
					 | 
				
			||||||
      499C1B0EB3B2 52B73E0DBCA0 EFB2B20F5FD8 CE3CDB0FBE12 \
 | 
					 | 
				
			||||||
      E4B49C0CEA2D 6344A80A5A7C 08C8FE0A1FFE 2BB9860B0A0E \
 | 
					 | 
				
			||||||
      51486F0E44E1 8BCC64113B05 B6F4EC0EEB36 4413170A5B48 \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcPCM32Test(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-pcm32.aiff'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 4
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'NONE'
 | 
					 | 
				
			||||||
    compname = b'not compressed'
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      022D65BCFFEB9D92 4B5A0F8000FA549C 3113C34004EE2BC0 80DCD680084303E0 \
 | 
					 | 
				
			||||||
      CBDEC0C006B26140 48A9980003F2F8FC BFE8248001B07D92 036BFB60FE7B5D34 \
 | 
					 | 
				
			||||||
      B8575600FA3EC920 B4B05500F3502BC0 29983000EBCB6240 1A5CA7A0E6D99A60 \
 | 
					 | 
				
			||||||
      EDFA3E80E491BD40 C625EB80E27884A0 0E05A9A0E0B6CFE0 EF292940E0292280 \
 | 
					 | 
				
			||||||
      5758D800E2706700 FB3557D8E83E1640 1377BF00EF840280 D82C5B80F7272A80 \
 | 
					 | 
				
			||||||
      978F1600FB774560 F5F86510FC101364 086635A0FB9C4E20 DF30FC40FB40EE28 \
 | 
					 | 
				
			||||||
      117FE0A0FA3438B0 3EE6B840FB5AC3F0 BC77A380FCB2F454 66D6DA80FF5F32B4 \
 | 
					 | 
				
			||||||
      CF13B980041275B0 431D6980097A8C00 C1BB60000EC74E00 5120B98012A2BAA0 \
 | 
					 | 
				
			||||||
      EEDF64C01754C060 820700001664B780 7FFFFFFF14453F40 800000001294E6E0 \
 | 
					 | 
				
			||||||
      499C1B000EB3B270 52B73E000DBCA020 EFB2B2E00F5FD880 CE3CDB400FBE1270 \
 | 
					 | 
				
			||||||
      E4B49CC00CEA2D90 6344A8800A5A7CA0 08C8FE800A1FFEE0 2BB986C00B0A0E00 \
 | 
					 | 
				
			||||||
      51486F800E44E190 8BCC6480113B0580 B6F4EC000EEB3630 441317800A5B48A0 \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcULAWTest(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-ulaw.aifc'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 2
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'ulaw'
 | 
					 | 
				
			||||||
    compname = b''
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      022CFFE8 497C0104 307C04DC 8284083C CB84069C 497C03DC BE8401AC 036CFE74 \
 | 
					 | 
				
			||||||
      B684FA24 B684F344 2A7CEC04 19FCE704 EE04E504 C584E204 0E3CE104 EF04DF84 \
 | 
					 | 
				
			||||||
      557CE204 FB24E804 12FCEF04 D784F744 9684FB64 F5C4FC24 083CFBA4 DF84FB24 \
 | 
					 | 
				
			||||||
      11FCFA24 3E7CFB64 BA84FCB4 657CFF5C CF84041C 417C093C C1840EBC 517C12FC \
 | 
					 | 
				
			||||||
      EF0416FC 828415FC 7D7C13FC 828412FC 497C0EBC 517C0DBC F0040F3C CD840FFC \
 | 
					 | 
				
			||||||
      E5040CBC 617C0A3C 08BC0A3C 2C7C0B3C 517C0E3C 8A8410FC B6840EBC 457C0A3C \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
    if sys.byteorder != 'big':
 | 
					 | 
				
			||||||
        frames = audioop.byteswap(frames, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcALAWTest(AifcTest, unittest.TestCase):
 | 
					 | 
				
			||||||
    sndfilename = 'pluck-alaw.aifc'
 | 
					 | 
				
			||||||
    sndfilenframes = 3307
 | 
					 | 
				
			||||||
    nchannels = 2
 | 
					 | 
				
			||||||
    sampwidth = 2
 | 
					 | 
				
			||||||
    framerate = 11025
 | 
					 | 
				
			||||||
    nframes = 48
 | 
					 | 
				
			||||||
    comptype = b'alaw'
 | 
					 | 
				
			||||||
    compname = b''
 | 
					 | 
				
			||||||
    frames = bytes.fromhex("""\
 | 
					 | 
				
			||||||
      0230FFE8 4A0000F8 310004E0 82000840 CB0006A0 4A0003F0 BE0001A8 0370FE78 \
 | 
					 | 
				
			||||||
      BA00FA20 B600F340 2900EB80 1A80E680 ED80E480 C700E280 0E40E080 EF80E080 \
 | 
					 | 
				
			||||||
      5600E280 FB20E880 1380EF80 D900F740 9600FB60 F5C0FC10 0840FBA0 DF00FB20 \
 | 
					 | 
				
			||||||
      1180FA20 3F00FB60 BE00FCB0 6600FF58 CF000420 42000940 C1000EC0 52001280 \
 | 
					 | 
				
			||||||
      EE801780 82001680 7E001480 82001280 4A000EC0 52000DC0 EF800F40 CF000FC0 \
 | 
					 | 
				
			||||||
      E4800CC0 62000A40 08C00A40 2B000B40 52000E40 8A001180 B6000EC0 46000A40 \
 | 
					 | 
				
			||||||
      """)
 | 
					 | 
				
			||||||
    if sys.byteorder != 'big':
 | 
					 | 
				
			||||||
        frames = audioop.byteswap(frames, 2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AifcMiscTest(unittest.TestCase):
 | 
					 | 
				
			||||||
    def test_skipunknown(self):
 | 
					 | 
				
			||||||
        #Issue 2245
 | 
					 | 
				
			||||||
        #This file contains chunk types aifc doesn't recognize.
 | 
					 | 
				
			||||||
        f = aifc.open(findfile('Sine-1000Hz-300ms.aif'))
 | 
					 | 
				
			||||||
        f.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_close_opened_files_on_error(self):
 | 
					 | 
				
			||||||
        non_aifc_file = findfile('pluck-pcm8.wav', subdir='audiodata')
 | 
					 | 
				
			||||||
        with check_no_resource_warning(self):
 | 
					 | 
				
			||||||
            with self.assertRaises(aifc.Error):
 | 
					 | 
				
			||||||
                # Try opening a non-AIFC file, with the expectation that
 | 
					 | 
				
			||||||
                # `aifc.open` will fail (without raising a ResourceWarning)
 | 
					 | 
				
			||||||
                self.f = aifc.open(non_aifc_file, 'rb')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Aifc_write.initfp() won't raise in normal case.  But some errors
 | 
					 | 
				
			||||||
            # (e.g. MemoryError, KeyboardInterrupt, etc..) can happen.
 | 
					 | 
				
			||||||
            with mock.patch.object(aifc.Aifc_write, 'initfp',
 | 
					 | 
				
			||||||
                                   side_effect=RuntimeError):
 | 
					 | 
				
			||||||
                with self.assertRaises(RuntimeError):
 | 
					 | 
				
			||||||
                    self.fout = aifc.open(TESTFN, 'wb')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_params_added(self):
 | 
					 | 
				
			||||||
        f = self.f = aifc.open(TESTFN, 'wb')
 | 
					 | 
				
			||||||
        f.aiff()
 | 
					 | 
				
			||||||
        f.setparams((1, 1, 1, 1, b'NONE', b''))
 | 
					 | 
				
			||||||
        f.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        f = aifc.open(TESTFN, 'rb')
 | 
					 | 
				
			||||||
        self.addCleanup(f.close)
 | 
					 | 
				
			||||||
        params = f.getparams()
 | 
					 | 
				
			||||||
        self.assertEqual(params.nchannels, f.getnchannels())
 | 
					 | 
				
			||||||
        self.assertEqual(params.sampwidth, f.getsampwidth())
 | 
					 | 
				
			||||||
        self.assertEqual(params.framerate, f.getframerate())
 | 
					 | 
				
			||||||
        self.assertEqual(params.nframes, f.getnframes())
 | 
					 | 
				
			||||||
        self.assertEqual(params.comptype, f.getcomptype())
 | 
					 | 
				
			||||||
        self.assertEqual(params.compname, f.getcompname())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_header_comptype_sampwidth(self):
 | 
					 | 
				
			||||||
        for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
 | 
					 | 
				
			||||||
            fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
            fout.setnchannels(1)
 | 
					 | 
				
			||||||
            fout.setframerate(1)
 | 
					 | 
				
			||||||
            fout.setcomptype(comptype, b'')
 | 
					 | 
				
			||||||
            fout.close()
 | 
					 | 
				
			||||||
            self.assertEqual(fout.getsampwidth(), 2)
 | 
					 | 
				
			||||||
            fout.initfp(None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_markers_values(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getmarkers(), None)
 | 
					 | 
				
			||||||
        fout.setmark(1, 0, b'foo1')
 | 
					 | 
				
			||||||
        fout.setmark(1, 1, b'foo2')
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getmark(1), (1, 1, b'foo2'))
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getmarkers(), [(1, 1, b'foo2')])
 | 
					 | 
				
			||||||
        fout.initfp(None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_markers(self):
 | 
					 | 
				
			||||||
        fout = self.fout = aifc.open(TESTFN, 'wb')
 | 
					 | 
				
			||||||
        fout.aiff()
 | 
					 | 
				
			||||||
        fout.setparams((1, 1, 1, 1, b'NONE', b''))
 | 
					 | 
				
			||||||
        fout.setmark(1, 0, b'odd')
 | 
					 | 
				
			||||||
        fout.setmark(2, 0, b'even')
 | 
					 | 
				
			||||||
        fout.writeframes(b'\x00')
 | 
					 | 
				
			||||||
        fout.close()
 | 
					 | 
				
			||||||
        f = aifc.open(TESTFN, 'rb')
 | 
					 | 
				
			||||||
        self.addCleanup(f.close)
 | 
					 | 
				
			||||||
        self.assertEqual(f.getmarkers(), [(1, 0, b'odd'), (2, 0, b'even')])
 | 
					 | 
				
			||||||
        self.assertEqual(f.getmark(1), (1, 0, b'odd'))
 | 
					 | 
				
			||||||
        self.assertEqual(f.getmark(2), (2, 0, b'even'))
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, f.getmark, 3)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class AIFCLowLevelTest(unittest.TestCase):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_written(self):
 | 
					 | 
				
			||||||
        def read_written(self, what):
 | 
					 | 
				
			||||||
            f = io.BytesIO()
 | 
					 | 
				
			||||||
            getattr(aifc, '_write_' + what)(f, x)
 | 
					 | 
				
			||||||
            f.seek(0)
 | 
					 | 
				
			||||||
            return getattr(aifc, '_read_' + what)(f)
 | 
					 | 
				
			||||||
        for x in (-1, 0, 0.1, 1):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'float'), x)
 | 
					 | 
				
			||||||
        for x in (float('NaN'), float('Inf')):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'float'), aifc._HUGE_VAL)
 | 
					 | 
				
			||||||
        for x in (b'', b'foo', b'a' * 255):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'string'), x)
 | 
					 | 
				
			||||||
        for x in (-0x7FFFFFFF, -1, 0, 1, 0x7FFFFFFF):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'long'), x)
 | 
					 | 
				
			||||||
        for x in (0, 1, 0xFFFFFFFF):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'ulong'), x)
 | 
					 | 
				
			||||||
        for x in (-0x7FFF, -1, 0, 1, 0x7FFF):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'short'), x)
 | 
					 | 
				
			||||||
        for x in (0, 1, 0xFFFF):
 | 
					 | 
				
			||||||
            self.assertEqual(read_written(x, 'ushort'), x)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_raises(self):
 | 
					 | 
				
			||||||
        f = io.BytesIO(b'\x00')
 | 
					 | 
				
			||||||
        self.assertRaises(EOFError, aifc._read_ulong, f)
 | 
					 | 
				
			||||||
        self.assertRaises(EOFError, aifc._read_long, f)
 | 
					 | 
				
			||||||
        self.assertRaises(EOFError, aifc._read_ushort, f)
 | 
					 | 
				
			||||||
        self.assertRaises(EOFError, aifc._read_short, f)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_long_string_raises(self):
 | 
					 | 
				
			||||||
        f = io.BytesIO()
 | 
					 | 
				
			||||||
        with self.assertRaises(ValueError):
 | 
					 | 
				
			||||||
            aifc._write_string(f, b'too long' * 255)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_wrong_open_mode(self):
 | 
					 | 
				
			||||||
        with self.assertRaises(aifc.Error):
 | 
					 | 
				
			||||||
            aifc.open(TESTFN, 'wrong_mode')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_wrong_form(self):
 | 
					 | 
				
			||||||
        b1 = io.BytesIO(b'WRNG' + struct.pack('>L', 0))
 | 
					 | 
				
			||||||
        b2 = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'WRNG')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, aifc.open, b1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, aifc.open, b2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_no_comm_chunk(self):
 | 
					 | 
				
			||||||
        b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, aifc.open, b)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_no_ssnd_chunk(self):
 | 
					 | 
				
			||||||
        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
        b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, 8,
 | 
					 | 
				
			||||||
                                   0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
        b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00'
 | 
					 | 
				
			||||||
        with self.assertRaisesRegex(aifc.Error, 'COMM chunk and/or SSND chunk'
 | 
					 | 
				
			||||||
                                                ' missing'):
 | 
					 | 
				
			||||||
            aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_wrong_compression_type(self):
 | 
					 | 
				
			||||||
        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
        b += b'COMM' + struct.pack('>LhlhhLL', 23, 1, 0, 8,
 | 
					 | 
				
			||||||
                                   0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
        b += b'WRNG' + struct.pack('B', 0)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, aifc.open, io.BytesIO(b))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_wrong_number_of_channels(self):
 | 
					 | 
				
			||||||
        for nchannels in 0, -1:
 | 
					 | 
				
			||||||
            b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
            b += b'COMM' + struct.pack('>LhlhhLL', 38, nchannels, 0, 8,
 | 
					 | 
				
			||||||
                                       0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
            b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00'
 | 
					 | 
				
			||||||
            b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
 | 
					 | 
				
			||||||
            with self.assertRaisesRegex(aifc.Error, 'bad # of channels'):
 | 
					 | 
				
			||||||
                aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_wrong_sample_width(self):
 | 
					 | 
				
			||||||
        for sampwidth in 0, -1:
 | 
					 | 
				
			||||||
            b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
            b += b'COMM' + struct.pack('>LhlhhLL', 38, 1, 0, sampwidth,
 | 
					 | 
				
			||||||
                                       0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
            b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00'
 | 
					 | 
				
			||||||
            b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
 | 
					 | 
				
			||||||
            with self.assertRaisesRegex(aifc.Error, 'bad sample width'):
 | 
					 | 
				
			||||||
                aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_wrong_marks(self):
 | 
					 | 
				
			||||||
        b = b'FORM' + struct.pack('>L', 4) + b'AIFF'
 | 
					 | 
				
			||||||
        b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8,
 | 
					 | 
				
			||||||
                                   0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
 | 
					 | 
				
			||||||
        b += b'MARK' + struct.pack('>LhB', 3, 1, 1)
 | 
					 | 
				
			||||||
        with self.assertWarns(UserWarning) as cm:
 | 
					 | 
				
			||||||
            f = aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
        self.assertEqual(str(cm.warning), 'Warning: MARK chunk contains '
 | 
					 | 
				
			||||||
                                          'only 0 markers instead of 1')
 | 
					 | 
				
			||||||
        self.assertEqual(f.getmarkers(), None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_comm_kludge_compname_even(self):
 | 
					 | 
				
			||||||
        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
        b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8,
 | 
					 | 
				
			||||||
                                   0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
        b += b'NONE' + struct.pack('B', 4) + b'even' + b'\x00'
 | 
					 | 
				
			||||||
        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
 | 
					 | 
				
			||||||
        with self.assertWarns(UserWarning) as cm:
 | 
					 | 
				
			||||||
            f = aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
        self.assertEqual(str(cm.warning), 'Warning: bad COMM chunk size')
 | 
					 | 
				
			||||||
        self.assertEqual(f.getcompname(), b'even')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_read_comm_kludge_compname_odd(self):
 | 
					 | 
				
			||||||
        b = b'FORM' + struct.pack('>L', 4) + b'AIFC'
 | 
					 | 
				
			||||||
        b += b'COMM' + struct.pack('>LhlhhLL', 18, 1, 0, 8,
 | 
					 | 
				
			||||||
                                   0x4000 | 12, 11025<<18, 0)
 | 
					 | 
				
			||||||
        b += b'NONE' + struct.pack('B', 3) + b'odd'
 | 
					 | 
				
			||||||
        b += b'SSND' + struct.pack('>L', 8) + b'\x00' * 8
 | 
					 | 
				
			||||||
        with self.assertWarns(UserWarning) as cm:
 | 
					 | 
				
			||||||
            f = aifc.open(io.BytesIO(b))
 | 
					 | 
				
			||||||
        self.assertEqual(str(cm.warning), 'Warning: bad COMM chunk size')
 | 
					 | 
				
			||||||
        self.assertEqual(f.getcompname(), b'odd')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_params_raises(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        wrong_params = (0, 0, 0, 0, b'WRNG', '')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setparams, wrong_params)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.getparams)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setnchannels, 0)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.getnchannels)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setsampwidth, 0)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.getsampwidth)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setframerate, 0)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.getframerate)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setcomptype, b'WRNG', '')
 | 
					 | 
				
			||||||
        fout.aiff()
 | 
					 | 
				
			||||||
        fout.setnchannels(1)
 | 
					 | 
				
			||||||
        fout.setsampwidth(1)
 | 
					 | 
				
			||||||
        fout.setframerate(1)
 | 
					 | 
				
			||||||
        fout.setnframes(1)
 | 
					 | 
				
			||||||
        fout.writeframes(b'\x00')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setparams, (1, 1, 1, 1, 1, 1))
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setnchannels, 1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setsampwidth, 1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setframerate, 1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setnframes, 1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setcomptype, b'NONE', '')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.aiff)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.aifc)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_params_singles(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        fout.aifc()
 | 
					 | 
				
			||||||
        fout.setnchannels(1)
 | 
					 | 
				
			||||||
        fout.setsampwidth(2)
 | 
					 | 
				
			||||||
        fout.setframerate(3)
 | 
					 | 
				
			||||||
        fout.setnframes(4)
 | 
					 | 
				
			||||||
        fout.setcomptype(b'NONE', b'name')
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getnchannels(), 1)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getsampwidth(), 2)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getframerate(), 3)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getnframes(), 0)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.tell(), 0)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getcomptype(), b'NONE')
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getcompname(), b'name')
 | 
					 | 
				
			||||||
        fout.writeframes(b'\x00' * 4 * fout.getsampwidth() * fout.getnchannels())
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getnframes(), 4)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.tell(), 4)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_params_bunch(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        fout.aifc()
 | 
					 | 
				
			||||||
        p = (1, 2, 3, 4, b'NONE', b'name')
 | 
					 | 
				
			||||||
        fout.setparams(p)
 | 
					 | 
				
			||||||
        self.assertEqual(fout.getparams(), p)
 | 
					 | 
				
			||||||
        fout.initfp(None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_header_raises(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.close)
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        fout.setnchannels(1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.close)
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        fout.setnchannels(1)
 | 
					 | 
				
			||||||
        fout.setsampwidth(1)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.close)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_header_comptype_raises(self):
 | 
					 | 
				
			||||||
        for comptype in (b'ULAW', b'ulaw', b'ALAW', b'alaw', b'G722'):
 | 
					 | 
				
			||||||
            fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
            fout.setsampwidth(1)
 | 
					 | 
				
			||||||
            fout.setcomptype(comptype, b'')
 | 
					 | 
				
			||||||
            self.assertRaises(aifc.Error, fout.close)
 | 
					 | 
				
			||||||
            fout.initfp(None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_markers_raises(self):
 | 
					 | 
				
			||||||
        fout = aifc.open(io.BytesIO(), 'wb')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setmark, 0, 0, b'')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setmark, 1, -1, b'')
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.setmark, 1, 0, None)
 | 
					 | 
				
			||||||
        self.assertRaises(aifc.Error, fout.getmark, 1)
 | 
					 | 
				
			||||||
        fout.initfp(None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_write_aiff_by_extension(self):
 | 
					 | 
				
			||||||
        sampwidth = 2
 | 
					 | 
				
			||||||
        filename = TESTFN + '.aiff'
 | 
					 | 
				
			||||||
        fout = self.fout = aifc.open(filename, 'wb')
 | 
					 | 
				
			||||||
        self.addCleanup(unlink, filename)
 | 
					 | 
				
			||||||
        fout.setparams((1, sampwidth, 1, 1, b'ULAW', b''))
 | 
					 | 
				
			||||||
        frames = b'\x00' * fout.getnchannels() * sampwidth
 | 
					 | 
				
			||||||
        fout.writeframes(frames)
 | 
					 | 
				
			||||||
        fout.close()
 | 
					 | 
				
			||||||
        f = self.f = aifc.open(filename, 'rb')
 | 
					 | 
				
			||||||
        self.assertEqual(f.getcomptype(), b'NONE')
 | 
					 | 
				
			||||||
        f.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    unittest.main()
 | 
					 | 
				
			||||||
| 
						 | 
					@ -21,9 +21,9 @@
 | 
				
			||||||
      getparams()     -- returns a namedtuple consisting of all of the
 | 
					      getparams()     -- returns a namedtuple consisting of all of the
 | 
				
			||||||
                         above in the above order
 | 
					                         above in the above order
 | 
				
			||||||
      getmarkers()    -- returns None (for compatibility with the
 | 
					      getmarkers()    -- returns None (for compatibility with the
 | 
				
			||||||
                         aifc module)
 | 
					                         old aifc module)
 | 
				
			||||||
      getmark(id)     -- raises an error since the mark does not
 | 
					      getmark(id)     -- raises an error since the mark does not
 | 
				
			||||||
                         exist (for compatibility with the aifc module)
 | 
					                         exist (for compatibility with the old aifc module)
 | 
				
			||||||
      readframes(n)   -- returns at most n frames of audio
 | 
					      readframes(n)   -- returns at most n frames of audio
 | 
				
			||||||
      rewind()        -- rewind to the beginning of the audio stream
 | 
					      rewind()        -- rewind to the beginning of the audio stream
 | 
				
			||||||
      setpos(pos)     -- seek to the specified position
 | 
					      setpos(pos)     -- seek to the specified position
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -325,7 +325,7 @@ documentation.
 | 
				
			||||||
.. section: Library
 | 
					.. section: Library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Improved exceptions raised for invalid number of channels and sample width
 | 
					Improved exceptions raised for invalid number of channels and sample width
 | 
				
			||||||
when read an audio file in modules :mod:`aifc`, :mod:`wave` and
 | 
					when read an audio file in modules :mod:`!aifc`, :mod:`wave` and
 | 
				
			||||||
:mod:`!sunau`.
 | 
					:mod:`!sunau`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
..
 | 
					..
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5576,7 +5576,7 @@ documentation.
 | 
				
			||||||
.. section: Library
 | 
					.. section: Library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Improved exceptions raised for invalid number of channels and sample width
 | 
					Improved exceptions raised for invalid number of channels and sample width
 | 
				
			||||||
when read an audio file in modules :mod:`aifc`, :mod:`wave` and
 | 
					when read an audio file in modules :mod:`!aifc`, :mod:`wave` and
 | 
				
			||||||
:mod:`!sunau`.
 | 
					:mod:`!sunau`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
..
 | 
					..
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					:pep:`594`: Remove the :mod:`!aifc` module, deprecated in Python 3.11. Patch
 | 
				
			||||||
 | 
					by Victor Stinner.
 | 
				
			||||||
							
								
								
									
										1
									
								
								Python/stdlib_module_names.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Python/stdlib_module_names.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -89,7 +89,6 @@ static const char* _Py_stdlib_module_names[] = {
 | 
				
			||||||
"_winapi",
 | 
					"_winapi",
 | 
				
			||||||
"_zoneinfo",
 | 
					"_zoneinfo",
 | 
				
			||||||
"abc",
 | 
					"abc",
 | 
				
			||||||
"aifc",
 | 
					 | 
				
			||||||
"antigravity",
 | 
					"antigravity",
 | 
				
			||||||
"argparse",
 | 
					"argparse",
 | 
				
			||||||
"array",
 | 
					"array",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OMIT_MODULE_FILES = {
 | 
					OMIT_MODULE_FILES = {
 | 
				
			||||||
    "_asyncio": ["asyncio/"],
 | 
					    "_asyncio": ["asyncio/"],
 | 
				
			||||||
    "audioop": ["aifc.py", "wave.py"],
 | 
					    "audioop": ["wave.py"],
 | 
				
			||||||
    "_curses": ["curses/"],
 | 
					    "_curses": ["curses/"],
 | 
				
			||||||
    "_ctypes": ["ctypes/"],
 | 
					    "_ctypes": ["ctypes/"],
 | 
				
			||||||
    "_decimal": ["decimal.py"],
 | 
					    "_decimal": ["decimal.py"],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue