-
Notifications
You must be signed in to change notification settings - Fork 0
/
fm.js
59 lines (52 loc) · 1.93 KB
/
fm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// fm.js
// FM synthesis
//
// MUMT307 project - Alastair Porter
function makeFM(frequency, bufferSize) {
var sampleRate = 44100;
var ops = [];
var envs = [];
// FM only uses the first 2 operators, regardless of
// if they are on or not
for (var i = 0; i < 2; i++) {
var oper = $('#operator'+(i+1)).operator();
var env = $('#envelope'+(i+1)).envelope();
ops.push(oper.getSettings().freqRatio);
envs.push(env.getSettings());
}
if (ops.length > 0) {
startSample = currentSoundSample;
var ret = new Float32Array(bufferSize);
// Make Envelope
e = envs[0];
startLevel = e.l1/100.0;
attackLevel = e.l2/100.0;
sustainLevel = e.l3/100.0;
attack = e.r1 * (sampleRate / 1000);
decay = e.r2 * (sampleRate / 1000);
var k = 2* Math.PI * frequency * ops[0] / sampleRate;
var modulator = new Float32Array(bufferSize);
for (var i=0, size=ret.length; i<size; i++) {
amp = getEnvelopeLevel(currentSoundSample, startLevel, attackLevel, attack, decay, sustainLevel);
modulator[i] = Math.sin(k * currentSoundSample++) * amp;
}
if (ops.length > 1) {
for (var o = 1; o < ops.length; o++) {
var sample = startSample
e = envs[o];
startLevel = e.l1/100.0;
attackLevel = e.l2/100.0;
sustainLevel = e.l3/100.0;
attack = e.r1 * (sampleRate / 1000);
decay = e.r2 * (sampleRate / 1000);
for (var i=0, size=ret.length; i<size; i++) {
var k = 2* Math.PI * (modulator[i] + ops[o]) / sampleRate;
amp = getEnvelopeLevel(sample, startLevel, attackLevel, attack, decay, sustainLevel);
ret[i] = Math.sin(k * sample++) * amp;
}
}
}
return ret;
}
return [];
}