define(["Tone/component/Envelope", "helper/Basic", "helper/Offline", "Test"], function (Envelope, Basic, Offline, Test) { describe("Envelope", function(){ Basic(Envelope); context("Envelope", function(){ it("has an output connections", function(){ var env = new Envelope(); env.connect(Test); env.dispose(); }); it ("can get and set values an Objects", function(){ var env = new Envelope(); var values = { "attack" : 0, "decay" : 0.5, "sustain" : 1, "release" : "4n" }; env.set(values); expect(env.get()).to.contain.keys(Object.keys(values)); env.dispose(); }); it ("passes no signal before being triggered", function(done){ var env; var offline = new Offline(0.1); offline.before(function(dest){ env = new Envelope().connect(dest); }); offline.test(function(sample){ expect(sample).to.be.closeTo(0, 0.001); }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("passes signal once triggered", function(done){ var env; var offline = new Offline(0.2); offline.before(function(dest){ env = new Envelope().connect(dest); env.triggerAttack(0.1); }); offline.test(function(sample, time){ if (time <= 0.1){ expect(sample).to.be.closeTo(0, 0.001); } else { expect(sample).to.be.above(0); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("can take parameters as both an object and as arguments", function(){ var env0 = new Envelope({ "attack" : 0, "decay" : 0.5, "sustain" : 1 }); expect(env0.attack).to.equal(0); expect(env0.decay).to.equal(0.5); expect(env0.sustain).to.equal(1); env0.dispose(); var env1 = new Envelope(0.1, 0.2, 0.3); expect(env1.attack).to.equal(0.1); expect(env1.decay).to.equal(0.2); expect(env1.sustain).to.equal(0.3); env1.dispose(); }); it("can set attack to exponential or linear", function(){ var env = new Envelope(0.01, 0.01, 0.5, 0.3); env.attackCurve = "exponential"; expect(env.attackCurve).to.equal("exponential"); env.triggerAttack(); env.dispose(); //and can be linear var env2 = new Envelope(0.01, 0.01, 0.5, 0.3); env2.attackCurve = "linear"; expect(env2.attackCurve).to.equal("linear"); env2.triggerAttack(); //and test a non-curve expect(function(){ env2.attackCurve = "other"; }).to.throw(Error); env2.dispose(); }); it("can set release to exponential or linear", function(){ var env = new Envelope(0.01, 0.01, 0.5, 0.3); env.releaseCurve = "exponential"; expect(env.releaseCurve).to.equal("exponential"); env.triggerRelease(); env.dispose(); //and can be linear var env2 = new Envelope(0.01, 0.01, 0.5, 0.3); env2.releaseCurve = "linear"; expect(env2.releaseCurve).to.equal("linear"); env2.triggerRelease(); //and test a non-curve expect(function(){ env2.releaseCurve = "other"; }).to.throw(Error); env2.dispose(); }); it ("correctly schedules an exponential attack", function(done){ var env; var offline = new Offline(0.7); offline.before(function(dest){ env = new Envelope(0.01, 0.4, 0.5, 0.1); env.attackCurve = "exponential"; env.connect(dest); env.triggerAttack(0); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, 1); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(env.sustain, 1); } else { expect(sample).to.be.closeTo(env.sustain, 0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("correctly schedules an exponential attack", function(done){ var env; var offline = new Offline(0.7); offline.before(function(dest){ env = new Envelope(0.3, 0.001, 0.5, 0.1); env.attackCurve = "exponential"; env.connect(dest); env.triggerAttack(0); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, 1); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(env.sustain, 1); } else { expect(sample).to.be.closeTo(env.sustain, 0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("can schedule a very short attack", function(done){ var env; var offline = new Offline(0.2); offline.before(function(dest){ env = new Envelope(0.001, 0.001, 0); env.connect(dest); env.triggerAttack(0); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, 1); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(0, 1); } else { expect(sample).to.be.below(0.02); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("correctly schedule a release", function(done){ var releaseTime = 0.2; var env; var offline = new Offline(0.7); offline.before(function(dest){ env = new Envelope(0.001, 0.001, 0.5, 0.3); env.connect(dest); env.triggerAttack(0); env.triggerRelease(releaseTime); }); offline.test(function(sample, time){ if (time > env.attack + env.decay && time < env.attack + env.decay + releaseTime){ expect(sample).to.be.below(env.sustain + 0.01); } else if (time > 0.5){ //silent expect(sample).to.be.below(0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("correctly schedule an attack release envelope", function(done){ var env; var releaseTime = 0.4; var offline = new Offline(0.8); offline.before(function(dest){ env = new Envelope(0.08, 0.2, 0.1, 0.2); env.connect(dest); env.triggerAttack(0); env.triggerRelease(releaseTime); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, 1); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(env.sustain, 1); } else if (time < releaseTime){ expect(sample).to.be.closeTo(env.sustain, 0.1); } else if (time < releaseTime + env.release){ expect(sample).to.be.within(0, env.sustain + 0.01); } else { //silent expect(sample).to.be.below(0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("can schedule a combined AttackRelease", function(done){ var env; var duration = 0.4; var offline = new Offline(0.7); offline.before(function(dest){ env = new Envelope(0.1, 0.2, 0.35, 0.1); env.connect(dest); env.triggerAttackRelease(duration, 0); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, 1); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(env.sustain - 0.001, 1); } else if (time < duration){ expect(sample).to.be.closeTo(env.sustain, 0.1); } else if (time < duration + env.release){ expect(sample).to.be.within(0, env.sustain + 0.01); } else { expect(sample).to.be.below(0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("can schedule a combined AttackRelease with velocity", function(done){ var env; var duration = 0.4; var velocity = 0.4; var offline = new Offline(0.8); offline.before(function(dest){ env = new Envelope(0.1, 0.2, 0.35, 0.1); env.connect(dest); env.triggerAttackRelease(duration, 0, velocity); }); offline.test(function(sample, time){ if (time < env.attack){ expect(sample).to.be.within(0, velocity + 0.01); } else if (time < env.attack + env.decay){ expect(sample).to.be.within(env.sustain * velocity, velocity + 0.01); } else if (time < duration){ expect(sample).to.be.closeTo(env.sustain * velocity, 0.1); } else if (time < duration + env.release){ expect(sample).to.be.within(0, env.sustain * velocity + 0.01); } else { expect(sample).to.be.below(0.01); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("can schedule multiple envelopes", function(done){ var env; var offline = new Offline(1); offline.before(function(dest){ env = new Envelope(0.1, 0.2, 0); env.connect(dest); env.triggerAttack(0); env.triggerAttack(0.5); }); offline.test(function(sample, time){ if (time > 0 && time < 0.3){ expect(sample).to.be.above(0); } else if (time <= 0.5){ expect(sample).to.be.below(0.02); } else if (time <= 0.8){ expect(sample).to.be.above(0); } else { expect(sample).to.be.below(0.02); } }); offline.after(function(){ env.dispose(); done(); }); offline.run(); }); it ("reports its current envelope value (.value)", function(done){ var env = new Envelope(0.1, 0.2, 1).noGC(); expect(env.value).to.be.closeTo(0, 0.01); env.triggerAttack(); setTimeout(function(){ expect(env.value).to.be.closeTo(1, 0.01); env.dispose(); done(); }, 200); }); }); }); });