-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaudio.js
More file actions
94 lines (79 loc) · 2.71 KB
/
audio.js
File metadata and controls
94 lines (79 loc) · 2.71 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
function AudioDataDestination(sampleRate, readFn) {
// Initialize the audio output.
var audio = new Audio();
audio.mozSetup(1, sampleRate);
var currentWritePosition = 0;
var prebufferSize = sampleRate / 2; // buffer 500ms
var tail = null;
// The function called with regular interval to populate
// the audio output buffer.
setInterval(function() {
var written;
// Check if some data was not written in previous attempts.
if(tail) {
written = audio.mozWriteAudio(tail);
currentWritePosition += written;
if(written < tail.length) {
// Not all the data was written, saving the tail...
tail = tail.slice(written);
return; // ... and exit the function.
}
tail = null;
}
// Check if we need add some data to the audio output.
var currentPosition = audio.mozCurrentSampleOffset();
var available = currentPosition + prebufferSize - currentWritePosition;
if(available > 0) {
// Request some sound data from the callback function.
var soundData = new Float32Array(available);
readFn(soundData);
// Writting the data.
written = audio.mozWriteAudio(soundData);
if(written < soundData.length) {
// Not all the data was written, saving the tail.
tail = soundData.slice(written);
}
currentWritePosition += written;
}
}, 100);
}
// Control and generate the sound.
var frequency = 0, currentSoundSample;
var sampleRate = 44100;
function requestSoundData(soundData) {
if (!frequency) {
return; // no sound selected
}
square(soundData);
}
function sine(soundData) {
var k = 2* Math.PI * frequency / sampleRate;
for (var i=0, size=soundData.length; i<size; i++) {
soundData[i] = volume *= Math.sin(k * currentSoundSample++);
}
}
function square(soundData) {
var k = 2* Math.PI * frequency / sampleRate;
var overtones = 20;
for (var i=0, size=soundData.length; i<size; i++) {
soundData[i] = 0;
for(var j=0; j != overtones; j++) {
var o = 2*j + 1;
soundData[i] += 1/o * Math.sin(o * k * currentSoundSample);
}
soundData[i] *= volume;
currentSoundSample++;
}
}
var audioDestination = new AudioDataDestination(sampleRate, requestSoundData);
var volume = 1.0;
function setVolume() {
volume = parseFloat(document.getElementById("vol").value);
}
function start() {
currentSoundSample = 0;
frequency = parseFloat(document.getElementById("freq").value);
}
function stop() {
frequency = 0;
}