diff --git a/src/nodes.jl b/src/nodes.jl index e640a00..f4f5002 100644 --- a/src/nodes.jl +++ b/src/nodes.jl @@ -54,15 +54,21 @@ end function render(node::SinOscRenderer{AudioNode}, device_input::AudioBuf, info::DeviceInfo) - freq = render(node.freq, device_input, info) + freq = render(node.freq, device_input, info)::AudioBuf block_size = min(length(freq), info.buf_size) - outbuf = Array(AudioSample, block_size) + if(length(node.buf) != block_size) + resize!(node.buf, block_size) + end + outbuf = node.buf - phase = node.phase - dt = 1/(info.sample_rate) - for i in 1:block_size + phase::Float32 = node.phase + pi2::Float32 = 2pi + phase_step::Float32 = 2pi/(info.sample_rate) + i::Int = 1 + while i <= block_size outbuf[i] = sin(phase) - phase += 2pi*dt*freq[i] + phase = (phase + phase_step*freq[i]) % pi2 + i += 1 end node.phase = phase return outbuf diff --git a/test/test_nodes.jl b/test/test_nodes.jl index 4697d95..9b6a1dc 100644 --- a/test/test_nodes.jl +++ b/test/test_nodes.jl @@ -55,7 +55,7 @@ render_output = render(mix, dev_input, test_info) @test render_output == AudioSample[] # TODO: I think we can do better than this -const FLOAT_THRESH = 1e-9 +const MSE_THRESH = 1e-7 info("Testing SinOSC...") freq = 440 @@ -64,34 +64,36 @@ t = linspace(0, 1, test_info.sample_rate+1) test_vect = convert(AudioBuf, sin(2pi * t * freq)) osc = SinOsc(freq) render_output = render(osc, dev_input, test_info) -@test mse(render_output, test_vect[1:test_info.buf_size]) < FLOAT_THRESH +@test mse(render_output, test_vect[1:test_info.buf_size]) < MSE_THRESH render_output = render(osc, dev_input, test_info) @test mse(render_output, - test_vect[test_info.buf_size+1:2*test_info.buf_size]) < FLOAT_THRESH + test_vect[test_info.buf_size+1:2*test_info.buf_size]) < MSE_THRESH @test 200 > (@allocated render(osc, dev_input, test_info)) stop(osc) render_output = render(osc, dev_input, test_info) @test render_output == AudioSample[] -#info("Testing SinOsc with signal input") -#t = linspace(0, 1, test_info.sample_rate+1) -#f = 440 .- t .* (440-110) -#dt = 1 / test_info.sample_rate -## NOTE - this treats the phase as constant at each sample, which isn't strictly -## true. Unfortunately doing this correctly requires knowing more about the -## modulating signal and doing the real integral -#phase = cumsum(2pi * dt .* f) -#unshift!(phase, 0) -#expected = convert(AudioBuf, sin(phase)) -# -#freq = LinRamp(440, 110, 1) -#osc = SinOsc(freq) -#render_output = render(osc, dev_input, test_info) -#@test mse(render_output, expected[1:test_info.buf_size]) < FLOAT_THRESH -#render_output = render(osc, dev_input, test_info) -#@test mse(render_output, -# expected[test_info.buf_size+1:2*test_info.buf_size]) < FLOAT_THRESH -##@test 400 > (@allocated render(osc, dev_input, test_info)) +info("Testing SinOsc with signal input") +t = linspace(0, 1, test_info.sample_rate+1) +f = 440 .- t .* (440-110) +dt = 1 / test_info.sample_rate +# NOTE - this treats the phase as constant at each sample, which isn't strictly +# true. Unfortunately doing this correctly requires knowing more about the +# modulating signal and doing the real integral +phase = cumsum(2pi * dt .* f) +unshift!(phase, 0) +expected = convert(AudioBuf, sin(phase)) + +freq = LinRamp(440, 110, 1) +osc = SinOsc(freq) +render_output = render(osc, dev_input, test_info) +@test mse(render_output, expected[1:test_info.buf_size]) < MSE_THRESH +render_output = render(osc, dev_input, test_info) +@test mse(render_output, + expected[test_info.buf_size+1:2*test_info.buf_size]) < MSE_THRESH +# give a bigger budget here because we're rendering 2 nodes +println("alloc: ", @allocated render(osc, dev_input, test_info)) +@test 500 > (@allocated render(osc, dev_input, test_info)) info("Testing ArrayPlayer...") v = rand(AudioSample, 44100) @@ -121,8 +123,8 @@ info("Testing LinRamp...") ramp = LinRamp(0.25, 0.80, 1) expected = convert(AudioBuf, linspace(0.25, 0.80, test_info.sample_rate+1)) render_output = render(ramp, dev_input, test_info) -@test mse(render_output, expected[1:test_info.buf_size]) < FLOAT_THRESH +@test mse(render_output, expected[1:test_info.buf_size]) < MSE_THRESH render_output = render(ramp, dev_input, test_info) @test mse(render_output, - expected[(test_info.buf_size+1):(2*test_info.buf_size)]) < FLOAT_THRESH + expected[(test_info.buf_size+1):(2*test_info.buf_size)]) < MSE_THRESH @test 300 > (@allocated render(ramp, dev_input, test_info))