The audiomath
package
Summary
audiomath
is a package for reading, manipulating, and writing
sound waveforms. It also lets you record and play sounds, with a
high degree of real-time control over playback.
To manipulate sound waveforms, plot them, and write them to disk,
use the Sound
class. Usually you would initialize a Sound
instance from a filename, or from a numpy
array—in the latter
case your array would contain floating-point values in the range
[-1, +1], arranged samples-by-channels.
To play sounds, use the Player
class. You can initialize a
Player
instance from a Sound
instance, or from anything that
can be used to create one (e.g. a filename). You can also supply
a sequence of Sound
instances, or a sequence of filenames or a
glob
pattern that matches multiple files: then you can have the
Player
instance manage multiple “tracks”. Each Player
will
only play one sound at a time: to overlap sounds, create multiple
Player
instances.
To record a sound, use the Record
function, or the Recorder
class if you want to do it asynchronously.
Classes
audiomath.Sound
for manipulating, visualizing and writing sounds.audiomath.Synth
for functionally generating sounds on-the-fly instead of storing them as static arrays.audiomath.Player
for playing sounds.audiomath.Queue
for managing playlists (everyPlayer
automatically has one of these).audiomath.Fader
andaudiomath.Delay
are examples of “dynamic” callable objects that can be assigned toPlayer
properties.audiomath.Recorder
for recording sounds—see also theRecord()
function.audiomath.ffmpeg
for streaming audio data to file via the auxiliary third-party utility ffmpeg, from https://ffmpeg.orgaudiomath.sox
for transforming audio data via the auxiliary third-party utility sox, from https://sox.sourceforge.net
Global functions and constants
- audiomath.Concatenate(*args)
Concatenate sounds in time, to make a new
Sound
instance containing a new array.You can also concatenate
Sound
instances using the%
operator, and can modifying an existingSound
instances
(replacing its arrays.y
) using%=
:s = s1 % s2 s %= s1
Note that, in the above examples, either
s1
ors2
may also be a numeric scalar:s %= 0.5
appends half a second of silence tos
.
- audiomath.MakeFall(duration, fs=1000, hann=False)
Return a single-channel
Sound
object of the specifiedduration
in seconds at the specified sampling frequencyfs
in Hz, containing a “fade-out” envelope (i.e. a ramp from 1 to 0). Ifhann
is True, use a raised-cosine profile instead of a linear ramp.See also:
MakeRise()
,MakePlateau()
,MakeHannWindow()
- audiomath.MakeHannWindow(duration, fs=1000, plateau_duration=0)
Return a single-channel
Sound
object of the specifiedduration
in seconds at the specified sampling frequencyfs
in Hz, containing a Hann or Tukey window—i.e. a raised-cosine “fade-in”, followed by an optional plateau, followed by a raised-cosine “fade-out”.See also:
MakeRise()
,MakePlateau()
,MakeFall()
- audiomath.MakePlateau(duration, fs=1000, dc=1.0)
Return a single-channel
Sound
object of the specifiedduration
in seconds at the specified sampling frequencyfs
in Hz, containing a constantdc
value.See also:
MakeRise()
,MakeFall()
,MakeHannWindow()
- audiomath.MakeRise(duration, fs=1000, hann=False)
Return a single-channel
Sound
object of the specifiedduration
in seconds at the specified sampling frequencyfs
in Hz, containing a “fade-in” envelope (i.e. a ramp from 0 to 1). Ifhann
is True, use a raised-cosine profile instead of a linear ramp.See also:
MakePlateau()
,MakeFall()
,MakeHannWindow()
- audiomath.QueueTest()
Construct and return an example
Queue
containing exampleSound
instances. Initialize aPlayer
with this to test management of multiple tracks by thePlayer
class.
- audiomath.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.
- audiomath.Stack(*args)
Stack multiple Sound objects to make a new multi-channel
Sound
object (appending silence to the end of each argument where necessary to equalize lengths).You can also stack channels of
Sound
instances using the&
operator, and can modifying an existingSound
instances
(replacing its arrays.y
) using&=
:s = s1 & s2 s &= s1
- audiomath.TestSound(*channels)
Return an 8-channel
Sound
object, read from awav
file that is bundled withaudiomath
, suitable for testing multi-channel sound output devices. Optionally, you can select particular channels using the same argument conventions as theIsolateChannels()
method. For example, you could choose to return only the first two channels, as follows:s = TestSound('12')
- audiomath.ToneTest(freq=441, amplitude=0.1, nChannels=2, waveform=<function SineWave>, **kwargs)
This diagnostic test function creates a looped
Player
whoseSound
is a 1-second pure tone, sampled at the preferred frequency of thePlayer
(or thefs
keyword argument passed through to it, if you want to specify that). Use an integer frequencyfreq
to ensure glitch-free looping—any remaining glitches and crackles you hear when youPlay()
are likely the result of buffer underflows in the audio driver. This can happen if the same Python process that is driving the sound is also working too hard on other tasks: higher latencies protect against this.