Tone.js/test/source/TickSource.js

435 lines
14 KiB
JavaScript
Raw Normal View History

define(["Test", "Tone/source/TickSource", "helper/Offline", "helper/Basic"], function(Test, TickSource, Offline, BasicTests) {
describe("TickSource", function(){
BasicTests(TickSource);
context("Constructor", function(){
it("can pass in the frequency", function(){
var source = new TickSource(2);
expect(source.frequency.value).to.equal(2);
source.dispose();
});
});
context("Ticks", function(){
it("ticks are 0 before started", function(){
var source = new TickSource();
expect(source.ticks).to.equal(0);
source.dispose();
});
it("ticks increment at the rate of the frequency after started", function(){
return Offline(function(){
var source = new TickSource();
source.start(0);
return function(time){
expect(source.ticks).to.be.closeTo(time, 0.1);
};
}, 0.5);
});
it("ticks return to 0 after stopped", function(){
return Offline(function(){
var source = new TickSource(2);
source.start(0).stop(0.4);
return function(time){
if (time < 0.4){
expect(source.ticks).to.be.closeTo(2*time, 0.01);
} else {
expect(source.ticks).to.be.equal(0);
}
};
}, 0.5);
});
it("ticks restart at 0 when started after stop", function(){
var source = new TickSource(3);
source.start(0).stop(1).start(2);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(1.5, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(3, 0.01);
source.dispose();
});
it("handles multiple starts/stops", function(){
var source = new TickSource(1);
source.start(0).stop(0.3).start(0.4).stop(0.5).start(0.6);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.1)).to.be.closeTo(0.1, 0.01);
expect(source.getTicksAtTime(0.2)).to.be.closeTo(0.2, 0.01);
expect(source.getTicksAtTime(0.3)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.4)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.6)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.7)).to.be.closeTo(0.1, 0.01);
expect(source.getTicksAtTime(0.8)).to.be.closeTo(0.2, 0.01);
source.dispose();
});
it("can get ticks when started with an offset", function(){
var source = new TickSource(1);
source.start(0, 2).stop(3).start(5, 1);
expect(source.getTicksAtTime(0)).to.be.closeTo(2, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(3, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(4, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(4)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(5)).to.be.closeTo(1, 0.01);
expect(source.getTicksAtTime(6)).to.be.closeTo(2, 0.01);
source.dispose();
});
it("can set multiple setTicksAtTime", function(){
var source = new TickSource(1);
source.start(0, 1).stop(3);
source.setTicksAtTime(1, 4);
source.stop(5).start(6);
source.setTicksAtTime(2, 7);
expect(source.getTicksAtTime(0)).to.be.closeTo(1, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(2, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(3, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(3.5)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(4)).to.be.closeTo(1, 0.01);
expect(source.getTicksAtTime(5)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(6)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(6.5)).to.be.closeTo(0.5, 0.01);
expect(source.getTicksAtTime(7)).to.be.closeTo(2, 0.01);
source.dispose();
});
});
context("forEachTickBetween", function(){
it("invokes a callback function when started", function(){
var source = new TickSource(1);
source.start(0);
var wasCalled = false;
source.forEachTickBetween(0, 2, function(){
wasCalled = true;
});
expect(wasCalled).to.be.true;
source.dispose();
});
it("does not invoke callback when not overlapping with tick", function(){
var source = new TickSource(1);
source.start(0);
var wasCalled = false;
source.forEachTickBetween(1.1, 2, function(){
wasCalled = true;
});
expect(wasCalled).to.be.false;
source.dispose();
});
it("iterates only at times when the state is 'started'", function(){
var source = new TickSource(4);
source.start(0.2).stop(2).start(3.5).stop(5);
var iterations = 0;
var expectedTimes = [1.2, 1.45, 1.7, 1.95, 3.5, 3.75, 4, 4.25, 4.5, 4.75];
var expectedTicks = [4, 5, 6, 7, 0, 1, 2, 3, 4, 5];
source.forEachTickBetween(1, 7, function(time, ticks){
expect(time).to.be.closeTo(expectedTimes[iterations], 0.001);
expect(ticks).to.equal(expectedTicks[iterations]);
iterations++;
});
expect(iterations).to.equal(expectedTimes.length);
source.dispose();
});
it("can start at time = 0", function(){
var source = new TickSource(1);
source.start(0);
var iterations = 0;
source.forEachTickBetween(0, 0.1, function(){
iterations++;
});
expect(iterations).to.equal(1);
source.dispose();
});
it("can throw an error in the callback but still invokes all loops", function(){
var source = new TickSource(1);
source.start(0);
expect(function(){
source.forEachTickBetween(0, 3, function(){
throw new Error("should throw");
});
}).throws(Error);
source.dispose();
});
it("iterates once per tick", function(){
var source = new TickSource(1);
source.start(0.5);
var iterations = 0;
source.forEachTickBetween(0, 2, function(){
iterations++;
});
expect(iterations).to.equal(2);
source.dispose();
});
it("passes time and tick into the callback", function(){
var source = new TickSource(2);
source.start(0.5);
var iterations = 0;
var times = [0.5, 1.0, 1.5];
source.forEachTickBetween(0, 2, function(time, ticks){
expect(times[ticks]).to.be.closeTo(time, 0.001);
iterations++;
});
expect(iterations).to.equal(3);
source.dispose();
});
it("ticks = 0 when restarted", function(){
var source = new TickSource(1);
source.start(0.5).stop(1).start(2);
var iterations = 0;
var expectedTicks = [0, 0, 1];
var expectedTimes = [0.5, 2, 3];
source.forEachTickBetween(0, 3.1, function(time, ticks){
expect(time).to.be.closeTo(expectedTimes[iterations], 0.001);
expect(ticks).to.equal(expectedTicks[iterations]);
iterations++;
});
expect(iterations).to.equal(expectedTicks.length);
source.dispose();
});
it("handles start and stop", function(){
var source = new TickSource(2);
source.start(0.5).stop(2);
var iterations = 0;
var times = [0.5, 1.0, 1.5];
source.forEachTickBetween(0, 3, function(time, ticks){
expect(times[ticks]).to.be.closeTo(time, 0.001);
iterations++;
});
expect(iterations).to.equal(3);
source.dispose();
});
it("handles multiple start and stop", function(){
var source = new TickSource(2);
source.start(0.5).stop(2).start(2.5).stop(4.1);
var iterations = 0;
var times = [0.5, 1.0, 1.5, 2.5, 3, 3.5, 4];
source.forEachTickBetween(0, 10, function(time){
expect(times[iterations]).to.be.closeTo(time, 0.001);
iterations++;
});
expect(iterations).to.equal(times.length);
source.dispose();
});
it("works with a frequency ramp", function(){
var source = new TickSource(1);
source.frequency.setValueAtTime(1, 0);
source.frequency.linearRampToValueAtTime(4, 1);
source.start(0.5);
var iterations = 0;
const times = [0.500, 0.833, 1.094, 1.344, 1.594, 1.844];
source.forEachTickBetween(0, 2, function(time, ticks){
expect(time).to.be.closeTo(times[ticks], 0.001);
iterations++;
});
expect(iterations).to.equal(times.length);
source.dispose();
});
it("can start with a tick offset", function(){
var source = new TickSource(10);
source.start(0.5, 5);
var iterations = 0;
source.forEachTickBetween(0, 2, function(time, ticks){
expect(ticks).to.be.gte(5);
iterations++;
});
expect(iterations).to.equal(15);
source.dispose();
});
it("can handle multiple starts with tick offsets", function(){
var source = new TickSource(1);
source.start(0.5, 10).stop(2).start(3, 1);
var iterations = 0;
var expectedTimes = [0.5, 1.5, 3];
var expectedTicks = [10, 11, 1];
source.forEachTickBetween(0, 4, function(time, ticks){
expect(time).to.be.closeTo(expectedTimes[iterations], 0.001);
expect(ticks).to.equal(expectedTicks[iterations]);
iterations++;
});
expect(iterations).to.equal(expectedTicks.length);
source.dispose();
});
it("can set ticks after start", function(){
var source = new TickSource(1);
source.start(0.4, 3);
source.setTicksAtTime(1, 1.4);
source.setTicksAtTime(10, 3);
var iterations = 0;
var expectedTicks = [3, 1, 2, 10];
source.forEachTickBetween(0, 4, function(time, ticks){
expect(ticks).to.equal(expectedTicks[iterations]);
iterations++;
});
expect(iterations).to.equal(expectedTicks.length);
source.dispose();
});
it("can pass in the frequency", function(){
var source = new TickSource(20);
source.start(0.5);
var iterations = 0;
var lastTime = 0.5;
source.forEachTickBetween(0.51, 2.01, function(time){
expect(time - lastTime).to.be.closeTo(0.05, 0.001);
lastTime = time;
iterations++;
});
expect(iterations).to.equal(30);
source.dispose();
});
it("can iterate from later in the timeline", function(){
var source = new TickSource(1);
source.start(0.2);
var iterations = 0;
source.forEachTickBetween(100, 101, function(time, ticks){
expect(ticks).to.equal(100);
expect(time).to.be.closeTo(100.2, 0.001);
iterations++;
});
expect(iterations).to.equal(1);
source.dispose();
});
});
context("Seconds", function(){
it("get the elapsed time in seconds", function(){
return Offline(function(){
var source = new TickSource(1).start(0);
return function(time){
expect(source.seconds).to.be.closeTo(time, 0.01);
};
}, 2);
});
it("seconds is 0 before starting", function(){
var source = new TickSource(1);
expect(source.seconds).to.be.closeTo(0, 0.001);
source.dispose();
});
it("can set the seconds", function(){
var source = new TickSource(1);
expect(source.seconds).to.be.closeTo(0, 0.001);
source.dispose();
});
it("get the elapsed time in seconds when starting in the future", function(){
return Offline(function(){
var source = new TickSource(1).start(0.1);
return function(time){
if (time < 0.1){
expect(source.seconds).to.be.closeTo(0, 0.001);
} else {
expect(source.seconds).to.be.closeTo(time - 0.1, 0.01);
}
};
}, 2);
});
it("handles multiple starts and stops", function(){
return Offline(function(){
var source = new TickSource(1).start(0).stop(0.5).start(1).stop(1.5);
expect(source.getSecondsAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getSecondsAtTime(0.4)).to.be.closeTo(0.4, 0.01);
expect(source.getSecondsAtTime(0.5)).to.be.closeTo(0, 0.01);
expect(source.getSecondsAtTime(0.9)).to.be.closeTo(0, 0.01);
expect(source.getSecondsAtTime(1)).to.be.closeTo(0, 0.01);
expect(source.getSecondsAtTime(1.4)).to.be.closeTo(0.4, 0.01);
expect(source.getSecondsAtTime(1.5)).to.be.closeTo(0, 0.01);
}, 2);
});
});
context("Frequency", function(){
it("can automate frequency with setValueAtTime", function(){
var source = new TickSource(1);
source.start(0).stop(0.3).start(0.4).stop(0.5).start(0.6);
source.frequency.setValueAtTime(2, 0.3);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.1)).to.be.closeTo(0.1, 0.01);
expect(source.getTicksAtTime(0.2)).to.be.closeTo(0.2, 0.01);
expect(source.getTicksAtTime(0.3)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.4)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.45)).to.be.closeTo(0.1, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.6)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.7)).to.be.closeTo(0.2, 0.01);
expect(source.getTicksAtTime(0.8)).to.be.closeTo(0.4, 0.01);
source.dispose();
});
it("can automate frequency with linearRampToValueAtTime", function(){
var source = new TickSource(1);
source.start(0).stop(1).start(2);
source.frequency.linearRampToValueAtTime(2, 2);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(0.56, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(2, 0.01);
source.dispose();
});
it("can automate frequency with exponentialRampToValueAtTime", function(){
var source = new TickSource(1);
source.start(0).stop(1).start(2).stop(5);
source.frequency.exponentialRampToValueAtTime(4, 2);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(0.6, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(4, 0.01);
expect(source.getTicksAtTime(4)).to.be.closeTo(8, 0.01);
source.dispose();
});
it("can automate frequency with setTargetAtTime", function(){
var source = new TickSource(1);
source.start(0).stop(1).start(2).stop(5);
source.frequency.setTargetAtTime(2, 1, 0.5);
expect(source.getTicksAtTime(0)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(0.5)).to.be.closeTo(0.5, 0.01);
expect(source.getTicksAtTime(1)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(2)).to.be.closeTo(0, 0.01);
expect(source.getTicksAtTime(3)).to.be.closeTo(1.86, 0.01);
expect(source.getTicksAtTime(4)).to.be.closeTo(3.73, 0.01);
expect(source.getTicksAtTime(5)).to.be.closeTo(0, 0.01);
source.dispose();
});
});
});
});