Skip to content

Instantly share code, notes, and snippets.

@jonbro
Created September 3, 2010 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonbro/563338 to your computer and use it in GitHub Desktop.
Save jonbro/563338 to your computer and use it in GitHub Desktop.
<script type="text/javascript">
function clone(obj) {
// A clone of an object is an empty object with a prototype reference to the original.
// As such, you can access the current properties of the original through the clone.
// If you set a clone's property, it will override the orignal's property, and
// not affect the orignal. You can use the delete operator on the clone's overridden
// property to return to the earlier lookup behavior.
function Clone() { } // a private constructor, used only by this one clone.
Clone.prototype = obj;
var c = new Clone();
c.constructor = Clone;
return c;
}
var lerp = function(start, target, amt){
return start + (target-start) * amt;
};
var synth = {
start: 0,
ampEnv: [[400, 1],[20, 0]],
ampEnvStep: 0,
ampEnvAmt: 0,
lastAmp: 0,
freq: 0,
audioRequest: function(count){
//sample = dx.algo14(count);
sample = Math.sin( count * this.freq ); // tone
if(this.ampEnvStep < this.ampEnv.length){
if ((1+count-this.start)/audioRate*this.ampEnv[this.ampEnvStep][0] > 1) {
this.lastAmp = this.ampEnvAmt;
this.ampEnvStep++;
this.start = count;
}else{
this.ampEnvAmt = lerp(this.lastAmp, this.ampEnv[this.ampEnvStep][1], (1+count-this.start)/audioRate*this.ampEnv[this.ampEnvStep][0]);
}
}
sample *= this.ampEnvAmt;// vol
return sample;
},
trigger: function(count, pitch, volume){
this.start = count;
this.lastAmp = volume;
this.ampEnvStep = 0;
this.freq = 440.0*Math.pow(2.0, (pitch-60)/12);
this.freq *= 2*Math.PI/audioRate;
dx.rf = this.freq;
}
};
var m = Math;
var dx = {
f: [1,0.5,0.5,0.5,0,0],
g: function(c,f){
return this.f[f]*this.rf*c;
},
rf: 0,
algo14: function(c){
return m.sin(m.sin(this.g(c, 1))*this.g(c, 0))+m.sin(m.sin((m.sin(this.g(c, 4)+m.sin(this.g(c, 5)*m.sin(this.g(c, 5)))))*this.g(c, 3))*this.g(c, 2));
}
}
// Create an Audio interface
var output = new Audio();
var audioRate = 44100.0;
// Set up a mono channel at 44.1Khz
output.mozSetup( 1, audioRate );
// samples/second * 120/1 * 60/1
var beatLength = 60*audioRate/(120.0*16);
var beat = 0;
var triggers1 = [
[1, 36], [1, 36], [1, 36], [0],
[1, 36], [0], [1, 36], [0],
[1, 36], [0], [1, 36], [0],
[1, 36], [0], [1, 36], [1, 36],
[1, 36], [0], [1, 36], [0],
[1, 36], [0], [1, 36], [0],
[1, 36], [1, 36], [0], [1, 36],
[1, 36], [1, 36], [1, 36], [1, 36]
];
var triggers2 = [
[0], [1, 56], [0], [1, 56],
[0], [1, 56], [0], [1, 56],
[0], [1, 56], [0], [1, 56],
[1, 56], [1, 53], [1, 51], [1, 50]
];
synth2 = clone(synth);
synth2.ampEnv = [[2, 1],[500, 0]];
// Create a sample buffer array
//num triggers, trigger size
var samples;
function writeLong(){
samples = new Float32Array( Math.ceil(32 * 16 * beatLength) );
for(var i=0, l=samples.length; i<l; i++){
remainder = i%beatLength;
if(remainder == 0){
if (triggers1[beat%triggers1.length][0] == 1) {
synth.trigger(i, triggers1[beat%triggers1.length][1], 0);
};
if (triggers2[beat%triggers2.length][0] == 1) {
synth2.trigger(i, triggers2[beat%triggers2.length][1], 0);
};
beat++;
}
samples[i] = synth.audioRequest(i)+synth2.audioRequest(i)*0.45;
}
return samples;
}
function writeShort(){
samples = new Float32Array( Math.ceil(beatLength*30) );
synth.ampEnv = [[2, 1],[500, 0]];
synth.trigger(0, 36, 0);
for(var i=0, l=samples.length; i<l; i++){
samples[i] = synth.audioRequest(i);
}
return samples;
}
</script>
<button onclick="output.mozWriteAudio( writeLong() );">Play</button>
<button onclick="output.mozWriteAudio( writeShort() );">Play Short</button>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment