-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaudio.js
More file actions
120 lines (92 loc) · 2.89 KB
/
Copy pathaudio.js
File metadata and controls
120 lines (92 loc) · 2.89 KB
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
108
109
110
111
112
113
114
115
116
117
118
119
120
// simple web audio synthesizer
// @blurspline
// Instrument synthesis code based on http://www.iquilezles.org/
var skipLow = -36
function noteOn(note, vol, delay) {
// console.log(note, vol);
if (note) play(note, vol ? vol * 0.5 : vol, delay)
}
/***
* Web Audio Synth
*/
var AC = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
if (!AC) {
console.log('Web Audio API not found');
}
var audioContext = new AC();
var sampleRate = 44100;
var bufferLength = 1 * sampleRate; // 1 second
var buffer;
var samples;
// Number of cache notes
var notes = 12 * 10; // octaves
var noteSamples = new Array(notes);
var buffers = 16;
var currentBuffer = 0;
var playbackBuffers = new Array(buffers);
var i;
var sin = Math.sin;
var cos = Math.cos;
var exp = Math.exp;
function func(w,num,buf, isr) { // sound function
for(var i=0; i<num; i++ ) {
var t = i*isr;
var y = 0.0;
// Audio Synth Code here
// Modified from iq (2006) - http://www.iquilezles.org/apps/soundtoy/?p=Piano%202
y = 0.2 * sin(0.25 * w * t) * exp(-40 * t);
y += 0.5 * sin(0.5 * w * t) * exp(-10 * t);
y += 0.9*sin(1.0*w*t)*exp(-0.0008*w*t);
y += 0.3*sin(2.0*w*t)*exp(-0.0010*w*t);
y += 0.1*sin(4.0*w*t)*exp(-0.0015*w*t);
y += 0.2*y*y*y;
y *= 0.9 + 0.1*cos(170.0*t);
buf[i] = y;
}
}
function generateSample(note, outputBuffer) {
var semitones = note - 69; // Semitones from A440 (Midi no 69)
var frequency = 440.0 * Math.pow( 2.0, semitones / 12.0 );
var wavelength = Math.PI * 2 * frequency;
var isr = 1.0 / sampleRate; // inverse sample rate
func(wavelength, bufferLength, outputBuffer, isr);
}
// A0 - 21, C1 - 24, C2 - 36
console.time('generate')
for (i=0; i<notes; i++) {
samples = new Float32Array(bufferLength);
generateSample(i + 12, samples);
noteSamples[i] = samples;
}
console.timeEnd('generate')
var current = 0;
// Caching samples for all notes
for (i=0; i<buffers;i++) {
buffer = audioContext.createBuffer(1, bufferLength, sampleRate);
playbackBuffers[i] = buffer;
}
var vol = 100;
var gainNode = audioContext.createGain();
gainNode.connect(audioContext.destination);
// gainNode.gain.value = 0.5 * vol / 100.0;
function play(k, vol, delay) {
currentBuffer = ++currentBuffer % 8;;
if (vol !== undefined) gainNode.gain.setTargetAtTime(vol, 0, 0)
if (k>noteSamples.length || k < 0) {
console.log('out of range', k);
return;
}
var destinationBuffer = playbackBuffers[currentBuffer].getChannelData(0);
var num = bufferLength;
var sourceBuffer = noteSamples[k];
for( i=0; i<bufferLength; i++) {
destinationBuffer[i] = sourceBuffer[i];
}
var node = audioContext.createBufferSource();
node.buffer = playbackBuffers[currentBuffer];
node.connect(gainNode);
// console.log('delay', delay, audioContext.currentTime + delay)
node.start(delay > 0 ? audioContext.currentTime + delay : 0);
}
// if (RANDOM_DURATIONS) PlayLoop();
// else setInterval(PlayLoop, 400);