Merge pull request #17 from Calder/master
Added support for multiple consecutive linear ramps.
This commit is contained in:
commit
00e98a2b88
2 changed files with 76 additions and 19 deletions
32
examples/ramp.jl
Normal file
32
examples/ramp.jl
Normal 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)
|
||||||
|
|
||||||
|
|
||||||
|
println("""
|
||||||
|
*
|
||||||
|
* * *
|
||||||
|
* * * * *
|
||||||
|
* * * * * * *
|
||||||
|
* * * * * * * * *
|
||||||
|
* * * * * * * * * * *
|
||||||
|
""")
|
||||||
|
wave = SinOsc(440) * LinRamp([0.0, 1.0, 0.0], [2.0, 2.0])
|
||||||
|
play(wave)
|
||||||
|
sleep(4)
|
||||||
|
stop(wave)
|
61
src/nodes.jl
61
src/nodes.jl
|
@ -276,40 +276,65 @@ 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
|
|
||||||
|
duration::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, sum(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)
|
# Resize buffer if (1) it's too small or (2) we've hit the end of the ramp
|
||||||
|
ramp_samples = int(node.duration * info.sample_rate)
|
||||||
block_samples = min(ramp_samples, info.buf_size)
|
block_samples = min(ramp_samples, info.buf_size)
|
||||||
if length(node.buf) != block_samples
|
if length(node.buf) != block_samples
|
||||||
resize!(node.buf, block_samples)
|
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 <= length(node.buf) && 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 <= length(node.buf)
|
||||||
val += inc
|
node.buf[i] = node.key_samples[1]
|
||||||
|
node.key_samples[1] += ds
|
||||||
|
node.key_durations[1] -= dt
|
||||||
|
node.duration -= 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
|
return node.buf
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue