-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFMToneGenerator.js
108 lines (87 loc) · 2.81 KB
/
FMToneGenerator.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
var FMToneGenerator = function() {
this.sampleRate = 0;
this.algorithm = 0;
this.phaseIncrement = new Array(4);
this.fixed = new Array(4);
this.freq = new Array(4);
this.phase = new Array(4);
this.output = new Array(4);
this.eg = new Array(4);
this.velsens = new Array(4);
this.velocity = 0.0;
this.feedback = 0.0;
this.egStopCount = 0;
this.onAllEGStopped = null;
for (var i = 0; i < 4; i++) {
this.phaseIncrement[i] = 0.0;
this.freq[i] = 0.0;
this.phase[i] = 0.0;
this.output[i] = 0.0;
this.eg[i] = new EG();
this.velsens[i] = false;
}
};
FMToneGenerator.prototype.generateAudio = function(e) {
var left = e.outputBuffer.getChannelData(0);
var right = e.outputBuffer.getChannelData(1);
var numSamples = right.length;
for (var i = 0; i < numSamples; i++) {
main_output = 0;
for (var op = 3; op >= 0; op--) {
var mod_output = 0;
for (var op_mod = 0; op_mod < 4; op_mod++) {
mod_output += this.algorithm[op][op_mod] * this.output[op_mod];
}
mod_output *= 10;
if (op == 3) {
mod_output += this.output[op] * this.feedback * 3;
}
this.output[op] = Math.sin(this.phase[op] + mod_output) * this.eg[op].amp * this.eg[op].amp;
if (this.velsens[op]) {
this.output[op] *= this.velocity;
}
this.phase[op] += this.phaseIncrement[op];
main_output += this.output[op] * this.algorithm[4][op];
}
right[i] = left[i] = main_output;
for (var op = 0; op < 4; op++) {
this.eg[op].next();
}
}
};
FMToneGenerator.prototype.noteOn = function(noteNo, velocity) {
var self = this;
function calcPhaseIncrement(freq) {
return 2 * Math.PI * freq / self.sampleRate;
}
this.velocity = velocity;
for (var i = 0; i < 4; i++) {
if (this.fixed[i] == true) {
this.phaseIncrement[i] = calcPhaseIncrement(this.freq[i]);
} else {
this.phaseIncrement[i] = calcPhaseIncrement(440 * Math.pow(2.0, (noteNo - 69) / 12.0)) * this.freq[i];
}
this.phase[i] = 0.0;
this.output[i] = 0.0;
}
for (var i = 0; i < 4; i++) {
this.eg[i].note_on();
}
};
FMToneGenerator.prototype.noteOff = function(noteNo) {
this.egStopCount = 4;
for (var i = 0; i < 4; i++) {
this.eg[i].onEGStopped = function () {
this.egStopCount--;
if (this.egStopCount == 0) {
if (this.onAllEGStopped != null) {
this.onAllEGStopped();
}
}
}.bind(this);
this.eg[i].note_off();
}
};
FMToneGenerator.prototype.changeAlgorithm = function(algNo) {
this.algorithm = OpConnection[algNo];
};