Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/gba/user_scripts/XAudioJS/XAudioServer.js
28798 views
1
//2010-2013 Grant Galitz - XAudioJS realtime audio output compatibility library:
2
var XAudioJSscriptsHandle = document.getElementsByTagName("script");
3
var XAudioJSsourceHandle = XAudioJSscriptsHandle[XAudioJSscriptsHandle.length-1].src;
4
function XAudioServer(channels, sampleRate, minBufferSize, maxBufferSize, underRunCallback, volume, failureCallback) {
5
XAudioJSChannelsAllocated = Math.max(channels, 1);
6
this.XAudioJSSampleRate = Math.abs(sampleRate);
7
XAudioJSMinBufferSize = (minBufferSize >= (XAudioJSSamplesPerCallback * XAudioJSChannelsAllocated) && minBufferSize < maxBufferSize) ? (minBufferSize & (-XAudioJSChannelsAllocated)) : (XAudioJSSamplesPerCallback * XAudioJSChannelsAllocated);
8
XAudioJSMaxBufferSize = (Math.floor(maxBufferSize) > XAudioJSMinBufferSize + XAudioJSChannelsAllocated) ? (maxBufferSize & (-XAudioJSChannelsAllocated)) : (XAudioJSMinBufferSize * XAudioJSChannelsAllocated);
9
this.underRunCallback = (typeof underRunCallback == "function") ? underRunCallback : function () {};
10
XAudioJSVolume = (volume >= 0 && volume <= 1) ? volume : 1;
11
this.failureCallback = (typeof failureCallback == "function") ? failureCallback : function () { throw(new Error("XAudioJS has encountered a fatal error.")); };
12
this.initializeAudio();
13
}
14
XAudioServer.prototype.MOZWriteAudioNoCallback = function (buffer) {
15
//Resample before passing to the moz audio api:
16
var bufferLength = buffer.length;
17
for (var bufferIndex = 0; bufferIndex < bufferLength;) {
18
var sliceLength = Math.min(bufferLength - bufferIndex, XAudioJSMaxBufferSize);
19
for (var sliceIndex = 0; sliceIndex < sliceLength; ++sliceIndex) {
20
XAudioJSAudioContextSampleBuffer[sliceIndex] = buffer[bufferIndex++];
21
}
22
var resampleLength = XAudioJSResampleControl.resampler(XAudioJSGetArraySlice(XAudioJSAudioContextSampleBuffer, sliceIndex));
23
if (resampleLength > 0) {
24
var resampledResult = XAudioJSResampleControl.outputBuffer;
25
var resampledBuffer = XAudioJSGetArraySlice(resampledResult, resampleLength);
26
this.samplesAlreadyWritten += this.audioHandleMoz.mozWriteAudio(resampledBuffer);
27
}
28
}
29
}
30
XAudioServer.prototype.callbackBasedWriteAudioNoCallback = function (buffer) {
31
//Callback-centered audio APIs:
32
var length = buffer.length;
33
for (var bufferCounter = 0; bufferCounter < length && XAudioJSAudioBufferSize < XAudioJSMaxBufferSize;) {
34
XAudioJSAudioContextSampleBuffer[XAudioJSAudioBufferSize++] = buffer[bufferCounter++];
35
}
36
}
37
/*Pass your samples into here!
38
Pack your samples as a one-dimenional array
39
With the channel samples packed uniformly.
40
examples:
41
mono - [left, left, left, left]
42
stereo - [left, right, left, right, left, right, left, right]
43
*/
44
XAudioServer.prototype.writeAudio = function (buffer) {
45
switch (this.audioType) {
46
case 0:
47
this.MOZWriteAudioNoCallback(buffer);
48
this.MOZExecuteCallback();
49
break;
50
case 2:
51
this.checkFlashInit();
52
case 1:
53
case 3:
54
this.callbackBasedWriteAudioNoCallback(buffer);
55
this.callbackBasedExecuteCallback();
56
break;
57
default:
58
this.failureCallback();
59
}
60
}
61
/*Pass your samples into here if you don't want automatic callback calling:
62
Pack your samples as a one-dimenional array
63
With the channel samples packed uniformly.
64
examples:
65
mono - [left, left, left, left]
66
stereo - [left, right, left, right, left, right, left, right]
67
Useful in preventing infinite recursion issues with calling writeAudio inside your callback.
68
*/
69
XAudioServer.prototype.writeAudioNoCallback = function (buffer) {
70
switch (this.audioType) {
71
case 0:
72
this.MOZWriteAudioNoCallback(buffer);
73
break;
74
case 2:
75
this.checkFlashInit();
76
case 1:
77
case 3:
78
this.callbackBasedWriteAudioNoCallback(buffer);
79
break;
80
default:
81
this.failureCallback();
82
}
83
}
84
//Developer can use this to see how many samples to write (example: minimum buffer allotment minus remaining samples left returned from this function to make sure maximum buffering is done...)
85
//If null is returned, then that means metric could not be done.
86
XAudioServer.prototype.remainingBuffer = function () {
87
switch (this.audioType) {
88
case 0:
89
return Math.floor((this.samplesAlreadyWritten - this.audioHandleMoz.mozCurrentSampleOffset()) * XAudioJSResampleControl.ratioWeight / XAudioJSChannelsAllocated) * XAudioJSChannelsAllocated;
90
case 2:
91
this.checkFlashInit();
92
case 1:
93
case 3:
94
return (Math.floor((XAudioJSResampledSamplesLeft() * XAudioJSResampleControl.ratioWeight) / XAudioJSChannelsAllocated) * XAudioJSChannelsAllocated) + XAudioJSAudioBufferSize;
95
default:
96
this.failureCallback();
97
return null;
98
}
99
}
100
XAudioServer.prototype.MOZExecuteCallback = function () {
101
//mozAudio:
102
var samplesRequested = XAudioJSMinBufferSize - this.remainingBuffer();
103
if (samplesRequested > 0) {
104
this.MOZWriteAudioNoCallback(this.underRunCallback(samplesRequested));
105
}
106
}
107
XAudioServer.prototype.callbackBasedExecuteCallback = function () {
108
//WebKit /Flash Audio:
109
var samplesRequested = XAudioJSMinBufferSize - this.remainingBuffer();
110
if (samplesRequested > 0) {
111
this.callbackBasedWriteAudioNoCallback(this.underRunCallback(samplesRequested));
112
}
113
}
114
//If you just want your callback called for any possible refill (Execution of callback is still conditional):
115
XAudioServer.prototype.executeCallback = function () {
116
switch (this.audioType) {
117
case 0:
118
this.MOZExecuteCallback();
119
break;
120
case 2:
121
this.checkFlashInit();
122
case 1:
123
case 3:
124
this.callbackBasedExecuteCallback();
125
break;
126
default:
127
this.failureCallback();
128
}
129
}
130
//DO NOT CALL THIS, the lib calls this internally!
131
XAudioServer.prototype.initializeAudio = function () {
132
try {
133
this.initializeMozAudio();
134
}
135
catch (error) {
136
try {
137
this.initializeWebAudio();
138
}
139
catch (error) {
140
try {
141
this.initializeMediaStream();
142
}
143
catch (error) {
144
try {
145
this.initializeFlashAudio();
146
}
147
catch (error) {
148
this.audioType = -1;
149
this.failureCallback();
150
}
151
}
152
}
153
}
154
}
155
XAudioServer.prototype.initializeMediaStream = function () {
156
this.audioHandleMediaStream = new Audio();
157
this.resetCallbackAPIAudioBuffer(XAudioJSMediaStreamSampleRate);
158
if (XAudioJSMediaStreamWorker) {
159
//WebWorker is not GC'd, so manually collect it:
160
XAudioJSMediaStreamWorker.terminate();
161
}
162
XAudioJSMediaStreamWorker = new Worker(XAudioJSsourceHandle.substring(0, XAudioJSsourceHandle.length - 3) + "MediaStreamWorker.js");
163
this.audioHandleMediaStreamProcessing = new ProcessedMediaStream(XAudioJSMediaStreamWorker, XAudioJSMediaStreamSampleRate, XAudioJSChannelsAllocated);
164
this.audioHandleMediaStream.src = this.audioHandleMediaStreamProcessing;
165
this.audioHandleMediaStream.volume = XAudioJSVolume;
166
XAudioJSMediaStreamWorker.onmessage = XAudioJSMediaStreamPushAudio;
167
XAudioJSMediaStreamWorker.postMessage([1, XAudioJSResampleBufferSize, XAudioJSChannelsAllocated]);
168
this.audioHandleMediaStream.play();
169
this.audioType = 3;
170
}
171
XAudioServer.prototype.initializeMozAudio = function () {
172
this.audioHandleMoz = new Audio();
173
this.audioHandleMoz.mozSetup(XAudioJSChannelsAllocated, XAudioJSMozAudioSampleRate);
174
this.audioHandleMoz.volume = XAudioJSVolume;
175
this.samplesAlreadyWritten = 0;
176
this.audioType = 0;
177
//if (navigator.platform != "MacIntel" && navigator.platform != "MacPPC") {
178
//Add some additional buffering space to workaround a moz audio api issue:
179
var bufferAmount = (this.XAudioJSSampleRate * XAudioJSChannelsAllocated / 10) | 0;
180
bufferAmount -= bufferAmount % XAudioJSChannelsAllocated;
181
this.samplesAlreadyWritten -= bufferAmount;
182
//}
183
this.initializeResampler(XAudioJSMozAudioSampleRate);
184
}
185
XAudioServer.prototype.initializeWebAudio = function () {
186
if (!XAudioJSWebAudioLaunchedContext) {
187
try {
188
XAudioJSWebAudioContextHandle = new AudioContext(); //Create a system audio context.
189
}
190
catch (error) {
191
XAudioJSWebAudioContextHandle = new webkitAudioContext(); //Create a system audio context.
192
}
193
XAudioJSWebAudioLaunchedContext = true;
194
}
195
if (XAudioJSWebAudioAudioNode) {
196
XAudioJSWebAudioAudioNode.disconnect();
197
XAudioJSWebAudioAudioNode.onaudioprocess = null;
198
XAudioJSWebAudioAudioNode = null;
199
}
200
try {
201
XAudioJSWebAudioAudioNode = XAudioJSWebAudioContextHandle.createScriptProcessor(XAudioJSSamplesPerCallback, 0, XAudioJSChannelsAllocated); //Create the js event node.
202
}
203
catch (error) {
204
XAudioJSWebAudioAudioNode = XAudioJSWebAudioContextHandle.createJavaScriptNode(XAudioJSSamplesPerCallback, 0, XAudioJSChannelsAllocated); //Create the js event node.
205
}
206
XAudioJSWebAudioAudioNode.onaudioprocess = XAudioJSWebAudioEvent; //Connect the audio processing event to a handling function so we can manipulate output
207
XAudioJSWebAudioAudioNode.connect(XAudioJSWebAudioContextHandle.destination); //Send and chain the output of the audio manipulation to the system audio output.
208
this.resetCallbackAPIAudioBuffer(XAudioJSWebAudioContextHandle.sampleRate);
209
this.audioType = 1;
210
/*
211
Firefox has a bug in its web audio implementation...
212
The node may randomly stop playing on Mac OS X for no
213
good reason. Keep a watchdog timer to restart the failed
214
node if it glitches. Google Chrome never had this issue.
215
*/
216
XAudioJSWebAudioWatchDogLast = (new Date()).getTime();
217
if (navigator.userAgent.indexOf('Gecko/') > -1) {
218
if (XAudioJSWebAudioWatchDogTimer) {
219
clearInterval(XAudioJSWebAudioWatchDogTimer);
220
}
221
var parentObj = this;
222
XAudioJSWebAudioWatchDogTimer = setInterval(function () {
223
var timeDiff = (new Date()).getTime() - XAudioJSWebAudioWatchDogLast;
224
if (timeDiff > 500) {
225
parentObj.initializeWebAudio();
226
}
227
}, 500);
228
}
229
}
230
XAudioServer.prototype.initializeFlashAudio = function () {
231
var existingFlashload = document.getElementById("XAudioJS");
232
this.flashInitialized = false;
233
this.resetCallbackAPIAudioBuffer(44100);
234
switch (XAudioJSChannelsAllocated) {
235
case 1:
236
XAudioJSFlashTransportEncoder = XAudioJSGenerateFlashMonoString;
237
break;
238
case 2:
239
XAudioJSFlashTransportEncoder = XAudioJSGenerateFlashStereoString;
240
break;
241
default:
242
XAudioJSFlashTransportEncoder = XAudioJSGenerateFlashSurroundString;
243
}
244
if (existingFlashload == null) {
245
this.audioHandleFlash = null;
246
var thisObj = this;
247
var mainContainerNode = document.createElement("div");
248
mainContainerNode.setAttribute("style", "position: fixed; bottom: 0px; right: 0px; margin: 0px; padding: 0px; border: none; width: 8px; height: 8px; overflow: hidden; z-index: -1000; ");
249
var containerNode = document.createElement("div");
250
containerNode.setAttribute("style", "position: static; border: none; width: 0px; height: 0px; visibility: hidden; margin: 8px; padding: 0px;");
251
containerNode.setAttribute("id", "XAudioJS");
252
mainContainerNode.appendChild(containerNode);
253
document.getElementsByTagName("body")[0].appendChild(mainContainerNode);
254
swfobject.embedSWF(
255
XAudioJSsourceHandle.substring(0, XAudioJSsourceHandle.length - 9) + "JS.swf",
256
"XAudioJS",
257
"8",
258
"8",
259
"9.0.0",
260
"",
261
{},
262
{"allowscriptaccess":"always"},
263
{"style":"position: static; visibility: hidden; margin: 8px; padding: 0px; border: none"},
264
function (event) {
265
if (event.success) {
266
thisObj.audioHandleFlash = event.ref;
267
thisObj.checkFlashInit();
268
}
269
else {
270
thisObj.failureCallback();
271
thisObj.audioType = -1;
272
}
273
}
274
);
275
}
276
else {
277
this.audioHandleFlash = existingFlashload;
278
this.checkFlashInit();
279
}
280
this.audioType = 2;
281
}
282
XAudioServer.prototype.changeVolume = function (newVolume) {
283
if (newVolume >= 0 && newVolume <= 1) {
284
XAudioJSVolume = newVolume;
285
switch (this.audioType) {
286
case 0:
287
this.audioHandleMoz.volume = XAudioJSVolume;
288
case 1:
289
break;
290
case 2:
291
if (this.flashInitialized) {
292
this.audioHandleFlash.changeVolume(XAudioJSVolume);
293
}
294
else {
295
this.checkFlashInit();
296
}
297
break;
298
case 3:
299
this.audioHandleMediaStream.volume = XAudioJSVolume;
300
break;
301
default:
302
this.failureCallback();
303
}
304
}
305
}
306
//Checks to see if the NPAPI Adobe Flash bridge is ready yet:
307
XAudioServer.prototype.checkFlashInit = function () {
308
if (!this.flashInitialized) {
309
try {
310
if (this.audioHandleFlash && this.audioHandleFlash.initialize) {
311
this.flashInitialized = true;
312
this.audioHandleFlash.initialize(XAudioJSChannelsAllocated, XAudioJSVolume);
313
}
314
}
315
catch (error) {
316
this.flashInitialized = false;
317
}
318
}
319
}
320
//Set up the resampling:
321
XAudioServer.prototype.resetCallbackAPIAudioBuffer = function (APISampleRate) {
322
XAudioJSAudioBufferSize = XAudioJSResampleBufferEnd = XAudioJSResampleBufferStart = 0;
323
this.initializeResampler(APISampleRate);
324
XAudioJSResampledBuffer = this.getFloat32(XAudioJSResampleBufferSize);
325
}
326
XAudioServer.prototype.initializeResampler = function (sampleRate) {
327
XAudioJSAudioContextSampleBuffer = this.getFloat32(XAudioJSMaxBufferSize);
328
XAudioJSResampleBufferSize = Math.max(XAudioJSMaxBufferSize * Math.ceil(sampleRate / this.XAudioJSSampleRate) + XAudioJSChannelsAllocated, XAudioJSSamplesPerCallback * XAudioJSChannelsAllocated);
329
XAudioJSResampleControl = new Resampler(this.XAudioJSSampleRate, sampleRate, XAudioJSChannelsAllocated, XAudioJSResampleBufferSize, true);
330
}
331
XAudioServer.prototype.getFloat32 = function (size) {
332
try {
333
return new Float32Array(size);
334
}
335
catch (error) {
336
return [];
337
}
338
}
339
function XAudioJSFlashAudioEvent() { //The callback that flash calls...
340
XAudioJSResampleRefill();
341
return XAudioJSFlashTransportEncoder();
342
}
343
function XAudioJSGenerateFlashSurroundString() { //Convert the arrays to one long string for speed.
344
var XAudioJSTotalSamples = XAudioJSSamplesPerCallback << 1;
345
if (XAudioJSBinaryString.length > XAudioJSTotalSamples) {
346
XAudioJSBinaryString = [];
347
}
348
XAudioJSTotalSamples = 0;
349
for (var index = 0; index < XAudioJSSamplesPerCallback && XAudioJSResampleBufferStart != XAudioJSResampleBufferEnd; ++index) {
350
//Sanitize the buffer:
351
XAudioJSBinaryString[XAudioJSTotalSamples++] = String.fromCharCode(((Math.min(Math.max(XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] + 1, 0), 2) * 0x3FFF) | 0) + 0x3000);
352
XAudioJSBinaryString[XAudioJSTotalSamples++] = String.fromCharCode(((Math.min(Math.max(XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] + 1, 0), 2) * 0x3FFF) | 0) + 0x3000);
353
XAudioJSResampleBufferStart += XAudioJSChannelsAllocated - 2;
354
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
355
XAudioJSResampleBufferStart = 0;
356
}
357
}
358
return XAudioJSBinaryString.join("");
359
}
360
function XAudioJSGenerateFlashStereoString() { //Convert the arrays to one long string for speed.
361
var XAudioJSTotalSamples = XAudioJSSamplesPerCallback << 1;
362
if (XAudioJSBinaryString.length > XAudioJSTotalSamples) {
363
XAudioJSBinaryString = [];
364
}
365
for (var index = 0; index < XAudioJSTotalSamples && XAudioJSResampleBufferStart != XAudioJSResampleBufferEnd;) {
366
//Sanitize the buffer:
367
XAudioJSBinaryString[index++] = String.fromCharCode(((Math.min(Math.max(XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] + 1, 0), 2) * 0x3FFF) | 0) + 0x3000);
368
XAudioJSBinaryString[index++] = String.fromCharCode(((Math.min(Math.max(XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] + 1, 0), 2) * 0x3FFF) | 0) + 0x3000);
369
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
370
XAudioJSResampleBufferStart = 0;
371
}
372
}
373
return XAudioJSBinaryString.join("");
374
}
375
function XAudioJSGenerateFlashMonoString() { //Convert the array to one long string for speed.
376
if (XAudioJSBinaryString.length > XAudioJSSamplesPerCallback) {
377
XAudioJSBinaryString = [];
378
}
379
for (var index = 0; index < XAudioJSSamplesPerCallback && XAudioJSResampleBufferStart != XAudioJSResampleBufferEnd;) {
380
//Sanitize the buffer:
381
XAudioJSBinaryString[index++] = String.fromCharCode(((Math.min(Math.max(XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] + 1, 0), 2) * 0x3FFF) | 0) + 0x3000);
382
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
383
XAudioJSResampleBufferStart = 0;
384
}
385
}
386
return XAudioJSBinaryString.join("");
387
}
388
//Some Required Globals:
389
var XAudioJSWebAudioContextHandle = null;
390
var XAudioJSWebAudioAudioNode = null;
391
var XAudioJSWebAudioWatchDogTimer = null;
392
var XAudioJSWebAudioWatchDogLast = false;
393
var XAudioJSWebAudioLaunchedContext = false;
394
var XAudioJSAudioContextSampleBuffer = [];
395
var XAudioJSResampledBuffer = [];
396
var XAudioJSMinBufferSize = 15000;
397
var XAudioJSMaxBufferSize = 25000;
398
var XAudioJSChannelsAllocated = 1;
399
var XAudioJSVolume = 1;
400
var XAudioJSResampleControl = null;
401
var XAudioJSAudioBufferSize = 0;
402
var XAudioJSResampleBufferStart = 0;
403
var XAudioJSResampleBufferEnd = 0;
404
var XAudioJSResampleBufferSize = 0;
405
var XAudioJSMediaStreamWorker = null;
406
var XAudioJSMediaStreamBuffer = [];
407
var XAudioJSMediaStreamSampleRate = 44100;
408
var XAudioJSMozAudioSampleRate = 44100;
409
var XAudioJSSamplesPerCallback = 2048; //Has to be between 2048 and 4096 (If over, then samples are ignored, if under then silence is added).
410
var XAudioJSFlashTransportEncoder = null;
411
var XAudioJSMediaStreamLengthAliasCounter = 0;
412
var XAudioJSBinaryString = [];
413
function XAudioJSWebAudioEvent(event) { //Web Audio API callback...
414
if (XAudioJSWebAudioWatchDogTimer) {
415
XAudioJSWebAudioWatchDogLast = (new Date()).getTime();
416
}
417
//Find all output channels:
418
for (var bufferCount = 0, buffers = []; bufferCount < XAudioJSChannelsAllocated; ++bufferCount) {
419
buffers[bufferCount] = event.outputBuffer.getChannelData(bufferCount);
420
}
421
//Make sure we have resampled samples ready:
422
XAudioJSResampleRefill();
423
//Copy samples from XAudioJS to the Web Audio API:
424
for (var index = 0; index < XAudioJSSamplesPerCallback && XAudioJSResampleBufferStart != XAudioJSResampleBufferEnd; ++index) {
425
for (bufferCount = 0; bufferCount < XAudioJSChannelsAllocated; ++bufferCount) {
426
buffers[bufferCount][index] = XAudioJSResampledBuffer[XAudioJSResampleBufferStart++] * XAudioJSVolume;
427
}
428
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
429
XAudioJSResampleBufferStart = 0;
430
}
431
}
432
//Pad with silence if we're underrunning:
433
while (index < XAudioJSSamplesPerCallback) {
434
for (bufferCount = 0; bufferCount < XAudioJSChannelsAllocated; ++bufferCount) {
435
buffers[bufferCount][index] = 0;
436
}
437
++index;
438
}
439
}
440
//MediaStream API buffer push
441
function XAudioJSMediaStreamPushAudio(event) {
442
var index = 0;
443
var audioLengthRequested = event.data;
444
var samplesPerCallbackAll = XAudioJSSamplesPerCallback * XAudioJSChannelsAllocated;
445
var XAudioJSMediaStreamLengthAlias = audioLengthRequested % XAudioJSSamplesPerCallback;
446
audioLengthRequested = audioLengthRequested - (XAudioJSMediaStreamLengthAliasCounter - (XAudioJSMediaStreamLengthAliasCounter % XAudioJSSamplesPerCallback)) - XAudioJSMediaStreamLengthAlias + XAudioJSSamplesPerCallback;
447
XAudioJSMediaStreamLengthAliasCounter -= XAudioJSMediaStreamLengthAliasCounter - (XAudioJSMediaStreamLengthAliasCounter % XAudioJSSamplesPerCallback);
448
XAudioJSMediaStreamLengthAliasCounter += XAudioJSSamplesPerCallback - XAudioJSMediaStreamLengthAlias;
449
if (XAudioJSMediaStreamBuffer.length != samplesPerCallbackAll) {
450
XAudioJSMediaStreamBuffer = new Float32Array(samplesPerCallbackAll);
451
}
452
XAudioJSResampleRefill();
453
while (index < audioLengthRequested) {
454
var index2 = 0;
455
while (index2 < samplesPerCallbackAll && XAudioJSResampleBufferStart != XAudioJSResampleBufferEnd) {
456
XAudioJSMediaStreamBuffer[index2++] = XAudioJSResampledBuffer[XAudioJSResampleBufferStart++];
457
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
458
XAudioJSResampleBufferStart = 0;
459
}
460
}
461
XAudioJSMediaStreamWorker.postMessage([0, XAudioJSMediaStreamBuffer]);
462
index += XAudioJSSamplesPerCallback;
463
}
464
}
465
function XAudioJSResampleRefill() {
466
if (XAudioJSAudioBufferSize > 0) {
467
//Resample a chunk of audio:
468
var resampleLength = XAudioJSResampleControl.resampler(XAudioJSGetBufferSamples());
469
var resampledResult = XAudioJSResampleControl.outputBuffer;
470
for (var index2 = 0; index2 < resampleLength;) {
471
XAudioJSResampledBuffer[XAudioJSResampleBufferEnd++] = resampledResult[index2++];
472
if (XAudioJSResampleBufferEnd == XAudioJSResampleBufferSize) {
473
XAudioJSResampleBufferEnd = 0;
474
}
475
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferEnd) {
476
XAudioJSResampleBufferStart += XAudioJSChannelsAllocated;
477
if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) {
478
XAudioJSResampleBufferStart = 0;
479
}
480
}
481
}
482
XAudioJSAudioBufferSize = 0;
483
}
484
}
485
function XAudioJSResampledSamplesLeft() {
486
return ((XAudioJSResampleBufferStart <= XAudioJSResampleBufferEnd) ? 0 : XAudioJSResampleBufferSize) + XAudioJSResampleBufferEnd - XAudioJSResampleBufferStart;
487
}
488
function XAudioJSGetBufferSamples() {
489
return XAudioJSGetArraySlice(XAudioJSAudioContextSampleBuffer, XAudioJSAudioBufferSize);
490
}
491
function XAudioJSGetArraySlice(buffer, lengthOf) {
492
//Typed array and normal array buffer section referencing:
493
try {
494
return buffer.subarray(0, lengthOf);
495
}
496
catch (error) {
497
try {
498
//Regular array pass:
499
buffer.length = lengthOf;
500
return buffer;
501
}
502
catch (error) {
503
//Nightly Firefox 4 used to have the subarray function named as slice:
504
return buffer.slice(0, lengthOf);
505
}
506
}
507
}
508