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.Soundfor manipulating, visualizing and writing sounds.audiomath.Synthfor functionally generating sounds on-the-fly instead of storing them as static arrays.audiomath.Playerfor playing sounds.audiomath.Queuefor managing playlists (everyPlayerautomatically has one of these).audiomath.Faderandaudiomath.Delayare examples of “dynamic” callable objects that can be assigned toPlayerproperties.audiomath.Recorderfor recording sounds—see also theRecord()function.audiomath.ffmpegfor streaming audio data to file via the auxiliary third-party utility ffmpeg, from https://ffmpeg.orgaudiomath.soxfor 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
Soundinstance containing a new array.You can also concatenate
Soundinstances using the%operator, and can modifying an existingSoundinstances(replacing its arrays.y) using%=:s = s1 % s2 s %= s1
Note that, in the above examples, either
s1ors2may also be a numeric scalar:s %= 0.5appends half a second of silence tos.
- audiomath.MakeFall(duration, fs=1000, hann=False)
Return a single-channel
Soundobject of the specifieddurationin seconds at the specified sampling frequencyfsin Hz, containing a “fade-out” envelope (i.e. a ramp from 1 to 0). Ifhannis 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
Soundobject of the specifieddurationin seconds at the specified sampling frequencyfsin 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
Soundobject of the specifieddurationin seconds at the specified sampling frequencyfsin Hz, containing a constantdcvalue.See also:
MakeRise(),MakeFall(),MakeHannWindow()
- audiomath.MakeRise(duration, fs=1000, hann=False)
Return a single-channel
Soundobject of the specifieddurationin seconds at the specified sampling frequencyfsin Hz, containing a “fade-in” envelope (i.e. a ramp from 0 to 1). Ifhannis True, use a raised-cosine profile instead of a linear ramp.See also:
MakePlateau(),MakeFall(),MakeHannWindow()
- audiomath.QueueTest()
Construct and return an example
Queuecontaining exampleSoundinstances. Initialize aPlayerwith this to test management of multiple tracks by thePlayerclass.
- audiomath.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.
- audiomath.Stack(*args)
Stack multiple Sound objects to make a new multi-channel
Soundobject (appending silence to the end of each argument where necessary to equalize lengths).You can also stack channels of
Soundinstances using the&operator, and can modifying an existingSoundinstances(replacing its arrays.y) using&=:s = s1 & s2 s &= s1
- audiomath.TestSound(*channels)
Return an 8-channel
Soundobject, read from awavfile 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
PlayerwhoseSoundis a 1-second pure tone, sampled at the preferred frequency of thePlayer(or thefskeyword argument passed through to it, if you want to specify that). Use an integer frequencyfreqto 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.