adds ability to wait for an AudioNode

This commit is contained in:
Spencer Russell 2014-01-13 19:19:56 -05:00
parent 83c4199096
commit 22dba358b8
3 changed files with 41 additions and 18 deletions

View file

@ -33,7 +33,7 @@ include("sndfile.jl")
# Play an AudioNode by adding it as an input to the root mixer node # Play an AudioNode by adding it as an input to the root mixer node
function play(node::AudioNode, stream::AudioStream) function play(node::AudioNode, stream::AudioStream)
node.active = true activate(node)
add_input(stream.mixer, node) add_input(stream.mixer, node)
return node return node
end end
@ -76,8 +76,27 @@ function play{T <: Unsigned}(arr::Array{T}, args...)
end end
function stop(node::AudioNode) function stop(node::AudioNode)
deactivate(node)
node
end
function activate(node::AudioNode)
node.active = true
end
function deactivate(node::AudioNode)
node.active = false node.active = false
return node notify(node.deactivate_cond)
end
function is_active(node::AudioNode)
node.active
end
function Base.wait(node::AudioNode)
if is_active(node)
wait(node.deactivate_cond)
end
end end
end # module AudioIO end # module AudioIO

View file

@ -6,11 +6,12 @@ export SinOsc, AudioMixer, ArrayPlayer, AudioInput
type SinOsc <: AudioNode type SinOsc <: AudioNode
active::Bool active::Bool
deactivate_cond::Condition
freq::Real freq::Real
phase::FloatingPoint phase::FloatingPoint
function SinOsc(freq::Real) function SinOsc(freq::Real)
new(false, freq, 0.0) new(false, Condition(), freq, 0.0)
end end
end end
@ -18,7 +19,7 @@ function render(node::SinOsc, device_input::AudioBuf, info::DeviceInfo)
phase = AudioSample[1:info.buf_size] * 2pi * node.freq / info.sample_rate phase = AudioSample[1:info.buf_size] * 2pi * node.freq / info.sample_rate
phase += node.phase phase += node.phase
node.phase = phase[end] node.phase = phase[end]
return sin(phase), node.active return sin(phase), is_active(node)
end end
#### AudioMixer #### #### AudioMixer ####
@ -31,6 +32,7 @@ const MAX_MIXER_INPUTS = 32
type AudioMixer <: AudioNode type AudioMixer <: AudioNode
active::Bool active::Bool
deactivate_cond::Condition
mix_inputs::Array{MaybeAudioNode} mix_inputs::Array{MaybeAudioNode}
function AudioMixer{T <: AudioNode}(mix_inputs::Array{T}) function AudioMixer{T <: AudioNode}(mix_inputs::Array{T})
@ -39,7 +41,7 @@ type AudioMixer <: AudioNode
for (i, node) in enumerate(mix_inputs) for (i, node) in enumerate(mix_inputs)
input_array[i] = node input_array[i] = node
end end
new(false, input_array) new(false, Condition(), input_array)
end end
function AudioMixer() function AudioMixer()
@ -87,7 +89,7 @@ function render(node::AudioMixer, device_input::AudioBuf, info::DeviceInfo)
end end
end end
end end
return mix_buffer, node.active return mix_buffer, is_active(node)
end end
#### Array Player #### #### Array Player ####
@ -96,11 +98,12 @@ end
type ArrayPlayer <: AudioNode type ArrayPlayer <: AudioNode
active::Bool active::Bool
deactivate_cond::Condition
arr::AudioBuf arr::AudioBuf
arr_index::Int arr_index::Int
function ArrayPlayer(arr::AudioBuf) function ArrayPlayer(arr::AudioBuf)
new(false, arr, 1) new(false, Condition(), arr, 1)
end end
end end
@ -111,13 +114,12 @@ function render(node::ArrayPlayer, device_input::AudioBuf, info::DeviceInfo)
range_end = min(i + info.buf_size-1, length(node.arr)) range_end = min(i + info.buf_size-1, length(node.arr))
output = node.arr[i:range_end] output = node.arr[i:range_end]
if length(output) < info.buf_size if length(output) < info.buf_size
# we're finished with the array, pad with zeros and clear our active # we're finished with the array, pad with zeros and deactivate
# flag
output = vcat(output, zeros(AudioSample, info.buf_size - length(output))) output = vcat(output, zeros(AudioSample, info.buf_size - length(output)))
node.active = false deactivate(node)
end end
node.arr_index = range_end + 1 node.arr_index = range_end + 1
return output, node.active return output, is_active(node)
end end
#### AudioInput #### #### AudioInput ####
@ -126,14 +128,15 @@ end
type AudioInput <: AudioNode type AudioInput <: AudioNode
active::Bool active::Bool
deactivate_cond::Condition
channel::Int channel::Int
function AudioInput(channel::Int) function AudioInput(channel::Int)
new(false, channel) new(false, Condition(), channel)
end end
end end
function render(node::AudioInput, device_input::AudioBuf, info::DeviceInfo) function render(node::AudioInput, device_input::AudioBuf, info::DeviceInfo)
@assert size(device_input, 1) == info.buf_size @assert size(device_input, 1) == info.buf_size
return device_input[:, node.channel], node.active return device_input[:, node.channel], is_active(node)
end end

View file

@ -91,10 +91,11 @@ end
type FilePlayer <: AudioNode type FilePlayer <: AudioNode
active::Bool active::Bool
deactivate_cond::Condition
file::AudioFile file::AudioFile
function FilePlayer(file::AudioFile) function FilePlayer(file::AudioFile)
node = new(false, file) node = new(false, Condition(), file)
finalizer(node, node -> close(node.file)) finalizer(node, node -> close(node.file))
return node return node
end end
@ -110,16 +111,16 @@ function render(node::FilePlayer, device_input::AudioBuf, info::DeviceInfo)
audio = read(node.file, info.buf_size, AudioSample) audio = read(node.file, info.buf_size, AudioSample)
if audio == Nothing if audio == Nothing
node.active = false deactivate(node)
return zeros(AudioSample, info.buf_size), node.active return zeros(AudioSample, info.buf_size), is_active(node)
end end
# if the file is stereo, mix the two channels together # if the file is stereo, mix the two channels together
if node.file.sfinfo.channels == 2 if node.file.sfinfo.channels == 2
return (audio[1, :] / 2) + (audio[2, :] / 2), node.active return (audio[1, :] / 2) + (audio[2, :] / 2), is_active(node)
end end
return audio, node.active return audio, is_active(node)
end end
function play(filename::String, args...) function play(filename::String, args...)