-
Notifications
You must be signed in to change notification settings - Fork 0
/
ks.js
63 lines (62 loc) · 2.06 KB
/
ks.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
/** Karplus-Strong string synthesis.
* See: http:// en.wikipedia.org/wiki/Karplus-Strong_string_synthesis
* https://ccrma.stanford.edu/realsimple/faust_strings/faust_strings.pdf
*/
// Use freq=0 to suppress output.
function KS(sampleRate, freq, volume) {
this.reset(sampleRate, freq, volume);
}
KS.prototype = {
// sample rate of this generator
sampleRate: 1,
// Buffer length of buffer1; buffer2 is 1 sample longer
// (We use linear interpolation to simulate non-integer delays)
bufferLen: 0,
// Shorter sample buffer: equal to bufferLen
buffer1: null,
// Longer sample buffer: 1 longer than bufferLen
buffer2: null,
// Position in buffer1
buffer1Pos: 0,
// Position in buffer2
buffer2Pos: 0,
// Actual buffer length is (bufferLen + fracLen); fracLen is in [0,1)
fracLen: 0,
// Current sample generated by this synthesizer
sample: 0,
generate: function() {
var next1 = this.buffer1[this.buffer1Pos];
var next2 = this.buffer2[this.buffer2Pos];
var next = next1*(1-this.fracLen) + next2*this.fracLen;
var feedback = (this.sample + next) / 2.01;
this.buffer1[this.buffer1Pos++] = feedback;
this.buffer2[this.buffer2Pos++] = feedback;
this.sample = next;
if (this.buffer1Pos >= this.bufferLen) {
this.buffer1Pos = 0;
}
if (this.buffer2Pos > this.bufferLen) {
this.buffer2Pos = 0;
}
},
getMix: function() {
return this.sample;
},
reset: function(sampleRate, freq, volume) {
volume = volume || 1;
this.sampleRate = sampleRate || this.sampleRate;
var length = freq ? ((this.sampleRate/freq)-.5) : 100;
this.bufferLen = Math.floor(length);
this.fracLen = length - this.bufferLen;
this.buffer1 = new Float32Array(this.bufferLen);
this.buffer2 = new Float32Array(this.bufferLen+1);
if (!freq) volume=0;
for (var i=0; i<=this.bufferLen; i++) {
this.buffer2[i] = 2*(Math.random()-0.5)*volume;
if (i<this.bufferLen)
this.buffer1[i] = this.buffer2[i];
}
this.buffer1Pos = this.buffer2Pos = 0;
this.sample = this.buffer2[this.bufferLen];
}
}