NOTE: This package is being renamed and move to a new repository SignalOperators. This version of the repository is for Julia 0.6 and lower.
Sounds is a Julia package that aims to provide a clean interface for generating and manipulating sounds.
using Sounds
# create a pure tone 20 dB below a power 1 signal
sound1 = tone(1kHz,5s) |> normpower |> amplify(-20dB)
# load a sound from a file, matching the power to that of sound1
sound2 = Sound("mysound.wav") |> normpower |> amplify(-20dB)
# create a 1kHz sawtooth wave
sound3 = Sound(t -> 1000t .% 1,2s) |> normpower
# create a 5Hz amplitude modulated noise
sound4 = noise(2s) |> envelope(tone(5Hz,2s)) |> normpower
# create 1kHz tone surrounded by a notch noise
SNR = 5dB
x = tone(1kHz,1s) |> ramp |> normpower |> amplify(-20dB + SNR)
y = noise(1s) |> bandstop(0.5kHz,2kHz) |> normpower |>
amplify(-20dB)
scene = mix(x,y)
Once you've created a sound you can save it or use PortAudio.jl to play it.
sound1 = tone(1kHz,5s) |> normpower |> amplify(-20dB)
save("puretone.wav",sound1)
using PortAudio
play(sound1)
Sounds work much like arrays, and in addition to the normal ways of indexing an
array, you can access the channels by name (:left
and :right
) and you can
access time slices using Untiful.jl
values and IntervalSets.jl. For
example:
sound1[1s .. 2s,:left]
sound1[3s .. ends,:right]
sound1[200ms .. 500ms]
sound1[:right]
leftright(sound1[0s .. 1s,:left],sound2[1s .. 2s,:right])
Because sounds have well defined promotion semantics, when working with multiple sounds, things "just work". Specifically, if the sounds have a different number of channels, a different sampling rate or different bit rate, the sounds are first promoted to the highest fidelity representation, and then the given method is applied over the promoted representation.
See the documentation for a complete description of available methods.
There are two other ways you might represent sounds in Julia,
AxisArrays.jl and
SampledSignals.jl. A lot of
the ideas for this package came from these two packages (thanks!). Here are some
of the ways that a Sound
differs from these other solutions.
SampledSignals
vs. Sounds
:
SampledSignals
does not include the various sound manipulation routines available inSounds
. This was the primary motivation for the present package.Sound
objects were designed to make these manipulation routines easy to define.- In
SampledSignals
automatic conversion is handled with I/O sinks and sources. InSounds
, I use the standard type promotion mechanism. Sounds
uses more recent packages for representing units and intervals of time.SampledSignals
has a more ambitious scope, and seeks to represent many kinds of signals in multiple domains, not just sounds in their time-amplitude representation.
AxisArray
vs. Sounds
:
- An
AxisArray
must have its dimensions explicitly specified during construction.Sounds
knows what the axes for a sound should be. - There is no automatic promotion of the sample rate or channel number when using
an
AxisArray
. - The methods defined on an
AxisArray
are not defined for aSound
(e.g. axes, axisnames, etc...). - Unlike indexing into a
Sound
, there is noends
defined for anAxisArray
; you must explicitly calculate the duration of the array when indexing by time.
If you want to use either of these other packages with Sounds
, many of the
sound manipulation routines provided here are written generically enough to
handle any type (though some routines will promote the output to a Sound
). If
you construct a sound using this package you can easily convert it to one of
these other types, or vice versa, by calling an appropriate constructor.
(e.g. SampleBuf(tone(1kHz,1s))
, Sound(samplebuf)
, AxisArray(sound)
). Bear
in mind that SampledSignals
exports some symbols that conflict with Sounds
(e.g. last time I checked it uses an older approach for representing units and
exports conflicting symbosl for these units), so it is probably best to import
Sounds or SampledSignals and employ using
on the other.
I use this package all the time in other projects, so it should be pretty bug free. However, it is not yet well integrated into the rest of the ecosystem in Julia for working with audio. I'm in the process of thinking through how to do that with this issue.