import BasicTests from "helper/Basic"; import OscillatorNode from "Tone/source/OscillatorNode"; import Offline from "helper/Offline"; import Frequency from "Tone/type/Frequency"; import Test from "helper/Test"; import Meter from "helper/Meter"; import Supports from "helper/Supports"; import CompareToFile from "helper/CompareToFile"; describe("OscillatorNode", function(){ BasicTests(OscillatorNode); it("matches a file", function(){ return CompareToFile(function(){ var osc = new OscillatorNode().toMaster(); osc.start(0.5); }, "oscillatorNode.wav"); }); context("Constructor", function(){ it("can be constructed with a frequency and type", function(){ var osc0 = new OscillatorNode(330, "square"); expect(osc0.frequency.value).to.equal(330); osc0.dispose(); var osc1 = new OscillatorNode(Frequency(550), "sawtooth"); expect(osc1.frequency.value).to.equal(550); osc1.dispose(); var osc2 = new OscillatorNode("A3", "triangle"); expect(osc2.frequency.value).to.equal(220); osc2.dispose(); }); it("can be constructed with no arguments", function(){ var osc = new OscillatorNode(); expect(osc.frequency.value).to.equal(440); expect(osc.detune.value).to.equal(0); expect(osc.type).to.equal("sine"); osc.dispose(); }); it("can be constructed with an options object", function(){ var osc = new OscillatorNode({ type : "square", detune : -20, frequency : 123 }); expect(osc.frequency.value).to.equal(123); expect(osc.detune.value).to.equal(-20); expect(osc.type).to.equal("square"); osc.dispose(); }); }); context("Type", function(){ it("can get and set the type", function(){ var osc = new OscillatorNode(); osc.type = "triangle"; expect(osc.type).to.equal("triangle"); osc.dispose(); }); it("can set a periodic wave", function(){ var osc = new OscillatorNode(); var periodicWave = osc.context.createPeriodicWave(Float32Array.from([1, 0]), Float32Array.from([1, 0])); osc.setPeriodicWave(periodicWave); expect(osc.type).to.equal("custom"); osc.dispose(); }); }); context("onended", function(){ if (Supports.ONLINE_TESTING){ it("invokes the onended callback in the online context", function(done){ var osc = new OscillatorNode(); osc.start(); osc.stop("+0.3"); var now = osc.now(); osc.onended = function(){ expect(osc.now() - now).to.be.within(0.25, 0.5); osc.dispose(); done(); }; }); it("invokes the onended callback only once in the online context", function(done){ var osc = new OscillatorNode(); osc.start(); osc.stop("+0.1"); osc.stop("+0.2"); osc.stop("+0.3"); var now = osc.now(); osc.onended = function(){ expect(osc.now() - now).to.be.within(0.25, 0.5); osc.dispose(); done(); }; }); } it("invokes the onended callback in the offline context", function(done){ Offline(function(){ var osc = new OscillatorNode(); osc.start(0); osc.stop(0.2); osc.onended = function(){ expect(osc.now() - 0.2).to.be.closeTo(0, 0.05); osc.dispose(); done(); }; }, 0.3); }); it("invokes the onended callback only once in offline context", function(done){ Offline(function(){ var osc = new OscillatorNode(); osc.start(0); osc.stop(0.1); osc.stop(0.2); osc.stop(0.3); osc.onended = function(){ expect(osc.now() - 0.3).to.be.closeTo(0, 0.05); osc.dispose(); done(); }; }, 0.4); }); }); context("Scheduling", function(){ it("throw an error if start is called multiple time", function(){ var osc = new OscillatorNode(); osc.start(); expect(function(){ osc.start(); }).to.throw(); osc.dispose(); }); it("can play for a specific duration", function(){ return Meter(function(){ var osc = new OscillatorNode().toMaster(); osc.start(0).stop(0.1); }, 0.4).then(function(level){ expect(level.getValueAtTime(0)).to.be.above(0); expect(level.getValueAtTime(0.09)).to.be.above(0); expect(level.getValueAtTime(0.1)).to.equal(0); }); }); it("can call stop multiple times and takes the last value", function(){ return Meter(function(){ var osc = new OscillatorNode().toMaster(); osc.start(0).stop(0.1).stop(0.2); }, 0.4).then(function(level){ expect(level.getValueAtTime(0)).to.be.above(0); expect(level.getValueAtTime(0.1)).to.be.above(0); expect(level.getValueAtTime(0.19)).to.be.above(0); expect(level.getValueAtTime(0.2)).to.equal(0); }); }); if (Supports.ONLINE_TESTING){ it("clamps start time to the currentTime", function(){ var osc = new OscillatorNode(); osc.start(0); var currentTime = osc.context.currentTime; expect(osc.getStateAtTime(0)).to.equal("stopped"); expect(osc.getStateAtTime(currentTime)).to.equal("started"); osc.dispose(); }); it("clamps stop time to the currentTime", function(done){ var osc = new OscillatorNode(); osc.start(0); var currentTime = osc.context.currentTime; expect(osc.getStateAtTime(0)).to.equal("stopped"); expect(osc.getStateAtTime(currentTime)).to.equal("started"); setTimeout(function(){ currentTime = osc.context.currentTime; osc.stop(0); expect(osc.getStateAtTime(currentTime + 0.01)).to.equal("stopped"); osc.dispose(); done(); }, 100); }); } }); context("State", function(){ it("reports the right state", function(){ return Offline(function(){ var osc = new OscillatorNode(); osc.start(0); osc.stop(0.05); return function(time){ Test.whenBetween(time, 0, 0.05, function(){ expect(osc.state).to.equal("started"); }); Test.whenBetween(time, 0.05, 0.1, function(){ expect(osc.state).to.equal("stopped"); }); }; }, 0.1); }); it("can call stop multiple times, takes the last value", function(){ return Offline(function(){ var osc = new OscillatorNode(); osc.start(0); osc.stop(0.05); osc.stop(0.1); return function(time){ Test.whenBetween(time, 0, 0.1, function(){ expect(osc.state).to.equal("started"); }); Test.whenBetween(time, 0.1, 0.2, function(){ expect(osc.state).to.equal("stopped"); }); }; }, 0.2); }); }); });