jsynth-midi
Version:
time based function for reading events from midi files
87 lines (84 loc) • 2.59 kB
JavaScript
var sampleRate = 48000
var bpm = 120;
var numer = 4;
var bps = bpm / 60;
var spb = sampleRate / bps;
var secpb = 60 / bpm;
var d = spb * 4 / 4;
var player = require('./index');
var baudio = require('../baudio');
var Time = require('since-when');
var b = baudio({rate:sampleRate, size: 256 * 2 * 2, duration: (sampleRate * 16 * 60) + 's'});
var fs = require('fs');
var file = fs.readFileSync('./rach.mid', 'binary');
var midi = player(sampleRate, file);
var notes = {};
var tau = Math.PI * 2;
var TIME = 0;
var time = new Time();
var jynth = require('jynth');
var synth = new jynth();
var jdelay = require('jdelay');
var amod = require('amod');
var delay = jdelay(sampleRate / 16, 1, .5, 48000);
var delay2 = jdelay(d, 0, .332, 48000);
//var m = require('midi');
//var output = new m.output();
//output.openPort(0);
b.push(function(time){
var e = midi(time *1.05);
if(e && e.length){
e.forEach(function(event){
if(event.subtype == 'noteOn'){
//output.sendMessage([144, event.noteNumber, event.velocity])
var f = 440 * Math.pow(2, (event.noteNumber - 49) / 12);
if(notes[event.noteNumber] && notes[event.noteNumber].play) notes[event.noteNumber].play = false;
notes[event.noteNumber] = {play: true, start: new Date().getTime(), f: f, v: event.velocity}
}
else if(event.subtype == 'noteOff'){
//output.sendMessage([128, event.noteNumber, event.velocity])
delete notes[event.noteNumber]
}
else if(event.subtype == 'setTempo'){
bpm = 60000000 / event.microsecondsPerBeat;
bps = bpm / 60;
spb = sampleRate / bps;
d = spb;
secpb = 60 / bpm;
}
else if(event.subtype == 'timeSignature'){
numer = event.numerator;
}
})
};
delete e
var sample = x = 0;
for(n in notes){
var hammer = false
, v = notes[n].v / 100;
x++;
if(notes[n].f < 1100) hammer = true;
sample +=
synth(time, 0, notes[n].f)
.sine(hammer ? .72 * v : .52 * v, notes[n].f)
.sine(hammer ? .72 * v / 3: .52 * v / 3, notes[n].f)
.triangle(hammer ? .72 * v / 9 : .52 * v / 9, notes[n].f)
.envelope(
[1/64, v],
[((hammer?2/3: 2/4)) * v , v/3],
[((hammer?2/12: 2/8)) * v , v / 5],
[1/(hammer?2:1) , 0]
)
.amod(.1, .05, bpm/4)
.sample
}
if(x) sample = (sample / Math.sqrt(x))
// return sample
return delay(sample, Math.floor(sampleRate * bpm / 100))
return delay(sample, amod(sampleRate / 16, amod(66, 35, time, 2), time, 3))
return delay2(delay(sample, amod(sampleRate / 16, amod(50, 35, time, 2), time, 3)), spb)
});
b.play();
//b.record('rachMaster.take2.wav');
//time.every(1e9/1100, loop, false)
//b.play();