adds test for SinOsc and updates README
This commit is contained in:
parent
210dcf66e2
commit
6516537985
5 changed files with 79 additions and 7 deletions
64
README.md
64
README.md
|
@ -3,16 +3,68 @@ PortAudio.jl
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/ssfrr/PortAudio.jl.png)](https://travis-ci.org/ssfrr/PortAudio.jl)
|
[![Build Status](https://travis-ci.org/ssfrr/PortAudio.jl.png)](https://travis-ci.org/ssfrr/PortAudio.jl)
|
||||||
|
|
||||||
This is a Julia interface to PortAudio. It is currently under heavy development
|
This is a Julia interface to PortAudio. It is currently under heavy
|
||||||
and certainly not even close to being useful.
|
development. The API could change, there will be bugs, there are important
|
||||||
|
missing features.
|
||||||
|
|
||||||
If you want to try it anyways, from your julia console:
|
If you want to try it anyways, from your julia console:
|
||||||
|
|
||||||
julia> Pkg.clone("https://github.com/ssfrr/PortAudio.jl.git")
|
julia> Pkg.clone("https://github.com/ssfrr/PortAudio.jl.git")
|
||||||
julia> Pkg.build("PortAudio")
|
julia> Pkg.build("PortAudio")
|
||||||
|
|
||||||
Right now you can just play and stop some sin tones in your speakers:
|
Basic Array Playback
|
||||||
|
--------------------
|
||||||
|
|
||||||
julia> using PortAudio
|
Arrays in various formats can be played through your soundcard. Currently the
|
||||||
julia> play_sin()
|
native format that is delivered to the PortAudio backend is `Float32` in the
|
||||||
julia> stop_sin()
|
range of `[-1, 1]`. Arrays in other sizes of float are `convert`ed. Arrays
|
||||||
|
in Signed or Unsigned Integer types are scaled so that the full range is
|
||||||
|
mapped to `[-1, 1]` floating point values.
|
||||||
|
|
||||||
|
To play a 1-second burst of noise:
|
||||||
|
|
||||||
|
julia> v = rand(44100) * 0.1
|
||||||
|
julia> play(v)
|
||||||
|
|
||||||
|
AudioNodes
|
||||||
|
----------
|
||||||
|
|
||||||
|
In addition to the basic `play` function you can create more complex networks
|
||||||
|
of `AudioNode`s in a render chain. In fact, when using the basic `play` to play
|
||||||
|
an Array, behind the scenes an instance of the `ArrayPlayer` type is created
|
||||||
|
and added to the master `AudioMixer` inputs.
|
||||||
|
|
||||||
|
To explictly do the same as above:
|
||||||
|
|
||||||
|
julia> v = rand(44100) * 0.1
|
||||||
|
julia> player = ArrayPlayer(v)
|
||||||
|
julia> play(player)
|
||||||
|
|
||||||
|
To generate 2 sin tones:
|
||||||
|
|
||||||
|
julia> osc1 = SinOsc(440)
|
||||||
|
julia> osc2 = SinOsc(660)
|
||||||
|
julia> play(osc1)
|
||||||
|
julia> play(osc2)
|
||||||
|
|
||||||
|
All AudioNodes should implement a `render` function that can be called to
|
||||||
|
retreive the next block of audio.
|
||||||
|
|
||||||
|
AudioStreams
|
||||||
|
------------
|
||||||
|
|
||||||
|
AudioStreams represent a destination for audio, such as the sound card. The
|
||||||
|
`play` function attaches AudioNodes to the default stream unless a stream is
|
||||||
|
given as the 2nd argument.
|
||||||
|
|
||||||
|
AudioStream is an abstract type, which currently has a PortAudioStream subtype
|
||||||
|
that writes to the sound card, and a TestAudioStream that is used in the unit
|
||||||
|
tests.
|
||||||
|
|
||||||
|
Currently only 1 stream at a time is supported so there's no reason to provide
|
||||||
|
an explicit stream to the `play` function. The stream has a root mixer field
|
||||||
|
which is an instance of the `AudioMixer` type, so that multiple `AudioNode`s
|
||||||
|
can be heard at the same time. Whenever a new frame of audio is needed by the
|
||||||
|
sound card, the stream calls the `render` method on the root audio mixer, which
|
||||||
|
will in turn call the `render` methods on any input `AudioNode`s that are set
|
||||||
|
up as inputs.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
module PortAudio
|
module PortAudio
|
||||||
|
|
||||||
|
# export the basic API
|
||||||
export play
|
export play
|
||||||
export SinOsc, AudioMixer, ArrayPlayer, AudioInput
|
|
||||||
|
|
||||||
typealias PaTime Cdouble
|
typealias PaTime Cdouble
|
||||||
typealias PaError Cint
|
typealias PaError Cint
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
export SinOsc, AudioMixer, ArrayPlayer, AudioInput
|
||||||
|
|
||||||
#### SinOsc ####
|
#### SinOsc ####
|
||||||
|
|
||||||
# Generates a sin tone at the given frequency
|
# Generates a sin tone at the given frequency
|
||||||
|
|
|
@ -59,3 +59,12 @@ test_stream = TestAudioStream()
|
||||||
player = play(ui8, test_stream)
|
player = play(ui8, test_stream)
|
||||||
@test_approx_eq(process(test_stream)[1:255],
|
@test_approx_eq(process(test_stream)[1:255],
|
||||||
convert(PortAudio.AudioBuf, linspace(-1.0, 1.0, 255)))
|
convert(PortAudio.AudioBuf, linspace(-1.0, 1.0, 255)))
|
||||||
|
|
||||||
|
|
||||||
|
#info("Testing AudioNode Stopping...")
|
||||||
|
#test_stream = TestAudioStream()
|
||||||
|
#node = SinOsc(440)
|
||||||
|
#play(node, test_stream)
|
||||||
|
#process(test_stream)
|
||||||
|
#stop(node)
|
||||||
|
#@test process(test_stream) == zeros(PortAudio.AudioSample, TEST_BUF_SIZE)
|
||||||
|
|
|
@ -34,3 +34,12 @@ test2 = TestNode()
|
||||||
mix = AudioMixer([test1, test2])
|
mix = AudioMixer([test1, test2])
|
||||||
@test PortAudio.render(mix, dev_input, test_info) == 2 * PortAudio.AudioSample[1:test_info.buf_size]
|
@test PortAudio.render(mix, dev_input, test_info) == 2 * PortAudio.AudioSample[1:test_info.buf_size]
|
||||||
|
|
||||||
|
info("Testing SinOSC...")
|
||||||
|
freq = 440
|
||||||
|
t = linspace(1 / test_info.sample_rate,
|
||||||
|
test_info.buf_size / test_info.sample_rate,
|
||||||
|
test_info.buf_size)
|
||||||
|
test_vect = convert(PortAudio.AudioBuf, sin(2pi * t * freq))
|
||||||
|
osc = SinOsc(freq)
|
||||||
|
rendered = PortAudio.render(osc, dev_input, test_info)
|
||||||
|
@test_approx_eq(rendered, test_vect)
|
||||||
|
|
Loading…
Reference in a new issue