//This file is part of the XAudioJS library. var XAudioJSResampledBuffer = []; var XAudioJSOutputBuffer = []; var XAudioJSResampleBufferStart = 0; var XAudioJSResampleBufferEnd = 0; var XAudioJSResampleBufferSize = 0; var XAudioJSChannelsAllocated = 1; //Message Receiver: self.onmessage = function (event) { var data = event.data; switch (data[0]) { case 0: //Add new audio samples to our ring buffer: var resampledResult = data[1]; var length = resampledResult.length; for (var i = 0; i < length; ++i) { XAudioJSResampledBuffer[XAudioJSResampleBufferEnd++] = resampledResult[i]; if (XAudioJSResampleBufferEnd == XAudioJSResampleBufferSize) { XAudioJSResampleBufferEnd = 0; } if (XAudioJSResampleBufferStart == XAudioJSResampleBufferEnd) { XAudioJSResampleBufferStart += XAudioJSChannelsAllocated; if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) { XAudioJSResampleBufferStart = 0; } } } break; case 1: //Initialize: XAudioJSResampleBufferSize = data[1]; XAudioJSChannelsAllocated = data[2]; XAudioJSResampledBuffer = new Float32Array(XAudioJSResampleBufferSize); } } //MediaStream Polyfill Event: self.onprocessmedia = function (event) { //Get some buffer length computations: var apiBufferLength = event.audioLength; var apiBufferLengthAll = apiBufferLength * event.audioChannels; if (apiBufferLengthAll > XAudioJSOutputBuffer.length) { XAudioJSOutputBuffer = new Float32Array(apiBufferLengthAll); } //De-interleave the buffered audio while looping through our ring buffer: var sampleFramesCount = Math.min(apiBufferLength, XAudioJSResampledSamplesLeft() / XAudioJSChannelsAllocated); for (var sampleFramePosition = 0, channelOffset = 0; sampleFramePosition < sampleFramesCount; ++sampleFramePosition) { for (channelOffset = sampleFramePosition; channelOffset < apiBufferLengthAll; channelOffset += apiBufferLength) { XAudioJSOutputBuffer[channelOffset] = XAudioJSResampledBuffer[XAudioJSResampleBufferStart++]; if (XAudioJSResampleBufferStart == XAudioJSResampleBufferSize) { XAudioJSResampleBufferStart = 0; } } } //Add some zero fill if we underran the required buffer fill amount: while (sampleFramePosition < apiBufferLength) { for (channelOffset = sampleFramePosition++; channelOffset < apiBufferLengthAll; channelOffset += apiBufferLength) { XAudioJSOutputBuffer[channelOffset] = 0; } } //Write some buffered audio: event.writeAudio(XAudioJSOutputBuffer.subarray(0, apiBufferLengthAll)); //Request a buffer from the main thread: self.postMessage(event.audioLength); } //Accessory function used to determine remaining samples in the ring buffer: function XAudioJSResampledSamplesLeft() { return ((XAudioJSResampleBufferStart <= XAudioJSResampleBufferEnd) ? 0 : XAudioJSResampleBufferSize) + XAudioJSResampleBufferEnd - XAudioJSResampleBufferStart; }