audio.html
3.41 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
<html>
<head>
<title>Chunked Audio Test</title>
</head>
<body>
<button>Play</button>
</body>
</html>
<script src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var streamOffset = 0;
var Base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
var CharIdxArray = { };
for (var i = 0; i < Base64Chars.length; i++) CharIdxArray[Base64Chars[i]] = i;
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
var audioContext = new AudioContext();
var segments = [];
var ended = true;
function playNextSegment()
{
if (segments.length > 0 && ended)
{
ended = false;
var audioBufferSouceNode = audioContext.createBufferSource();
audioBufferSouceNode.onended = function()
{
// playNextSegment();
ended = true;
console.log('play ended...');
}
audioBufferSouceNode.buffer = segments.shift();
audioBufferSouceNode.connect(audioContext.destination);
audioBufferSouceNode.start(0);
}
}
$(document).ready(function()
{
var decodeCallback = function(buffer)
{
segments.push(buffer);
};
$('button').click(function()
{
var xhr = new XMLHttpRequest();
xhr.open('GET', '/audio/' + location.hash.substring(1), true);
xhr.onprogress = function()
{
var audioData = xhr.responseText;
while (true)
{
var audio = base64Decode(audioData);
if (audio == null) break;
console.log('decoded: ' + audio.length);
audioContext.decodeAudioData(audio.buffer, decodeCallback);
}
}
xhr.send();
});
setInterval(playNextSegment, 50);
});
function base64Decode(text)
{
var i, k = 0, l;
if (text.length < streamOffset + 8) return null;
var blockLength = parseInt(text.substring(streamOffset, streamOffset + 8), 16);
console.log('block: ' + blockLength);
if (text.length < streamOffset + 8 + blockLength) return null;
var audioBuffer = new Uint8Array(new ArrayBuffer(2048), 0);
for (i = streamOffset + 8, l = text.length; i < l && k < blockLength; )
{
var a = CharIdxArray[text.charAt(i + 0)];
var b = CharIdxArray[text.charAt(i + 1)];
var c = CharIdxArray[text.charAt(i + 2)];
var d = CharIdxArray[text.charAt(i + 3)];
var b1 = ((a << 2) | (b >> 4)) & 0xff;
var b2 = ((b << 4) | (c >> 2)) & 0xff;
var b3 = ((c << 6) | (d)) & 0xff;
audioBuffer[k++] = b1;
audioBuffer[k++] = b2;
audioBuffer[k++] = b3;
i += 4;
}
streamOffset += blockLength + 8;
/*
var hex = [];
for (i = 0; i < k && i < 32; i++)
{
var ch = (audioBuffer[i] & 0xff).toString(16).toUpperCase();
hex.push(ch.length == 1 ? '0' + ch : ch);
hex.push(' ');
if (i % 4 == 3) hex.push(" ");
if (i % 16 == 15) hex.push("\n");
}
console.log(hex.join(''));
*/
return audioBuffer.subarray(k);
}
</script>