Tone.js/test/tests/Components.js
2015-08-16 20:35:46 -04:00

1485 lines
No EOL
37 KiB
JavaScript

/* global it, describe, maxTimeout*/
define(["chai", "Tone/component/CrossFade", "Tone/core/Master", "Tone/signal/Signal",
"Recorder", "Tone/component/Panner", "Tone/component/LFO", "Tone/component/Gate",
"Tone/component/Follower", "Tone/component/Envelope", "Tone/component/Filter", "Tone/component/EQ3",
"Tone/component/Merge", "Tone/component/Split", "tests/Common", "Tone/component/AmplitudeEnvelope",
"Tone/component/LowpassCombFilter", "Tone/component/FeedbackCombFilter", "Tone/component/Mono",
"Tone/component/MultibandSplit", "Tone/component/Compressor", "Tone/component/PanVol",
"Tone/component/MultibandCompressor", "Tone/component/ScaledEnvelope", "Tone/component/Limiter",
"Tone/core/Transport", "Tone/component/Volume", "Tone/component/MidSideSplit",
"Tone/component/MidSideMerge", "Tone/component/MidSideCompressor", "Tone/component/Analyser"],
function(chai, CrossFade, Master, Signal, Recorder, Panner, LFO, Gate, Follower, Envelope,
Filter, EQ3, Merge, Split, Test, AmplitudeEnvelope, LowpassCombFilter, FeedbackCombFilter,
Mono, MultibandSplit, Compressor, PanVol, MultibandCompressor, ScaledEnvelope, Limiter, Transport,
Volume, MidSideSplit, MidSideMerge, MidSideCompressor, Analyser){
var expect = chai.expect;
Master.mute = true;
describe("Tone.CrossFade", function(){
this.timeout(maxTimeout);
var crossFade, drySignal, wetSignal, recorder;
it("can be created and disposed", function(){
var dw = new CrossFade();
dw.dispose();
Test.wasDisposed(dw);
});
it("handles input and output connections", function(){
Test.onlineContext();
var crossFade = new CrossFade();
Test.acceptsInput(crossFade, 0);
Test.acceptsInput(crossFade, 1);
Test.acceptsOutput(crossFade);
crossFade.dispose();
});
it("pass 100% dry signal", function(done){
Test.offlineTest(0.1, function(dest){
crossFade = new CrossFade();
drySignal = new Signal(10);
wetSignal = new Signal(20);
drySignal.connect(crossFade, 0, 0);
wetSignal.connect(crossFade, 0, 1);
recorder = new Recorder();
crossFade.fade.value = 0;
crossFade.connect(dest);
}, function(sample){
expect(sample).to.closeTo(10, 0.01);
}, function(){
crossFade.dispose();
drySignal.dispose();
wetSignal.dispose();
done();
});
});
it("pass 100% wet signal", function(done){
Test.offlineTest(0.1, function(dest){
crossFade = new CrossFade();
drySignal = new Signal(10);
wetSignal = new Signal(20);
drySignal.connect(crossFade, 0, 0);
wetSignal.connect(crossFade, 0, 1);
crossFade.fade.value = 1;
crossFade.connect(dest);
}, function(sample){
expect(sample).to.closeTo(20, 0.01);
}, function(){
crossFade.dispose();
drySignal.dispose();
wetSignal.dispose();
done();
});
});
it("can mix two signals", function(done){
Test.offlineTest(0.1, function(dest){
crossFade = new CrossFade();
drySignal = new Signal(0.5);
wetSignal = new Signal(0.5);
drySignal.connect(crossFade, 0, 0);
wetSignal.connect(crossFade, 0, 1);
crossFade.fade.value = 0.5;
crossFade.connect(dest);
}, function(sample){
expect(sample).to.closeTo(0.707, 0.01);
}, function(){
crossFade.dispose();
drySignal.dispose();
wetSignal.dispose();
done();
});
});
});
describe("Tone.Panner", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var panner = new Panner();
panner.dispose();
Test.wasDisposed(panner);
});
it("handles input and output connections", function(){
Test.onlineContext();
var panner = new Panner();
Test.acceptsInputAndOutput(panner);
panner.dispose();
});
it("passes the incoming signal through", function(done){
var panner;
Test.passesAudio(function(input, output){
panner = new Panner();
input.connect(panner);
panner.connect(output);
}, function(){
panner.dispose();
done();
});
});
it("can pan an incoming signal", function(done){
//pan hard right
var signal, panner;
Test.offlineStereoTest(0.1, function(dest){
panner = new Panner();
signal = new Signal(1);
signal.connect(panner);
panner.pan.value = 1;
panner.connect(dest);
}, function(L, R){
expect(L).to.be.closeTo(0, 0.01);
expect(R).to.be.closeTo(1, 0.01);
}, function(){
panner.dispose();
signal.dispose();
done();
});
});
});
describe("Tone.LFO", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var l = new LFO();
l.dispose();
Test.wasDisposed(l);
});
it("can be started and stopped", function(){
Test.onlineContext();
var lfo = new LFO();
lfo.start();
lfo.stop();
lfo.dispose();
});
it("handles output connections", function(){
Test.onlineContext();
var lfo = new LFO();
Test.acceptsOutput(lfo);
lfo.dispose();
});
it("can sync to Transport", function(done){
var lfo;
Test.offlineTest(0.1, function(dest){
Transport.bpm.value = 120;
lfo = new LFO(2);
lfo.frequency.connect(dest);
lfo.sync();
Transport.bpm.value = 240;
}, function(freq){
expect(freq).to.be.closeTo(4, 0.001);
}, function(){
lfo.dispose();
done();
});
});
it("can unsync to Transport", function(done){
var lfo;
Test.offlineTest(0.1, function(dest){
Transport.bpm.value = 120;
lfo = new LFO(2);
lfo.frequency.connect(dest);
lfo.sync();
Transport.bpm.value = 240;
lfo.unsync();
}, function(freq){
expect(freq).to.be.closeTo(2, 0.001);
}, function(){
lfo.dispose();
done();
});
});
it("can be creates an oscillation in a specific range", function(done){
var lfo;
Test.offlineTest(0.1, function(dest){
lfo = new LFO(100, 10, 20);
lfo.connect(dest);
lfo.start();
}, function(sample){
expect(sample).to.be.within(10, 20);
}, function(){
lfo.dispose();
done();
});
});
it("can change the oscillation range", function(done){
var lfo;
Test.offlineTest(0.1, function(dest){
lfo = new LFO(100, 10, 20);
lfo.connect(dest);
lfo.start();
lfo.min = 15;
lfo.max = 18;
}, function(sample){
expect(sample).to.be.within(15, 18);
}, function(){
lfo.dispose();
done();
});
});
it("handles getters/setters as objects", function(){
var lfo = new LFO();
var values = {
"type" : "square",
"min" : -1,
"max" : 2,
"phase" : 180,
"frequency" : "8n",
};
lfo.set(values);
expect(lfo.get()).to.contain.keys(Object.keys(values));
expect(lfo.type).to.equal(values.type);
expect(lfo.min).to.equal(values.min);
expect(lfo.max).to.equal(values.max);
expect(lfo.phase).to.equal(values.phase);
lfo.dispose();
});
});
describe("Tone.Gate", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var g = new Gate();
g.dispose();
Test.wasDisposed(g);
});
it("handles input and output connections", function(){
Test.onlineContext();
var gate = new Gate();
Test.acceptsInputAndOutput(gate);
gate.dispose();
});
it("handles getter/setters", function(){
Test.onlineContext();
var gate = new Gate();
var values = {
"attack" : "4n",
"release" : "8n",
"threshold" : -25,
};
gate.set(values);
expect(gate.get()).to.have.keys(["attack", "release", "threshold"]);
expect(gate.attack).to.equal(values.attack);
expect(gate.decay).to.equal(values.decay);
expect(gate.threshold).to.be.closeTo(values.threshold, 0.1);
gate.dispose();
});
it("won't let signals below a db thresh through", function(done){
var gate, sig;
Test.offlineTest(0.5, function(dest){
gate = new Gate(-10, 0.01);
sig = new Signal(gate.dbToGain(-11));
sig.connect(gate);
gate.connect(dest);
}, function(sample){
expect(sample).to.equal(0);
}, function(){
gate.dispose();
sig.dispose();
done();
});
});
it("lets signals above the db thresh through", function(done){
var gate, sig, level;
Test.offlineTest(0.5, function(dest){
gate = new Gate(-8, 0.01);
level = gate.dbToGain(-6);
sig = new Signal(level);
sig.connect(gate);
gate.connect(dest);
}, function(sample, time){
if (time >= 0.1){
expect(sample).to.be.closeTo(level, 0.001);
}
}, function(){
gate.dispose();
sig.dispose();
done();
});
});
});
describe("Tone.Follower", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var f = new Follower();
f.dispose();
Test.wasDisposed(f);
});
it("handles input and output connections", function(){
Test.onlineContext();
var foll = new Follower(0.1, 0.5);
Test.acceptsInputAndOutput(foll);
foll.dispose();
});
it("smoothes the incoming signal", function(done){
var foll, sig;
Test.offlineTest(0.1, function(dest){
foll = new Follower(0.1, 0.5);
sig = new Signal(0);
sig.connect(foll);
foll.connect(dest);
sig.setValueAtTime(1, "+0.1");
}, function(sample){
expect(sample).to.lessThan(1);
}, function(){
foll.dispose();
sig.dispose();
done();
});
});
it("handles getter/setter as Object", function(){
var foll = new Follower();
var values = {
"attack" : "8n",
"release" : "4n"
};
foll.set(values);
expect(foll.get()).to.have.keys(["attack", "release"]);
expect(foll.get()).to.deep.equal(values);
foll.dispose();
});
});
describe("Tone.Envelope", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var e = new Envelope();
e.dispose();
Test.wasDisposed(e);
});
it("handles output connections", function(){
Test.onlineContext();
var e = new Envelope();
Test.acceptsOutput(e);
e.dispose();
});
it ("can take parameters as both an object and as arguments", function(){
var e0 = new Envelope({
"attack" : 0,
"decay" : 0.5,
"sustain" : 1
});
expect(e0.attack).to.equal(0);
expect(e0.decay).to.equal(0.5);
expect(e0.sustain).to.equal(1);
e0.dispose();
var e1 = new Envelope(0.1, 0.2, 0.3);
expect(e1.attack).to.equal(0.1);
expect(e1.decay).to.equal(0.2);
expect(e1.sustain).to.equal(0.3);
e1.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;
Test.offlineTest(0.7, function(dest){
env = new Envelope(0.01, 0.4, 0.5, 0.1);
env.attackCurve = "exponential";
env.connect(dest);
env.triggerAttack(0);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
it ("correctly schedules an exponential attack", function(done){
var env;
Test.offlineTest(0.7, function(dest){
env = new Envelope(0.3, 0.001, 0.5, 0.1);
env.attackCurve = "exponential";
env.connect(dest);
env.triggerAttack(0);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
it ("can schedule a very short attack", function(done){
var env;
Test.offlineTest(0.2, function(dest){
env = new Envelope(0.001, 0.001, 0);
env.connect(dest);
env.triggerAttack(0);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
it ("correctly schedule a release", function(done){
var releaseTime = 0.2;
var env;
Test.offlineTest(0.7, function(dest){
env = new Envelope(0.001, 0.001, 0.5, 0.3);
env.connect(dest);
env.triggerAttack(0);
env.triggerRelease(releaseTime);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
it ("correctly schedule an attack release envelope", function(done){
var env;
var releaseTime = 0.4;
Test.offlineTest(0.8, function(dest){
env = new Envelope(0.08, 0.2, 0.1, 0.2);
env.connect(dest);
env.triggerAttack(0);
env.triggerRelease(releaseTime);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
it ("can schedule a combined AttackRelease", function(done){
var env;
var duration = 0.4;
Test.offlineTest(0.7, function(dest){
env = new Envelope(0.1, 0.2, 0.35, 0.1);
env.connect(dest);
env.triggerAttackRelease(duration, 0);
}, 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 < 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);
}
}, function(){
env.dispose();
done();
});
});
it ("can schedule a combined AttackRelease with velocity", function(done){
var env;
var duration = 0.4;
var velocity = 0.4;
Test.offlineTest(0.7, function(dest){
env = new Envelope(0.1, 0.2, 0.35, 0.1);
env.connect(dest);
env.triggerAttackRelease(duration, 0, velocity);
}, 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);
}
}, function(){
env.dispose();
done();
});
});
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();
});
});
describe("Tone.Filter", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var f = new Filter();
f.dispose();
Test.wasDisposed(f);
});
it("handles input and output connections", function(){
Test.onlineContext();
var f = new Filter();
Test.acceptsInputAndOutput(f);
f.dispose();
});
it("can set/get values as an Object", function(){
var f = new Filter();
var values = {
"type" : "highpass",
"frequency" : 440,
"rolloff" : -24,
"Q" : 2,
"gain" : -6,
};
f.set(values);
expect(f.get()).to.have.keys(["type", "frequency", "rolloff", "Q", "gain"]);
expect(f.type).to.equal(values.type);
expect(f.frequency.value).to.equal(values.frequency);
expect(f.rolloff).to.equal(values.rolloff);
expect(f.Q.value).to.equal(values.Q);
expect(f.gain.value).to.be.closeTo(values.gain, 0.04);
f.dispose();
});
it("passes the incoming signal through", function(done){
var filter;
Test.passesAudio(function(input, output){
filter = new Filter();
input.connect(filter);
filter.connect(output);
}, function(){
filter.dispose();
done();
});
});
it("only accepts filter values -12, -24, -48 and -96", function(){
var filter = new Filter();
filter.rolloff = -12;
expect(filter.rolloff).to.equal(-12);
filter.rolloff = "-24";
expect(filter.rolloff).to.equal(-24);
filter.rolloff = -48;
expect(filter.rolloff).to.equal(-48);
filter.rolloff = -96;
expect(filter.rolloff).to.equal(-96);
expect(function(){
filter.rolloff = -95;
}).to.throw(Error);
filter.dispose();
});
it("can set the basic filter types", function(){
var filter = new Filter();
var types = ["lowpass", "highpass", "bandpass", "lowshelf", "highshelf", "notch", "allpass", "peaking"];
for (var i = 0; i < types.length; i++){
filter.type = types[i];
expect(filter.type).to.equal(types[i]);
}
expect(function(){
filter.type = "nontype";
}).to.throw(Error);
filter.dispose();
});
it ("can take parameters as both an object and as arguments", function(){
Test.onlineContext();
var f0 = new Filter({
"frequency" : 1000,
"type" : "highpass"
});
expect(f0.frequency.value).to.equal(1000);
expect(f0.type).to.equal("highpass");
f0.dispose();
var f1 = new Filter(200, "bandpass");
expect(f1.frequency.value).to.equal(200);
expect(f1.type).to.equal("bandpass");
f1.dispose();
});
});
describe("Tone.EQ33", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var eq = new EQ3();
eq.dispose();
Test.wasDisposed(eq);
});
it("handles input and output connections", function(){
Test.onlineContext();
var eq = new EQ3();
Test.acceptsInputAndOutput(eq);
eq.dispose();
});
it("passes the incoming signal through", function(done){
var eq;
Test.passesAudio(function(input, output){
eq = new EQ3();
input.connect(eq);
eq.connect(output);
}, function(){
eq.dispose();
done();
});
});
it("can set/get values as an Object", function(){
Test.onlineContext();
var eq = new EQ3();
var values = {
"high" : -12,
"mid" : -24,
"low" : -1
};
eq.set(values);
expect(eq.high.value).to.be.closeTo(values.high, 0.1);
expect(eq.mid.value).to.be.closeTo(values.mid, 0.1);
expect(eq.low.value).to.be.closeTo(values.low, 0.1);
eq.dispose();
});
});
//MERGE
describe("Tone.Merge", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var mer = new Merge();
mer.dispose();
Test.wasDisposed(mer);
});
it("handles input and output connections", function(){
Test.onlineContext();
var mer = new Merge();
Test.acceptsInput(mer.left);
Test.acceptsInput(mer.right);
Test.acceptsOutput(mer);
mer.dispose();
});
it("merge two signal into one stereo signal", function(done){
//make an oscillator to drive the signal
var sigL, sigR, merger;
Test.offlineStereoTest(0.1, function(dest){
sigL = new Signal(1);
sigR = new Signal(2);
merger = new Merge();
sigL.connect(merger.left);
sigR.connect(merger.right);
merger.connect(dest);
}, function(L, R){
expect(L).to.equal(1);
expect(R).to.equal(2);
}, function(){
sigL.dispose();
sigR.dispose();
merger.dispose();
done();
});
});
});
describe("Tone.Split", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var split = new Split();
split.dispose();
Test.wasDisposed(split);
});
it("handles input and output connections", function(){
Test.onlineContext();
var split = new Split();
Test.acceptsInput(split);
Test.acceptsOutput(split.left);
Test.acceptsOutput(split.right);
split.dispose();
});
it("merges two signal into one stereo signal and then split them back into two signals on left side", function(done){
var sigL, sigR, merger, split;
Test.offlineTest(0.1, function(dest){
sigL = new Signal(1);
sigR = new Signal(2);
merger = new Merge();
split = new Split();
sigL.connect(merger.left);
sigR.connect(merger.right);
merger.connect(split);
split.connect(dest, 0, 0);
}, function(sample){
expect(sample).to.equal(1);
}, function(){
sigL.dispose();
sigR.dispose();
merger.dispose();
split.dispose();
done();
});
});
it("merges two signal into one stereo signal and then split them back into two signals on right side", function(done){
var sigL, sigR, merger, split;
Test.offlineTest(0.1, function(dest){
sigL = new Signal(1);
sigR = new Signal(2);
merger = new Merge();
split = new Split();
sigL.connect(merger.left);
sigR.connect(merger.right);
merger.connect(split);
split.connect(dest, 1, 0);
}, function(sample){
expect(sample).to.equal(2);
}, function(){
sigL.dispose();
sigR.dispose();
merger.dispose();
split.dispose();
done();
});
});
});
describe("Tone.AmplitudeEnvelope", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var ampEnv = new AmplitudeEnvelope();
ampEnv.dispose();
Test.wasDisposed(ampEnv);
});
it("handles input and output connections", function(){
Test.onlineContext();
var ampEnv = new AmplitudeEnvelope();
Test.acceptsInputAndOutput(ampEnv);
ampEnv.dispose();
});
it("inherits all methods from Envelope", function(){
var ampEnv = new AmplitudeEnvelope();
expect(ampEnv).to.be.instanceOf(Envelope);
ampEnv.dispose();
});
});
describe("Tone.LowpassCombFilter", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var lfcf = new LowpassCombFilter();
lfcf.dispose();
Test.wasDisposed(lfcf);
});
it("handles input and output connections", function(){
Test.onlineContext();
var lfcf = new LowpassCombFilter();
Test.acceptsInputAndOutput(lfcf);
lfcf.dispose();
});
it("passes the incoming signal through", function(done){
var lfcf;
Test.passesAudio(function(input, output){
lfcf = new LowpassCombFilter();
input.connect(lfcf);
lfcf.connect(output);
}, function(){
lfcf.dispose();
done();
});
});
it("handles getters/setters", function(){
Test.onlineContext();
var lfcf = new LowpassCombFilter();
var values = {
"resonance" : 0.4,
"dampening" : 4000,
"delayTime" : "4n"
};
lfcf.set(values);
expect(lfcf.get()).to.have.keys(["resonance", "dampening", "delayTime"]);
lfcf.dispose();
});
});
describe("Tone.FeedbackCombFilter", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var fbcf = new FeedbackCombFilter();
fbcf.dispose();
Test.wasDisposed(fbcf);
});
it("handles input and output connections", function(){
Test.onlineContext();
var fbcf = new FeedbackCombFilter();
Test.acceptsInputAndOutput(fbcf);
fbcf.dispose();
});
it("can set delayTime", function(){
Test.onlineContext();
var fbcf = new FeedbackCombFilter();
fbcf.delayTime.value = "4n";
var quarterSeconds = fbcf.toSeconds("4n");
expect(fbcf.delayTime.value).to.equal(quarterSeconds);
fbcf.dispose();
});
it("passes the incoming signal through", function(done){
var fbcf;
Test.passesAudio(function(input, output){
fbcf = new FeedbackCombFilter();
input.connect(fbcf);
fbcf.connect(output);
}, function(){
fbcf.dispose();
done();
});
});
});
describe("Tone.Mono", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var mono = new Mono();
mono.dispose();
Test.wasDisposed(mono);
});
it("handles input and output connections", function(){
Test.onlineContext();
var mono = new Mono();
Test.acceptsInputAndOutput(mono);
mono.dispose();
});
it("passes the incoming signal through", function(done){
var mono;
Test.passesAudio(function(input, output){
mono = new FeedbackCombFilter();
input.connect(mono);
mono.connect(output);
}, function(){
mono.dispose();
done();
});
});
});
describe("Tone.MultibandSplit", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var mband = new MultibandSplit();
mband.dispose();
Test.wasDisposed(mband);
});
it("handles input and output connections", function(){
Test.onlineContext();
var mband = new MultibandSplit();
Test.acceptsInput(mband);
Test.acceptsOutput(mband.low);
Test.acceptsOutput(mband, 1);
Test.acceptsOutput(mband, 2);
mband.dispose();
});
});
describe("Tone.Compressor", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var comp = new Compressor();
comp.dispose();
Test.wasDisposed(comp);
});
it("handles input and output connections", function(){
Test.onlineContext();
var comp = new Compressor();
Test.acceptsInputAndOutput(comp);
comp.dispose();
});
it("passes the incoming signal through", function(done){
var comp;
Test.passesAudio(function(input, output){
comp = new Compressor();
input.connect(comp);
comp.connect(output);
}, function(){
comp.dispose();
done();
});
});
it("can be get and set through object", function(){
var comp = new Compressor();
var values = {
"ratio" : 22,
"threshold" : -30,
"release" : 0.5,
"attack" : 0.03,
"knee" : 20
};
comp.set(values);
expect(comp.get()).to.have.keys(["ratio", "threshold", "release", "attack", "ratio"]);
comp.dispose();
});
it("can get/set all interfaces", function(){
var comp = new Compressor();
var values = {
"ratio" : 22,
"threshold" : -30,
"release" : 0.5,
"attack" : 0.03,
"knee" : 20
};
comp.ratio.value = values.ratio;
comp.threshold.value = values.threshold;
comp.release.value = values.release;
comp.attack.value = values.attack;
comp.knee.value = values.knee;
expect(comp.ratio.value).to.equal(values.ratio);
expect(comp.threshold.value).to.equal(values.threshold);
expect(comp.release.value).to.equal(values.release);
expect(comp.attack.value).to.be.closeTo(values.attack, 0.01);
expect(comp.knee.value).to.equal(values.knee);
comp.dispose();
});
});
describe("Tone.PanVol", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var panvol = new PanVol();
panvol.dispose();
Test.wasDisposed(panvol);
});
it("handles input and output connections", function(){
Test.onlineContext();
var panvol = new PanVol();
Test.acceptsInputAndOutput(panvol);
panvol.dispose();
});
it("passes the incoming signal through", function(done){
var panvol;
Test.passesAudio(function(input, output){
panvol = new PanVol();
input.connect(panvol);
panvol.connect(output);
}, function(){
panvol.dispose();
done();
});
});
it("can set the pan and volume", function(){
var panvol = new PanVol();
panvol.volume.value = -12;
panvol.pan.value = 0;
expect(panvol.volume.value).to.be.closeTo(-12, 0.1);
expect(panvol.pan.value).to.be.equal(0);
});
});
describe("Tone.MultibandCompressor", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var comp = new MultibandCompressor();
comp.dispose();
Test.wasDisposed(comp);
});
it("handles input and output connections", function(){
Test.onlineContext();
var comp = new MultibandCompressor();
Test.acceptsInputAndOutput(comp);
comp.dispose();
});
it("passes the incoming signal through", function(done){
var comp;
Test.passesAudio(function(input, output){
comp = new MultibandCompressor();
input.connect(comp);
comp.connect(output);
}, function(){
comp.dispose();
done();
});
});
it("handles getters/setters", function(){
Test.onlineContext();
var comp = new MultibandCompressor();
var values = {
"low" : {
"attack" : 0.3
},
"mid" : {
"threshold" : -12
}
};
comp.set(values);
expect(comp.get()).to.have.deep.property("low.attack");
expect(comp.get()).to.have.deep.property("mid.threshold");
expect(comp.low.attack.value).to.be.closeTo(0.3, 0.05);
expect(comp.mid.threshold.value).to.be.closeTo(-12, 0.05);
comp.dispose();
});
});
describe("Tone.ScaledEnvelope", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var e = new ScaledEnvelope();
e.dispose();
Test.wasDisposed(e);
});
it("handles output connections", function(){
Test.onlineContext();
var e = new ScaledEnvelope();
Test.acceptsOutput(e);
e.dispose();
});
it ("can take parameters as an object", function(){
var e0 = new ScaledEnvelope({
"attack" : 0,
"decay" : 0.5,
"sustain" : 1,
"min" : 10,
"max": 5
});
expect(e0.attack).to.equal(0);
expect(e0.decay).to.equal(0.5);
expect(e0.sustain).to.equal(1);
e0.dispose();
});
it ("can schedule an ADSR envelope", function(done){
var env;
Test.offlineTest(0.7, function(dest){
env = new ScaledEnvelope({
"attack" : 0.1,
"decay" : 0.2,
"sustain" : 0.5,
"release" : 0.1,
"min" : 0,
"max": 100
});
env.connect(dest);
env.triggerAttack(0);
env.triggerRelease(0.4);
}, function(sample, time){
if (time < 0.1){
expect(sample).to.be.within(0, 100);
} else if (time < 0.3){
expect(sample).to.be.within(0.5, 100);
} else if (time < 0.4){
expect(sample).to.be.within(0.5, 51);
} else if (time < 0.5){
expect(sample).to.be.within(0, 51);
} else {
expect(sample).to.be.below(1);
}
}, function(){
env.dispose();
done();
});
});
it ("can scale the range", function(done){
var env;
Test.offlineTest(0.7, function(dest){
env = new ScaledEnvelope(0.1, 0.2, 0.5, 0.1);
env.connect(dest);
env.min = 5;
env.max = 10;
env.triggerAttack(0.1);
}, function(sample, time){
if (time < 0.1){
expect(sample).to.be.closeTo(5, 0.1);
} else if (time < 0.2){
expect(sample).to.be.within(5, 10);
}
}, function(){
env.dispose();
done();
});
});
});
describe("Tone.Limiter", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var lim = new Limiter();
lim.dispose();
Test.wasDisposed(lim);
});
it("handles input and output connections", function(){
Test.onlineContext();
var lim = new Limiter();
Test.acceptsInputAndOutput(lim);
lim.dispose();
});
it("can get and set values", function(){
Test.onlineContext();
var lim = new Limiter();
lim.threshold.value = -12;
expect(lim.threshold.value).to.be.closeTo(-12, 0.05);
lim.dispose();
});
it("passes the incoming signal through", function(done){
var lim;
Test.passesAudio(function(input, output){
lim = new Limiter();
input.connect(lim);
lim.connect(output);
}, function(){
lim.dispose();
done();
});
});
});
describe("Tone.Volume", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var vol = new Volume();
vol.dispose();
Test.wasDisposed(vol);
});
it("handles input and output connections", function(){
Test.onlineContext();
var vol = new Volume();
Test.acceptsInputAndOutput(vol);
vol.dispose();
});
it("can get and set values", function(){
Test.onlineContext();
var vol = new Volume();
vol.volume.value = -12;
expect(vol.volume.value).to.be.closeTo(-12, 0.05);
vol.dispose();
});
it("passes the incoming signal through", function(done){
var vol;
Test.passesAudio(function(input, output){
vol = new Volume();
input.connect(vol);
vol.connect(output);
}, function(){
vol.dispose();
done();
});
});
});
describe("Tone.MidSideSplit", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var split = new MidSideSplit();
split.dispose();
Test.wasDisposed(split);
});
it("handles input and output connections", function(){
Test.onlineContext();
var split = new MidSideSplit();
Test.acceptsInput(split);
Test.acceptsOutput(split.mid);
Test.acceptsOutput(split.side);
split.dispose();
});
});
describe("Tone.MidSideMerge", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var merge = new MidSideMerge();
merge.dispose();
Test.wasDisposed(merge);
});
it("handles input and output connections", function(){
Test.onlineContext();
var merge = new MidSideMerge();
Test.acceptsInput(merge.side);
Test.acceptsInput(merge.mid);
Test.acceptsOutput(merge);
merge.dispose();
});
it("passes the mid signal through", function(done){
var merge;
Test.passesAudio(function(input, output){
merge = new MidSideMerge();
input.connect(merge.mid);
merge.connect(output);
}, function(){
merge.dispose();
done();
});
});
it("passes the side signal through", function(done){
var merge;
Test.passesAudio(function(input, output){
merge = new MidSideMerge();
input.connect(merge.side);
merge.connect(output);
}, function(){
merge.dispose();
done();
});
});
});
describe("Tone.MidSideCompressor", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var comp = new MidSideCompressor();
comp.dispose();
Test.wasDisposed(comp);
});
it("handles input and output connections", function(){
Test.onlineContext();
var comp = new MidSideCompressor();
Test.acceptsInput(comp);
Test.acceptsOutput(comp);
comp.dispose();
});
it("passes signal through", function(done){
var comp;
Test.passesAudio(function(input, output){
comp = new MidSideCompressor();
input.connect(comp);
comp.connect(output);
}, function(){
comp.dispose();
done();
});
});
});
describe("Tone.Analyser", function(){
this.timeout(maxTimeout);
it("can be created and disposed", function(){
var anl = new Analyser();
anl.dispose();
Test.wasDisposed(anl);
});
it("handles input connections", function(){
Test.onlineContext();
var anl = new Analyser();
Test.acceptsInput(anl);
anl.dispose();
});
it("can get and set properties", function(){
Test.onlineContext();
var anl = new Analyser();
anl.set({
"size" : 32,
"maxDecibels" : -20,
"minDecibels" : -80,
"smoothing" : 0.2
});
var values = anl.get();
expect(values.size).to.equal(32);
expect(values.minDecibels).to.equal(-80);
expect(values.maxDecibels).to.equal(-20);
expect(values.smoothing).to.equal(0.2);
anl.dispose();
});
it("can correctly set the size", function(){
Test.onlineContext();
var anl = new Analyser(512);
expect(anl.size).to.equal(512);
anl.size = 1024;
expect(anl.size).to.equal(1024);
anl.dispose();
});
it("can run fft analysis in both bytes and floats", function(){
Test.onlineContext();
var anl = new Analyser(512, "fft");
anl.returnType = "byte";
var analysis = anl.analyse();
expect(analysis.length).to.equal(512);
var i;
for (i = 0; i < analysis.length; i++){
expect(analysis[i]).is.within(0, 255);
}
anl.returnType = "float";
analysis = anl.analyse();
expect(analysis.length).to.equal(512);
for (i = 0; i < analysis.length; i++){
expect(analysis[i]).is.within(anl.minDecibels, anl.maxDecibels);
}
anl.dispose();
});
it("can run waveform analysis in both bytes and floats", function(){
Test.onlineContext();
var anl = new Analyser(256, "waveform");
anl.returnType = "byte";
var analysis = anl.analyse();
expect(analysis.length).to.equal(256);
var i;
for (i = 0; i < analysis.length; i++){
expect(analysis[i]).is.within(0, 255);
}
anl.returnType = "float";
analysis = anl.analyse();
expect(analysis.length).to.equal(256);
for (i = 0; i < analysis.length; i++){
expect(analysis[i]).is.within(0, 1);
}
anl.dispose();
});
});
});