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 rewound to the file’s start, 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.has_binaries() 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.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.

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

audiotools.stripped_pcm_cmp(pcmreader1, pcmreader2)

This function takes two PCMReader objects and compares their PCM output after stripping any 0 samples from the beginning and end of each. Returns True if the remaining output matches exactly, False if not.

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. 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_metadata_file(path)

Given a path to a FreeDB XMCD file or MusicBrainz XML file, returns an AlbumMetaDataFile-compatible object or raises a MetaDataFileException if the file cannot be read or parsed correctly.

audiotools.read_sheet(filename)

Reads a Cuesheet-compatible file such as toc.TOCFile or cue.Cuesheet or raises SheetException if the file cannot be opened, identified 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.

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 decimal.Decimal number of seconds.

AudioFile.lossless()

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

AudioFile.set_metadata(metadata)

Takes a MetaData-compatible object and sets this audio file’s metadata to that value, if possible. 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.from_pcm(filename, pcmreader[, compression])

Takes a filename string, PCMReader-compatible object and optional compression level string. Creates a new audio file as the same format as this audio class and returns a new AudioFile-compatible object. 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.MP3Audio.from_pcm("track.mp3",
...                              audiotools.open("track.flac").to_pcm())
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 two integer arguments: amount_processed and total_amount. 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. Note that these numbers are only meaningful when compared to one another; amount may represent PCM frames, bytes or anything else. The only restriction is that total_amount will remain static during processing and amount_processed will progress from 0 to total_amount.

>>> def print_progress(x, y):
...   print "%d%%" % (x * 100 / y)
...
>>> audiotools.open("track.flac").convert("track.wv",
...                                       audiotools.WavPackAudio,
...                                       progress=print_progress)
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(). That is, it takes a two integer argument function which is called at regular intervals to indicate the status of verification.

AudioFile.track_number()

Returns this audio file’s track number as a non-negative integer. This method first checks the file’s metadata values. If unable to find one, it then tries to determine a track number from the track’s filename. If that method is also unsuccessful, it returns 0.

AudioFile.album_number()

Returns this audio file’s album number as a non-negative integer. This method first checks the file’s metadata values. If unable to find metadata, it then tries to determine an album number from the track’s filename. If that method is also unsuccessful, it returns 0.

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

Given a file path string and optional MetaData-compatible object a UTF-8 encoded Python format string, and an ASCII-encoded suffix string, returns a filename string with the format string fields filled-in. If not provided by metadata, track_number and album_number will be determined from file_path, if possible. 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.add_replay_gain(filenames[, progress])

Given a list of filename strings of the same class as this AudioFile class, calculates and adds ReplayGain metadata to those files. Raises ValueError if some problem occurs during ReplayGain calculation or application. progress, if indicated, is a function which takes two arguments that is called as needed during ReplayGain application to indicate progress - identical to the argument used by convert().

classmethod AudioFile.supports_replay_gain()

Returns True if this class supports ReplayGain metadata.

classmethod AudioFile.lossless_replay_gain()

Returns True if this audio class applies ReplayGain via a lossless process - such as by adding a metadata tag of some sort. Returns False if applying metadata modifies the audio file data itself.

classmethod AudioFile.can_add_replay_gain(audiofiles)

Given a list of AudioFile objects, returns True if this class can run AudioFile.add_replay_gain() on those objects, False if not.

AudioFile.replay_gain()

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

AudioFile.set_cuesheet(cuesheet)

Takes a cuesheet-compatible object with catalog(), IRSCs(), indexes() and pcm_lengths() methods and sets this audio file’s embedded cuesheet to those values, if possible. Raises IOError if this AudioFile supports embedded cuesheets but some error occurred when writing the file.

AudioFile.get_cuesheet()

Returns a cuesheet-compatible object with catalog(), IRSCs(), indexes() and pcm_lengths() methods or None if no cuesheet is embedded. Raises IOError if some error occurs when reading the file.

AudioFile.clean(fixes_performed[, output_filename])

Cleans the audio file of known data and metadata problems. fixes_performed is a list-like object which is appended with Unicode strings of the fixes performed.

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.

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

classmethod AudioFile.has_binaries(system_binaries)

Takes the audiotools.BIN object of system binaries. Returns True if all the binaries necessary to implement this AudioFile-compatible class are present and executable. Returns False if not.

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][, 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.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(fixes_performed)

Returns a new MetaData object of the same class that’s been cleaned of known problems including, but not limited to

  • Leading whitespace in text fields
  • Trailing whitespace in text fields
  • Empty fields
  • Leading zeroes in numerical fields
  • Incorrectly labeled image metadata fields

fixes_performed is a list object with an append method. Text descriptions of the fixes performed are appended to that list as Unicode strings.

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.

AlbumMetaData Objects

class audiotools.AlbumMetaData(metadata_iter)

This is a dictionary-like object of track_number -> MetaData values. It is designed to represent metadata returned by CD lookup services such as FreeDB or MusicBrainz.

AlbumMetaData.metadata()

Returns a single MetaData object containing all the fields that are consistent across this object’s collection of MetaData.

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

Note that PCMReader-compatible objects need only implement the sample_rate, channels, channel_mask and bits_per_sample fields. The rest are helpers for converting raw strings into pcm.FrameList objects.

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.

May raise a DecodingError, typically indicating that a helper subprocess used for decoding has exited with an error.

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 pcm.FrameList objects and always raises a DecodingError with the given error_message when closed. 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 the DecodingError 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.

RemaskedPCMReader Objects

class audiotools.RemaskedPCMReader(pcmreader, channel_count, channel_mask)

This class wraps around an existing PCMReader object and constructs a new PCMReader with the given channel count and mask.

Channels common to pcmreader and the given channel mask are output by calls to RemaskedPCMReader.read() while missing channels are populated with silence.

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)

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.

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))

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

CDDA Objects

class audiotools.CDDA(device[, speed[, perform_logging]])

This class is used to access a CD-ROM device. It functions as a list of CDTrackReader objects, each representing a CD track and starting from index 1.

>>> cd = CDDA("/dev/cdrom")
>>> len(cd)
17
>>> cd[1]
<audiotools.CDTrackReader instance at 0x170def0>
>>> cd[17]
<audiotools.CDTrackReader instance at 0x1341b00>

If True, perform_logging indicates that track reads should generate CDTrackLog entries. Otherwise, no logging is performed.

Warning

perform_logging also determines the level of multithreading allowed during CD reading. If logging is active, CDTrackReader‘s read method will block all other threads until the read is complete. If logging is inactive, a read will not block other threads. This is an unfortunate necessity due to libcdio’s callback mechanism implementation.

CDDA.length()

The length of the entire CD, in sectors.

CDDA.first_sector()

The position of the first sector on the CD, typically 0.

CDDA.last_sector()

The position of the last sector on the CD.

CDDA.freedb_disc_id()

A freedb.DiscID object from this CD’s table-of-contents.

CDDA.musicbrainz_disc_id()

A musicbrainz.DiscID object from this CD’s table-of-contents.

CDDA.metadata_lookup([musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Calls metadata_lookup() using this CD’s table-of-contents.

CD Lookups

audiotools.metadata_lookup(first_track_number, last_track_number, offsets, lead_out_offset, total_length[, musicbrainz_server][, musicbrainz_port][, freedb_server][, freedb_port][, use_musicbrainz][, use_freedb])

Generates a set of MetaData objects from CD information. first_track_number and last_track_number are positive ints. offsets is a list of track offsets, in CD frames. lead_out_offset is the offset of the “lead-out” track, in CD frames. total_length is the total length of the disc, in CD frames.

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.

CDTrackReader Objects

class audiotools.CDTrackReader(cdda, track_number[, perform_logging])

These objects are usually retrieved from CDDA objects rather than instantiated directly. Each is a PCMReader-compatible object with a few additional methods specific to CD reading.

CDTrackReader.rip_log

A CDTrackLog object indicating cdparanoia’s results from reading this track from the CD. This attribute should be checked only after the track has been fully read.

CDTrackReader.offset()

Returns the offset of this track within the CD, in sectors.

CDTrackReader.length()

Returns the total length of this track, in sectors.

CDTrackLog Objects

class audiotools.CDTrackLog

This is a dictionary-like object which should be retrieved from CDTrackReader rather than instantiated directly. Its __str__() method will return a human-readable collection of error statistics comparable to what’s returned by the cdda2wav program.

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(progress_display[, total_progress_message])

This class runs multiple jobs in parallel and displays their progress output to the given ProgressDisplay object. The optional total_progress_message argument is a Unicode string which displays an additional progress bar of the queue’s total progress.

ExecProgressQueue.results

A dict of results returned by the queued functions once executed. The key is an integer starting from 0.

Note

Why not a list? Since jobs may finish in an arbitrary order, a dict is used so that results can be accumulated out-of-order. Even using placeholder values such as None may not be appropriate if queued functions return None as a significant value.

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 current and total integer arguments. 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. 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 or accumulation in the ExecProgressQueue.results dict.

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(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()
>>> queue.results

Messenger Objects

class audiotools.Messenger(executable_name, options)

This is a helper class for displaying program data, analogous to a primitive logging facility. It takes a raw executable_name string and optparse.OptionParser object. Its behavior changes depending on whether the options object’s verbosity attribute is "normal", "debug" or "silent".

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("audiotools",options)
>>> 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.usage(string)

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

>>> m.usage(u"<arg1> <arg2> <arg3>")
*** Usage: audiotools <arg1> <arg2> <arg3>
Messenger.new_row()

This method begins the process of creating aligned table data output. It sets up a new row in our output table to which we can add columns of text which will be aligned automatically upon completion.

Messenger.output_column(string[, right_aligned])

This method adds a new Unicode string to the currently open row. If right_aligned is True, its text will be right-aligned when it is displayed. When you’ve finished with one row and wish to start on another, call Messenger.new_row() again.

Messenger.blank_row()

This method adds a completely blank row to its table data. Note that the first row within an output table cannot be blank.

Messenger.output_rows()

Formats and displays the entire table data through the Messenger.output() method (which will do nothing if verbosity level is "silent").

>>> m.new_row()
>>> m.output_column(u"a",True)
>>> m.output_column(u" : ",True)
>>> m.output_column(u"This is some test data")
>>> m.new_row()
>>> m.output_column(u"ab",True)
>>> m.output_column(u" : ",True)
>>> m.output_column(u"Another row of test data")
>>> m.new_row()
>>> m.output_column(u"abc",True)
>>> m.output_column(u" : ",True)
>>> m.output_column(u"The final row of test data")
>>> m.output_rows()
  a : This is some test data
 ab : Another row of test data
abc : The final row of test data
Messenger.info_rows()

Functions like Messenger.output_rows(), but displays output via Messenger.info() rather than Messenger.output().

Messenger.divider_row(dividers)

This method takes a list of vertical divider Unicode characters, one per output column, and multiplies those characters by their column width when displayed.

>>> m.new_row()
>>> m.output_column(u"foo")
>>> m.output_column(u" ")
>>> m.output_column(u"bar")
>>> m.divider_row([u"-",u" ",u"-"])
>>> m.new_row()
>>> m.output_column(u"test")
>>> m.output_column(u" ")
>>> m.output_column(u"column")
>>> m.output_rows()
foo  bar
---- ------
test column
Messenger.ansi(string, codes)

Takes a Unicode string and list of ANSI SGR code integers. If stdout is to a TTY, returns a Unicode string formatted with those codes. If not, the string is returned as is. Codes can be taken from the many predefined values in the Messenger class. Note that not all output terminals are guaranteed to support all ANSI escape codes.

Messenger.ansi_err(string, codes)

This is identical to Messenger.ansi, but it checks whether stderr is a TTY instead of stdout.

Code Effect
Messenger.RESET resets current codes
Messenger.BOLD bold font
Messenger.FAINT faint font
Messenger.ITALIC italic font
Messenger.UNDERLINE underline text
Messenger.BLINK_SLOW blink slowly
Messenger.BLINK_FAST blink quickly
Messenger.REVERSE reverse text
Messenger.STRIKEOUT strikeout text
Messenger.FG_BLACK foreground black
Messenger.FG_RED foreground red
Messenger.FG_GREEN foreground green
Messenger.FG_YELLOW foreground yellow
Messenger.FG_BLUE foreground blue
Messenger.FG_MAGENTA foreground magenta
Messenger.FG_CYAN foreground cyan
Messenger.FG_WHITE foreground write
Messenger.BG_BLACK background black
Messenger.BG_RED background red
Messenger.BG_GREEN background green
Messenger.BG_YELLOW background yellow
Messenger.BG_BLUE background blue
Messenger.BG_MAGENTA background magenta
Messenger.BG_CYAN background cyan
Messenger.BG_WHITE background white
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("audiotools", None)
>>> 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("audiotools", None)
>>> 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(row_id, output_line)

Adds a row of output to be displayed with progress indicated. row_id should be a unique identifier, typically an int. output_line should be a Unicode string indicating what we’re displaying the progress of.

ProgressDisplay.update_row(row_id, current, total)

Updates the progress of the given row. current and total are integers such that current / total indicates the percentage of progress performed.

ProgressDisplay.refresh()

Refreshes the screen output, clearing and displaying a fresh progress rows as needed. This is called automatically by update_row().

ProgressDisplay.clear()

Clears the screen output. Although refresh() will call this method as needed, one may need to call it manually when generating output independently for the progress monitor so that partial updates aren’t left on the user’s screen.

ProgressDisplay.delete_row(row_id)

Removes the row with the given ID from the current list of progress monitors.

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(current, total)

Updates the status of our output row with current and total integers, which function identically to those of ProgressDisplay.update_row().

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(current, total)

Updates the status of ReplayGain application.

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()
class audiotools.ProgressRow(row_id, output_line)

This is used by ProgressDisplay and its subclasses for actual output generation. row_id is a unique identifier and output_line is a Unicode string. It is not typically instantiated directly.

ProgressRow.update(current, total)

Updates the current progress with current and total integer values.

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.

display_unicode Objects

This class is for displaying portions of a Unicode string to the screen. The reason this is needed is because not all Unicode characters are the same width. 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.display_unicode(unicode_string)
display_unicode.head(display_characters)

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

>>> s = u"".join(map(unichr, range(0x30a1, 0x30a1+25)))
>>> len(s)
25
>>> u = unicode(display_unicode(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'
display_unicode.tail(display_characters)

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

>>> s = u"".join(map(unichr, range(0x30a1, 0x30a1+25)))
>>> len(s)
25
>>> u = unicode(display_unicode(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'
display_unicode.split(display_characters)

Returns a tuple of display_unicode 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'

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.