Merge branch 'dev' of https://github.com/Tonejs/Tone.js into dev

This commit is contained in:
tambien 2018-05-31 13:18:32 -04:00
commit 1d265a48a0
30 changed files with 353 additions and 118 deletions

View file

@ -42,7 +42,7 @@ module.exports = {
"keyword-spacing" : ["error", { "before": true }],
"space-before-function-paren": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"space-before-blocks": ["error", "never"]
"space-before-blocks": ["error", { "functions": "never", "keywords": "never", "classes": "always" }]
// "one-var-declaration-per-line": [ "error" , "always" ],
// "object-curly-newline": [ "error" , { "multiline": true }],
// "array-bracket-newline": [ "error" , "always" ],

View file

@ -89,6 +89,7 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
//set the attackCurve initially
this.attackCurve = options.attackCurve;
this.releaseCurve = options.releaseCurve;
this.decayCurve = options.decayCurve;
};
Tone.extend(Tone.Envelope, Tone.AudioNode);
@ -104,6 +105,7 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
"sustain" : 0.5,
"release" : 1,
"attackCurve" : "linear",
"decayCurve" : "exponential",
"releaseCurve" : "exponential",
};
@ -121,6 +123,51 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
}
});
/**
* Get the curve
* @param {Array|String} curve
* @param {String} direction In/Out
* @return {String} The curve name
* @private
*/
Tone.Envelope.prototype._getCurve = function(curve, direction){
if (Tone.isString(curve)){
return curve;
} else if (Tone.isArray(curve)){
//look up the name in the curves array
for (var t in Tone.Envelope.Type){
if (Tone.Envelope.Type[t][direction] === curve){
return t;
}
}
//otherwise just return the array
return curve;
}
};
/**
* Assign a the curve to the given name using the direction
* @param {String} name
* @param {String} direction In/Out
* @param {Array} curve
* @private
*/
Tone.Envelope.prototype._setCurve = function(name, direction, curve){
//check if it's a valid type
if (Tone.Envelope.Type.hasOwnProperty(curve)){
var curveDef = Tone.Envelope.Type[curve];
if (Tone.isObject(curveDef)){
this[name] = curveDef[direction];
} else {
this[name] = curveDef;
}
} else if (Tone.isArray(curve)){
this[name] = curve;
} else {
throw new Error("Tone.Envelope: invalid curve: " + curve);
}
};
/**
* The shape of the attack.
* Can be any of these strings:
@ -147,33 +194,10 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
*/
Object.defineProperty(Tone.Envelope.prototype, "attackCurve", {
get : function(){
if (Tone.isString(this._attackCurve)){
return this._attackCurve;
} else if (Tone.isArray(this._attackCurve)){
//look up the name in the curves array
for (var type in Tone.Envelope.Type){
if (Tone.Envelope.Type[type].In === this._attackCurve){
return type;
}
}
//otherwise just return the array
return this._attackCurve;
}
return this._getCurve(this._attackCurve, "In");
},
set : function(curve){
//check if it's a valid type
if (Tone.Envelope.Type.hasOwnProperty(curve)){
var curveDef = Tone.Envelope.Type[curve];
if (Tone.isObject(curveDef)){
this._attackCurve = curveDef.In;
} else {
this._attackCurve = curveDef;
}
} else if (Tone.isArray(curve)){
this._attackCurve = curve;
} else {
throw new Error("Tone.Envelope: invalid curve: " + curve);
}
this._setCurve("_attackCurve", "In", curve);
}
});
@ -187,32 +211,31 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
*/
Object.defineProperty(Tone.Envelope.prototype, "releaseCurve", {
get : function(){
if (Tone.isString(this._releaseCurve)){
return this._releaseCurve;
} else if (Tone.isArray(this._releaseCurve)){
//look up the name in the curves array
for (var type in Tone.Envelope.Type){
if (Tone.Envelope.Type[type].Out === this._releaseCurve){
return type;
}
}
//otherwise just return the array
return this._releaseCurve;
}
return this._getCurve(this._releaseCurve, "Out");
},
set : function(curve){
//check if it's a valid type
if (Tone.Envelope.Type.hasOwnProperty(curve)){
var curveDef = Tone.Envelope.Type[curve];
if (Tone.isObject(curveDef)){
this._releaseCurve = curveDef.Out;
} else {
this._releaseCurve = curveDef;
}
} else if (Tone.isArray(curve)){
this._releaseCurve = curve;
} else {
this._setCurve("_releaseCurve", "Out", curve);
}
});
/**
* The shape of the decay either "linear" or "exponential"
* @memberOf Tone.Envelope#
* @type {String}
* @name decayCurve
* @example
* env.decayCurve = "linear";
*/
Object.defineProperty(Tone.Envelope.prototype, "decayCurve", {
get : function(){
return this._decayCurve;
},
set : function(curve){
var curves = ["linear", "exponential"];
if (!curves.includes(curve)){
throw new Error("Tone.Envelope: invalid curve: " + curve);
} else {
this._decayCurve = curve;
}
}
});
@ -250,19 +273,27 @@ define(["Tone/core/Tone", "Tone/signal/Signal",
} else if (attack > 0){
this._sig.cancelAndHoldAtTime(time);
var curve = this._attackCurve;
//take only a portion of the curve
if (attack < originalAttack){
var percentComplete = 1 - attack / originalAttack;
var sliceIndex = Math.floor(percentComplete * this._attackCurve.length);
curve = this._attackCurve.slice(sliceIndex);
//the first index is the current value
curve[0] = currentValue;
//find the starting position in the curve
for (var i = 1; i < curve.length; i++){
//the starting index is between the two values
if (curve[i-1] <= currentValue && currentValue <= curve[i]){
curve = this._attackCurve.slice(i);
//the first index is the current value
curve[0] = currentValue;
break;
}
}
this._sig.setValueCurveAtTime(curve, time, attack, velocity);
}
//decay
if (decay){
this._sig.targetRampTo(velocity * this.sustain, decay, attack + time);
var decayValue = velocity * this.sustain;
var decayStart = time + attack;
if (this._decayCurve === "linear"){
this._sig.linearRampTo(decayValue, decay, decayStart);
} else if (this._decayCurve === "exponential"){
this._sig.targetRampTo(decayValue, decay, decayStart);
}
}
return this;
};

View file

@ -195,8 +195,6 @@ define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator",
set : function(count){
count = Math.max(count, 1);
if (this._oscillators.length !== count){
// var partials = this.partials;
// var type = this.type;
//dispose the previous oscillators
this._forEach(function(osc){
osc.dispose();
@ -209,7 +207,7 @@ define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator",
} else {
osc.type = this._type;
}
osc.phase = this._phase;
osc.phase = this._phase + (i / count) * 360;
osc.volume.value = -6 - count*1.1;
this.frequency.connect(osc.frequency);
this.detune.connect(osc.detune);

View file

@ -10,7 +10,7 @@ if (process.env.BROWSER === "chrome"){
} else if (process.env.BROWSER === "safari"){
BROWSERS = ["Safari"];
} else {
BROWSERS = ["HeadlessChrome"];
BROWSERS = ["HeadlessChrome", "HeadlessFirefox"];
}
module.exports = function(config){
@ -106,6 +106,7 @@ module.exports = function(config){
// enable / disable watching file and executing tests whenever any file changes
autoWatch : false,
// restartOnFileChange : true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,10 +1,60 @@
define(["Tone/component/AmplitudeEnvelope", "helper/Basic", "helper/Offline",
"Tone/component/Envelope", "helper/Test", "Tone/signal/Signal"],
function(AmplitudeEnvelope, Basic, Offline, Envelope, Test, Signal){
"Tone/component/Envelope", "helper/Test", "Tone/signal/Signal", "helper/CompareToFile", "Tone/source/Oscillator"],
function(AmplitudeEnvelope, Basic, Offline, Envelope, Test, Signal, CompareToFile, Oscillator){
describe("AmplitudeEnvelope", function(){
Basic(AmplitudeEnvelope);
context("Comparisons", function(){
it("matches a file", function(){
return CompareToFile(function(){
var ampEnv = new AmplitudeEnvelope({
attack : 0.1,
decay : 0.2,
sustain : 0.1,
release : 0.2,
}).toMaster();
var osc = new Oscillator().start(0).connect(ampEnv);
ampEnv.triggerAttack(0);
ampEnv.triggerRelease(0.3);
}, "ampEnvelope.wav");
});
it("matches a file with multiple retriggers", function(){
return CompareToFile(function(){
var ampEnv = new AmplitudeEnvelope({
attack : 0.1,
decay : 0.2,
sustain : 0.1,
release : 0.2,
}).toMaster();
var osc = new Oscillator().start(0).connect(ampEnv);
ampEnv.triggerAttack(0);
ampEnv.triggerAttack(0.3);
}, "ampEnvelope2.wav");
});
it("matches a file with ripple attack/release", function(){
return CompareToFile(function(){
var ampEnv = new AmplitudeEnvelope({
attack : 0.5,
attackCurve : "ripple",
decay : 0.2,
sustain : 0.1,
release : 0.3,
releaseCurve : "ripple",
}).toMaster();
var osc = new Oscillator().start(0).connect(ampEnv);
ampEnv.triggerAttack(0);
ampEnv.triggerRelease(0.7);
ampEnv.triggerAttack(1);
ampEnv.triggerRelease(1.6);
}, "ampEnvelope3.wav");
});
});
context("Envelope", function(){
it("handles input and output connections", function(){

View file

@ -13,7 +13,8 @@ function(Envelope, Basic, Offline, Test, PassAudio, APITest){
"sustain" : "NormalRange=",
"release" : "Time=",
"attackCurve" : ["linear", "exponential"],
"releaseCurve" : ["linear", "exponential"]
"releaseCurve" : ["linear", "exponential"],
"decayCurve" : ["linear", "exponential"]
});
APITest.constructor(Envelope, ["Time=", "Time=", "NormalRange=", "Time="]);
@ -94,6 +95,24 @@ function(Envelope, Basic, Offline, Test, PassAudio, APITest){
env2.dispose();
});
it("can set decay to exponential or linear", function(){
var env = new Envelope(0.01, 0.01, 0.5, 0.3);
env.decayCurve = "exponential";
expect(env.decayCurve).to.equal("exponential");
env.triggerAttack();
env.dispose();
//and can be linear
var env2 = new Envelope(0.01, 0.01, 0.5, 0.3);
env2.decayCurve = "linear";
expect(env2.decayCurve).to.equal("linear");
env2.triggerAttack();
//and test a non-curve
expect(function(){
env2.decayCurve = "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";
@ -157,6 +176,50 @@ function(Envelope, Basic, Offline, Test, PassAudio, APITest){
});
});
it("correctly schedules a linear decay", function(){
var e = {
attack : 0.1,
decay : 0.5,
sustain : 0,
release : 0.1,
};
return Offline(function(){
var env = new Envelope(e.attack, e.decay, e.sustain, e.release);
env.decayCurve = "linear";
env.toMaster();
env.triggerAttack(0);
}, 0.7).then(function(buffer){
expect(buffer.getValueAtTime(0.1)).to.be.closeTo(1, 0.01);
expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0.8, 0.01);
expect(buffer.getValueAtTime(0.3)).to.be.closeTo(0.6, 0.01);
expect(buffer.getValueAtTime(0.4)).to.be.closeTo(0.4, 0.01);
expect(buffer.getValueAtTime(0.5)).to.be.closeTo(0.2, 0.01);
expect(buffer.getValueAtTime(0.6)).to.be.closeTo(0, 0.01);
});
});
it("correctly schedules an exponential decay", function(){
var e = {
attack : 0.1,
decay : 0.5,
sustain : 0,
release : 0.1,
};
return Offline(function(){
var env = new Envelope(e.attack, e.decay, e.sustain, e.release);
env.decayCurve = "exponential";
env.toMaster();
env.triggerAttack(0);
}, 0.7).then(function(buffer){
expect(buffer.getValueAtTime(0.1)).to.be.closeTo(1, 0.01);
expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0.27, 0.01);
expect(buffer.getValueAtTime(0.3)).to.be.closeTo(0.07, 0.01);
expect(buffer.getValueAtTime(0.4)).to.be.closeTo(0.02, 0.01);
expect(buffer.getValueAtTime(0.5)).to.be.closeTo(0.005, 0.01);
expect(buffer.getValueAtTime(0.6)).to.be.closeTo(0, 0.01);
});
});
it("can schedule a very short attack", function(){
var e = {
attack : 0.001,
@ -432,6 +495,52 @@ function(Envelope, Basic, Offline, Test, PassAudio, APITest){
});
});
it("can schedule multiple 'sine' attack/releases with no discontinuities", function(){
return Offline(function(){
var env = new Envelope(0.1, 0.2, 0.2, 0.4).toMaster();
env.attackCurve = "sine";
env.releaseCurve = "sine";
env.triggerAttackRelease(0, 0.4);
env.triggerAttackRelease(0.4, 0.11);
env.triggerAttackRelease(0.45, 0.1);
env.triggerAttackRelease(1.1, 0.09);
env.triggerAttackRelease(1.5, 0.3);
env.triggerAttackRelease(1.8, 0.29);
}, 2).then(function(buffer){
//test for discontinuities
var lastSample = 0;
buffer.forEach(function(sample, time){
expect(sample).to.be.at.most(1);
var diff = Math.abs(lastSample - sample);
expect(diff).to.be.lessThan(0.002);
lastSample = sample;
});
});
});
it("can schedule multiple 'cosine' attack/releases with no discontinuities", function(){
return Offline(function(){
var env = new Envelope(0.1, 0.2, 0.2, 0.4).toMaster();
env.attackCurve = "cosine";
env.releaseCurve = "cosine";
env.triggerAttackRelease(0, 0.4);
env.triggerAttackRelease(0.4, 0.11);
env.triggerAttackRelease(0.45, 0.1);
env.triggerAttackRelease(1.1, 0.09);
env.triggerAttackRelease(1.5, 0.3);
env.triggerAttackRelease(1.8, 0.29);
}, 2).then(function(buffer){
//test for discontinuities
var lastSample = 0;
buffer.forEach(function(sample, time){
expect(sample).to.be.at.most(1);
var diff = Math.abs(lastSample - sample);
expect(diff).to.be.lessThan(0.002);
lastSample = sample;
});
});
});
it("reports its current envelope value (.value)", function(){
return Offline(function(){
var env = new Envelope(1, 0.2, 1).toMaster();
@ -612,24 +721,27 @@ function(Envelope, Basic, Offline, Test, PassAudio, APITest){
it("can retrigger partial envelope with custom type", function(){
return Offline(function(){
var env = new Envelope({
attack : 0.3,
attack : 0.5,
sustain : 1,
release : 0.3,
release : 0.5,
decay : 0,
attackCurve : "step",
releaseCurve : "step",
attackCurve : "cosine",
releaseCurve : "sine",
}).toMaster();
env.triggerAttackRelease(0.1, 0.3);
env.triggerAttackRelease(0.1, 0.35);
env.triggerAttackRelease(0.1, 0.8);
env.triggerAttack(0);
env.triggerRelease(0.2);
env.triggerAttack(0.5);
}, 1).then(function(buffer){
buffer.forEach(function(sample, time){
if (time > 0.3 && time < 0.5){
expect(sample).to.be.above(0);
} else if (time < 0.1){
expect(sample).to.equal(0);
}
});
expect(buffer.getValueAtTime(0)).to.equal(0);
expect(buffer.getValueAtTime(0.1)).to.be.closeTo(0.32, 0.01);
expect(buffer.getValueAtTime(0.2)).to.be.closeTo(0.6, 0.01);
expect(buffer.getValueAtTime(0.3)).to.be.closeTo(0.53, 0.01);
expect(buffer.getValueAtTime(0.4)).to.be.closeTo(0.38, 0.01);
expect(buffer.getValueAtTime(0.5)).to.be.closeTo(0.2, 0.01);
expect(buffer.getValueAtTime(0.6)).to.be.closeTo(0.52, 0.01);
expect(buffer.getValueAtTime(0.7)).to.be.closeTo(0.78, 0.01);
expect(buffer.getValueAtTime(0.8)).to.be.closeTo(0.95, 0.01);
expect(buffer.getValueAtTime(0.9)).to.be.closeTo(1, 0.01);
});
});
});

View file

@ -1,9 +1,8 @@
define(["helper/Offline", "Tone/core/Buffer", "audiobuffer-to-wav", "fft-js"], function(Offline, Buffer, audioBufferToWav, FFT){
define(["helper/Offline", "Tone/core/Buffer", "audiobuffer-to-wav", "fft-js", "Tone/core/Tone"], function(Offline, Buffer, audioBufferToWav, FFT, Tone){
return function(callback, url, threshold, RENDER_NEW){
if (!RENDER_NEW){
threshold = threshold || 20;
threshold = Tone.defaultArg(threshold, 0.001);
var baseUrl = "./audio/compare/";
return Buffer.fromUrl(baseUrl+url).then(function(buffer){
return Offline(callback, buffer.duration, buffer.numberOfChannels).then(function(renderedBuffer){
@ -16,6 +15,8 @@ define(["helper/Offline", "Tone/core/Buffer", "audiobuffer-to-wav", "fft-js"], f
//go through and compare everything
var renderedValues = buffers.rendered.toArray();
var targetValues = buffers.target.toArray();
var difference = 0;
var samples = 0;
targetValues.forEach(function(channel, channelNumber){
var fftSize = 4096;
var renderedChannel = renderedValues[channelNumber];
@ -26,11 +27,13 @@ define(["helper/Offline", "Tone/core/Buffer", "audiobuffer-to-wav", "fft-js"], f
var renderedMagnitudes = FFT.util.fftMag(renderedPhasors);
var targetMagnitudes = FFT.util.fftMag(targetPhasors);
targetMagnitudes.forEach(function(value, index){
expect(value).to.be.closeTo(renderedMagnitudes[index], threshold);
difference += Math.abs(renderedMagnitudes[index] - value);
samples++;
});
}
}
});
expect(difference/samples).to.be.lt(threshold);
});
} else {

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/AMSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile"],
function(AMSynth, Basic, InstrumentTest, CompareToFile) {
function(AMSynth, Basic, InstrumentTest, CompareToFile){
describe("AMSynth", function(){
@ -11,7 +11,7 @@ function(AMSynth, Basic, InstrumentTest, CompareToFile) {
return CompareToFile(function(){
const synth = new AMSynth().toMaster();
synth.triggerAttackRelease("C5", 0.1, 0.1);
}, "amSynth.wav", 50);
}, "amSynth.wav", 0.15);
});
context("API", function(){

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/DuoSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile", "helper/Supports"],
function(DuoSynth, Basic, InstrumentTest, CompareToFile, Supports) {
function(DuoSynth, Basic, InstrumentTest, CompareToFile, Supports){
describe("DuoSynth", function(){
@ -33,7 +33,7 @@ function(DuoSynth, Basic, InstrumentTest, CompareToFile, Supports) {
return CompareToFile(function(){
const synth = new DuoSynth().toMaster();
synth.triggerAttackRelease("C5", 0.1, 0.1);
}, "duoSynth.wav", 150);
}, "duoSynth.wav", 0.01);
});
}

View file

@ -12,7 +12,7 @@ function(FMSynth, Basic, InstrumentTest, CompareToFile, Supports){
return CompareToFile(function(){
const synth = new FMSynth().toMaster();
synth.triggerAttackRelease("G4", 0.1, 0.05);
}, "fmSynth.wav", 40);
}, "fmSynth.wav", 0.1);
});
}

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/MembraneSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile"],
function(MembraneSynth, Basic, InstrumentTest, CompareToFile) {
function(MembraneSynth, Basic, InstrumentTest, CompareToFile){
describe("MembraneSynth", function(){
@ -11,7 +11,7 @@ function(MembraneSynth, Basic, InstrumentTest, CompareToFile) {
return CompareToFile(function(){
const synth = new MembraneSynth().toMaster();
synth.triggerAttackRelease("F#2", 0.1, 0.05);
}, "membraneSynth.wav", 50);
}, "membraneSynth.wav", 0.5);
});
context("API", function(){

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/MetalSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile", "helper/Supports"],
function(MetalSynth, Basic, InstrumentTest, CompareToFile, Supports) {
function(MetalSynth, Basic, InstrumentTest, CompareToFile, Supports){
describe("MetalSynth", function(){
@ -12,7 +12,7 @@ function(MetalSynth, Basic, InstrumentTest, CompareToFile, Supports) {
return CompareToFile(function(){
const synth = new MetalSynth().toMaster();
synth.triggerAttackRelease(0.1, 0.05);
}, "metalSynth.wav", 200);
}, "metalSynth.wav", 5.9);
});
}

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/MonoSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile", "helper/Supports", "helper/Offline"],
function(MonoSynth, Basic, InstrumentTest, CompareToFile, Supports, Offline) {
function(MonoSynth, Basic, InstrumentTest, CompareToFile, Supports, Offline){
describe("MonoSynth", function(){
@ -12,7 +12,7 @@ function(MonoSynth, Basic, InstrumentTest, CompareToFile, Supports, Offline) {
return CompareToFile(function(){
const synth = new MonoSynth().toMaster();
synth.triggerAttackRelease("C4", 0.1, 0.05);
}, "monoSynth.wav", 250);
}, "monoSynth.wav", 1.75);
});
}

View file

@ -22,7 +22,7 @@ define(["Tone/instrument/NoiseSynth", "helper/Basic", "helper/InstrumentTests",
}).toMaster();
synth.triggerAttack(0);
synth.triggerAttack(0.3);
}, "noiseSynth.wav", 110);
}, "noiseSynth.wav", 3.8);
});
it("matches another file", function(){
@ -34,7 +34,7 @@ define(["Tone/instrument/NoiseSynth", "helper/Basic", "helper/InstrumentTests",
}
}).toMaster();
synth.triggerAttackRelease(0.1, 0);
}, "noiseSynthRelease.wav", 110);
}, "noiseSynthRelease.wav", 3.8);
});
context("API", function(){

View file

@ -1,6 +1,6 @@
define(["Tone/instrument/PluckSynth", "helper/Basic",
"helper/InstrumentTests", "helper/CompareToFile", "helper/Supports"],
function(PluckSynth, Basic, InstrumentTest, CompareToFile, Supports) {
function(PluckSynth, Basic, InstrumentTest, CompareToFile, Supports){
describe("PluckSynth", function(){
@ -13,7 +13,7 @@ function(PluckSynth, Basic, InstrumentTest, CompareToFile, Supports) {
return CompareToFile(function(){
const synth = new PluckSynth().toMaster();
synth.triggerAttack("C4");
}, "pluckSynth.wav", 250);
}, "pluckSynth.wav", 0.2);
});
}

View file

@ -11,7 +11,7 @@ function(Synth, Basic, InstrumentTest, APITest, Offline, Frequency, CompareToFil
return CompareToFile(function(){
const synth = new Synth().toMaster();
synth.triggerAttackRelease("C4", 0.1, 0.05);
}, "synth_basic.wav");
}, "synth_basic.wav", 0.3);
});
it("matches a file melody", function(){
@ -21,7 +21,7 @@ function(Synth, Basic, InstrumentTest, APITest, Offline, Frequency, CompareToFil
synth.triggerAttack("E4", 0.1, 0.5);
synth.triggerAttackRelease("G4", 0.5, 0.3);
synth.triggerAttackRelease("B4", 0.5, 0.5, 0.2);
}, "synth_melody.wav");
}, "synth_melody.wav", 0.3);
});
context("API", function(){

View file

@ -13,7 +13,7 @@ function(BasicTests, AMOscillator, Offline, SourceTests, OscillatorTests, Test,
return CompareToFile(function(){
var osc = new AMOscillator().toMaster();
osc.start(0.1).stop(0.4);
}, "amOscillator.wav");
}, "amOscillator.wav", 0.01);
});
context("Amplitude Modulation", function(){

View file

@ -13,7 +13,7 @@ function(BasicTests, FMOscillator, Offline, SourceTests, OscillatorTests, Test,
return CompareToFile(function(){
var osc = new FMOscillator().toMaster();
osc.start(0);
}, "fmOscillator.wav");
}, "fmOscillator.wav", 0.01);
});
context("Frequency Modulation", function(){

View file

@ -1,6 +1,6 @@
define(["helper/Basic", "Tone/source/FatOscillator", "helper/Offline",
"helper/SourceTests", "helper/OscillatorTests", "helper/CompareToFile"],
function(BasicTests, FatOscillator, Offline, SourceTests, OscillatorTests, CompareToFile) {
function(BasicTests, FatOscillator, Offline, SourceTests, OscillatorTests, CompareToFile){
describe("FatOscillator", function(){
@ -13,7 +13,7 @@ function(BasicTests, FatOscillator, Offline, SourceTests, OscillatorTests, Compa
return CompareToFile(function(){
var osc = new FatOscillator().toMaster();
osc.start(0);
}, "fatOscillator.wav");
}, "fatOscillator.wav", 0.2);
});
context("Detuned Oscillators", function(){

View file

@ -22,7 +22,7 @@ function(BasicTests, GrainPlayer, Offline, SourceTests, Buffer, Test, Tone, Comp
player.start(0.1).stop(0.2);
player.detune = -100,
player.playbackRate = 2;
}, "grainPlayer.wav");
}, "grainPlayer.wav", 0.16);
});
context("Constructor", function(){

View file

@ -1,5 +1,5 @@
define(["helper/Basic", "Tone/source/Noise", "helper/SourceTests", "helper/OutputAudio", "helper/CompareToFile"],
function(BasicTests, Noise, SourceTests, OutputAudio, CompareToFile) {
function(BasicTests, Noise, SourceTests, OutputAudio, CompareToFile){
describe("Noise", function(){
@ -11,7 +11,7 @@ define(["helper/Basic", "Tone/source/Noise", "helper/SourceTests", "helper/Outpu
return CompareToFile(function(){
const noise = new Noise().toMaster();
noise.start(0.1).stop(0.2);
}, "noise.wav", 150);
}, "noise.wav", 9);
});
context("Get/Set", function(){

View file

@ -1,6 +1,6 @@
define(["helper/Basic", "Tone/source/OmniOscillator", "helper/Offline",
"helper/SourceTests", "helper/OscillatorTests", "helper/OutputAudio", "helper/CompareToFile"],
function(BasicTests, OmniOscillator, Offline, SourceTests, OscillatorTests, OutputAudio, CompareToFile) {
function(BasicTests, OmniOscillator, Offline, SourceTests, OscillatorTests, OutputAudio, CompareToFile){
describe("OmniOscillator", function(){
@ -13,7 +13,7 @@ function(BasicTests, OmniOscillator, Offline, SourceTests, OscillatorTests, Outp
return CompareToFile(function(){
const osc = new OmniOscillator(220, "fmsquare").toMaster();
osc.start(0.1).stop(0.2);
}, "omniOscillator.wav", 100);
}, "omniOscillator.wav", 1.6);
});
context("Sound", function(){

View file

@ -1,6 +1,6 @@
define(["helper/Basic", "Tone/source/Oscillator", "helper/Offline", "helper/SourceTests",
"helper/OscillatorTests", "helper/OutputAudio", "Tone/core/Transport", "helper/CompareToFile"],
function(BasicTests, Oscillator, Offline, SourceTests, OscillatorTests, OutputAudio, Transport, CompareToFile) {
function(BasicTests, Oscillator, Offline, SourceTests, OscillatorTests, OutputAudio, Transport, CompareToFile){
describe("Oscillator", function(){
@ -14,7 +14,7 @@ function(BasicTests, Oscillator, Offline, SourceTests, OscillatorTests, OutputAu
const osc = new Oscillator().toMaster();
osc.type = "square";
osc.start(0).stop(0.2);
}, "oscillator.wav");
}, "oscillator.wav", 0.005);
});
context("Get/Set", function(){

View file

@ -21,7 +21,7 @@ function(BasicTests, Player, Offline, SourceTests, Buffer, Meter, Test, Tone, Co
const player = new Player(buffer).toMaster();
player.start(0.1).stop(0.2);
player.playbackRate = 2;
}, "player.wav");
}, "player.wav", 0.005);
});
context("Constructor", function(){

View file

@ -1,6 +1,6 @@
define(["helper/Basic", "Tone/source/PulseOscillator", "helper/Offline",
"helper/SourceTests", "helper/OscillatorTests", "helper/CompareToFile"],
function(BasicTests, PulseOscillator, Offline, SourceTests, OscillatorTests, CompareToFile) {
function(BasicTests, PulseOscillator, Offline, SourceTests, OscillatorTests, CompareToFile){
describe("PulseOscillator", function(){
@ -13,7 +13,7 @@ function(BasicTests, PulseOscillator, Offline, SourceTests, OscillatorTests, Com
return CompareToFile(function(){
var osc = new PulseOscillator().toMaster();
osc.start(0);
}, "pulseOscillator.wav", 50);
}, "pulseOscillator.wav", 0.03);
});
context("Phase Rotation", function(){

View file

@ -447,15 +447,55 @@ define(["helper/Test", "Tone/source/TickSource", "helper/Offline", "helper/Basic
source.dispose();
});
it("always increments by 1", function(){
var source = new TickSource(200);
source.frequency.setValueAtTime(200, 0);
source.frequency.linearRampToValueAtTime(1000, 4);
it("always increments by 1 at a fixed rate", function(){
var source = new TickSource(960);
source.start(0);
var previousTick = -1;
source.forEachTickBetween(0, 10, function(time, ticks){
var previousTime = -1;
source.forEachTickBetween(1000, 1010, function(time, ticks){
expect(time).to.be.gt(previousTime);
if (previousTick !== -1){
expect(ticks - previousTick).to.equal(1);
}
previousTick = ticks;
previousTime = time;
});
source.dispose();
});
it("always increments by 1 when linearly changing rate", function(){
var source = new TickSource(200);
source.frequency.setValueAtTime(200, 0);
source.frequency.linearRampToValueAtTime(1000, 100);
source.start(10);
var previousTick = -1;
var previousTime = -1;
source.forEachTickBetween(10, 30, function(time, ticks){
expect(time).to.be.gt(previousTime);
expect(ticks - previousTick).to.equal(1);
previousTick = ticks;
previousTime = time;
});
source.dispose();
});
it("always increments by 1 when setting values", function(){
var source = new TickSource(200);
source.frequency.setValueAtTime(300, 0);
source.frequency.setValueAtTime(3, 0.1);
source.frequency.setValueAtTime(100, 0.2);
source.frequency.setValueAtTime(10, 0.3);
source.frequency.setValueAtTime(1000, 0.4);
source.frequency.setValueAtTime(1, 0.5);
source.frequency.setValueAtTime(50, 0.6);
source.start(0);
var previousTick = -1;
var previousTime = -1;
source.forEachTickBetween(0, 10, function(time, ticks){
expect(time).to.be.gt(previousTime);
expect(ticks - previousTick).to.equal(1);
previousTick = ticks;
previousTime = time;
});
source.dispose();
});