-
Notifications
You must be signed in to change notification settings - Fork 1
/
readWav.html
172 lines (154 loc) · 5.52 KB
/
readWav.html
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>read wav file</title>
<link rel="stylesheet" href="">
<style>
button {
padding: 5px 8px;
cursor: pointer;
}
</style>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<h1>read wav file</h1>
<button id="btn1" disabled="true">Read Wav and make noise</button>
<button id="btn2">Stop</button>
<p id="progress"></p>
</body>
<script>
var playButton1 = document.getElementById('btn1');
var stopBtn = document.getElementById('btn2');
var progress = document.getElementById('progress');
// Create AudioContext and buffer source
var audioCtx = new AudioContext();
var source = audioCtx.createBufferSource();
var audioBuffer = null;
// Create a ScriptProcessorNode with a bufferSize of 4096 and a single input and output channel
var scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
console.log(scriptNode.bufferSize);
// load in an audio track via XHR and decodeAudioData
function getData() {
request = new XMLHttpRequest();
request.open('GET', 'audio.wav', true);
request.responseType = 'arraybuffer';
request.onload = function () {
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function (buffer) {
console.log('myBuffer', buffer);
audioBuffer = buffer;
playButton1.removeAttribute('disabled');
}, function (e) {
console.error("Error with decoding audio data: " + e)
});
}
request.onprogress = function(event) {
if (event.lengthComputable) {
var percentComplete = (event.loaded / event.total * 100).toFixed(2);
var percentText = 'Read wav file completion progress: ' + percentComplete + '%';
progress.innerHTML = percentText;
}
}
request.send();
}
getData();
// Give the node a function to process audio events
scriptNode.onaudioprocess = function (audioProcessingEvent) {
// The input buffer is the song we loaded earlier
var inputBuffer = audioProcessingEvent.inputBuffer;
// The output buffer contains the samples that will be modified and played
var outputBuffer = audioProcessingEvent.outputBuffer;
// Loop through the output channels (in this case there is only one)
for (var channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
var inputData = inputBuffer.getChannelData(channel);
var outputData = outputBuffer.getChannelData(channel);
var springFactor = 48000 / 48000;
// Loop through the 4096 samples
for (var sample = 0; sample < inputBuffer.length; sample += springFactor) {
// make output equal to the same as the input
var s = Math.max(-1, Math.min(1, inputData[sample]));
if (sample > 3000 && sample <= 3022) {
console.log(inputData[sample], s, s < 0 ? s * 0x8000 : s * 0x7FFF);
}
outputData[sample] = s < 0 ? Math.round(s * 0x8000) : Math.round(s * 0x7FFF);
// add noise to each output sample
// outputData[sample] += ((Math.random() * 2) - 1) * 0.2;
}
}
}
function floatTo16BitPCM(output, input) {
for (var i = 0; i < input.length; i++) {
var s = Math.max(-1, Math.min(1, input[i]));
if (i > 30000 && i <= 30022) {
console.log(input[i], s, s < 0 ? s * 0x8000 : s * 0x7FFF);
}
output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
}
}
function int16ToInt8Array(input) {
return Int8Array.from(input);
}
function int16ToAudioBuffer(input) {
var myArrayBuffer = audioCtx.createBuffer(1, input.length, audioCtx.sampleRate);
var nowBuffering = myArrayBuffer.getChannelData(0);
for (var i = 0; i < input.length; i++) {
nowBuffering[i] = input[i];
}
return myArrayBuffer;
}
function compress (orignData, newRate) { //合并压缩
//压缩
var compression = parseInt(48000 / newRate);
var length = orignData.length / compression;
var result = new Float32Array(length);
var index = 0, j = 1;
while (index < length) {
result[index] = orignData[orignData.length - j];
j++;
index++;
}
return result;
}
function interpolateArray(data, newSampleRate) {
var fitCount = Math.round(data.length * (newSampleRate / 48000));
var newData = new Array();
var springFactor = new Number((data.length - 1) / (fitCount - 1));
newData[0] = data[0]; // for new allocation
for (var i = 1; i < fitCount - 1; i++) {
var tmp = i * springFactor;
var before = new Number(Math.floor(tmp)).toFixed();
var after = new Number(Math.ceil(tmp)).toFixed();
var atPoint = tmp - before;
newData[i] = linearInterpolate(data[before], data[after], atPoint);
}
newData[fitCount - 1] = data[data.length - 1]; // for new allocation
return newData;
};
function linearInterpolate(before, after, atPoint) {
return before + (after - before) * atPoint;
};
// wire up play button
playButton1.onclick = function () {
source.buffer = audioBuffer;
source.loop = true;
source.connect(scriptNode);
scriptNode.connect(audioCtx.destination);
source.start(0);
}
// stop
stopBtn.onclick = function () {
source.stop(0);
}
// When the buffer source stops playing, disconnect everything
source.onended = function () {
source.disconnect(scriptNode);
scriptNode.disconnect(audioCtx.destination);
}
</script>
</html>