Added support for consecutive linear ramps.

This commit is contained in:
Calder Coalson 2014-06-28 15:22:35 -05:00
parent 16857615d3
commit 4eb15ae29f
2 changed files with 75 additions and 22 deletions

32
examples/ramp.jl Normal file
View file

@ -0,0 +1,32 @@
using AudioIO
# Give PortAudio time to load
play([0])
sleep(2)
println("""
*
* *
* * *
* * * *
* * * * *
* * * * * *
""")
wave = SinOsc(440) * LinRamp(0.0,1.0,2.0)
play(wave)
sleep(2)
stop(wave)
print("""
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
""")
wave = SinOsc(440) * LinRamp([0.0,1.0,0.0], [2.0,2.0])
play(wave)
sleep(4)
stop(wave)

View file

@ -276,40 +276,61 @@ end
typealias AudioInput AudioNode{InputRenderer} typealias AudioInput AudioNode{InputRenderer}
export AudioInput export AudioInput
#### Ramp #### #### LinRamp ####
type LinRampRenderer <: AudioRenderer type LinRampRenderer <: AudioRenderer
start::AudioSample key_samples::Array{AudioSample}
finish::AudioSample key_durations::Array{Float32}
dur::Float32
buf::AudioBuf buf::AudioBuf
LinRampRenderer(start, finish, dur) = new(start, finish, dur, AudioSample[]) LinRampRenderer(start, finish, dur) = LinRampRenderer([start,finish], [dur])
LinRampRenderer(key_samples, key_durations) =
LinRampRenderer(
[convert(AudioSample,s) for s in key_samples],
[convert(Float32,d) for d in key_durations]
)
function LinRampRenderer(key_samples::Array{AudioSample}, key_durations::Array{Float32})
@assert length(key_samples) == length(key_durations) + 1
new(key_samples, key_durations, AudioSample[])
end
end end
typealias LinRamp AudioNode{LinRampRenderer} typealias LinRamp AudioNode{LinRampRenderer}
export LinRamp export LinRamp
function render(node::LinRampRenderer, device_input::AudioBuf, info::DeviceInfo) function render(node::LinRampRenderer, device_input::AudioBuf, info::DeviceInfo)
ramp_samples = int(node.dur * info.sample_rate) # Grow buffer if it's too small
block_samples = min(ramp_samples, info.buf_size) if length(node.buf) < info.buf_size
if length(node.buf) != block_samples resize!(node.buf, info.buf_size)
resize!(node.buf, block_samples)
end end
out_block = node.buf # Fill the buffer as long as there are more segments
dt::Float32 = 1/info.sample_rate
i::Int = 1 i::Int = 1
val::AudioSample = node.start while i <= info.buf_size && length(node.key_samples) > 1
inc::AudioSample = (node.finish - node.start) / ramp_samples
while i <= block_samples # Fill as much of the buffer as we can with the current segment
out_block[i] = val ds::Float32 = (node.key_samples[2] - node.key_samples[1]) / node.key_durations[1] / info.sample_rate
i += 1 while i <= info.buf_size
val += inc node.buf[i] = node.key_samples[1]
node.key_samples[1] += ds
node.key_durations[1] -= dt
i += 1
# Discard segment if we're finished
if node.key_durations[1] <= 0
if length(node.key_durations) > 1
node.key_durations[2] -= node.key_durations[1]
end
shift!(node.key_samples)
shift!(node.key_durations)
break
end
end
end end
node.dur -= block_samples / info.sample_rate
node.start = val
return out_block
end
return node.buf
end