mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 08:38:00 +00:00
197 lines
5.5 KiB
JavaScript
197 lines
5.5 KiB
JavaScript
define(["helper/OutputAudio", "Tone/instrument/Instrument", "helper/OutputAudioStereo",
|
|
"Test", "helper/Offline", "Tone/core/Tone", "helper/Meter"],
|
|
function(OutputAudio, Instrument, OutputAudioStereo, Test, Offline, Tone, Meter) {
|
|
|
|
return function(Constr, note, constrArg, optionsIndex){
|
|
|
|
context("Instrument Tests", function(){
|
|
|
|
it("extends Tone.Instrument", function(){
|
|
var instance = new Constr(constrArg);
|
|
expect(instance).to.be.an.instanceof(Instrument);
|
|
instance.dispose();
|
|
});
|
|
|
|
it("can connect the output", function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.connect(Test);
|
|
instance.dispose();
|
|
});
|
|
|
|
it("can set the volume", function(){
|
|
if (!optionsIndex){
|
|
var instance = new Constr({
|
|
"volume" : -10
|
|
});
|
|
} else if (optionsIndex === 1){
|
|
var instance = new Constr(constrArg, {
|
|
"volume" : -10
|
|
});
|
|
}
|
|
expect(instance.volume.value).to.be.closeTo(-10, 0.1);
|
|
instance.dispose();
|
|
});
|
|
|
|
it("makes a sound", function(){
|
|
return OutputAudio(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
instance.triggerAttack(note);
|
|
});
|
|
});
|
|
|
|
it("produces sound in both channels", function(){
|
|
return OutputAudioStereo(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
instance.triggerAttack(note);
|
|
});
|
|
});
|
|
|
|
it("is silent before being triggered", function(){
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
}).then(function(buffer){
|
|
expect(buffer.isSilent()).to.be.true;
|
|
});
|
|
});
|
|
|
|
if (Constr.prototype.triggerRelease){
|
|
|
|
it("can trigger release after attack", function(){
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.05);
|
|
} else {
|
|
instance.triggerAttack(0.05);
|
|
}
|
|
instance.triggerRelease(0.1);
|
|
}, 1).then(function(buffer){
|
|
expect(buffer.getFirstSoundTime()).to.be.within(0.05, 0.1);
|
|
});
|
|
});
|
|
|
|
it("can trigger another attack before the release has ended", function(){
|
|
//compute the end time
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.05);
|
|
} else {
|
|
instance.triggerAttack(0.05);
|
|
}
|
|
instance.triggerRelease(0.1);
|
|
}, 1).then(function(buffer){
|
|
return buffer.getLastSoundTime();
|
|
}).then(function(bufferDuration){
|
|
var secondTrigger = 0.15;
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.05);
|
|
} else {
|
|
instance.triggerAttack(0.05);
|
|
}
|
|
instance.triggerRelease(0.1);
|
|
//star the note again before the last one has finished
|
|
if (note){
|
|
instance.triggerAttack(note, secondTrigger);
|
|
} else {
|
|
instance.triggerAttack(secondTrigger);
|
|
}
|
|
}, bufferDuration + secondTrigger * 2).then(function(buffer){
|
|
expect(buffer.getLastSoundTime()).to.be.gt(bufferDuration);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("can combine triggerAttack and triggerRelease", function(){
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
if (note){
|
|
instance.triggerAttackRelease(note, 0.1, 0.05);
|
|
} else {
|
|
instance.triggerAttackRelease(0.1, 0.05);
|
|
}
|
|
}, 0.2).then(function(buffer){
|
|
expect(buffer.getFirstSoundTime()).to.be.within(0.05, 0.1);
|
|
});
|
|
});
|
|
}
|
|
|
|
it("be scheduled to start in the future", function(){
|
|
return Offline(function(){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.1);
|
|
} else {
|
|
instance.triggerAttack(0.1);
|
|
}
|
|
}, 0.2).then(function(buffer){
|
|
expect(buffer.getFirstSoundTime()).to.be.within(0.1, 0.15);
|
|
});
|
|
});
|
|
|
|
it("can sync triggerAttack to the Transport", function(){
|
|
return Offline(function(Transport){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
instance.sync();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.1);
|
|
} else {
|
|
instance.triggerAttack(0.1);
|
|
}
|
|
Transport.start(0.1);
|
|
}, 0.3).then(function(buffer){
|
|
expect(buffer.getFirstSoundTime()).to.be.within(0.19, 0.25);
|
|
});
|
|
});
|
|
|
|
it("can unsync triggerAttack to the Transport", function(){
|
|
return Offline(function(Transport){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
instance.sync();
|
|
if (note){
|
|
instance.triggerAttack(note, 0.1);
|
|
} else {
|
|
instance.triggerAttack(0.1);
|
|
}
|
|
instance.unsync();
|
|
Transport.start(0.1);
|
|
}, 0.3).then(function(buffer){
|
|
expect(buffer.isSilent()).to.be.true;
|
|
});
|
|
});
|
|
|
|
it("can sync triggerAttackRelease to the Transport", function(){
|
|
return Offline(function(Transport){
|
|
var instance = new Constr(constrArg);
|
|
instance.toMaster();
|
|
instance.sync();
|
|
if (note){
|
|
instance.triggerAttackRelease(note, 0.25, 0.1);
|
|
} else {
|
|
instance.triggerAttackRelease(0.25, 0.1);
|
|
}
|
|
Transport.start(0.1);
|
|
}, 1).then(function(buffer){
|
|
expect(buffer.getFirstSoundTime()).to.be.within(0.19, 0.25);
|
|
//test a sample enough in the future for the decay to die down
|
|
var endSample = Math.floor(0.9 * Tone.context.sampleRate);
|
|
expect(buffer.getRMS()[endSample]).to.be.closeTo(0, 0.1);
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
});
|