audiotools — the Base Python Audio Tools Module

The audiotools module contains a number of useful base classes and functions upon which all of the other modules depend.

audiotools.VERSION

The current Python Audio Tools version as a plain string.

audiotools.AVAILABLE_TYPES

A tuple of AudioFile-compatible classes of available audio types. Note these are types available to audiotools, not necessarily available to the user - depending on whether the required binaries are installed or not.

Class Format
AACAudio AAC in ADTS container
AiffAudio Audio Interchange File Format
ALACAudio Apple Lossless
AuAudio Sun Au
FlacAudio Native Free Lossless Audio Codec
M4AAudio AAC in M4A container
MP3Audio MPEG-1 Layer 3
MP2Audio MPEG-1 Layer 2
OggFlacAudio Ogg Free Lossless Audio Codec
OpusAudio Opus Audio Codec
ShortenAudio Shorten
SpeexAudio Ogg Speex
VorbisAudio Ogg Vorbis
WaveAudio Waveform Audio File Format
WavPackAudio WavPack
audiotools.DEFAULT_TYPE

The default type to use as a plain string, such as 'wav' or 'flac'.

audiotools.DEFAULT_QUALITY

A dict of type name strings -> quality value strings indicating the default compression quality value for the given type name suitable for AudioFile.from_pcm() and AudioFile.convert() method calls.

audiotools.DEFAULT_CDROM

The default CD-ROM device to use for CD audio and DVD-Audio extraction as a plain string.

audiotools.TYPE_MAP

A dictionary of type name strings -> AudioFile values containing only types which have all required binaries installed.

audiotools.FILENAME_FORMAT

The default format string to use for newly created files.

audiotools.BIN

A dictionary-like class for performing lookups of system binaries. This checks the system and user’s config files and ensures that any redirected binaries are called from their proper location. For example, if the user has configured flac(1) to be run from /opt/flac/bin/flac

>>> BIN["flac"]
"/opt/flac/bin/flac"

This class also has a can_execute() method which returns True if the given binary is executable.

>>> BIN.can_execute(BIN["flac"])
True
audiotools.IO_ENCODING

The defined encoding to use for output to the screen as a plain string. This is typically 'utf-8'.

audiotools.FS_ENCODING

The defined encoding to use for filenames read and written to disk as a plain string. This is typically 'utf-8'.

audiotools.MAX_JOBS

The maximum number of simultaneous jobs to run at once by default as an integer. This may be defined from the user’s config file. Otherwise, if Python’s multiprocessing module is available, this is set to the user’s CPU count. If neither is available, this is set to 1.

audiotools.file_type(file)

Given a seekable file object returns an AudioFile-compatible class of the stream’s detected type, or None if the stream’s type is unknown.

The AudioFile class may not be available for use and so its AudioFile.available() classmethod may need to be checked separately.

audiotools.open(filename)

Opens the given filename string and returns an AudioFile-compatible object. Raises UnsupportedFile if the file cannot identified or is not supported. Raises IOError if the file cannot be opened at all.

audiotools.open_files(filenames[, sorted][, messenger][, no_duplicates][, warn_duplicates][, opened_files])

Given a list of filename strings, returns a list of AudioFile-compatible objects which are successfully opened. By default, they are returned sorted by album number and track number.

If sorted is False, they are returned in the same order as they appear in the filenames list.

If messenger is given, use that Messenger object to for warnings if files cannot be opened. Otherwise, such warnings are sent to stdout.

If no_duplicates is True, attempting to open the same file twice raises a DuplicateFile exception.

If no_duplicates is False and warn_duplicates is True, attempting to open the same file twice results in a warning to messenger, if present.

opened_files, if present, is a set of previously opened Filename objects for the purpose of detecting duplicates. Any opened files are added to that set.

audiotools.open_directory(directory[, sorted[, messenger]])

Given a root directory, returns an iterator of all the AudioFile-compatible objects found via a recursive search of that directory. sorted, and messenger work as in open_files().

audiotools.sorted_tracks(audiofiles)

Given a list of AudioFile objects, returns a new list of those objects sorted by album number and track number, if present. If album number and track number aren’t present, objects are sorted by base filename.

audiotools.group_tracks(audiofiles)

Given an iterable collection of AudioFile-compatible objects, returns an iterator of objects grouped into lists by album. That is, all objects with the same album_name and album_number metadata fields will be returned in the same list on each pass.

audiotools.filename_to_type(path)

Given a path, try to guess its AudioFile class based on its filename suffix. Raises UnknownAudioType if the suffix is unrecognized. Raises AmbiguousAudioType if more than one type of audio shares the same suffix.

audiotools.transfer_data(from_function, to_function)

This function takes two functions, presumably analogous to write() and read() functions, respectively. It calls to_function on the object returned by calling from_function with an integer argument (presumably a string) until that object’s length is 0.

>>> infile = open("input.txt", "r")
>>> outfile = open("output.txt", "w")
>>> transfer_data(infile.read, outfile.write)
>>> infile.close()
>>> outfile.close()
audiotools.transfer_framelist_data(pcmreader, to_function[, signed[, big_endian]])

A natural progression of transfer_data(), this function takes a PCMReader object and transfers the pcm.FrameList objects returned by its PCMReader.read() method to to_function after converting them to plain strings.

The pcmreader is closed once decoding is complete.

May raise IOError or ValueError if a problem occurs during decoding.

>>> pcm_data = audiotools.open("file.wav").to_pcm()
>>> outfile = open("output.pcm","wb")
>>> transfer_framelist_data(pcm_data,outfile)
>>> pcm_data.close()
>>> outfile.close()
audiotools.pcm_cmp(pcmreader1, pcmreader2)

This function takes two PCMReader objects and compares their PCM output. Returns True if that output matches exactly, False if not.

Both streams are closed once comparison is completed.

May raise IOError or ValueError if problems occur during reading.

audiotools.pcm_frame_cmp(pcmreader1, pcmreader2)

This function takes two PCMReader objects and compares their PCM frame output. It returns the frame number of the first mismatch as an integer which begins at frame number 0. If the two streams match completely, it returns None.

Both streams are closed once comparison is completed.

May raise IOError or ValueError if problems occur during reading.

audiotools.pcm_split(pcmreader, pcm_lengths)

Takes a PCMReader object and list of PCM sample length integers. Returns an iterator of new PCMReader objects, each limited to the given lengths. The original pcmreader is closed upon the iterator’s completion.

audiotools.calculate_replay_gain(audiofiles)

Takes a list of AudioFile-compatible objects. Returns an iterator of (audiofile, track_gain, track_peak, album_gain, album_peak) tuples or raises ValueError if a problem occurs during calculation.

audiotools.read_sheet(filename)

Given a .cue or .toc filename, returns a Sheet of that file’s cuesheet data. May raise SheetException if the file cannot be read or parsed correctly.

audiotools.to_pcm_progress(audiofile, progress)

Given an AudioFile-compatible object and progress function, returns a PCMReaderProgress object of that object’s PCM stream.

If progress is None, the audiofile’s PCM stream is returned as-is.

Filename Objects

class audiotools.Filename(filename)

Filename is a file which may or may not exist on disk. filename is a raw string of the actual filename. Filename objects are immutable and hashable, which means they can be used as dictionary keys or placed in sets.

The purpose of Filename objects is for easier conversion of raw string filename paths to Unicode, and to make it easier to detect filenames which point to the same file on disk.

The former case is used by utilities to display output about file operations in progress. The latter case is for utilities which need to avoid overwriting input files with output files.

Filename.__str__()

Returns the raw string of the actual filename after being normalized.

Filename.__unicode__()

Returns a Unicode string of the filename after being decoded through FS_ENCODING.

Filename.__eq__(filename)

Filename objects which exist on disk hash and compare equally if their device ID and inode number values match (the st_dev and st_ino fields according to stat(2)). Filename objects which don’t exist on disk hash and compare equally if their filename string matches.

Filename.open(mode)

Returns a file object of this filename opened with the given mode.

Filename.disk_file()

Returns True if the file currently exists on disk.

Filename.dirname()

Returns the directory name of this filename as a new Filename object.

Filename.basename()

Returns the base name (no directory) of this filename as a new Filename object.

Filename.expanduser()

Returns a new Filename object with the user directory expanded, if any.

AudioFile Objects

class audiotools.AudioFile

The AudioFile class represents an audio file on disk, such as a FLAC file, MP3 file, WAVE file and so forth. It is not meant to be instantiated directly. Instead, functions such as open() will return AudioFile-compatible objects with the following attributes and methods.

AudioFile.NAME

The name of the format as a string. This is how the format is referenced by utilities via the -t option, and must be unique among all formats.

AudioFile.SUFFIX

The default file suffix as a string. This is used by the %(suffix)s format field in the track_name() classmethod, and by the filename_to_type() function for inferring the file format from its name. However, it need not be unique among all formats.

AudioFile.DESCRIPTION

A longer, descriptive name for the audio type as a Unicode string. This is meant to be human-readable.

AudioFile.COMPRESSION_MODES

A tuple of valid compression level strings, for use with the from_pcm() and convert() methods. If the format has no compression levels, this tuple will be empty.

AudioFile.DEFAULT_COMPRESSION

A string of the default compression level to use with from_pcm() and convert(), if none is given. This is not the default compression indicated in the user’s configuration file; it is a hard-coded value of last resort.

AudioFile.COMPRESSION_DESCRIPTIONS

A dict of compression descriptions, as Unicode strings. The key is a valid compression mode string. Not all compression modes need have a description; some may be left blank.

AudioFile.BINARIES

A tuple of binary strings required by the format. For example, the Vorbis format may require "oggenc" and "oggdec" in order to be available for the user.

AudioFile.REPLAYGAIN_BINARIES

A tuple of binary strings required for ReplayGain application. For example, the Vorbis format may require "vorbisgain" in order to use the add_replay_gain() classmethod. This tuple may be empty if the format requires no binaries or has no ReplayGain support.

AudioFile.bits_per_sample()

Returns the number of bits-per-sample in this audio file as a positive integer.

AudioFile.channels()

Returns the number of channels in this audio file as a positive integer.

AudioFile.channel_mask()

Returns a ChannelMask object representing the channel assignment of this audio file. If the channel assignment is unknown or undefined, that ChannelMask object may have an undefined value.

AudioFile.sample_rate()

Returns the sample rate of this audio file, in Hz, as a positive integer.

AudioFile.total_frames()

Returns the total number of PCM frames in this audio file, as a non-negative integer.

AudioFile.cd_frames()

Returns the total number of CD frames in this audio file, as a non-negative integer. Each CD frame is 1/75th of a second.

AudioFile.seconds_length()

Returns the length of this audio file as a fractions.Fraction number of seconds.

AudioFile.lossless()

Returns True if the data in the audio file has been stored losslessly. Returns False if not.

classmethod AudioFile.supports_metadata()

Returns True is this audio type supports metadata. If not, AudioFile.get_metadata() will always return None and the metadata updating routines will do nothing.

AudioFile.set_metadata(metadata)

Takes a MetaData object and sets this audio file’s metadata to that value, if possible. Setting metadata to None is the same as calling AudioFile.delete_metadata(). Raises IOError if a problem occurs when writing the file.

AudioFile.update_metadata(metadata)

Takes the MetaData-compatible object returned by this audio file’s AudioFile.get_metadata() method and sets this audiofile’s metadata to that value, if possible. Raises IOError if a problem occurs when writing the file.

Note

What’s the difference between AudioFile.set_metadata() and AudioFile.update_metadata()?

Metadata implementations may also contain side information such as track length, file encoder, and so forth. AudioFile.set_metadata() presumes the MetaData object is from a different AudioFile object or has been built from scratch. Therefore, it will update the newly added metadata side info as needed so as to not break the file.

AudioFile.update_metadata() presumes the MetaData object is either taken from the original AudioFile object or has been carefully constructed to not break anything when applied to the file. It is a lower-level routine which does not update metadata side info (which may be necessary when modifying that side info is required).

AudioFile.get_metadata()

Returns a MetaData-compatible object representing this audio file’s metadata, or None if this file contains no metadata. Raises IOError if a problem occurs when reading the file.

AudioFile.delete_metadata()

Deletes the audio file’s metadata, removing or unsetting tags as necessary. Raises IOError if a problem occurs when writing the file.

AudioFile.to_pcm()

Returns this audio file’s PCM data as a PCMReader-compatible object. May return a PCMReaderError if an error occurs initializing the decoder.

classmethod AudioFile.supports_to_pcm()

Returns True if the necessary libraries or binaries are installed to support decoding this format.

classmethod AudioFile.from_pcm(filename, pcmreader[, compression][, total_pcm_frames])

Takes a filename string, PCMReader-compatible object, optional compression level string and optional total_pcm_frames integer. Creates a new audio file as the same format as this audio class and returns a new AudioFile-compatible object. The PCMReader.close() method is called once encoding is complete.

Raises EncodingError if a problem occurs during encoding.

Specifying the total number of PCM frames to be encoded, when the number is known in advance, may allow the encoder to work more efficiently but is never required.

In this example, we’ll transcode track.flac to track.mp3 at the default compression level:

>>> audiotools.MP3Audio.from_pcm("track.mp3",
...                              audiotools.open("track.flac").to_pcm())
classmethod AudioFile.supports_from_pcm()

Returns True if the necessary libraries or binaries are installed to support encoding this format.

AudioFile.convert(filename, target_class[, compression[, progress]])

Takes a filename string, AudioFile subclass and optional compression level string. Creates a new audio file and returns an object of the same class. Raises EncodingError if a problem occurs during encoding.

In this example, we’ll transcode track.flac to track.mp3 at the default compression level:

>>> audiotools.open("track.flac").convert("track.mp3",
...                                       audiotools.MP3Audio)

Why have both a convert method as well as to_pcm/from_pcm methods? Although the former is often implemented using the latter, the pcm methods alone contain only raw audio data. By comparison, the convert method has information about what is the file is being converted to and can transfer other side data if necessary.

For example, if .wav file with non-audio RIFF chunks is converted to WavPack, this method will preserve those chunks:

>>> audiotools.open("chunks.wav").convert("chunks.wv",
...                                       audiotools.WavPackAudio)

whereas the to_pcm/from_pcm method alone will not.

The optional progress argument is a function which takes a single Fraction argument which is the current progress between 0 and 1, inclusive. If supplied, this function is called at regular intervals during the conversion process and may be used to indicate the current status to the user.

AudioFile.seekable()

Returns True if the file is seekable. That is, if its PCMReader has a .seek() method and that method supports some fine-grained seeking when the PCMReader is working from on-disk files.

AudioFile.verify([progress])

Verifies the track for correctness. Returns True if verification is successful. Raises an InvalidFile subclass if some problem is detected. If the file has built-in checksums or other error detection capabilities, this method checks those values to ensure it has not been damaged in some way.

The optional progress argument functions identically to the one provided to convert().

classmethod AudioFile.track_name(file_path[, track_metadata[, format[, suffix]]])

Given a file path string, optional MetaData-compatible object, optional Python format string, and optional suffix string, returns a filename string with the format string fields filled-in. Raises UnsupportedTracknameField if the format string contains unsupported fields.

Currently supported fields are:

Field Value
%(album_name)s track_metadata.album_name
%(album_number)s track_metadata.album_number
%(album_total)s track_metadata.album_total
%(album_track_number)s album_number combined with track_number
%(artist_name)s track_metadata.artist_name
%(catalog)s track_metadata.catalog
%(comment)s track_metadata.comment
%(composer_name)s track_metadata.composer_name
%(conductor_name)s track_metadata.conductor_name
%(copyright)s track_metadata.copyright
%(date)s track_metadata.date
%(ISRC)s track_metadata.ISRC
%(media)s track_metadata.year
%(performer_name)s track_metadata.performer_name
%(publisher)s track_metadata.publisher
%(suffix)s the AudioFile suffix
%(track_name)s track_metadata.track_name
%(track_number)2.2d track_metadata.track_number
%(track_total)s track_metadata.track_total
%(year)s track_metadata.year
%(basename)s file_path basename without suffix
classmethod AudioFile.supports_replay_gain()

Returns True if this class supports ReplayGain metadata.

AudioFile.get_replay_gain()

Returns this audio file’s ReplayGain values as a ReplayGain object, or None if this audio file has no values.

AudioFile.set_replay_gain(replaygain)

Given a ReplayGain object, sets the audio file’s gain values.

Raises IOError if unable to modify the file.

AudioFile.delete_replay_gain()

Removes any gain values from the file.

Raises IOError if unable to modify the file.

classmethod AudioFile.supports_cuesheet()

Returns True if the audio format supports embedded Sheet objects.

AudioFile.set_cuesheet(cuesheet)

Given a Sheet object, embeds a cuesheet in the track. This is for tracks which represent a whole CD image and wish to store track break data internally. May raise IOError if an error occurs writing the file.

AudioFile.get_cuesheet()

Returns a Sheet object of a track’s embedded cuesheet, or None if the track contains no cuesheet. May raise IOError if an error occurs reading the file.

AudioFile.delete_cuesheet()

Deletes embedded Sheet object, if any. May raise IOError if an error occurs updating the file.

AudioFile.clean([output_filename])

Cleans the audio file of known data and metadata problems.

output_filename is an optional string in which the fixed audio file is placed. If omitted, no actual fixes are performed. Note that this method never modifies the original file.

Returns list of fixes performed as Unicode strings.

Raises IOError if some error occurs when writing the new file. Raises ValueError if the file itself is invalid.

WaveContainer Objects

This is an abstract AudioFile subclass suitable for extending by formats that store RIFF WAVE chunks internally, such as Wave, FLAC, WavPack and Shorten. It overrides the AudioFile.convert() method such that any stored chunks are transferred properly from one file to the next. This is accomplished by implementing three additional methods.

class audiotools.WaveContainer
WaveContainer.has_foreign_wave_chunks()

Returns True if our object has non-audio RIFF WAVE chunks.

Returns (header, footer) tuple of strings where header is everything before the PCM data and footer is everything after the PCM data.

May raise ValueError if there’s a problem with the header or footer data, such as invalid chunk IDs. May raise IOError if there’s a problem reading the header or footer data from the file.

classmethod WaveContainer.from_wave(filename, header, pcmreader, footer[, compression])

Encodes a new file from wave data. header and footer are binary strings as returned by a WaveContainer.wave_header_footer() method, pcmreader is a PCMReader object and compression is a binary string.

Returns a new AudioFile-compatible object or raises EncodingError if some error occurs when encoding the file.

AiffContainer Objects

Much like WaveContainer, this is an abstract AudioFile subclass suitable for extending by formats that store AIFF chunks internally, such as AIFF, FLAC and Shorten. It overrides the AudioFile.convert() method such that any stored chunks are transferred properly from one file to the next. This is accomplished by implementing three additional methods.

class audiotools.AiffContainer
AiffContainer.has_foreign_aiff_chunks()

Returns True if our object has non-audio AIFF chunks.

Returns (header, footer) tuple of strings where header is everything before the PCM data and footer is everything after the PCM data.

May raise ValueError if there’s a problem with the header or footer data, such as invalid chunk IDs. May raise IOError if there’s a problem reading the header or footer data from the file.

classmethod AiffContainer.from_aiff(filename, header, pcmreader, footer[, compression])

Encodes a new file from wave data. header and footer are binary strings as returned by a AiffContainer.aiff_header_footer() method, pcmreader is a PCMReader object and compression is a binary string.

Returns a new AudioFile-compatible object or raises EncodingError if some error occurs when encoding the file.

MetaData Objects

class audiotools.MetaData([track_name][, track_number][, track_total][, album_name][, artist_name][, performer_name][, composer_name][, conductor_name][, media][, ISRC][, catalog][, copyright][, publisher][, year][, data][, album_number][, album_total][, comment][, compilation][, images])

The MetaData class represents an AudioFile‘s non-technical metadata. It can be instantiated directly for use by the set_metadata() method. However, the get_metadata() method will typically return MetaData-compatible objects corresponding to the audio file’s low-level metadata implementation rather than actual MetaData objects. Modifying fields within a MetaData-compatible object will modify its underlying representation and those changes will take effect should set_metadata() be called with that updated object.

The images argument, if given, should be an iterable collection of Image-compatible objects.

MetaData attributes may be None, which indicates the low-level implementation has no corresponding entry. For instance, ID3v2.3 tags use the "TALB" frame to indicate the track’s album name. If that frame is present, an audiotools.ID3v23Comment MetaData object will have an album_name field containing a Unicode string of its value. If that frame is not present in the ID3v2.3 tag, its album_name field will be None.

For example, to access a track’s album name field:

>>> metadata = track.get_metadata()
>>> metadata.album_name
u"Album Name"

To change a track’s album name field:

>>> metadata = track.get_metadata()
>>> metadata.album_name = u"Updated Album Name"
>>> track.update_metadata(metadata)  # because metadata comes from track's get_metadata() method, one can use update_metadata()

To delete a track’s album name field:

>>> metadata = track.get_metadata()
>>> del(metadata.album_name)
>>> track.update_metadata(metadata)

Or to replace a track’s entire set of metadata:

>>> metadata = MetaData(track_name=u"Track Name",
...                     album_name=u"Updated Album Name",
...                     track_number=1,
...                     track_total=3)
>>> track.set_metadata(metadata)  # because metadata is built from scratch, one must use set_metadata()
MetaData.track_name

This individual track’s name as a Unicode string.

MetaData.track_number

This track’s number within the album as an integer.

MetaData.track_total

The total number of tracks on the album as an integer.

MetaData.album_name

The name of this track’s album as a Unicode string.

MetaData.artist_name

The name of this track’s original creator/composer as a Unicode string.

MetaData.performer_name

The name of this track’s performing artist as a Unicode string.

MetaData.composer_name

The name of this track’s composer as a Unicode string.

MetaData.conductor_name

The name of this track’s conductor as a Unicode string.

MetaData.media

The album’s media type, such as u”CD”, u”tape”, u”LP”, etc. as a Unicode string.

MetaData.ISRC

This track’s ISRC value as a Unicode string.

MetaData.catalog

This track’s album catalog number as a Unicode string.

MetaData.year

This track’s album release year as a Unicode string.

MetaData.date

This track’s album recording date as a Unicode string.

MetaData.album_number

This track’s album number if it is one of a series of albums, as an integer.

MetaData.album_total

The total number of albums within the set, as an integer.

MetaData.comment

This track’s comment as a Unicode string.

MetaData.compilation

Whether this track is part of a compilation, as a boolean.

MetaData.fields()

Yields an (attr, value) tuple per MetaData field.

MetaData.filled_fields()

Yields an (attr, value) tuple per non-blank MetaData field. Non-blank fields are those with a value other than None.

MetaData.empty_fields()

Yields an (attr, value) tuple per blank MetaData field. Blank fields are those with a value of None.

classmethod MetaData.converted(metadata)

Takes a MetaData-compatible object (or None) and returns a new MetaData object of the same class, or None. For instance, VorbisComment.converted() returns VorbisComment objects. The purpose of this classmethod is to offload metadata conversion to the metadata classes themselves. Therefore, by using the VorbisComment.converted() classmethod, the VorbisAudio class only needs to know how to handle VorbisComment metadata.

Why not simply handle all metadata using this high-level representation and avoid conversion altogether? The reason is that MetaData is often only a subset of what the low-level implementation can support. For example, a VorbisComment may contain the 'FOO' tag which has no analogue in MetaData‘s list of fields. But when passed through the VorbisComment.converted() classmethod, that 'FOO' tag will be preserved as one would expect.

The key is that performing:

>>> track.set_metadata(track.get_metadata())

should always round-trip properly and not lose any metadata values.

classmethod MetaData.supports_images()

Returns True if this MetaData implementation supports images. Returns False if not.

MetaData.images()

Returns a list of Image-compatible objects this metadata contains.

MetaData.front_covers()

Returns a subset of images() which are marked as front covers.

MetaData.back_covers()

Returns a subset of images() which are marked as back covers.

MetaData.leaflet_pages()

Returns a subset of images() which are marked as leaflet pages.

MetaData.media_images()

Returns a subset of images() which are marked as media.

MetaData.other_images()

Returns a subset of images() which are marked as other.

MetaData.add_image(image)

Takes a Image-compatible object and adds it to this metadata’s list of images.

MetaData.delete_image(image)

Takes an Image from this class, as returned by images(), and removes it from this metadata’s list of images.

MetaData.clean()

Returns a (MetaData, fixes_performed) tuple where MetaData is an object that’s been cleaned of problems and fixes_performed is a list of unicode strings detailing those problems. Problems include:

  • Leading whitespace in text fields
  • Trailing whitespace in text fields
  • Empty fields
  • Leading zeroes in numerical fields
  • Incorrectly labeled image metadata fields
MetaData.raw_info()

Returns a Unicode string of raw metadata information with as little filtering as possible. This is meant to be useful for debugging purposes.

MetaData.intersection(metadata)

Given a MetaData object, this returns a new MetaData object containing only the fields which match those in this object. It is analagous to a set intersection in that only common fields are preserved.

If both objects are of the same class, an object of the same class will be returned.

If metadata is None, returns None.

Image Objects

class audiotools.Image(data, mime_type, width, height, color_depth, color_count, description, type)

This class is a container for image data.

Image.data

A plain string of raw image bytes.

Image.mime_type

A Unicode string of this image’s MIME type, such as u’image/jpeg’

Image.width

This image’s width in pixels as an integer.

Image.height

This image’s height in pixels as an integer

Image.color_depth

This image’s color depth in bits as an integer. 24 for JPEG, 8 for GIF, etc.

Image.color_count

For palette-based images, this is the number of colors the image contains as an integer. For non-palette images, this value is 0.

Image.description

A Unicode string of this image’s description.

Image.type

An integer representing this image’s type.

Value Type
0 front cover
1 back cover
2 leaflet page
3 media
4 other
Image.suffix()

Returns this image’s typical filename suffix as a plain string. For example, JPEGs return "jpg"

Image.type_string()

Returns this image’s type as a plain string. For example, an image of type 0 returns "Front Cover"

classmethod Image.new(image_data, description, type)

Given a string of raw image bytes, a Unicode description string and image type integer, returns an Image-compatible object. Raises InvalidImage If unable to determine the image type from the data string.

ReplayGain Objects

class audiotools.ReplayGain(track_gain, track_peak, album_gain, album_peak)

This is a simple container for ReplayGain values.

ReplayGain.track_gain

A float of a track’s ReplayGain value.

ReplayGain.track_peak

A float of a track’s peak value, from 0.0 to 1.0

ReplayGain.album_gain

A float of an album’s ReplayGain value.

ReplayGain.album_peak

A float of an album’s peak value, from 0.0 to 1.0

PCMReader Objects

class audiotools.PCMReader(sample_rate, channels, channel_mask, bits_per_sample)

This is an abstract base class for streams of audio data which are file-like objects with additional stream parameters. Subclasses are expected to implement read and close.

PCMReader.sample_rate

The sample rate of this audio stream, in Hz, as a positive integer.

PCMReader.channels

The number of channels in this audio stream as a positive integer.

PCMReader.channel_mask

The channel mask of this audio stream as a non-negative integer.

PCMReader.bits_per_sample

The number of bits-per-sample in this audio stream as a positive integer.

PCMReader.read(pcm_frames)

Try to read a pcm.FrameList object with the given number of PCM frames, if possible. This method is not guaranteed to read that amount of frames. It may return less, particularly at the end of an audio stream. It may even return FrameLists larger than requested. However, it must always return a non-empty FrameList until the end of the PCM stream is reached.

Once the end of the stream is reached, subsequent calls will return empty FrameLists.

May raise IOError if there is a problem reading the source file, or ValueError if the source file has some sort of error.

PCMReader.close()

Closes the audio stream. If any subprocesses were used for audio decoding, they will also be closed and waited for their process to finish.

Subsequent calls to PCMReader.read() will raise ValueError exceptions once the stream is closed.

PCMReader.__enter__()

Returns the PCMReader. This is used for implementing context management.

PCMReader.__exit__(exc_type, exc_value, traceback)

Calls PCMReader.close(). This is used for implementing context management.

PCMFileReader Objects

class audiotools.PCMFileReader(file, sample_rate, channels, channel_mask, bits_per_sample[, process[, signed[, big_endian]]])

This class wraps around file-like objects and generates pcm.FrameList objects on each call to read(). sample_rate, channels, channel_mask and bits_per_sample should be integers. process is a subprocess helper object which generates PCM data. signed is True if the generated PCM data is signed. big_endian is True if the generated PCM data is big-endian.

PCMReaderError Objects

class audiotools.PCMReaderError(error_message, sample_rate, channels, channel_mask, bits_per_sample)

This is a subclass of PCMReader which always returns empty always raises a ValueError when its read method is called. The purpose of this is to postpone error generation so that all encoding errors, even those caused by unsuccessful decoding, are restricted to the from_pcm() classmethod which can then propagate an EncodingError error message to the user.

PCMConverter Objects

class audiotools.PCMConverter(pcmreader, sample_rate, channels, channel_mask, bits_per_sample)

This class takes an existing PCMReader-compatible object along with a new set of sample_rate, channels, channel_mask and bits_per_sample values. Data from pcmreader is then automatically converted to the same format as those values.

PCMConverter.sample_rate

If the new sample rate differs from pcmreader‘s sample rate, audio data is automatically resampled on each call to read().

PCMConverter.channels

If the new number of channels is smaller than pcmreader‘s channel count, existing channels are removed or downmixed as necessary. If the new number of channels is larger, data from the first channel is duplicated as necessary to fill the rest.

PCMConverter.channel_mask

If the new channel mask differs from pcmreader‘s channel mask, channels are removed as necessary such that the proper channel only outputs to the proper speaker.

PCMConverter.bits_per_sample

If the new bits-per-sample differs from pcmreader‘s number of bits-per-sample, samples are shrunk or enlarged as necessary to cover the full amount of bits.

PCMConverter.read()

This method functions the same as the PCMReader.read() method.

PCMConverter.close()

This method functions the same as the PCMReader.close() method.

BufferedPCMReader Objects

class audiotools.BufferedPCMReader(pcmreader)

This class wraps around an existing PCMReader object. Its calls to read() are guaranteed to return pcm.FrameList objects as close to the requested amount of PCM frames as possible without going over by buffering data internally.

The reason such behavior is not required is that we often don’t care about the size of the individual FrameLists being passed from one routine to another. But on occasions when we need pcm.FrameList objects to be of a particular size, this class can accomplish that.

CounterPCMReader Objects

class audiotools.CounterPCMReader(pcmreader)

This class wraps around an existing PCMReader object and keeps track of the number of bytes and frames written upon each call to read.

CounterPCMReader.frames_written

The number of PCM frames written thus far.

CounterPCMReader.bytes_written()

The number of bytes written thus far.

ReorderedPCMReader Objects

class audiotools.ReorderedPCMReader(pcmreader, channel_order)

This class wraps around an existing PCMReader object. It takes a list of channel number integers (which should be the same as pcmreader‘s channel count) and reorders channels upon each call to read().

For example, to swap channels 0 and 1 in a stereo stream, one could do the following:

>>> reordered = ReorderedPCMReader(original, [1, 0])

Calls to reordered.read() will then have the left channel on the right side and vice versa.

PCMCat Objects

class audiotools.PCMCat(pcmreaders)

This class wraps around a list of PCMReader objects and concatenates their output into a single output stream.

If any of the readers has different attributes from the first reader in the stream, ValueError is raised at init-time.

PCMReaderWindow Objects

class audiotools.PCMReaderWindow(pcmreader, initial_offset, total_pcm_frames[, forward_close=True])

This class wraps around an existing PCMReader object and truncates or extends its samples as needed. initial_offset, if positive, indicates how many PCM frames to truncate from the beginning of the stream. If negative, the beginning of the stream is padded by that many PCM frames - all of which have a value of 0. total_pcm_frames indicates the total length of the stream as a non-negative number of PCM frames. If shorter than the actual length of the PCM reader’s stream, the reader is truncated. If longer, the stream is extended by as many PCM frames as needed. Again, padding frames have a value of 0.

If forward_close is True, calls to PCMReaderWindow.close() are passed along to the wrapped PCMReader object. Otherwise, the close is confined to the PCMReaderWindow object. This may be necessary when encoding sub-streams from a larger stream in which closing the larger stream after each encode isn’t desirable.

LimitedPCMReader Objects

class audiotools.LimitedPCMReader(buffered_pcmreader, total_pcm_frames)

This class wraps around an existing BufferedPCMReader and ensures that no more than total_pcm_frames will be read from that stream by limiting reads to it.

Note

PCMReaderWindow is designed primarily for handling sample offset values in a CDTrackReader, or for skipping a potentially large number of samples in a stream. LimitedPCMReader is designed for splitting a stream into several smaller streams without losing any PCM frames.

Which to use for a given situation depends on whether one cares about consuming the samples outside of the sub-reader or not.

PCMReaderProgress Objects

class audiotools.PCMReaderProgress(pcmreader, total_frames, progress)

This class wraps around an existing PCMReader object and generates periodic updates to a given progress function. total_frames indicates the total number of PCM frames in the PCM stream.

>>> progress_display = SingleProgressDisplay(Messenger("audiotools"), u"encoding file")
>>> pcmreader = source_audiofile.to_pcm()
>>> source_frames = source_audiofile.total_frames()
>>> target_audiofile = AudioType.from_pcm("target_filename",
...                                       PCMReaderProgress(pcmreader,
...                                                         source_frames,
...                                                         progress_display.update))

ReplayGainCalculator Objects

class audiotools.ReplayGainCalculator(sample_rate)

This class is for incrementally calculating ReplayGain for an album during decoding. All tracks calculated must have the same sample rate which may mean resampling them to that rate if necessary.

ReplayGainCalculator.to_pcm(pcmreader)

Given a PCMReader object, returns a ReplayGainCalculatorReader linked to this calculator.

ReplayGainCalculator.__iter__()

Yields (title_gain, title_peak, album_gain, album_peak) tuples for each PCMReader processed with ReplayGainCalculator.to_pcm() in the order in which they were processed.

ReplayGainCalculatorReader Objects

class audiotools.ReplayGainCalculatorReader(replaygain, pcmreader)

These objects are typically returned from ReplayGainCalculator.to_pcm() rather than instantiated directly. They function as PCMReader objects which process the pcm.FrameList objects returned by read prior to returning them.

ReplayGainCalculatorReader.title_gain()

Returns the title gain of the whole track as a floating point value.

ReplayGainCalculatorReader.title_peak()

Returns the title peak of the whole track as a floating point value.

ChannelMask Objects

class audiotools.ChannelMask(mask)

This is an integer-like class that abstracts channel assignments into a set of bit fields.

Mask Speaker
0x1 front_left
0x2 front_right
0x4 front_center
0x8 low_frequency
0x10 back_left
0x20 back_right
0x40 front_left_of_center
0x80 front_right_of_center
0x100 back_center
0x200 side_left
0x400 side_right
0x800 top_center
0x1000 top_front_left
0x2000 top_front_center
0x4000 top_front_right
0x8000 top_back_left
0x10000 top_back_center
0x20000 top_back_right

All channels in a pcm.FrameList will be in RIFF WAVE order as a sensible convention. But which channel corresponds to which speaker is decided by this mask. For example, a 4 channel PCMReader with the channel mask 0x33 corresponds to the bits 00110011

Reading those bits from right to left (least significant first) the front_left, front_right, back_left, back_right speakers are set. Therefore, the PCMReader’s 4 channel FrameLists are laid out as follows:

  1. front_left
  2. front_right
  3. back_left
  4. back_right

Since the front_center and low_frequency bits are not set, those channels are skipped in the returned FrameLists.

Many formats store their channels internally in a different order. Their PCMReader objects will be expected to reorder channels and set a ChannelMask matching this convention. And, their from_pcm() classmethods will be expected to reverse the process.

A ChannelMask of 0 is “undefined”, which means that channels aren’t assigned to any speaker. This is an ugly last resort for handling formats where multi-channel assignments aren’t properly defined. In this case, a from_pcm() classmethod is free to assign the undefined channels any way it likes, and is under no obligation to keep them undefined when passing back out to to_pcm()

ChannelMask.defined()

Returns True if this mask is defined.

ChannelMask.undefined()

Returns True if this mask is undefined.

ChannelMask.channels()

Returns the speakers this mask contains as a list of strings in the order they appear in the PCM stream.

ChannelMask.index(channel_name)

Given a channel name string, returns the index of that channel within the PCM stream. For example:

>>> mask = ChannelMask(0xB)     #fL, fR, LFE, but no fC
>>> mask.index("low_frequency")
2
classmethod ChannelMask.from_fields(**fields)

Takes channel names as function arguments and returns a ChannelMask object.

>>> mask = ChannelMask.from_fields(front_right=True,
...                                front_left=True,
...                                front_center=True)
>>> int(mask)
7
classmethod ChannelMask.from_channels(channel_count)

Takes a channel count integer and returns a ChannelMask object.

Warning

from_channels() only works for 1 and 2 channel counts and is meant purely as a convenience method for mono or stereo streams. All other values will trigger a ValueError

CD Lookups

audiotools.metadata_lookup(musicbrainz_disc_id, freedb_disc_id[, musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Given a audiotools.musicbrainz.DiscID and audiotools.freedb.DiscID, returns a metadata[c][t] list of lists where c is a possible choice and t is the MetaData for a given track (starting from 0).

This will always return a list of MetaData objects for at least one choice. In the event that no matches for the CD can be found, those objects will only contain track_number and track_total fields.

audiotools.cddareader_metadata_lookup(cddareader[, musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Given a cdio.CDDAReader object, returns metadata[c][t] list of lists where c is a possible choice and t is the MetaData for a given track (starting from 0).

This will always return a list of MetaData objects for at least one choice. In the event that no matches for the CD can be found, those objects will only contain track_number and track_total fields.

audiotools.track_metadata_lookup(audiofiles, [, musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Given a sorted list of AudioFile objects, returns metadata[c][t] list of lists where c is a possible choice and t is the MetaData for a given track (starting from 0).

This will always return a list of MetaData objects for at least one choice. In the event that no matches for the CD can be found, those objects will only contain track_number and track_total fields.

audiotools.sheet_metadata_lookup(sheet, total_pcm_frames, sample_rate, [, musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Given a Sheet object, total number of PCM frames and the disc’s sample rate, returns metadata[c][t] list of lists where c is a possible choice and t is the MetaData for a given track (starting from 0).

This will always return a list of MetaData objects for at least one choice. In the event that no matches for the CD can be found, those objects will only contain track_number and track_total fields.

audiotools.accuraterip_lookup(sorted_tracks[, server][, port])

Given a list of AudioFile objects sorted by track number, returns a {track_number:[(confidence, checksum, alt), ...], ...} dict of values retrieved from the AccurateRip database where track_number is an int starting from 1, confidence is the number of people with the same people with a matching checksum of the track.

May return a dict of empty lists if no AccurateRip entry is found.

May return urllib2.HTTPError if an error occurs querying the server.

audiotools.accuraterip_sheet_lookup(sheet, total_pcm_frames, sample_rate[, server][, port])

Given a Sheet object, total number of PCM frames and sample rate, returns a {track_number:[(confidence, checksum, alt), ...], ...} dict of values retrieved from the AccurateRip database where track_number is an int starting from 1, confidence is the number of people with the same people with a matching checksum of the track.

May return a dict of empty lists if no AccurateRip entry is found.

May return urllib2.HTTPError if an error occurs querying the server.

Cuesheets

Sheet Objects

These objects represent a CDDA layout such as provided by a .cue or .toc file. This can be used to recreate the exact layout of the disc when burning a set of tracks back to CD.

class audiotools.Sheet(sheet_tracks[, metadata])

sheet_tracks is a list of SheetTrack objects, one per track on the CD. metadata is a MetaData object or None

classmethod Sheet.converted(sheet)

Given a Sheet-compatible object, returns a Sheet object.

Sheet.__len__()

Returns the number of tracks in the sheet.

Sheet.__getitem__(track_index)

Given a track index (starting from 0), returns a SheetTrack object. Raises IndexError if the track cannot be found.

Sheet.track_numbers()

Returns a list of all track numbers in the sheet.

Sheet.track(track_number)

Given a track number (often starting from 1), returns a SheetTrack object with that number. Raises KeyError if the track cannot be found.

Sheet.pre_gap()

Returns the disc’s pre-gap (the amount of empty samples before the first track) as a Fraction number of seconds. This number is often zero.

Sheet.track_offset(track_number)

Given a track number (often starting from 1), returns the offset to that track as a Fraction number of seconds.

May raise KeyError if the track cannot be found.

Sheet.track_length(track_number)

Given a track number (often starting from 1), returns the length of that track as a Fraction number of seconds.

May return None if the track is to use the remainder of the samples in the stream. This is typical of the last track in an album.

May raise KeyError if the track cannot be found.

Sheet.get_metadata()

Returns a MetaData object containing metadata for the entire sheet such as catalog number or CD-TEXT information. May return None if there is no such metadata.

SheetTrack Objects

These objects represent a track on a given cuesheet.

class audiotools.SheetTrack(number, track_indexes[, metadata][, filename][, is_audio=True][, pre_emphasis=False][, copy_permitted=False])
argument type value
number int track number, starting from 1
track_indexes [SheetIndex] list of SheetIndex objects
metadata MetaData track’s metadata, or None
filename unicode track’s filename on disc
is_audio boolean whether track contains audio data
pre_emphasis boolean whether track has pre-emphasis
copy_permitted boolean whether copying is permitted
classmethod SheetTrack.converted(sheet_track)

Given a SheetTrack-compatible object, returns a SheetTrack.

SheetTrack.__len__()

Returns the number of SheetIndex objects in the track.

SheetTrack.__getitem__(i)

Given an index (starting from 0), returns a track’s SheetIndex object. Raises IndexError if the index cannot be found.

SheetTrack.indexes()

Returns a list of all index numbers in the track.

SheetTrack.index(sheet_index)

Given an index number (often starting from 1), returns a track’s SheetIndex object. Raises KeyError if the index is not present.

SheetTrack.number()

Returns the track’s number, typically starting from 1.

SheetTrack.get_metadata()

Returns the track’s metadata such as ISRC and CD-TEXT information as a MetaData object. May return None if it has no metadata.

SheetTrack.filename()

Returns the track’s filename as a Unicode string.

SheetTrack.is_audio()

Returns whether the track contains audio data.

SheetTrack.pre_emphasis()

Returns whether the track has pre-emphasis.

SheetTrack.copy_permitted()

Returns whether copying is permitted.

SheetIndex Objects

class audiotools.SheetIndex(number, offset)

number is the number of the index in the track, often starting from 1. A number of 0 indicates a pre-gap index. offset is the index’s offset from the start of the stream as a Fraction number of seconds.

SheetIndex.number()

Returns the track’s index as an integer.

SheetIndex.offset()

Returns the index point’s offset from the start of the stream as a Fraction number of seconds.

DVDAudio Objects

class audiotools.DVDAudio(audio_ts_path[, device])

This class is used to access a DVD-Audio. It contains a collection of titlesets. Each titleset contains a list of audiotools.dvda.DVDATitle objects, and each audiotools.dvda.DVDATitle contains a list of audiotools.dvda.DVDATrack objects. audio_ts_path is the path to the DVD-Audio’s AUDIO_TS directory, such as /media/cdrom/AUDIO_TS. device is the path to the DVD-Audio’s mount device, such as /dev/cdrom.

For example, to access the 3rd DVDATrack object of the 2nd DVDATitle of the first titleset, one can simply perform the following:

>>> track = DVDAudio(path)[0][1][2]

Note

If device is indicated and the AUDIO_TS directory contains a DVDAUDIO.MKB file, unprotection will be performed automatically if supported on the user’s platform. Otherwise, the files are assumed to be unprotected.

ExecQueue Objects

class audiotools.ExecQueue

This is a class for executing multiple Python functions in parallel across multiple CPUs.

ExecQueue.execute(function, args[, kwargs])

Queues a Python function, list of arguments and optional dictionary of keyword arguments.

ExecQueue.run([max_processes])

Executes all queued Python functions, running max_processes number of functions at a time until the entire queue is empty. This operates by forking a new subprocess per function, executing that function and then, regardless of the function’s result, the child job performs an unconditional exit.

This means that any side effects of executed functions have no effect on ExecQueue’s caller besides those which modify files on disk (encoding an audio file, for example).

class audiotools.ExecQueue2

This is a class for executing multiple Python functions in parallel across multiple CPUs and receiving results from those functions.

ExecQueue2.execute(function, args[, kwargs])

Queues a Python function, list of arguments and optional dictionary of keyword arguments.

ExecQueue2.run([max_processes])

Executes all queued Python functions, running max_processes number of functions at a time until the entire queue is empty. Returns an iterator of the returned values of those functions. This operates by forking a new subprocess per function with a pipe between them, executing that function in the child process and then transferring the resulting pickled object back to the parent before performing an unconditional exit.

Queued functions that raise an exception or otherwise exit uncleanly yield None. Likewise, any side effects of the called function have no effect on ExecQueue’s caller.

ExecProgressQueue Objects

class audiotools.ExecProgressQueue(messenger)

This class runs multiple jobs in parallel and displays their progress output to the given Messenger object.

ExecProgressQueue.execute(function[, progress_text[, completion_output[, *args[, **kwargs]]]])

Queues a Python function for execution. This function is passed the optional args and kwargs arguments upon execution. However, this function is also passed an additional progress keyword argument which is a function that takes the current progress value as a Fraction object between 0 and 1, inclusive. The executed function can then call that progress function at regular intervals to indicate its progress.

If given, progress_text is a Unicode string to be displayed while the function is being executed.

completion_output is displayed once the executed function is completed. It can be either a Unicode string or a function whose argument is the returned result of the executed function and which must output either a Unicode string or None. If None, no output text is generated for the completed job.

ExecProgressQueue.run([max_processes])

Executes all the queued functions, running max_processes number of functions at a time until the entire queue is empty. Returns the results of the called functions in the order in which they were added for execution. This operates by forking a new subprocess per function in which the running progress and function output are piped to the parent for display to the screen.

If an exception occurs in one of the subprocesses, that exception will be raised by ExecProgressQueue.run() and all the running jobs will be terminated.

>>> def progress_function(progress, filename):
...   # perform work here
...   progress(Fraction(current, total))
...   # more work
...   result.a = a
...   result.b = b
...   result.c = c
...   return result
...
>>> def format_result(result):
...    return u"%s %s %s" % (result.a, result.b, result.c)
...
>>> queue = ExecProgressQueue(ProgressDisplay(Messenger("executable")))
>>> queue.execute(function=progress_function,
...               progress_text=u"%s progress" % (filename1),
...               completion_output=format_result,
...               filename=filename1)
...
>>> queue.execute(function=progress_function,
...               progress_text=u"%s progress" % (filename2),
...               completion_output=format_result,
...               filename=filename2)
...
>>> queue.run()

Messenger Objects

class audiotools.Messenger(silent=False)

This is a helper class for displaying program data, analogous to a primitive logging facility. If silent is True, the output methods will not actually display any output to the screen.

Messenger.output(string)

Outputs Unicode string to stdout and adds a newline, unless verbosity level is "silent".

Messenger.partial_output(string)

Output Unicode string to stdout and flushes output so it is displayed, but does not add a newline. Does nothing if verbosity level is "silent".

Messenger.info(string)

Outputs Unicode string to stdout and adds a newline, unless verbosity level is "silent".

Messenger.partial_info(string)

Output Unicode string to stdout and flushes output so it is displayed, but does not add a newline. Does nothing if verbosity level is "silent".

Note

What’s the difference between Messenger.output() and Messenger.info()? Messenger.output() is for a program’s primary data. Messenger.info() is for incidental information. For example, trackinfo uses Messenger.output() for what it displays since that output is its primary function. But track2track uses Messenger.info() for its lines of progress since its primary function is converting audio and tty output is purely incidental.

Messenger.warning(string)

Outputs warning text, Unicode string and a newline to stderr, unless verbosity level is "silent".

>>> m = audiotools.Messenger()
>>> m.warning(u"Watch Out!")
*** Warning: Watch Out!
Messenger.error(string)

Outputs error text, Unicode string and a newline to stderr.

>>> m.error(u"Fatal Error!")
*** Error: Fatal Error!
Messenger.os_error(oserror)

Given an OSError object, displays it as a properly formatted error message with an appended newline.

Note

This is necessary because of the way OSError handles its embedded filename string. Using this method ensures that filename is properly encoded when displayed. Otherwise, there’s a good chance that non-ASCII filenames will be garbled.

Messenger.output_isatty()

Returns True if the output method sends to a TTY rather than a file.

Messenger.info_isatty()

Returns True if the info method sends to a TTY rather than a file.

Messenger.error_isatty()

Returns True if the error method sends to a TTY rather than a file.

Messenger.ansi_clearline()

Generates a ANSI escape codes to clear the current line.

This works only if stdout is a TTY, otherwise is does nothing.

>>> msg = Messenger()
>>> msg.partial_output(u"working")
>>> time.sleep(1)
>>> msg.ansi_clearline()
>>> msg.output(u"done")
Messenger.ansi_uplines(self, lines)

Moves the cursor upwards by the given number of lines.

Messenger.ansi_cleardown(self)

Clears all the output below the current line. This is typically used in conjunction with Messenger.ansi_uplines().

>>> msg = Messenger()
>>> msg.output(u"line 1")
>>> msg.output(u"line 2")
>>> msg.output(u"line 3")
>>> msg.output(u"line 4")
>>> time.sleep(2)
>>> msg.ansi_uplines(4)
>>> msg.ansi_cleardown()
>>> msg.output(u"done")
Messenger.terminal_size(fd)

Given a file descriptor integer, or file object with a fileno() method, returns the size of the current terminal as a (height, width) tuple of integers.

ProgressDisplay Objects

class audiotools.ProgressDisplay(messenger)

This is a class for displaying incremental progress updates to the screen. It takes a Messenger object which is used for generating output. Whether or not sys.stdout is a TTY determines how this class operates. If a TTY is detected, screen updates are performed incrementally with individual rows generated and refreshed as needed using ANSI escape sequences such that the user’s screen need not scroll. If a TTY is not detected, most progress output is omitted.

ProgressDisplay.add_row(output_line)

output_line is a Unicode string indicating what we’re displaying the progress of. Returns a ProgressRow object which can be updated with the current progress for display.

ProgressDisplay.remove_row(row_index)

Removes the given row index and frees the slot for reuse.

ProgressDisplay.display_rows()

Outputs the current state of all progress rows.

ProgressDisplay.clear_row()

Clears all previously displayed output rows, if any.

class audiotools.ProgressRow(progress_display, row_index, output_line)

This is used by ProgressDisplay and its subclasses for actual output generation. progress_display is a parent ProgressDisplay object. row_index is this row’s index on the screen. output_line is a unicode string. It is not typically instantiated directly.

ProgressRow.update(progress)

Updates the current progress as a Fraction between 0 and 1, inclusive.

ProgressRow.finish()

Indicate output is finished and the row will no longer be needed.

ProgressRow.unicode(width)

Returns the output line and its current progress as a Unicode string, formatted to the given width in onscreen characters. Screen width can be determined from the Messenger.terminal_size() method.

class audiotools.SingleProgressDisplay(messenger, progress_text)

This is a subclass of ProgressDisplay used for generating only a single line of progress output. As such, one only specifies a single row of Unicode progress_text at initialization time and can avoid the row management functions entirely.

SingleProgressDisplay.update(progress)

Updates the status of our output row with the current progress, which is a Fraction between 0 and 1, inclusive.

class audiotools.ReplayGainProgressDisplay(messenger, lossless_replay_gain)

This is another ProgressDisplay subclass optimized for the display of ReplayGain application progress. messenger is a Messenger object and lossless_replay_gain is a boolean indicating whether ReplayGain is being applied losslessly or not (which can be determined from the AudioFile.lossless_replay_gain() classmethod). Whether or not sys.stdout is a TTY determines how this class behaves.

ReplayGainProgressDisplay.initial_message()

If operating on a TTY, this does nothing since progress output will be displayed. Otherwise, this indicates that ReplayGain application has begun.

ReplayGainProgressDisplay.update(progress)

Updates the status of ReplayGain application with the current progress which is a Fraction between 0 and 1, inclusive.

ReplayGainProgressDisplay.final_message()

If operating on a TTY, this indicates that ReplayGain application is complete. Otherwise, this does nothing.

>>> rg_progress = ReplayGainProgressDisplay(messenger, AudioType.lossless_replay_gain())
>>> rg_progress.initial_message()
>>> AudioType.add_replay_gain(filename_list, rg_progress.update)
>>> rg_Progress.final_message()

output_text Objects

This class is for displaying portions of a Unicode string to the screen and applying formatting such as color via ANSI escape sequences.

The reason this is needed is because not all Unicode characters are the same width when displayed to the screen. So, for example, if one wishes to display a portion of a Unicode string to a screen that’s 80 ASCII characters wide, one can’t simply perform:

>>> messenger.output(unicode_string[0:80])

since some of those Unicode characters might be double width, which would cause the string to wrap.

class audiotools.output_text(unicode_string[, fg_color][, bg_color][, style])

unicode_string is the text to display. fg_color and bg_color may be one of "black", "red", "green", "yellow", "blue", "magenta", "cyan", or "white". style may be one of "bold", "underline", "blink" or "inverse".

output_text.__unicode__()

Returns the raw Unicode string.

output_text.__len__()

Returns the width of the text in displayed characters.

output_text.fg_color()

Returns the foreground color as a string, or None.

output_text.bg_color()

Returns the background color as a string, or None.

output_text.style()

Returns the style as a string, or None.

output_text.set_format([fg_color][, bg_color][, style])

Returns a new output_text object with the given styles.

output_text.format([is_tty])

If formatting is present and is_tty is True, returns a Unicode string with ANSI escape sequences applied. Otherwise, returns the Unicode string with no ANSI formatting.

output_text.head(display_characters)

Returns a new output_text object that’s been truncated up to the given number of display characters, but may return less.

>>> s = u"".join(map(unichr, range(0x30a1, 0x30a1+25)))
>>> len(s)
25
>>> u = unicode(output_text(s).head(40))
>>> len(u)
20
>>> print repr(u)
u'\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8\u30a9\u30aa\u30ab\u30ac\u30ad\u30ae\u30af\u30b0\u30b1\u30b2\u30b3\u30b4'

Note

Because some characters are double-width, this method along with output_text.tail() and output_text.split() may not return strings that are the same length as requested if the dividing point in the middle of a character.

output_text.tail(display_characters)

Returns a new output_text object that’s been truncated up to the given number of display characters.

>>> s = u"".join(map(unichr, range(0x30a1, 0x30a1+25)))
>>> len(s)
25
>>> u = unicode(output_text(s).tail(40))
>>> len(u)
20
>>> print repr(u)
u'\u30a6\u30a7\u30a8\u30a9\u30aa\u30ab\u30ac\u30ad\u30ae\u30af\u30b0\u30b1\u30b2\u30b3\u30b4\u30b5\u30b6\u30b7\u30b8\u30b9'
output_text.split(display_characters)

Returns a tuple of output_text objects. The first is up to display_characters wide, while the second contains the remainder.

>>> s = u"".join(map(unichr, range(0x30a1, 0x30a1+25)))
>>> (head, tail) = display_unicode(s).split(40)
>>> print repr(unicode(head))
u'\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8\u30a9\u30aa\u30ab\u30ac\u30ad\u30ae\u30af\u30b0\u30b1\u30b2\u30b3\u30b4'
>>> print repr(unicode(tail))
u'\u30b5\u30b6\u30b7\u30b8\u30b9'
output_text.join(output_texts)

Given an iterable collection of output_text objects, returns an output_list joined by our formatted text.

output_list Objects

output_list is an output_text subclass for formatting multiple output_text objects as a unit.

class audiotools.output_list(output_texts[, fg_color][, bg_color][, style])

output_texts is an iterable collection of output_text or unicode objects. fg_color and bg_color may be one of "black", "red", "green", "yellow", "blue", "magenta", "cyan", or "white". style may be one of "bold", "underline", "blink" or "inverse".

Warning

Formatting is unlikely to nest properly since ANSI is un-escaped to the terminal default. Therefore, if the output_list has formatting, its contained output_text objects should not have formatting. Or if the output_text objects do have formatting, the output_list container should not have formatting.

output_list.fg_color()

Returns the foreground color as a string, or None.

output_list.bg_color()

Returns the background color as a string, or None.

output_list.style()

Returns the style as a string, or None.

output_list.set_format([fg_color][, bg_color][, style])

Returns a new output_list object with the given formatting.

output_list.format([is_tty])

If formatting is present and is_tty is True, returns a Unicode string with ANSI escape sequences applied. Otherwise, returns the Unicode string with no ANSI formatting.

output_list.head(display_characters)

Returns a new output_list object that’s been truncated up to the given number of display characters, but may return less.

output_list.tail(display_characters)

Returns a new output_list object that’s been truncated up to the given number of display characters.

output_list.split(display_characters)

Returns a tuple of output_text objects. The first is up to display_characters wide, while the second contains the remainder.

output_list.join(output_texts)

Given an iterable collection of output_text objects, returns an output_list joined by our formatted text.

output_table Objects

output_table is for formatting text into rows and columns.

class audiotools.output_table
output_table.row()

Adds new row to table and returns output_table_row object which columns may be added to.

output_table.blank_row()

Adds empty row to table whose columns will be blank.

output_table.divider_row(dividers)

Takes a list of Unicode characters, one per column, and generates a row which will expand those characters as needed to fill each column.

output_table.format([is_tty])

Yields one formatted Unicode string per row. If is_tty is True, rows may contain ANSI escape sequences for color and style.

output_table_row Objects

output_table_row is a container for table columns and is returned from output_table.row() rather than instantiated directly.

class audiotools.output_table_row
output_table_row.__len__()

Returns the total number of columns in the table.

output_table_row.add_column(text[, alignment="left"][, colspan=1])

Adds text, which may be a Unicode string or output_text object. alignment may be "left", "center" or "right". If colspan is greater than 1, the column is widened to span that many other non-spanning columns.

output_table_row.column_width(column)

Returns the width of the given column in printable characters.

output_table_row.format(column_widths[, is_tty])

Given a list of column widths, returns the table row as a Unicode string such that each column is padded to the corresponding width depending on its alignment. If is_tty is True, columns may contain ANSI escape sequences for color and style.

Exceptions

exception audiotools.UnknownAudioType

Raised by filename_to_type() if the file’s suffix is unknown.

exception audiotools.AmbiguousAudioType

Raised by filename_to_type() if the file’s suffix applies to more than one audio class.

exception audiotools.DecodingError

Raised by PCMReader‘s .close() method if a helper subprocess exits with an error, typically indicating a problem decoding the file.

exception audiotools.DuplicateFile

Raised by open_files() if the same file is included more than once and no_duplicates is indicated.

exception audiotools.DuplicateOutputFile

Raised by audiotools.ui.process_output_options() if the same output file is generated more than once.

exception audiotools.EncodingError

Raised by AudioFile.from_pcm() and AudioFile.convert() if an error occurs when encoding an input file. This includes errors from the input stream, a problem writing the output file in the given location, or EncodingError subclasses such as UnsupportedBitsPerSample if the input stream is formatted in a way the output class does not support.

exception audiotools.InvalidFile

Raised by AudioFile.__init__() if the file is invalid in some way.

exception audiotools.InvalidFilenameFormat

Raised by AudioFile.track_name() if the format string contains broken fields.

exception audiotools.InvalidImage

Raised by Image.new() if the image cannot be parsed correctly.

exception audiotools.OutputFileIsInput

Raised by process_output_options() if an output file is the same as any of the input files.

exception audiotools.SheetException

A parent exception of audiotools.cue.CueException and audiotools.toc.TOCException, to be raised by read_sheet() if a .toc or .cue file is unable to be parsed correctly.

exception audiotools.UnsupportedBitsPerSample

Subclass of EncodingError, indicating the input stream’s bits-per-sample is not supported by the output class.

exception audiotools.UnsupportedChannelCount

Subclass of EncodingError, indicating the input stream’s channel count is not supported by the output class.

exception audiotools.UnsupportedChannelMask

Subclass of EncodingError, indicating the input stream’s channel mask is not supported by the output class.

exception audiotools.UnsupportedFile

Raised by open() if the given file is not something identifiable, or we do not have the installed binaries to support.

exception audiotools.UnsupportedTracknameField

Raised by AudioFile.track_name() if a track name field is not supported.