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 whoseindex
field matchesid
;dict
(including the objects returned by this function, which aredict
subclassses): matches only the device whoseindex
field matchesid['index']
str
: matches any device with the specified word or phrase in itsname
field (you can also matchhostApi.name
andname
simultaneously 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 themode
argument requests any inputs) orPORTAUDIO.DEFAULT_OUTPUT_API_PREFERENCE_ORDER
otherwise. 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
Stream
orPlayer
instance.On Windows,
LowLatencyMode(True)
will manipulatePORTAUDIO.DEFAULT_OUTPUT_API_PREFERENCE_ORDER
to cause the WDM-KS host API (or the ASIO host API, ifpreferASIO
isTrue
) 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_MSEC
is set to'auto'
(which means 60 for DirectSound and at least 10 elsewhere) for futureStream
instances.
- class audiomath.PortAudioInterface.Player(sound, device=None, stream=None, bufferLengthMsec=None, minLatencyMsec=None, fs=None, resample=False, verbose=None, **kwargs)
A
Player
provides a persistent connection to the chosen playback hardware, allowing aSound
instance to be played.A
Player
instance can only play oneSound
at a time, but it can optionally maintain a list ofSound
instances in aQueue
and switch between them. For overlapping sounds, use multiplePlayer
instances.A
Player
instance can be created directly from a filename, list of filenames or filename glob pattern. The currentSound
instance is available in thesound
property and the completeQueue
is available in thequeue
property.It is better to create a
Player
instance than to rely on the quick-and-dirtyPlay()
methods of theSound
andQueue
classes—these methods just create aPlayer
(entailing some computational overhead), wait synchronously for it to finish, and then destroy it again. Creating your ownPlayer
instance provides much greater flexibility and performance.- Parameters:
sound (str, Sound, Queue, None) –
Sound
instance to play (or sequence ofSound
instances in alist
orQueue
). Alternatively, supply any argument that is also a valid input to theSound
orQueue
constructors (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-openStream
instance.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
Player
or firstStream
(after that,Player
instances may share an openStream
instance so it is possible that only the first call will make any difference). Larger buffer lengths lead to higher playback latencies.None
means 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.None
means 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
Player
or firstStream
(after that,Player
instances may share an openStream
instance 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.fs
and the sampling frequency of the output streamself.stream.fs
. If true, replaceself.sound
with 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 thePlayer
instance.
- audiomath.PortAudioInterface.Record(space=60, prompt=None, verbose=None, cut=True, nChannels=None, filename=None, **kwargs)
Record and return a
Sound
synchronously. Slightly easier than creating your ownRecorder
instance 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
Sound
instance into which to record, or a number of seconds. In the latter case aSound
instance 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. Ifprompt
is a string, it is printed to the console and theRecorder
waits until it has finished (or until ctrl-C is pressed). Alternatively, supply a callable whose non-None
return value signals that the recording should end.verbose (bool) – Passed through to the constructor of the
Recorder
object that is being used.cut (bool) – If true, return a
Cut()
version of theSound
when recording stops—i.e. ensure that the duration of theSound
does not exceed the duration of the recording. If false, the entire pre-allocatedspace
is 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
ffmpeg
class to stream the recorded content to the specified file. This requires theffmpeg
binary to be (separately) installed—see theffmpeg
class documentation.**kwargs – Additional keyword arguments are passed through to the constructor of the
Recorder
object (for example, to specify thedevice
that 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
Recorder
provides a persistent connection to the chosen recording hardware, allowing sound to be recorded into aSound
instance.You may find it more useful to use the global function
Record
, which synchronously records and returns aSound
instance, than to create or interact directly withRecorder
instances. However,Recorder
instances 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
Sound
instance 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-openStream
instance)stream (int, str, dict, Stream) – synonymous with
device
, for compatibilityfs (float, None) – Optionally specify the sampling frequency, in Hz, when creating your first
Recorder
or firstStream
(after that,Recorder
instances may share an openStream
instance 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.sound
as a circular buffer, or simply stop when the capacity ofself.sound
is 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 theRecorder
instance.
- 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=True
orverbose=False
, but by default they inherit their verbosity from the setting you specify here.
- audiomath.PortAudioInterface.SetInputDevice(device)
Set the specified
device
as the default device to be used forRecorder
objects. Thedevice
argument 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
device
as the default device to be used forPlayer
objects. Thedevice
argument may be the device index, one or more words from the device name, or the full device record fromGetDeviceInfo()
orFindDevices()
.Note that, by default,
Player
instances share a singleStream
instance—this means that the preference you specify here (and the preference you specify in thePlayer
constructor) may not be honored if there are already otherPlayer
instances in existence (and hence an already-runningStream
). In short: it’s best to use this function before you construct your firstPlayer
orStream
instance.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
Stream
or add themselves to an existingStream
, so you will not usually need to construct aStream
instance yourself. The exception is when you need to ensure that the construction of such objects is itself fast: then, creating aStream
in advance, and keeping a reference to it to use in initializing the other objects, will speed things up.The
device
,mode
andapiPreferences
arguments are the same asid
,mode
andapiPreferences
inFindDevice()
.
- 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()
.