adds test for SinOsc and updates README

This commit is contained in:
Spencer Russell 2013-12-30 03:29:43 -08:00
parent 210dcf66e2
commit 6516537985
5 changed files with 79 additions and 7 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)