The audiomath.PortAudioInterface sub-module
This submodule contains PortAudio-specific implementations of high-
level Player and Recorder classes. They inherit their API-user-
facing functionality, as well as their code for manipulating raw
Sound data, from GenericInterface.GenericPlayer and
GenericInterface.GenericRecorder. The PortAudio-specific
subclasses act as intermediaries between the generic stuff and the
objects and functions in the _wrap_portaudio submodule.
This submodule also contains various global functions for listing and selecting the available sound devices and their host APIs.
The PortAudioInterface is the default playing/recording back-end
for audiomath. Therefore, all the symbols exported by this
submodule are also available at the top level audiomath.*
namespace (at least until another back-end is written, and loaded
with audiomath.BackEnd.Load()).
- audiomath.PortAudioInterface.FindDevice(id=None, mode=None, apiPreferences=None, _candidates=None)
Returns the first device matched by
FindDevices()(plural) according to the specified criteria. Raises an exception if there are no matches.
- audiomath.PortAudioInterface.FindDevices(id=None, mode=None, apiPreferences=None, _candidates=None)
Calls
GetDeviceInfo(), filtering and reordering the outputs according to the specified criteria. You canprint()the result, or otherwise convert it tostr(), to see a pretty tabulated summary.You can use
FindDevice()(singular) to return just the top-ranking result (and to assert that at least one result can be found).- Parameters:
id (int, dict, str, None) –
None: matches all devices;int: matches only the device whoseindexfield matchesid;dict(including the objects returned by this function, which aredictsubclassses): matches only the device whoseindexfield matchesid['index']str: matches any device with the specified word or phrase in itsnamefield (you can also matchhostApi.nameandnamesimultaneously if you delimit them with'//'—for example,'WDM-KS//Speakers');
mode (str, tuple, None) – May be either a two-element tuple such as
mode=(minInputChannels,minOutputChannels), or a string containing a number of'o'and/or'i'characters. In either case, devices are only matched if they provide at least the specified number of input and output channels. For example,FindDevices(mode='oo')matches all devices that provide two or more output channels.apiPreferences (str, None) – If this is left at
None, it defaults to the current value ofPORTAUDIO.DEFAULT_INPUT_API_PREFERENCE_ORDER(if themodeargument requests any inputs) orPORTAUDIO.DEFAULT_OUTPUT_API_PREFERENCE_ORDERotherwise. The string'*'matches all host APIs. Host APIs may be comma-delimited. For example,apiPreferences='DirectSound,*'means “give first priority to devices hosted by the DirectSound API, and then, failing that, match all other APIs”. If'*'is not included in the specification, this argument may limit the number of records returned. In any case it will affect the ordering of the returned records.
- audiomath.PortAudioInterface.GetDeviceInfo()
Returns a list of records corresponding to PortAudio’s
Pa_GetDeviceInfo()output for every available combination of host API and device. You canprint()the result, or otherwise convert it tostr(), to see a pretty tabulated summary.
- audiomath.PortAudioInterface.GetHostApiInfo()
Returns a list of records corresponding to PortAudio’s
Pa_GetHostApiInfo()output for every available host API. You canprint()the result, or otherwise convert it tostr(), to see a pretty tabulated summary.
- audiomath.PortAudioInterface.GetInputDevice()
Return the default input device, if any has been set.
See also:
SetInputDevice()
- audiomath.PortAudioInterface.GetOutputDevice()
Return the default output device, if any has been set.
See also:
SetOutputDevice()
- audiomath.PortAudioInterface.LowLatencyMode(turnOn, preferASIO=False)
Call this function before you create your first
StreamorPlayerinstance.On Windows,
LowLatencyMode(True)will manipulatePORTAUDIO.DEFAULT_OUTPUT_API_PREFERENCE_ORDERto cause the WDM-KS host API (or the ASIO host API, ifpreferASIOisTrue) to be preferred over DirectSound when constructing output streams. This will allow considerably lower output latencies, but will have the side-effect of taking exclusive control of the sound driver, meaning that sounds from other applications will no longer be audible (this may or may not be desirable, depending on your application).LowLatencyMode(True)also setsPORTAUDIO.DEFAULT_BUFFER_LENGTH_MSEC = None, andPORTAUDIO.DEFAULT_MIN_LATENCY_MSEC = 4, which will have the effect of lowering latencies but at the cost of making sounds vulnerable to stuttering if Python performs any significant work during playback.LowLatencyMode(False)reverts to factory settings (DirectSound is reinstated as the preferred host API on Windows, andPORTAUDIO.DEFAULT_MIN_LATENCY_MSECis set to'auto'(which means 60 for DirectSound and at least 10 elsewhere) for futureStreaminstances.
- class audiomath.PortAudioInterface.Player(sound, device=None, stream=None, bufferLengthMsec=None, minLatencyMsec=None, fs=None, resample=False, verbose=None, **kwargs)
A
Playerprovides a persistent connection to the chosen playback hardware, allowing aSoundinstance to be played.A
Playerinstance can only play oneSoundat a time, but it can optionally maintain a list ofSoundinstances in aQueueand switch between them. For overlapping sounds, use multiplePlayerinstances.A
Playerinstance can be created directly from a filename, list of filenames or filename glob pattern. The currentSoundinstance is available in thesoundproperty and the completeQueueis available in thequeueproperty.It is better to create a
Playerinstance than to rely on the quick-and-dirtyPlay()methods of theSoundandQueueclasses—these methods just create aPlayer(entailing some computational overhead), wait synchronously for it to finish, and then destroy it again. Creating your ownPlayerinstance provides much greater flexibility and performance.- Parameters:
sound (str, Sound, Queue, None) –
Soundinstance to play (or sequence ofSoundinstances in alistorQueue). Alternatively, supply any argument that is also a valid input to theSoundorQueueconstructors (e.g. a filename, list of filenames, or file glob pattern).device (int, str, dict, Stream, None) – Optionally use this argument to specify the device/stream to use for playback—as an integer index, a device name, a full device record from
FindDevice(), or (fastest of all) an already-openStreaminstance.stream (int, str, dict, Stream, None) – Synonymous with
device, for compatibility.bufferLengthMsec (float, None, ‘auto’) – Optionally specify a buffer length in milliseconds when creating your first
Playeror firstStream(after that,Playerinstances may share an openStreaminstance so it is possible that only the first call will make any difference). Larger buffer lengths lead to higher playback latencies.Nonemeans use whatever is currently globally configured inPORTAUDIO.DEFAULT_BUFFER_LENGTH_MSEC.'auto'or'pa-default'means use the default supplied by the PortAudio library.minLatencyMsec (float, None, ‘auto’) – Use this setting to override the PortAudio default for “suggested” latency when creating a
Stream. The values supplied here typically undershoot the empirically measurable latency (in a non-linear fashion) but larger values mean greater robustness (less crackle/stutter susceptibility) at the cost of longer latencies and higher jitter.Nonemeans use whatever is currently globally configured inPORTAUDIO.DEFAULT_MIN_LATENCY_MSEC.'auto'means use certain defaults that we have empirically derived to balance these factors.'pa-default'means use the defaults supplied by the PortAudio library.fs (float, None) – Optionally specify the sampling frequency, in Hz, when creating your first
Playeror firstStream(after that,Playerinstances may share an openStreaminstance so it is possible that only the first call will make any difference).resample (bool) – Specifies how to handle potential mismatch between the sampling frequency of the sound data
self.sound.fsand the sampling frequency of the output streamself.stream.fs. If true, replaceself.soundwith a copy resampled to the stream’s preferred rate. If false, simply adjust playback speed accordingly (at a small, ongoing, computational cost).verbose (bool, None) – Verbosity for debugging. If
None, inherit from the setting specified bySetDefaultVerbosity(), if any.**kwargs – passed through to
Set()to initialize properties of thePlayerinstance.
- audiomath.PortAudioInterface.Record(space=60, prompt=None, verbose=None, cut=True, nChannels=None, filename=None, **kwargs)
Record and return a
Soundsynchronously. Slightly easier than creating your ownRecorderinstance and working with that (which is what you would have to do if you want to record asynchronously).- Parameters:
space (Sound, float) – specifies either a pre-existing
Soundinstance into which to record, or a number of seconds. In the latter case aSoundinstance is created, pre- allocated with the specified amount of space in seconds.prompt (None, bool, str, function) – if this is left as
None, a default string is composed. Ifpromptis a string, it is printed to the console and theRecorderwaits until it has finished (or until ctrl-C is pressed). Alternatively, supply a callable whose non-Nonereturn value signals that the recording should end.verbose (bool) – Passed through to the constructor of the
Recorderobject that is being used.cut (bool) – If true, return a
Cut()version of theSoundwhen recording stops—i.e. ensure that the duration of theSounddoes not exceed the duration of the recording. If false, the entire pre-allocatedspaceis returned, with the recording at the beginning.nChannels (int) – Optionally specify the number of channels to record (some APIs have crazy defaults, like ALSA’s 32 channels - if you’re not using one of those APIs, you probably don’t need this).
filename (str) – Optionally, use the
ffmpegclass to stream the recorded content to the specified file. This requires theffmpegbinary to be (separately) installed—see theffmpegclass documentation.**kwargs – Additional keyword arguments are passed through to the constructor of the
Recorderobject (for example, to specify thedevicethat should be used).
Examples:
import audiomath as am s = am.Record() # this records for up to 60 seconds (less if ctrl-C # is pressed) and returns a `Sound` instance containing # the recorded data. s2 = am.Record(10, loop=True, filename='blah.mp3') # this records indefinitely into a 10-second circular # buffer, streaming the recorded data all the while into # the file `blah.mp3`, and when you press ctrl-C it # stops, cleans up, and returns the last 10 seconds as # a `Sound` instance.
- class audiomath.PortAudioInterface.Recorder(seconds, device=None, stream=None, bufferLengthMsec=None, minLatencyMsec=None, fs=None, start=True, loop=False, verbose=None, filename=None, **kwargs)
A
Recorderprovides a persistent connection to the chosen recording hardware, allowing sound to be recorded into aSoundinstance.You may find it more useful to use the global function
Record, which synchronously records and returns aSoundinstance, than to create or interact directly withRecorderinstances. However,Recorderinstances are the way to go if you want to record asynchronously, in the background.- Parameters:
seconds (float, Sound) – number of seconds to pre-allocate for recording, or an already-pre-allocated
Soundinstance into which to recorddevice (int, str, dict, Stream) – specification of the device/stream to use for recording (as an index, name, full device record from
FindDevice(), or already-openStreaminstance)stream (int, str, dict, Stream) – synonymous with
device, for compatibilityfs (float, None) – Optionally specify the sampling frequency, in Hz, when creating your first
Recorderor firstStream(after that,Recorderinstances may share an openStreaminstance so it is possible that only the first call will make any difference).start (bool) – whether to start recording immediately
loop (bool) – whether to record indefinitely, treating
self.soundas a circular buffer, or simply stop when the capacity ofself.soundis reachedverbose (bool, None) – verbosity for debugging. If
None, inherit from the setting specified bySetDefaultVerbosity(), if any**kwargs – passed through to
Set()to initialize properties of theRecorderinstance.
- audiomath.PortAudioInterface.Seconds()
A platform-dependent high-precision clock. Origin (time zero) is arbitrary, but fixed within a given Python session.
- audiomath.PortAudioInterface.SetDefaultVerbosity(value)
Useful for debugging when the PortAudio library is initialized or terminated, when streams are opened, started, stopped or closed, and when other objects such as players or recorders are initialized or garbage-collected. Objects may be individually marked as
verbose=Trueorverbose=False, but by default they inherit their verbosity from the setting you specify here.
- audiomath.PortAudioInterface.SetInputDevice(device)
Set the specified
deviceas the default device to be used forRecorderobjects. Thedeviceargument may be the device index, one or more words from the device name, or the full device record fromGetDeviceInfo()orFindDevices().See also:
GetInputDevice()
- audiomath.PortAudioInterface.SetOutputDevice(device)
Set the specified
deviceas the default device to be used forPlayerobjects. Thedeviceargument may be the device index, one or more words from the device name, or the full device record fromGetDeviceInfo()orFindDevices().Note that, by default,
Playerinstances share a singleStreaminstance—this means that the preference you specify here (and the preference you specify in thePlayerconstructor) may not be honored if there are already otherPlayerinstances in existence (and hence an already-runningStream). In short: it’s best to use this function before you construct your firstPlayerorStreaminstance.See also:
GetOutputDevice()
- class audiomath.PortAudioInterface.Stream(device=None, mode=None, apiPreferences=None, outputCallbacks=None, sampleRate=None, sampleFormat=None, verbose=None, bufferLengthMsec=None, minLatencyMsec=None)
A persistent connection to an audio driver. Multiple output callbacks (player objects) and/or multiple input callbacks (recorder objects) may share the same
Stream, or under some conditions it may be possible for each callback (or object) to have its ownStream.Typically, objects that play or record will automatically create a
Streamor add themselves to an existingStream, so you will not usually need to construct aStreaminstance yourself. The exception is when you need to ensure that the construction of such objects is itself fast: then, creating aStreamin advance, and keeping a reference to it to use in initializing the other objects, will speed things up.The
device,modeandapiPreferencesarguments are the same asid,modeandapiPreferencesinFindDevice().
- audiomath.PortAudioInterface.Tabulate(records, *fields)
Returns a pretty-printed table of the specified
fields(i.e. dictionary entries or attributes) of a list of records. This is called automatically, with certain default combinations of field names, when youprint()the results ofGetHostApiInfo(),GetDeviceInfo()orFindDevices().