1 line
353 KiB
Plaintext
1 line
353 KiB
Plaintext
{"version":3,"file":"icecast-metadata-player-1.17.3.main.min.js","mappings":"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","sources":["webpack://IcecastMetadataPlayer/webpack/runtime/chunk loaded","webpack://IcecastMetadataPlayer/webpack/runtime/load script","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/constants.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/utilities.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/HeaderCache.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/globals.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/Parser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/containers/Frame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/CodecFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/metadata/ID3v2.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/CodecHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/mpeg/MPEGHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/mpeg/MPEGFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/mpeg/MPEGParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/aac/AACHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/aac/AACFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/aac/AACParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/flac/FLACFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/flac/FLACHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/flac/FLACParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/containers/ogg/OggPageHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/containers/ogg/OggPage.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/opus/OpusFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/opus/OpusHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/opus/OpusParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/vorbis/VorbisFrame.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/vorbis/VorbisHeader.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/codecs/vorbis/VorbisParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/containers/ogg/OggParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/src/CodecParser.js","webpack://IcecastMetadataPlayer/./node_modules/codec-parser/index.js","webpack://IcecastMetadataPlayer/webpack/bootstrap","webpack://IcecastMetadataPlayer/webpack/runtime/chunk prefetch function","webpack://IcecastMetadataPlayer/webpack/runtime/define property getters","webpack://IcecastMetadataPlayer/webpack/runtime/ensure chunk","webpack://IcecastMetadataPlayer/webpack/runtime/get javascript chunk filename","webpack://IcecastMetadataPlayer/webpack/runtime/global","webpack://IcecastMetadataPlayer/webpack/runtime/hasOwnProperty shorthand","webpack://IcecastMetadataPlayer/webpack/runtime/make namespace object","webpack://IcecastMetadataPlayer/webpack/runtime/publicPath","webpack://IcecastMetadataPlayer/webpack/runtime/jsonp chunk loading","webpack://IcecastMetadataPlayer/webpack/runtime/startup prefetch","webpack://IcecastMetadataPlayer/./src/global.js","webpack://IcecastMetadataPlayer/./src/EventTargetPolyfill.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/MetadataParser/Stats.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/MetadataParser/MetadataParser.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/MetadataParser/IcyMetadataParser.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/MetadataParser/OggMetadataParser.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/MetadataParser/DualMetadataParser.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/IcecastMetadataReader.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/IcecastReadableStream.js","webpack://IcecastMetadataPlayer/./node_modules/icecast-metadata-js/src/IcecastMetadataQueue.js","webpack://IcecastMetadataPlayer/./src/FrameQueue.js","webpack://IcecastMetadataPlayer/./src/players/Player.js","webpack://IcecastMetadataPlayer/./src/players/HTML5Player.js","webpack://IcecastMetadataPlayer/./src/players/MediaSourcePlayer.js","webpack://IcecastMetadataPlayer/./src/players/WebAudioPlayer.js","webpack://IcecastMetadataPlayer/./src/PlayerFactory.js","webpack://IcecastMetadataPlayer/./src/IcecastMetadataPlayer.js"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","var inProgress = {};\nvar dataWebpackPrefix = \"IcecastMetadataPlayer:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = (url, done, key, chunkId) => {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tscript.timeout = 120;\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tvar onScriptComplete = (prev, event) => {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tvar doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach((fn) => (fn(event)));\n\t\tif(prev) return prev(event);\n\t}\n\tvar timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","const symbol = Symbol;\n\n// prettier-ignore\n/*\n[\n [\n \"left, right\",\n \"left, right, center\",\n \"left, center, right\",\n \"center, left, right\",\n \"center\"\n ],\n [\n \"front left, front right\",\n \"front left, front right, front center\",\n \"front left, front center, front right\",\n \"front center, front left, front right\",\n \"front center\"\n ],\n [\n \"side left, side right\",\n \"side left, side right, side center\",\n \"side left, side center, side right\",\n \"side center, side left, side right\",\n \"side center\"\n ],\n [\n \"rear left, rear right\",\n \"rear left, rear right, rear center\",\n \"rear left, rear center, rear right\",\n \"rear center, rear left, rear right\",\n \"rear center\"\n ]\n]\n*/\n\nconst mappingJoin = \", \";\n\nexport const channelMappings = (() => {\n const front = \"front\";\n const side = \"side\";\n const rear = \"rear\";\n const left = \"left\";\n const center = \"center\";\n const right = \"right\";\n\n return [\"\", front + \" \", side + \" \", rear + \" \"].map((x) =>\n [\n [left, right],\n [left, right, center],\n [left, center, right],\n [center, left, right],\n [center],\n ].flatMap((y) => y.map((z) => x + z).join(mappingJoin)),\n );\n})();\n\nexport const lfe = \"LFE\";\nexport const monophonic = \"monophonic (mono)\";\nexport const stereo = \"stereo\";\nconst surround = \"surround\";\n\nexport const getChannelMapping = (channelCount, ...mappings) =>\n `${\n [\n monophonic,\n stereo,\n `linear ${surround}`,\n \"quadraphonic\",\n `5.0 ${surround}`,\n `5.1 ${surround}`,\n `6.1 ${surround}`,\n `7.1 ${surround}`,\n ][channelCount - 1]\n } (${mappings.join(mappingJoin)})`;\n\n// prettier-ignore\nexport const vorbisOpusChannelMapping = [\n monophonic,\n getChannelMapping(2,channelMappings[0][0]),\n getChannelMapping(3,channelMappings[0][2]),\n getChannelMapping(4,channelMappings[1][0],channelMappings[3][0]),\n getChannelMapping(5,channelMappings[1][2],channelMappings[3][0]),\n getChannelMapping(6,channelMappings[1][2],channelMappings[3][0],lfe),\n getChannelMapping(7,channelMappings[1][2],channelMappings[2][0],channelMappings[3][4],lfe),\n getChannelMapping(8,channelMappings[1][2],channelMappings[2][0],channelMappings[3][0],lfe),\n]\n\n// sampleRates\nexport const rate192000 = 192000;\nexport const rate176400 = 176400;\nexport const rate96000 = 96000;\nexport const rate88200 = 88200;\nexport const rate64000 = 64000;\nexport const rate48000 = 48000;\nexport const rate44100 = 44100;\nexport const rate32000 = 32000;\nexport const rate24000 = 24000;\nexport const rate22050 = 22050;\nexport const rate16000 = 16000;\nexport const rate12000 = 12000;\nexport const rate11025 = 11025;\nexport const rate8000 = 8000;\nexport const rate7350 = 7350;\n\n// header key constants\nexport const absoluteGranulePosition = \"absoluteGranulePosition\";\nexport const bandwidth = \"bandwidth\";\nexport const bitDepth = \"bitDepth\";\nexport const bitrate = \"bitrate\";\nexport const bitrateMaximum = bitrate + \"Maximum\";\nexport const bitrateMinimum = bitrate + \"Minimum\";\nexport const bitrateNominal = bitrate + \"Nominal\";\nexport const buffer = \"buffer\";\nexport const bufferFullness = buffer + \"Fullness\";\nexport const codec = \"codec\";\nexport const codecFrames = codec + \"Frames\";\nexport const coupledStreamCount = \"coupledStreamCount\";\nexport const crc = \"crc\";\nexport const crc16 = crc + \"16\";\nexport const crc32 = crc + \"32\";\nexport const data = \"data\";\nexport const description = \"description\";\nexport const duration = \"duration\";\nexport const emphasis = \"emphasis\";\nexport const hasOpusPadding = \"hasOpusPadding\";\nexport const header = \"header\";\nexport const isContinuedPacket = \"isContinuedPacket\";\nexport const isCopyrighted = \"isCopyrighted\";\nexport const isFirstPage = \"isFirstPage\";\nexport const isHome = \"isHome\";\nexport const isLastPage = \"isLastPage\";\nexport const isOriginal = \"isOriginal\";\nexport const isPrivate = \"isPrivate\";\nexport const isVbr = \"isVbr\";\nexport const layer = \"layer\";\nexport const length = \"length\";\nexport const mode = \"mode\";\nexport const modeExtension = mode + \"Extension\";\nexport const mpeg = \"mpeg\";\nexport const mpegVersion = mpeg + \"Version\";\nexport const numberAACFrames = \"numberAAC\" + \"Frames\";\nexport const outputGain = \"outputGain\";\nexport const preSkip = \"preSkip\";\nexport const profile = \"profile\";\nexport const profileBits = symbol();\nexport const protection = \"protection\";\nexport const rawData = \"rawData\";\nexport const segments = \"segments\";\nexport const subarray = \"subarray\";\nexport const version = \"version\";\nexport const vorbis = \"vorbis\";\nexport const vorbisComments = vorbis + \"Comments\";\nexport const vorbisSetup = vorbis + \"Setup\";\n\nconst block = \"block\";\nexport const blockingStrategy = block + \"ingStrategy\";\nexport const blockingStrategyBits = symbol();\nexport const blockSize = block + \"Size\";\nexport const blocksize0 = block + \"size0\";\nexport const blocksize1 = block + \"size1\";\nexport const blockSizeBits = symbol();\n\nconst channel = \"channel\";\nexport const channelMappingFamily = channel + \"MappingFamily\";\nexport const channelMappingTable = channel + \"MappingTable\";\nexport const channelMode = channel + \"Mode\";\nexport const channelModeBits = symbol();\nexport const channels = channel + \"s\";\n\nconst copyright = \"copyright\";\nexport const copyrightId = copyright + \"Id\";\nexport const copyrightIdStart = copyright + \"IdStart\";\n\nexport const frame = \"frame\";\nexport const frameCount = frame + \"Count\";\nexport const frameLength = frame + \"Length\";\n\nconst Number = \"Number\";\nexport const frameNumber = frame + Number;\nexport const framePadding = frame + \"Padding\";\nexport const frameSize = frame + \"Size\";\n\nconst Rate = \"Rate\";\nexport const inputSampleRate = \"inputSample\" + Rate;\n\nconst page = \"page\";\nexport const pageChecksum = page + \"Checksum\";\nexport const pageSegmentBytes = symbol();\nexport const pageSegmentTable = page + \"SegmentTable\";\nexport const pageSequenceNumber = page + \"Sequence\" + Number;\n\nconst sample = \"sample\";\nexport const sampleNumber = sample + Number;\nexport const sampleRate = sample + Rate;\nexport const sampleRateBits = symbol();\nexport const samples = sample + \"s\";\n\nconst stream = \"stream\";\nexport const streamCount = stream + \"Count\";\nexport const streamInfo = stream + \"Info\";\nexport const streamSerialNumber = stream + \"Serial\" + Number;\nexport const streamStructureVersion = stream + \"StructureVersion\";\n\nconst total = \"total\";\nexport const totalBytesOut = total + \"BytesOut\";\nexport const totalDuration = total + \"Duration\";\nexport const totalSamples = total + \"Samples\";\n\n// private methods\nexport const readRawData = symbol();\nexport const incrementRawData = symbol();\nexport const mapCodecFrameStats = symbol();\nexport const mapFrameStats = symbol();\nexport const logWarning = symbol();\nexport const logError = symbol();\nexport const syncFrame = symbol();\nexport const fixedLengthFrameSync = symbol();\nexport const getHeader = symbol();\nexport const setHeader = symbol();\nexport const getFrame = symbol();\nexport const parseFrame = symbol();\nexport const parseOggPage = symbol();\nexport const checkCodecUpdate = symbol();\nexport const reset = symbol();\nexport const enable = symbol();\nexport const getHeaderFromUint8Array = symbol();\nexport const checkFrameFooterCrc16 = symbol();\n\nexport const uint8Array = Uint8Array;\nexport const dataView = DataView;\n\nexport const reserved = \"reserved\";\nexport const bad = \"bad\";\nexport const free = \"free\";\nexport const none = \"none\";\nexport const sixteenBitCRC = \"16bit CRC\";\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { length, uint8Array } from \"./constants.js\";\n\nconst getCrcTable = (crcTable, crcInitialValueFunction, crcFunction) => {\n for (let byte = 0; byte < crcTable[length]; byte++) {\n let crc = crcInitialValueFunction(byte);\n\n for (let bit = 8; bit > 0; bit--) crc = crcFunction(crc);\n\n crcTable[byte] = crc;\n }\n return crcTable;\n};\n\nconst crc8Table = getCrcTable(\n new uint8Array(256),\n (b) => b,\n (crc) => (crc & 0x80 ? 0x07 ^ (crc << 1) : crc << 1),\n);\n\nconst flacCrc16Table = [\n getCrcTable(\n new Uint16Array(256),\n (b) => b << 8,\n (crc) => (crc << 1) ^ (crc & (1 << 15) ? 0x8005 : 0),\n ),\n];\n\nconst crc32Table = [\n getCrcTable(\n new Uint32Array(256),\n (b) => b,\n (crc) => (crc >>> 1) ^ ((crc & 1) * 0xedb88320),\n ),\n];\n\n// build crc tables\nfor (let i = 0; i < 15; i++) {\n flacCrc16Table.push(new Uint16Array(256));\n crc32Table.push(new Uint32Array(256));\n\n for (let j = 0; j <= 0xff; j++) {\n flacCrc16Table[i + 1][j] =\n flacCrc16Table[0][flacCrc16Table[i][j] >>> 8] ^\n (flacCrc16Table[i][j] << 8);\n\n crc32Table[i + 1][j] =\n (crc32Table[i][j] >>> 8) ^ crc32Table[0][crc32Table[i][j] & 0xff];\n }\n}\n\nconst crc8 = (data) => {\n let crc = 0;\n const dataLength = data[length];\n\n for (let i = 0; i !== dataLength; i++) crc = crc8Table[crc ^ data[i]];\n\n return crc;\n};\n\nconst flacCrc16 = (data) => {\n const dataLength = data[length];\n const crcChunkSize = dataLength - 16;\n let crc = 0;\n let i = 0;\n\n while (i <= crcChunkSize) {\n crc ^= (data[i++] << 8) | data[i++];\n crc =\n flacCrc16Table[15][crc >> 8] ^\n flacCrc16Table[14][crc & 0xff] ^\n flacCrc16Table[13][data[i++]] ^\n flacCrc16Table[12][data[i++]] ^\n flacCrc16Table[11][data[i++]] ^\n flacCrc16Table[10][data[i++]] ^\n flacCrc16Table[9][data[i++]] ^\n flacCrc16Table[8][data[i++]] ^\n flacCrc16Table[7][data[i++]] ^\n flacCrc16Table[6][data[i++]] ^\n flacCrc16Table[5][data[i++]] ^\n flacCrc16Table[4][data[i++]] ^\n flacCrc16Table[3][data[i++]] ^\n flacCrc16Table[2][data[i++]] ^\n flacCrc16Table[1][data[i++]] ^\n flacCrc16Table[0][data[i++]];\n }\n\n while (i !== dataLength)\n crc = ((crc & 0xff) << 8) ^ flacCrc16Table[0][(crc >> 8) ^ data[i++]];\n\n return crc;\n};\n\nconst crc32Function = (data) => {\n const dataLength = data[length];\n const crcChunkSize = dataLength - 16;\n let crc = 0;\n let i = 0;\n\n while (i <= crcChunkSize)\n crc =\n crc32Table[15][(data[i++] ^ crc) & 0xff] ^\n crc32Table[14][(data[i++] ^ (crc >>> 8)) & 0xff] ^\n crc32Table[13][(data[i++] ^ (crc >>> 16)) & 0xff] ^\n crc32Table[12][data[i++] ^ (crc >>> 24)] ^\n crc32Table[11][data[i++]] ^\n crc32Table[10][data[i++]] ^\n crc32Table[9][data[i++]] ^\n crc32Table[8][data[i++]] ^\n crc32Table[7][data[i++]] ^\n crc32Table[6][data[i++]] ^\n crc32Table[5][data[i++]] ^\n crc32Table[4][data[i++]] ^\n crc32Table[3][data[i++]] ^\n crc32Table[2][data[i++]] ^\n crc32Table[1][data[i++]] ^\n crc32Table[0][data[i++]];\n\n while (i !== dataLength)\n crc = crc32Table[0][(crc ^ data[i++]) & 0xff] ^ (crc >>> 8);\n\n return crc ^ -1;\n};\n\nconst concatBuffers = (...buffers) => {\n const buffer = new uint8Array(\n buffers.reduce((acc, buf) => acc + buf[length], 0),\n );\n\n buffers.reduce((offset, buf) => {\n buffer.set(buf, offset);\n return offset + buf[length];\n }, 0);\n\n return buffer;\n};\n\nconst bytesToString = (bytes) => String.fromCharCode(...bytes);\n\n// prettier-ignore\nconst reverseTable = [0x0,0x8,0x4,0xc,0x2,0xa,0x6,0xe,0x1,0x9,0x5,0xd,0x3,0xb,0x7,0xf];\nconst reverse = (val) =>\n (reverseTable[val & 0b1111] << 4) | reverseTable[val >> 4];\n\nclass BitReader {\n constructor(data) {\n this._data = data;\n this._pos = data[length] * 8;\n }\n\n set position(position) {\n this._pos = position;\n }\n\n get position() {\n return this._pos;\n }\n\n read(bits) {\n const byte = Math.floor(this._pos / 8);\n const bit = this._pos % 8;\n this._pos -= bits;\n\n const window =\n (reverse(this._data[byte - 1]) << 8) + reverse(this._data[byte]);\n\n return (window >> (7 - bit)) & 0xff;\n }\n}\n\nexport {\n crc8,\n flacCrc16,\n crc32Function,\n reverse,\n concatBuffers,\n bytesToString,\n BitReader,\n};\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport {\n getHeader,\n setHeader,\n checkCodecUpdate,\n reset,\n enable,\n} from \"../constants.js\";\n\nexport default class HeaderCache {\n constructor(onCodecHeader, onCodecUpdate) {\n this._onCodecHeader = onCodecHeader;\n this._onCodecUpdate = onCodecUpdate;\n this[reset]();\n }\n\n [enable]() {\n this._isEnabled = true;\n }\n\n [reset]() {\n this._headerCache = new Map();\n this._codecUpdateData = new WeakMap();\n this._codecHeaderSent = false;\n this._codecShouldUpdate = false;\n this._bitrate = null;\n this._isEnabled = false;\n }\n\n [checkCodecUpdate](bitrate, totalDuration) {\n if (this._onCodecUpdate) {\n if (this._bitrate !== bitrate) {\n this._bitrate = bitrate;\n this._codecShouldUpdate = true;\n }\n\n // only update if codec data is available\n const codecData = this._codecUpdateData.get(\n this._headerCache.get(this._currentHeader),\n );\n\n if (this._codecShouldUpdate && codecData) {\n this._onCodecUpdate(\n {\n bitrate,\n ...codecData,\n },\n totalDuration,\n );\n }\n\n this._codecShouldUpdate = false;\n }\n }\n\n [getHeader](key) {\n const header = this._headerCache.get(key);\n\n if (header) {\n this._updateCurrentHeader(key);\n }\n\n return header;\n }\n\n [setHeader](key, header, codecUpdateFields) {\n if (this._isEnabled) {\n if (!this._codecHeaderSent) {\n this._onCodecHeader({ ...header });\n this._codecHeaderSent = true;\n }\n this._updateCurrentHeader(key);\n\n this._headerCache.set(key, header);\n this._codecUpdateData.set(header, codecUpdateFields);\n }\n }\n\n _updateCurrentHeader(key) {\n if (this._onCodecUpdate && key !== this._currentHeader) {\n this._codecShouldUpdate = true;\n this._currentHeader = key;\n }\n }\n}\n","export const headerStore = new WeakMap();\nexport const frameStore = new WeakMap();\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore } from \"../globals.js\";\nimport {\n frame,\n length,\n incrementRawData,\n mapFrameStats,\n logWarning,\n syncFrame,\n fixedLengthFrameSync,\n getFrame,\n getHeader,\n reset,\n enable,\n} from \"../constants.js\";\n\n/**\n * @abstract\n * @description Abstract class containing methods for parsing codec frames\n */\nexport default class Parser {\n constructor(codecParser, headerCache) {\n this._codecParser = codecParser;\n this._headerCache = headerCache;\n }\n\n *[syncFrame]() {\n let frameData;\n\n do {\n frameData = yield* this.Frame[getFrame](\n this._codecParser,\n this._headerCache,\n 0,\n );\n if (frameData) return frameData;\n this._codecParser[incrementRawData](1); // increment to continue syncing\n } while (true);\n }\n\n /**\n * @description Searches for Frames within bytes containing a sequence of known codec frames.\n * @param {boolean} ignoreNextFrame Set to true to return frames even if the next frame may not exist at the expected location\n * @returns {Frame}\n */\n *[fixedLengthFrameSync](ignoreNextFrame) {\n let frameData = yield* this[syncFrame]();\n const frameLength = frameStore.get(frameData)[length];\n\n if (\n ignoreNextFrame ||\n this._codecParser._flushing ||\n // check if there is a frame right after this one\n (yield* this.Header[getHeader](\n this._codecParser,\n this._headerCache,\n frameLength,\n ))\n ) {\n this._headerCache[enable](); // start caching when synced\n\n this._codecParser[incrementRawData](frameLength); // increment to the next frame\n this._codecParser[mapFrameStats](frameData);\n return frameData;\n }\n\n this._codecParser[logWarning](\n `Missing ${frame} at ${frameLength} bytes from current position.`,\n `Dropping current ${frame} and trying again.`,\n );\n this._headerCache[reset](); // frame is invalid and must re-sync and clear cache\n this._codecParser[incrementRawData](1); // increment to invalidate the current frame\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore } from \"../globals.js\";\nimport { data, header } from \"../constants.js\";\n\n/**\n * @abstract\n */\nexport default class Frame {\n constructor(headerValue, dataValue) {\n frameStore.set(this, { [header]: headerValue });\n\n this[data] = dataValue;\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore, headerStore } from \"../globals.js\";\nimport {\n sampleRate,\n length,\n frameNumber,\n header,\n samples,\n duration,\n totalBytesOut,\n totalSamples,\n totalDuration,\n frameLength,\n subarray,\n readRawData,\n getFrame,\n getHeader,\n} from \"../constants.js\";\nimport Frame from \"../containers/Frame.js\";\n\nexport default class CodecFrame extends Frame {\n static *[getFrame](Header, Frame, codecParser, headerCache, readOffset) {\n const headerValue = yield* Header[getHeader](\n codecParser,\n headerCache,\n readOffset,\n );\n\n if (headerValue) {\n const frameLengthValue = headerStore.get(headerValue)[frameLength];\n const samplesValue = headerStore.get(headerValue)[samples];\n\n const frame = (yield* codecParser[readRawData](\n frameLengthValue,\n readOffset,\n ))[subarray](0, frameLengthValue);\n\n return new Frame(headerValue, frame, samplesValue);\n } else {\n return null;\n }\n }\n\n constructor(headerValue, dataValue, samplesValue) {\n super(headerValue, dataValue);\n\n this[header] = headerValue;\n this[samples] = samplesValue;\n this[duration] = (samplesValue / headerValue[sampleRate]) * 1000;\n this[frameNumber] = null;\n this[totalBytesOut] = null;\n this[totalSamples] = null;\n this[totalDuration] = null;\n\n frameStore.get(this)[length] = dataValue[length];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n// https://id3.org/Developer%20Information\n\nimport { length, version, readRawData } from \"../constants.js\";\n\nconst unsynchronizationFlag = \"unsynchronizationFlag\";\nconst extendedHeaderFlag = \"extendedHeaderFlag\";\nconst experimentalFlag = \"experimentalFlag\";\nconst footerPresent = \"footerPresent\";\n\nexport default class ID3v2 {\n static *getID3v2Header(codecParser, headerCache, readOffset) {\n const headerLength = 10;\n const header = {};\n\n let data = yield* codecParser[readRawData](3, readOffset);\n // Byte (0-2 of 9)\n // ID3\n if (data[0] !== 0x49 || data[1] !== 0x44 || data[2] !== 0x33) return null;\n\n data = yield* codecParser[readRawData](headerLength, readOffset);\n\n // Byte (3-4 of 9)\n // * `BBBBBBBB|........`: Major version\n // * `........|BBBBBBBB`: Minor version\n header[version] = `id3v2.${data[3]}.${data[4]}`;\n\n // Byte (5 of 9)\n // * `....0000.: Zeros (flags not implemented yet)\n if (data[5] & 0b00001111) return null;\n\n // Byte (5 of 9)\n // * `CDEF0000`: Flags\n // * `C.......`: Unsynchronisation (indicates whether or not unsynchronisation is used)\n // * `.D......`: Extended header (indicates whether or not the header is followed by an extended header)\n // * `..E.....`: Experimental indicator (indicates whether or not the tag is in an experimental stage)\n // * `...F....`: Footer present (indicates that a footer is present at the very end of the tag)\n header[unsynchronizationFlag] = !!(data[5] & 0b10000000);\n header[extendedHeaderFlag] = !!(data[5] & 0b01000000);\n header[experimentalFlag] = !!(data[5] & 0b00100000);\n header[footerPresent] = !!(data[5] & 0b00010000);\n\n // Byte (6-9 of 9)\n // * `0.......|0.......|0.......|0.......`: Zeros\n if (\n data[6] & 0b10000000 ||\n data[7] & 0b10000000 ||\n data[8] & 0b10000000 ||\n data[9] & 0b10000000\n )\n return null;\n\n // Byte (6-9 of 9)\n // * `.FFFFFFF|.FFFFFFF|.FFFFFFF|.FFFFFFF`: Tag Length\n // The ID3v2 tag size is encoded with four bytes where the most significant bit (bit 7)\n // is set to zero in every byte, making a total of 28 bits. The zeroed bits are ignored,\n // so a 257 bytes long tag is represented as $00 00 02 01.\n const dataLength =\n (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | data[9];\n\n header[length] = headerLength + dataLength;\n\n return new ID3v2(header);\n }\n\n constructor(header) {\n this[version] = header[version];\n this[unsynchronizationFlag] = header[unsynchronizationFlag];\n this[extendedHeaderFlag] = header[extendedHeaderFlag];\n this[experimentalFlag] = header[experimentalFlag];\n this[footerPresent] = header[footerPresent];\n this[length] = header[length];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { headerStore } from \"../globals.js\";\nimport {\n bitDepth,\n channelMode,\n sampleRate,\n bitrate,\n channels,\n} from \"../constants.js\";\n\nexport default class CodecHeader {\n /**\n * @private\n */\n constructor(header) {\n headerStore.set(this, header);\n\n this[bitDepth] = header[bitDepth];\n this[bitrate] = null; // set during frame mapping\n this[channels] = header[channels];\n this[channelMode] = header[channelMode];\n this[sampleRate] = header[sampleRate];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport {\n reserved,\n bad,\n free,\n none,\n sixteenBitCRC,\n rate44100,\n rate48000,\n rate32000,\n rate22050,\n rate24000,\n rate16000,\n rate11025,\n rate12000,\n rate8000,\n monophonic,\n stereo,\n bitDepth,\n channelMode,\n sampleRate,\n bitrate,\n channels,\n isOriginal,\n isPrivate,\n layer,\n length,\n mpegVersion,\n frameLength,\n protection,\n emphasis,\n framePadding,\n isCopyrighted,\n modeExtension,\n description,\n samples,\n subarray,\n readRawData,\n incrementRawData,\n getHeader,\n setHeader,\n} from \"../../constants.js\";\nimport { bytesToString } from \"../../utilities.js\";\n\nimport ID3v2 from \"../../metadata/ID3v2.js\";\nimport CodecHeader from \"../CodecHeader.js\";\n\n// http://www.mp3-tech.org/programmer/frame_header.html\n\nconst bitrateMatrix = {\n // bits | V1,L1 | V1,L2 | V1,L3 | V2,L1 | V2,L2 & L3\n 0b00000000: [free, free, free, free, free],\n 0b00010000: [32, 32, 32, 32, 8],\n // 0b00100000: [64, 48, 40, 48, 16,],\n // 0b00110000: [96, 56, 48, 56, 24,],\n // 0b01000000: [128, 64, 56, 64, 32,],\n // 0b01010000: [160, 80, 64, 80, 40,],\n // 0b01100000: [192, 96, 80, 96, 48,],\n // 0b01110000: [224, 112, 96, 112, 56,],\n // 0b10000000: [256, 128, 112, 128, 64,],\n // 0b10010000: [288, 160, 128, 144, 80,],\n // 0b10100000: [320, 192, 160, 160, 96,],\n // 0b10110000: [352, 224, 192, 176, 112,],\n // 0b11000000: [384, 256, 224, 192, 128,],\n // 0b11010000: [416, 320, 256, 224, 144,],\n // 0b11100000: [448, 384, 320, 256, 160,],\n 0b11110000: [bad, bad, bad, bad, bad],\n};\n\nconst calcBitrate = (idx, interval, intervalOffset) =>\n 8 *\n (((idx + intervalOffset) % interval) + interval) *\n (1 << ((idx + intervalOffset) / interval)) -\n 8 * interval * ((interval / 8) | 0);\n\n// generate bitrate matrix\nfor (let i = 2; i < 15; i++)\n bitrateMatrix[i << 4] = [\n i * 32, // V1,L1\n calcBitrate(i, 4, 0), // V1,L2\n calcBitrate(i, 4, -1), // V1,L3\n calcBitrate(i, 8, 4), // V2,L1\n calcBitrate(i, 8, 0), // V2,L2 & L3\n ];\n\nconst v1Layer1 = 0;\nconst v1Layer2 = 1;\nconst v1Layer3 = 2;\nconst v2Layer1 = 3;\nconst v2Layer23 = 4;\n\nconst bands = \"bands \";\nconst to31 = \" to 31\";\nconst layer12ModeExtensions = {\n 0b00000000: bands + 4 + to31,\n 0b00010000: bands + 8 + to31,\n 0b00100000: bands + 12 + to31,\n 0b00110000: bands + 16 + to31,\n};\n\nconst bitrateIndex = \"bitrateIndex\";\nconst v2 = \"v2\";\nconst v1 = \"v1\";\n\nconst intensityStereo = \"Intensity stereo \";\nconst msStereo = \", MS stereo \";\nconst on = \"on\";\nconst off = \"off\";\nconst layer3ModeExtensions = {\n 0b00000000: intensityStereo + off + msStereo + off,\n 0b00010000: intensityStereo + on + msStereo + off,\n 0b00100000: intensityStereo + off + msStereo + on,\n 0b00110000: intensityStereo + on + msStereo + on,\n};\n\nconst layersValues = {\n 0b00000000: { [description]: reserved },\n 0b00000010: {\n [description]: \"Layer III\",\n [framePadding]: 1,\n [modeExtension]: layer3ModeExtensions,\n [v1]: {\n [bitrateIndex]: v1Layer3,\n [samples]: 1152,\n },\n [v2]: {\n [bitrateIndex]: v2Layer23,\n [samples]: 576,\n },\n },\n 0b00000100: {\n [description]: \"Layer II\",\n [framePadding]: 1,\n [modeExtension]: layer12ModeExtensions,\n [samples]: 1152,\n [v1]: {\n [bitrateIndex]: v1Layer2,\n },\n [v2]: {\n [bitrateIndex]: v2Layer23,\n },\n },\n 0b00000110: {\n [description]: \"Layer I\",\n [framePadding]: 4,\n [modeExtension]: layer12ModeExtensions,\n [samples]: 384,\n [v1]: {\n [bitrateIndex]: v1Layer1,\n },\n [v2]: {\n [bitrateIndex]: v2Layer1,\n },\n },\n};\n\nconst mpegVersionDescription = \"MPEG Version \";\nconst isoIec = \"ISO/IEC \";\nconst mpegVersions = {\n 0b00000000: {\n [description]: `${mpegVersionDescription}2.5 (later extension of MPEG 2)`,\n [layer]: v2,\n [sampleRate]: {\n 0b00000000: rate11025,\n 0b00000100: rate12000,\n 0b00001000: rate8000,\n 0b00001100: reserved,\n },\n },\n 0b00001000: { [description]: reserved },\n 0b00010000: {\n [description]: `${mpegVersionDescription}2 (${isoIec}13818-3)`,\n [layer]: v2,\n [sampleRate]: {\n 0b00000000: rate22050,\n 0b00000100: rate24000,\n 0b00001000: rate16000,\n 0b00001100: reserved,\n },\n },\n 0b00011000: {\n [description]: `${mpegVersionDescription}1 (${isoIec}11172-3)`,\n [layer]: v1,\n [sampleRate]: {\n 0b00000000: rate44100,\n 0b00000100: rate48000,\n 0b00001000: rate32000,\n 0b00001100: reserved,\n },\n },\n length,\n};\n\nconst protectionValues = {\n 0b00000000: sixteenBitCRC,\n 0b00000001: none,\n};\n\nconst emphasisValues = {\n 0b00000000: none,\n 0b00000001: \"50/15 ms\",\n 0b00000010: reserved,\n 0b00000011: \"CCIT J.17\",\n};\n\nconst channelModes = {\n 0b00000000: { [channels]: 2, [description]: stereo },\n 0b01000000: { [channels]: 2, [description]: \"joint \" + stereo },\n 0b10000000: { [channels]: 2, [description]: \"dual channel\" },\n 0b11000000: { [channels]: 1, [description]: monophonic },\n};\n\nexport default class MPEGHeader extends CodecHeader {\n static *[getHeader](codecParser, headerCache, readOffset) {\n const header = {};\n\n // check for id3 header\n const id3v2Header = yield* ID3v2.getID3v2Header(\n codecParser,\n headerCache,\n readOffset,\n );\n\n if (id3v2Header) {\n // throw away the data. id3 parsing is not implemented yet.\n yield* codecParser[readRawData](id3v2Header[length], readOffset);\n codecParser[incrementRawData](id3v2Header[length]);\n }\n\n // Must be at least four bytes.\n const data = yield* codecParser[readRawData](4, readOffset);\n\n // Check header cache\n const key = bytesToString(data[subarray](0, 4));\n const cachedHeader = headerCache[getHeader](key);\n if (cachedHeader) return new MPEGHeader(cachedHeader);\n\n // Frame sync (all bits must be set): `11111111|111`:\n if (data[0] !== 0xff || data[1] < 0xe0) return null;\n\n // Byte (2 of 4)\n // * `111BBCCD`\n // * `...BB...`: MPEG Audio version ID\n // * `.....CC.`: Layer description\n // * `.......D`: Protection bit (0 - Protected by CRC (16bit CRC follows header), 1 = Not protected)\n\n // Mpeg version (1, 2, 2.5)\n const mpegVersionValues = mpegVersions[data[1] & 0b00011000];\n if (mpegVersionValues[description] === reserved) return null;\n\n // Layer (I, II, III)\n const layerBits = data[1] & 0b00000110;\n if (layersValues[layerBits][description] === reserved) return null;\n const layerValues = {\n ...layersValues[layerBits],\n ...layersValues[layerBits][mpegVersionValues[layer]],\n };\n\n header[mpegVersion] = mpegVersionValues[description];\n header[layer] = layerValues[description];\n header[samples] = layerValues[samples];\n header[protection] = protectionValues[data[1] & 0b00000001];\n\n header[length] = 4;\n\n // Byte (3 of 4)\n // * `EEEEFFGH`\n // * `EEEE....`: Bitrate index. 1111 is invalid, everything else is accepted\n // * `....FF..`: Sample rate\n // * `......G.`: Padding bit, 0=frame not padded, 1=frame padded\n // * `.......H`: Private bit.\n header[bitrate] =\n bitrateMatrix[data[2] & 0b11110000][layerValues[bitrateIndex]];\n if (header[bitrate] === bad) return null;\n\n header[sampleRate] = mpegVersionValues[sampleRate][data[2] & 0b00001100];\n if (header[sampleRate] === reserved) return null;\n\n header[framePadding] = data[2] & 0b00000010 && layerValues[framePadding];\n header[isPrivate] = !!(data[2] & 0b00000001);\n\n header[frameLength] = Math.floor(\n (125 * header[bitrate] * header[samples]) / header[sampleRate] +\n header[framePadding],\n );\n if (!header[frameLength]) return null;\n\n // Byte (4 of 4)\n // * `IIJJKLMM`\n // * `II......`: Channel mode\n // * `..JJ....`: Mode extension (only if joint stereo)\n // * `....K...`: Copyright\n // * `.....L..`: Original\n // * `......MM`: Emphasis\n const channelModeBits = data[3] & 0b11000000;\n header[channelMode] = channelModes[channelModeBits][description];\n header[channels] = channelModes[channelModeBits][channels];\n\n header[modeExtension] = layerValues[modeExtension][data[3] & 0b00110000];\n header[isCopyrighted] = !!(data[3] & 0b00001000);\n header[isOriginal] = !!(data[3] & 0b00000100);\n\n header[emphasis] = emphasisValues[data[3] & 0b00000011];\n if (header[emphasis] === reserved) return null;\n\n header[bitDepth] = 16;\n\n // set header cache\n {\n const { length, frameLength, samples, ...codecUpdateFields } = header;\n\n headerCache[setHeader](key, header, codecUpdateFields);\n }\n return new MPEGHeader(header);\n }\n\n /**\n * @private\n * Call MPEGHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n super(header);\n\n this[bitrate] = header[bitrate];\n this[emphasis] = header[emphasis];\n this[framePadding] = header[framePadding];\n this[isCopyrighted] = header[isCopyrighted];\n this[isOriginal] = header[isOriginal];\n this[isPrivate] = header[isPrivate];\n this[layer] = header[layer];\n this[modeExtension] = header[modeExtension];\n this[mpegVersion] = header[mpegVersion];\n this[protection] = header[protection];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { getFrame } from \"../../constants.js\";\n\nimport CodecFrame from \"../CodecFrame.js\";\nimport MPEGHeader from \"./MPEGHeader.js\";\n\nexport default class MPEGFrame extends CodecFrame {\n static *[getFrame](codecParser, headerCache, readOffset) {\n return yield* super[getFrame](\n MPEGHeader,\n MPEGFrame,\n codecParser,\n headerCache,\n readOffset,\n );\n }\n\n constructor(header, frame, samples) {\n super(header, frame, samples);\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport {\n codec,\n mpeg,\n fixedLengthFrameSync,\n parseFrame,\n} from \"../../constants.js\";\n\nimport Parser from \"../Parser.js\";\nimport MPEGFrame from \"./MPEGFrame.js\";\nimport MPEGHeader from \"./MPEGHeader.js\";\n\nexport default class MPEGParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n this.Frame = MPEGFrame;\n this.Header = MPEGHeader;\n\n onCodec(this[codec]);\n }\n\n get [codec]() {\n return mpeg;\n }\n\n *[parseFrame]() {\n return yield* this[fixedLengthFrameSync]();\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n/*\nhttps://wiki.multimedia.cx/index.php/ADTS\n\nAAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ)\n\nAACHeader consists of 7 or 9 bytes (without or with CRC).\nLetter Length (bits) Description\nA 12 syncword 0xFFF, all bits must be 1\nB 1 MPEG Version: 0 for MPEG-4, 1 for MPEG-2\nC 2 Layer: always 0\nD 1 protection absent, Warning, set to 1 if there is no CRC and 0 if there is CRC\nE 2 profile, the MPEG-4 Audio Object Type minus 1\nF 4 MPEG-4 Sampling Frequency Index (15 is forbidden)\nG 1 private bit, guaranteed never to be used by MPEG, set to 0 when encoding, ignore when decoding\nH 3 MPEG-4 Channel Configuration (in the case of 0, the channel configuration is sent via an inband PCE)\nI 1 originality, set to 0 when encoding, ignore when decoding\nJ 1 home, set to 0 when encoding, ignore when decoding\nK 1 copyrighted id bit, the next bit of a centrally registered copyright identifier, set to 0 when encoding, ignore when decoding\nL 1 copyright id start, signals that this frame's copyright id bit is the first bit of the copyright id, set to 0 when encoding, ignore when decoding\nM 13 frame length, this value must include 7 or 9 bytes of header length: FrameLength = (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame)\nO 11 Buffer fullness // 0x7FF for VBR\nP 2 Number of AAC frames (RDBs) in ADTS frame minus 1, for maximum compatibility always use 1 AAC frame per ADTS frame\nQ 16 CRC if protection absent is 0 \n*/\n\nimport { headerStore } from \"../../globals.js\";\nimport { bytesToString } from \"../../utilities.js\";\nimport {\n reserved,\n bad,\n none,\n sixteenBitCRC,\n rate96000,\n rate88200,\n rate64000,\n rate48000,\n rate44100,\n rate32000,\n rate24000,\n rate22050,\n rate16000,\n rate12000,\n rate11025,\n rate8000,\n rate7350,\n channelMappings,\n getChannelMapping,\n monophonic,\n lfe,\n bitDepth,\n channelMode,\n sampleRate,\n channels,\n copyrightId,\n copyrightIdStart,\n bufferFullness,\n isHome,\n isOriginal,\n isPrivate,\n layer,\n length,\n mpegVersion,\n numberAACFrames,\n profile,\n protection,\n frameLength,\n description,\n samples,\n sampleRateBits,\n profileBits,\n channelModeBits,\n buffer,\n readRawData,\n getHeader,\n setHeader,\n uint8Array,\n dataView,\n} from \"../../constants.js\";\n\nimport CodecHeader from \"../CodecHeader.js\";\n\nconst mpegVersionValues = {\n 0b00000000: \"MPEG-4\",\n 0b00001000: \"MPEG-2\",\n};\n\nconst layerValues = {\n 0b00000000: \"valid\",\n 0b00000010: bad,\n 0b00000100: bad,\n 0b00000110: bad,\n};\n\nconst protectionValues = {\n 0b00000000: sixteenBitCRC,\n 0b00000001: none,\n};\n\nconst profileValues = {\n 0b00000000: \"AAC Main\",\n 0b01000000: \"AAC LC (Low Complexity)\",\n 0b10000000: \"AAC SSR (Scalable Sample Rate)\",\n 0b11000000: \"AAC LTP (Long Term Prediction)\",\n};\n\nconst sampleRates = {\n 0b00000000: rate96000,\n 0b00000100: rate88200,\n 0b00001000: rate64000,\n 0b00001100: rate48000,\n 0b00010000: rate44100,\n 0b00010100: rate32000,\n 0b00011000: rate24000,\n 0b00011100: rate22050,\n 0b00100000: rate16000,\n 0b00100100: rate12000,\n 0b00101000: rate11025,\n 0b00101100: rate8000,\n 0b00110000: rate7350,\n 0b00110100: reserved,\n 0b00111000: reserved,\n 0b00111100: \"frequency is written explicitly\",\n};\n\n// prettier-ignore\nconst channelModeValues = {\n 0b000000000: { [channels]: 0, [description]: \"Defined in AOT Specific Config\" },\n /*\n 'monophonic (mono)'\n 'stereo (left, right)'\n 'linear surround (front center, front left, front right)'\n 'quadraphonic (front center, front left, front right, rear center)'\n '5.0 surround (front center, front left, front right, rear left, rear right)'\n '5.1 surround (front center, front left, front right, rear left, rear right, LFE)'\n '7.1 surround (front center, front left, front right, side left, side right, rear left, rear right, LFE)'\n */\n 0b001000000: { [channels]: 1, [description]: monophonic },\n 0b010000000: { [channels]: 2, [description]: getChannelMapping(2,channelMappings[0][0]) },\n 0b011000000: { [channels]: 3, [description]: getChannelMapping(3,channelMappings[1][3]), },\n 0b100000000: { [channels]: 4, [description]: getChannelMapping(4,channelMappings[1][3],channelMappings[3][4]), },\n 0b101000000: { [channels]: 5, [description]: getChannelMapping(5,channelMappings[1][3],channelMappings[3][0]), },\n 0b110000000: { [channels]: 6, [description]: getChannelMapping(6,channelMappings[1][3],channelMappings[3][0],lfe), },\n 0b111000000: { [channels]: 8, [description]: getChannelMapping(8,channelMappings[1][3],channelMappings[2][0],channelMappings[3][0],lfe), },\n};\n\nexport default class AACHeader extends CodecHeader {\n static *[getHeader](codecParser, headerCache, readOffset) {\n const header = {};\n\n // Must be at least seven bytes. Out of data\n const data = yield* codecParser[readRawData](7, readOffset);\n\n // Check header cache\n const key = bytesToString([\n data[0],\n data[1],\n data[2],\n (data[3] & 0b11111100) | (data[6] & 0b00000011), // frame length, buffer fullness varies so don't cache it\n ]);\n const cachedHeader = headerCache[getHeader](key);\n\n if (!cachedHeader) {\n // Frame sync (all bits must be set): `11111111|1111`:\n if (data[0] !== 0xff || data[1] < 0xf0) return null;\n\n // Byte (2 of 7)\n // * `1111BCCD`\n // * `....B...`: MPEG Version: 0 for MPEG-4, 1 for MPEG-2\n // * `.....CC.`: Layer: always 0\n // * `.......D`: protection absent, Warning, set to 1 if there is no CRC and 0 if there is CRC\n header[mpegVersion] = mpegVersionValues[data[1] & 0b00001000];\n\n header[layer] = layerValues[data[1] & 0b00000110];\n if (header[layer] === bad) return null;\n\n const protectionBit = data[1] & 0b00000001;\n header[protection] = protectionValues[protectionBit];\n header[length] = protectionBit ? 7 : 9;\n\n // Byte (3 of 7)\n // * `EEFFFFGH`\n // * `EE......`: profile, the MPEG-4 Audio Object Type minus 1\n // * `..FFFF..`: MPEG-4 Sampling Frequency Index (15 is forbidden)\n // * `......G.`: private bit, guaranteed never to be used by MPEG, set to 0 when encoding, ignore when decoding\n header[profileBits] = data[2] & 0b11000000;\n header[sampleRateBits] = data[2] & 0b00111100;\n const privateBit = data[2] & 0b00000010;\n\n header[profile] = profileValues[header[profileBits]];\n\n header[sampleRate] = sampleRates[header[sampleRateBits]];\n if (header[sampleRate] === reserved) return null;\n\n header[isPrivate] = !!privateBit;\n\n // Byte (3,4 of 7)\n // * `.......H|HH......`: MPEG-4 Channel Configuration (in the case of 0, the channel configuration is sent via an inband PCE)\n header[channelModeBits] = ((data[2] << 8) | data[3]) & 0b111000000;\n header[channelMode] =\n channelModeValues[header[channelModeBits]][description];\n header[channels] = channelModeValues[header[channelModeBits]][channels];\n\n // Byte (4 of 7)\n // * `HHIJKLMM`\n // * `..I.....`: originality, set to 0 when encoding, ignore when decoding\n // * `...J....`: home, set to 0 when encoding, ignore when decoding\n // * `....K...`: copyrighted id bit, the next bit of a centrally registered copyright identifier, set to 0 when encoding, ignore when decoding\n // * `.....L..`: copyright id start, signals that this frame's copyright id bit is the first bit of the copyright id, set to 0 when encoding, ignore when decoding\n header[isOriginal] = !!(data[3] & 0b00100000);\n header[isHome] = !!(data[3] & 0b00001000);\n header[copyrightId] = !!(data[3] & 0b00001000);\n header[copyrightIdStart] = !!(data[3] & 0b00000100);\n header[bitDepth] = 16;\n header[samples] = 1024;\n\n // Byte (7 of 7)\n // * `......PP` Number of AAC frames (RDBs) in ADTS frame minus 1, for maximum compatibility always use 1 AAC frame per ADTS frame\n header[numberAACFrames] = data[6] & 0b00000011;\n\n {\n const {\n length,\n channelModeBits,\n profileBits,\n sampleRateBits,\n frameLength,\n samples,\n numberAACFrames,\n ...codecUpdateFields\n } = header;\n headerCache[setHeader](key, header, codecUpdateFields);\n }\n } else {\n Object.assign(header, cachedHeader);\n }\n\n // Byte (4,5,6 of 7)\n // * `.......MM|MMMMMMMM|MMM.....`: frame length, this value must include 7 or 9 bytes of header length: FrameLength = (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame)\n header[frameLength] =\n ((data[3] << 11) | (data[4] << 3) | (data[5] >> 5)) & 0x1fff;\n if (!header[frameLength]) return null;\n\n // Byte (6,7 of 7)\n // * `...OOOOO|OOOOOO..`: Buffer fullness\n const bufferFullnessBits = ((data[5] << 6) | (data[6] >> 2)) & 0x7ff;\n header[bufferFullness] =\n bufferFullnessBits === 0x7ff ? \"VBR\" : bufferFullnessBits;\n\n return new AACHeader(header);\n }\n\n /**\n * @private\n * Call AACHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n super(header);\n\n this[copyrightId] = header[copyrightId];\n this[copyrightIdStart] = header[copyrightIdStart];\n this[bufferFullness] = header[bufferFullness];\n this[isHome] = header[isHome];\n this[isOriginal] = header[isOriginal];\n this[isPrivate] = header[isPrivate];\n this[layer] = header[layer];\n this[length] = header[length];\n this[mpegVersion] = header[mpegVersion];\n this[numberAACFrames] = header[numberAACFrames];\n this[profile] = header[profile];\n this[protection] = header[protection];\n }\n\n get audioSpecificConfig() {\n // Audio Specific Configuration\n // * `000EEFFF|F0HHH000`:\n // * `000EE...|........`: Object Type (profileBit + 1)\n // * `.....FFF|F.......`: Sample Rate\n // * `........|.0HHH...`: Channel Configuration\n // * `........|.....0..`: Frame Length (1024)\n // * `........|......0.`: does not depend on core coder\n // * `........|.......0`: Not Extension\n const header = headerStore.get(this);\n\n const audioSpecificConfig =\n ((header[profileBits] + 0x40) << 5) |\n (header[sampleRateBits] << 5) |\n (header[channelModeBits] >> 3);\n\n const bytes = new uint8Array(2);\n new dataView(bytes[buffer]).setUint16(0, audioSpecificConfig, false);\n return bytes;\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { getFrame } from \"../../constants.js\";\n\nimport CodecFrame from \"../CodecFrame.js\";\nimport AACHeader from \"./AACHeader.js\";\n\nexport default class AACFrame extends CodecFrame {\n static *[getFrame](codecParser, headerCache, readOffset) {\n return yield* super[getFrame](\n AACHeader,\n AACFrame,\n codecParser,\n headerCache,\n readOffset,\n );\n }\n\n constructor(header, frame, samples) {\n super(header, frame, samples);\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { codec, fixedLengthFrameSync, parseFrame } from \"../../constants.js\";\n\nimport Parser from \"../Parser.js\";\nimport AACFrame from \"./AACFrame.js\";\nimport AACHeader from \"./AACHeader.js\";\n\nexport default class AACParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n this.Frame = AACFrame;\n this.Header = AACHeader;\n\n onCodec(this[codec]);\n }\n\n get [codec]() {\n return \"aac\";\n }\n\n *[parseFrame]() {\n return yield* this[fixedLengthFrameSync]();\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { headerStore } from \"../../globals.js\";\nimport { flacCrc16 } from \"../../utilities.js\";\nimport {\n length,\n streamInfo,\n crc16,\n samples,\n subarray,\n checkFrameFooterCrc16,\n} from \"../../constants.js\";\nimport CodecFrame from \"../CodecFrame.js\";\n\nexport default class FLACFrame extends CodecFrame {\n static _getFrameFooterCrc16(data) {\n return (data[data[length] - 2] << 8) + data[data[length] - 1];\n }\n\n // check frame footer crc\n // https://xiph.org/flac/format.html#frame_footer\n static [checkFrameFooterCrc16](data) {\n const expectedCrc16 = FLACFrame._getFrameFooterCrc16(data);\n const actualCrc16 = flacCrc16(data[subarray](0, -2));\n\n return expectedCrc16 === actualCrc16;\n }\n\n constructor(data, header, streamInfoValue) {\n header[streamInfo] = streamInfoValue;\n header[crc16] = FLACFrame._getFrameFooterCrc16(data);\n\n super(header, data, headerStore.get(header)[samples]);\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n/*\nhttps://xiph.org/flac/format.html\n\nAAAAAAAA AAAAAABC DDDDEEEE FFFFGGGH \n(IIIIIIII...)\n(JJJJJJJJ|JJJJJJJJ)\n(KKKKKKKK|KKKKKKKK)\nLLLLLLLLL\n\nFLAC Frame Header\nLetter Length (bits) Description\nA 13 11111111|11111\nB 1 Reserved 0 - mandatory, 1 - reserved\nC 1 Blocking strategy, 0 - fixed, 1 - variable\nD 4 Block size in inter-channel samples\nE 4 Sample rate\nF 4 Channel assignment\nG 3 Sample size in bits\nH 1 Reserved 0 - mandatory, 1 - reserved\nI ? if(variable blocksize)\n <8-56>:\"UTF-8\" coded sample number (decoded number is 36 bits) [4]\n else\n <8-48>:\"UTF-8\" coded frame number (decoded number is 31 bits) [4]\nJ ? if(blocksize bits == 011x)\n 8/16 bit (blocksize-1)\nK ? if(sample rate bits == 11xx)\n 8/16 bit sample rate\nL 8 CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) of everything before the crc, including the sync code\n \n*/\n\nimport {\n reserved,\n bad,\n rate88200,\n rate176400,\n rate192000,\n rate8000,\n rate16000,\n rate22050,\n rate24000,\n rate32000,\n rate44100,\n rate48000,\n rate96000,\n channelMappings,\n getChannelMapping,\n monophonic,\n stereo,\n lfe,\n bitDepth,\n channelMode,\n sampleRate,\n channels,\n length,\n crc16,\n blockingStrategy,\n blockSize,\n frameNumber,\n sampleNumber,\n streamInfo,\n description,\n samples,\n sampleRateBits,\n blockingStrategyBits,\n blockSizeBits,\n crc,\n subarray,\n readRawData,\n getHeader,\n setHeader,\n getHeaderFromUint8Array,\n} from \"../../constants.js\";\nimport { bytesToString, crc8 } from \"../../utilities.js\";\nimport CodecHeader from \"../CodecHeader.js\";\n\nconst getFromStreamInfo = \"get from STREAMINFO metadata block\";\n\nconst blockingStrategyValues = {\n 0b00000000: \"Fixed\",\n 0b00000001: \"Variable\",\n};\n\nconst blockSizeValues = {\n 0b00000000: reserved,\n 0b00010000: 192,\n // 0b00100000: 576,\n // 0b00110000: 1152,\n // 0b01000000: 2304,\n // 0b01010000: 4608,\n // 0b01100000: \"8-bit (blocksize-1) from end of header\",\n // 0b01110000: \"16-bit (blocksize-1) from end of header\",\n // 0b10000000: 256,\n // 0b10010000: 512,\n // 0b10100000: 1024,\n // 0b10110000: 2048,\n // 0b11000000: 4096,\n // 0b11010000: 8192,\n // 0b11100000: 16384,\n // 0b11110000: 32768,\n};\nfor (let i = 2; i < 16; i++)\n blockSizeValues[i << 4] = i < 6 ? 576 * 2 ** (i - 2) : 2 ** i;\n\nconst sampleRateValues = {\n 0b00000000: getFromStreamInfo,\n 0b00000001: rate88200,\n 0b00000010: rate176400,\n 0b00000011: rate192000,\n 0b00000100: rate8000,\n 0b00000101: rate16000,\n 0b00000110: rate22050,\n 0b00000111: rate24000,\n 0b00001000: rate32000,\n 0b00001001: rate44100,\n 0b00001010: rate48000,\n 0b00001011: rate96000,\n // 0b00001100: \"8-bit sample rate (in kHz) from end of header\",\n // 0b00001101: \"16-bit sample rate (in Hz) from end of header\",\n // 0b00001110: \"16-bit sample rate (in tens of Hz) from end of header\",\n 0b00001111: bad,\n};\n\n/* prettier-ignore */\nconst channelAssignments = {\n /*'\n 'monophonic (mono)'\n 'stereo (left, right)'\n 'linear surround (left, right, center)'\n 'quadraphonic (front left, front right, rear left, rear right)'\n '5.0 surround (front left, front right, front center, rear left, rear right)'\n '5.1 surround (front left, front right, front center, LFE, rear left, rear right)'\n '6.1 surround (front left, front right, front center, LFE, rear center, side left, side right)'\n '7.1 surround (front left, front right, front center, LFE, rear left, rear right, side left, side right)'\n */\n 0b00000000: {[channels]: 1, [description]: monophonic},\n 0b00010000: {[channels]: 2, [description]: getChannelMapping(2,channelMappings[0][0])},\n 0b00100000: {[channels]: 3, [description]: getChannelMapping(3,channelMappings[0][1])},\n 0b00110000: {[channels]: 4, [description]: getChannelMapping(4,channelMappings[1][0],channelMappings[3][0])},\n 0b01000000: {[channels]: 5, [description]: getChannelMapping(5,channelMappings[1][1],channelMappings[3][0])},\n 0b01010000: {[channels]: 6, [description]: getChannelMapping(6,channelMappings[1][1],lfe,channelMappings[3][0])},\n 0b01100000: {[channels]: 7, [description]: getChannelMapping(7,channelMappings[1][1],lfe,channelMappings[3][4],channelMappings[2][0])},\n 0b01110000: {[channels]: 8, [description]: getChannelMapping(8,channelMappings[1][1],lfe,channelMappings[3][0],channelMappings[2][0])},\n 0b10000000: {[channels]: 2, [description]: `${stereo} (left, diff)`},\n 0b10010000: {[channels]: 2, [description]: `${stereo} (diff, right)`},\n 0b10100000: {[channels]: 2, [description]: `${stereo} (avg, diff)`},\n 0b10110000: reserved,\n 0b11000000: reserved,\n 0b11010000: reserved,\n 0b11100000: reserved,\n 0b11110000: reserved,\n}\n\nconst bitDepthValues = {\n 0b00000000: getFromStreamInfo,\n 0b00000010: 8,\n 0b00000100: 12,\n 0b00000110: reserved,\n 0b00001000: 16,\n 0b00001010: 20,\n 0b00001100: 24,\n 0b00001110: reserved,\n};\n\nexport default class FLACHeader extends CodecHeader {\n // https://datatracker.ietf.org/doc/html/rfc3629#section-3\n // Char. number range | UTF-8 octet sequence\n // (hexadecimal) | (binary)\n // --------------------+---------------------------------------------\n // 0000 0000-0000 007F | 0xxxxxxx\n // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx\n // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx\n // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx\n static _decodeUTF8Int(data) {\n if (data[0] > 0xfe) {\n return null; // length byte must have at least one zero as the lsb\n }\n\n if (data[0] < 0x80) return { value: data[0], length: 1 };\n\n // get length by counting the number of msb that are set to 1\n let length = 1;\n for (let zeroMask = 0x40; zeroMask & data[0]; zeroMask >>= 1) length++;\n\n let idx = length - 1,\n value = 0,\n shift = 0;\n\n // sum together the encoded bits in bytes 2 to length\n // 1110xxxx 10[cccccc] 10[bbbbbb] 10[aaaaaa]\n //\n // value = [cccccc] | [bbbbbb] | [aaaaaa]\n for (; idx > 0; shift += 6, idx--) {\n if ((data[idx] & 0xc0) !== 0x80) {\n return null; // each byte should have leading 10xxxxxx\n }\n value |= (data[idx] & 0x3f) << shift; // add the encoded bits\n }\n\n // read the final encoded bits in byte 1\n // 1110[dddd] 10[cccccc] 10[bbbbbb] 10[aaaaaa]\n //\n // value = [dddd] | [cccccc] | [bbbbbb] | [aaaaaa]\n value |= (data[idx] & (0x7f >> length)) << shift;\n\n return { value, length };\n }\n\n static [getHeaderFromUint8Array](data, headerCache) {\n const codecParserStub = {\n [readRawData]: function* () {\n return data;\n },\n };\n\n return FLACHeader[getHeader](codecParserStub, headerCache, 0).next().value;\n }\n\n static *[getHeader](codecParser, headerCache, readOffset) {\n // Must be at least 6 bytes.\n let data = yield* codecParser[readRawData](6, readOffset);\n\n // Bytes (1-2 of 6)\n // * `11111111|111110..`: Frame sync\n // * `........|......0.`: Reserved 0 - mandatory, 1 - reserved\n if (data[0] !== 0xff || !(data[1] === 0xf8 || data[1] === 0xf9)) {\n return null;\n }\n\n const header = {};\n\n // Check header cache\n const key = bytesToString(data[subarray](0, 4));\n const cachedHeader = headerCache[getHeader](key);\n\n if (!cachedHeader) {\n // Byte (2 of 6)\n // * `.......C`: Blocking strategy, 0 - fixed, 1 - variable\n header[blockingStrategyBits] = data[1] & 0b00000001;\n header[blockingStrategy] =\n blockingStrategyValues[header[blockingStrategyBits]];\n\n // Byte (3 of 6)\n // * `DDDD....`: Block size in inter-channel samples\n // * `....EEEE`: Sample rate\n header[blockSizeBits] = data[2] & 0b11110000;\n header[sampleRateBits] = data[2] & 0b00001111;\n\n header[blockSize] = blockSizeValues[header[blockSizeBits]];\n if (header[blockSize] === reserved) {\n return null;\n }\n\n header[sampleRate] = sampleRateValues[header[sampleRateBits]];\n if (header[sampleRate] === bad) {\n return null;\n }\n\n // Byte (4 of 6)\n // * `FFFF....`: Channel assignment\n // * `....GGG.`: Sample size in bits\n // * `.......H`: Reserved 0 - mandatory, 1 - reserved\n if (data[3] & 0b00000001) {\n return null;\n }\n\n const channelAssignment = channelAssignments[data[3] & 0b11110000];\n if (channelAssignment === reserved) {\n return null;\n }\n\n header[channels] = channelAssignment[channels];\n header[channelMode] = channelAssignment[description];\n\n header[bitDepth] = bitDepthValues[data[3] & 0b00001110];\n if (header[bitDepth] === reserved) {\n return null;\n }\n } else {\n Object.assign(header, cachedHeader);\n }\n\n // Byte (5...)\n // * `IIIIIIII|...`: VBR block size ? sample number : frame number\n header[length] = 5;\n\n // check if there is enough data to parse UTF8\n data = yield* codecParser[readRawData](header[length] + 8, readOffset);\n\n const decodedUtf8 = FLACHeader._decodeUTF8Int(data[subarray](4));\n if (!decodedUtf8) {\n return null;\n }\n\n if (header[blockingStrategyBits]) {\n header[sampleNumber] = decodedUtf8.value;\n } else {\n header[frameNumber] = decodedUtf8.value;\n }\n\n header[length] += decodedUtf8[length];\n\n // Byte (...)\n // * `JJJJJJJJ|(JJJJJJJJ)`: Blocksize (8/16bit custom value)\n if (header[blockSizeBits] === 0b01100000) {\n // 8 bit\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[blockSize] = data[header[length] - 1] + 1;\n header[length] += 1;\n } else if (header[blockSizeBits] === 0b01110000) {\n // 16 bit\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[blockSize] =\n (data[header[length] - 1] << 8) + data[header[length]] + 1;\n header[length] += 2;\n }\n\n header[samples] = header[blockSize];\n\n // Byte (...)\n // * `KKKKKKKK|(KKKKKKKK)`: Sample rate (8/16bit custom value)\n if (header[sampleRateBits] === 0b00001100) {\n // 8 bit\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[sampleRate] = data[header[length] - 1] * 1000;\n header[length] += 1;\n } else if (header[sampleRateBits] === 0b00001101) {\n // 16 bit\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[sampleRate] =\n (data[header[length] - 1] << 8) + data[header[length]];\n header[length] += 2;\n } else if (header[sampleRateBits] === 0b00001110) {\n // 16 bit\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[sampleRate] =\n ((data[header[length] - 1] << 8) + data[header[length]]) * 10;\n header[length] += 2;\n }\n\n // Byte (...)\n // * `LLLLLLLL`: CRC-8\n if (data[length] < header[length])\n data = yield* codecParser[readRawData](header[length], readOffset);\n\n header[crc] = data[header[length] - 1];\n if (header[crc] !== crc8(data[subarray](0, header[length] - 1))) {\n return null;\n }\n\n {\n if (!cachedHeader) {\n const {\n blockingStrategyBits,\n frameNumber,\n sampleNumber,\n samples,\n sampleRateBits,\n blockSizeBits,\n crc,\n length,\n ...codecUpdateFields\n } = header;\n headerCache[setHeader](key, header, codecUpdateFields);\n }\n }\n return new FLACHeader(header);\n }\n\n /**\n * @private\n * Call FLACHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n super(header);\n\n this[crc16] = null; // set in FLACFrame\n this[blockingStrategy] = header[blockingStrategy];\n this[blockSize] = header[blockSize];\n this[frameNumber] = header[frameNumber];\n this[sampleNumber] = header[sampleNumber];\n this[streamInfo] = null; // set during ogg parsing\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore, headerStore } from \"../../globals.js\";\nimport {\n length,\n pageSequenceNumber,\n data,\n codec,\n codecFrames,\n segments,\n subarray,\n readRawData,\n incrementRawData,\n mapFrameStats,\n logWarning,\n parseFrame,\n parseOggPage,\n getHeader,\n enable,\n checkFrameFooterCrc16,\n getHeaderFromUint8Array,\n} from \"../../constants.js\";\nimport Parser from \"../Parser.js\";\nimport FLACFrame from \"./FLACFrame.js\";\nimport FLACHeader from \"./FLACHeader.js\";\n\nconst MIN_FLAC_FRAME_SIZE = 2;\nconst MAX_FLAC_FRAME_SIZE = 512 * 1024;\n\nexport default class FLACParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n this.Frame = FLACFrame;\n this.Header = FLACHeader;\n\n onCodec(this[codec]);\n }\n\n get [codec]() {\n return \"flac\";\n }\n\n *_getNextFrameSyncOffset(offset) {\n const data = yield* this._codecParser[readRawData](2, 0);\n const dataLength = data[length] - 2;\n\n while (offset < dataLength) {\n // * `11111111|111110..`: Frame sync\n // * `........|......0.`: Reserved 0 - mandatory, 1 - reserved\n const firstByte = data[offset];\n if (firstByte === 0xff) {\n const secondByte = data[offset + 1];\n if (secondByte === 0xf8 || secondByte === 0xf9) break;\n if (secondByte !== 0xff) offset++; // might as well check for the next sync byte\n }\n offset++;\n }\n\n return offset;\n }\n\n *[parseFrame]() {\n // find the first valid frame header\n do {\n const header = yield* FLACHeader[getHeader](\n this._codecParser,\n this._headerCache,\n 0,\n );\n\n if (header) {\n // found a valid frame header\n // find the next valid frame header\n let nextHeaderOffset =\n headerStore.get(header)[length] + MIN_FLAC_FRAME_SIZE;\n\n while (nextHeaderOffset <= MAX_FLAC_FRAME_SIZE) {\n if (\n this._codecParser._flushing ||\n (yield* FLACHeader[getHeader](\n this._codecParser,\n this._headerCache,\n nextHeaderOffset,\n ))\n ) {\n // found a valid next frame header\n let frameData = yield* this._codecParser[readRawData](\n nextHeaderOffset,\n );\n\n if (!this._codecParser._flushing)\n frameData = frameData[subarray](0, nextHeaderOffset);\n\n // check that this is actually the next header by validating the frame footer crc16\n if (FLACFrame[checkFrameFooterCrc16](frameData)) {\n // both frame headers, and frame footer crc16 are valid, we are synced (odds are pretty low of a false positive)\n const frame = new FLACFrame(frameData, header);\n\n this._headerCache[enable](); // start caching when synced\n this._codecParser[incrementRawData](nextHeaderOffset); // increment to the next frame\n this._codecParser[mapFrameStats](frame);\n\n return frame;\n }\n }\n\n nextHeaderOffset = yield* this._getNextFrameSyncOffset(\n nextHeaderOffset + 1,\n );\n }\n\n this._codecParser[logWarning](\n `Unable to sync FLAC frame after searching ${nextHeaderOffset} bytes.`,\n );\n this._codecParser[incrementRawData](nextHeaderOffset);\n } else {\n // not synced, increment data to continue syncing\n this._codecParser[incrementRawData](\n yield* this._getNextFrameSyncOffset(1),\n );\n }\n } while (true);\n }\n\n [parseOggPage](oggPage) {\n if (oggPage[pageSequenceNumber] === 0) {\n // Identification header\n\n this._headerCache[enable]();\n this._streamInfo = oggPage[data][subarray](13);\n } else if (oggPage[pageSequenceNumber] === 1) {\n // Vorbis comments\n } else {\n oggPage[codecFrames] = frameStore\n .get(oggPage)\n [segments].map((segment) => {\n const header = FLACHeader[getHeaderFromUint8Array](\n segment,\n this._headerCache,\n );\n\n if (header) {\n return new FLACFrame(segment, header, this._streamInfo);\n } else {\n this._codecParser[logWarning](\n \"Failed to parse Ogg FLAC frame\",\n \"Skipping invalid FLAC frame\",\n );\n }\n })\n .filter((frame) => !!frame);\n }\n\n return oggPage;\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n/*\nhttps://xiph.org/ogg/doc/framing.html\n\nAAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB 00000CDE\n\n(LSB) (MSB)\nFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF\nGGGGGGGG GGGGGGGG GGGGGGGG GGGGGGGG\nHHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH\nIIIIIIII IIIIIIII IIIIIIII IIIIIIII\n\nJJJJJJJJ\nLLLLLLLL...\n\nOgg Page Header\nLetter Length (bits) Description\nA 32 0x4f676753, \"OggS\"\nB 8 stream_structure_version\nC 1 (0 no, 1 yes) last page of logical bitstream (eos)\nD 1 (0 no, 1 yes) first page of logical bitstream (bos)\nE 1 (0 no, 1 yes) continued packet\n\nF 64 absolute granule position\nG 32 stream serial number\nH 32 page sequence no\nI 32 page checksum\nJ 8 Number of page segments in the segment table\nL n Segment table (n=page_segments+26).\n Segment table values sum to the total length of the packet.\n Last value is always < 0xFF. Last lacing value will be 0x00 if evenly divisible by 0xFF.\n \n*/\n\nimport { headerStore } from \"../../globals.js\";\nimport {\n absoluteGranulePosition,\n isContinuedPacket,\n isFirstPage,\n isLastPage,\n pageSequenceNumber,\n streamSerialNumber,\n length,\n pageChecksum,\n frameLength,\n streamStructureVersion,\n pageSegmentTable,\n pageSegmentBytes,\n buffer,\n subarray,\n readRawData,\n getHeader,\n uint8Array,\n dataView,\n} from \"../../constants.js\";\n\nexport default class OggPageHeader {\n static *[getHeader](codecParser, headerCache, readOffset) {\n const header = {};\n\n // Must be at least 28 bytes.\n let data = yield* codecParser[readRawData](28, readOffset);\n\n // Bytes (1-4 of 28)\n // Frame sync (must equal OggS): `AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA`:\n if (\n data[0] !== 0x4f || // O\n data[1] !== 0x67 || // g\n data[2] !== 0x67 || // g\n data[3] !== 0x53 // S\n ) {\n return null;\n }\n\n // Byte (5 of 28)\n // * `BBBBBBBB`: stream_structure_version\n header[streamStructureVersion] = data[4];\n\n // Byte (6 of 28)\n // * `00000CDE`\n // * `00000...`: All zeros\n // * `.....C..`: (0 no, 1 yes) last page of logical bitstream (eos)\n // * `......D.`: (0 no, 1 yes) first page of logical bitstream (bos)\n // * `.......E`: (0 no, 1 yes) continued packet\n const zeros = data[5] & 0b11111000;\n if (zeros) return null;\n\n header[isLastPage] = !!(data[5] & 0b00000100);\n header[isFirstPage] = !!(data[5] & 0b00000010);\n header[isContinuedPacket] = !!(data[5] & 0b00000001);\n\n const view = new dataView(uint8Array.from(data[subarray](0, 28))[buffer]);\n\n // Byte (7-14 of 28)\n // * `FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF`\n // * Absolute Granule Position\n\n /**\n * @todo Safari does not support getBigInt64, but it also doesn't support Ogg\n */\n try {\n header[absoluteGranulePosition] = view.getBigInt64(6, true);\n } catch {}\n\n // Byte (15-18 of 28)\n // * `GGGGGGGG|GGGGGGGG|GGGGGGGG|GGGGGGGG`\n // * Stream Serial Number\n header[streamSerialNumber] = view.getInt32(14, true);\n\n // Byte (19-22 of 28)\n // * `HHHHHHHH|HHHHHHHH|HHHHHHHH|HHHHHHHH`\n // * Page Sequence Number\n header[pageSequenceNumber] = view.getInt32(18, true);\n\n // Byte (23-26 of 28)\n // * `IIIIIIII|IIIIIIII|IIIIIIII|IIIIIIII`\n // * Page Checksum\n header[pageChecksum] = view.getInt32(22, true);\n\n // Byte (27 of 28)\n // * `JJJJJJJJ`: Number of page segments in the segment table\n const pageSegmentTableLength = data[26];\n header[length] = pageSegmentTableLength + 27;\n\n data = yield* codecParser[readRawData](header[length], readOffset); // read in the page segment table\n\n header[frameLength] = 0;\n header[pageSegmentTable] = [];\n header[pageSegmentBytes] = uint8Array.from(\n data[subarray](27, header[length]),\n );\n\n for (let i = 0, segmentLength = 0; i < pageSegmentTableLength; i++) {\n const segmentByte = header[pageSegmentBytes][i];\n\n header[frameLength] += segmentByte;\n segmentLength += segmentByte;\n\n if (segmentByte !== 0xff || i === pageSegmentTableLength - 1) {\n header[pageSegmentTable].push(segmentLength);\n segmentLength = 0;\n }\n }\n\n return new OggPageHeader(header);\n }\n\n /**\n * @private\n * Call OggPageHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n headerStore.set(this, header);\n\n this[absoluteGranulePosition] = header[absoluteGranulePosition];\n this[isContinuedPacket] = header[isContinuedPacket];\n this[isFirstPage] = header[isFirstPage];\n this[isLastPage] = header[isLastPage];\n this[pageSegmentTable] = header[pageSegmentTable];\n this[pageSequenceNumber] = header[pageSequenceNumber];\n this[pageChecksum] = header[pageChecksum];\n this[streamSerialNumber] = header[streamSerialNumber];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { headerStore, frameStore } from \"../../globals.js\";\nimport {\n codecFrames,\n rawData,\n absoluteGranulePosition,\n crc32,\n duration,\n isContinuedPacket,\n isFirstPage,\n isLastPage,\n pageSequenceNumber,\n samples,\n streamSerialNumber,\n length,\n pageChecksum,\n frameLength,\n subarray,\n readRawData,\n getFrame,\n getHeader,\n} from \"../../constants.js\";\n\nimport Frame from \"../Frame.js\";\nimport OggPageHeader from \"./OggPageHeader.js\";\n\nexport default class OggPage extends Frame {\n static *[getFrame](codecParser, headerCache, readOffset) {\n const header = yield* OggPageHeader[getHeader](\n codecParser,\n headerCache,\n readOffset,\n );\n\n if (header) {\n const frameLengthValue = headerStore.get(header)[frameLength];\n const headerLength = headerStore.get(header)[length];\n const totalLength = headerLength + frameLengthValue;\n\n const rawDataValue = (yield* codecParser[readRawData](totalLength, 0))[\n subarray\n ](0, totalLength);\n\n const frame = rawDataValue[subarray](headerLength, totalLength);\n\n return new OggPage(header, frame, rawDataValue);\n } else {\n return null;\n }\n }\n\n constructor(header, frame, rawDataValue) {\n super(header, frame);\n\n frameStore.get(this)[length] = rawDataValue[length];\n\n this[codecFrames] = [];\n this[rawData] = rawDataValue;\n this[absoluteGranulePosition] = header[absoluteGranulePosition];\n this[crc32] = header[pageChecksum];\n this[duration] = 0;\n this[isContinuedPacket] = header[isContinuedPacket];\n this[isFirstPage] = header[isFirstPage];\n this[isLastPage] = header[isLastPage];\n this[pageSequenceNumber] = header[pageSequenceNumber];\n this[samples] = 0;\n this[streamSerialNumber] = header[streamSerialNumber];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { sampleRate, frameCount, frameSize } from \"../../constants.js\";\nimport CodecFrame from \"../CodecFrame.js\";\n\nexport default class OpusFrame extends CodecFrame {\n constructor(data, header) {\n super(\n header,\n data,\n ((header[frameSize] * header[frameCount]) / 1000) * header[sampleRate],\n );\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n/*\nhttps://tools.ietf.org/html/rfc7845.html\n 0 1 2 3\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| 'O' | 'p' | 'u' | 's' |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| 'H' | 'e' | 'a' | 'd' |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| Version = 1 | Channel Count | Pre-skip |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| Input Sample Rate (Hz) |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| Output Gain (Q7.8 in dB) | Mapping Family| |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ :\n| |\n: Optional Channel Mapping Table... :\n| |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\nLetter Length (bits) Description\nA 64 Magic Signature - OpusHead\nB 8 Version number - 00000001\nC 8 Output channel count (unsigned)\nD 16 Pre-skip (unsigned, little endian)\nE 32 Sample rate (unsigned, little endian)\nF 16 Output Gain (signed, little endian)\nG 8 Channel Mapping family (unsigned)\n\n// if(channel mapping !== 0)\nH 8 Stream count (unsigned)\nI 8 Coupled Stream Count (unsigned)\nJ 8*C Channel Mapping\n*/\n\nimport {\n rate48000,\n vorbisOpusChannelMapping,\n bitDepth,\n channelMode,\n sampleRate,\n channels,\n length,\n bandwidth,\n channelMappingFamily,\n channelMappingTable,\n coupledStreamCount,\n frameCount,\n frameSize,\n hasOpusPadding,\n inputSampleRate,\n isVbr,\n mode,\n outputGain,\n preSkip,\n streamCount,\n data,\n buffer,\n subarray,\n getHeader,\n setHeader,\n getHeaderFromUint8Array,\n uint8Array,\n dataView,\n} from \"../../constants.js\";\nimport { bytesToString } from \"../../utilities.js\";\n\nimport CodecHeader from \"../CodecHeader.js\";\n\n/* prettier-ignore */\nconst channelMappingFamilies = {\n 0b00000000: vorbisOpusChannelMapping.slice(0,2),\n /*\n 0: \"monophonic (mono)\"\n 1: \"stereo (left, right)\"\n */\n 0b00000001: vorbisOpusChannelMapping\n /*\n 0: \"monophonic (mono)\"\n 1: \"stereo (left, right)\"\n 2: \"linear surround (left, center, right)\"\n 3: \"quadraphonic (front left, front right, rear left, rear right)\"\n 4: \"5.0 surround (front left, front center, front right, rear left, rear right)\"\n 5: \"5.1 surround (front left, front center, front right, rear left, rear right, LFE)\"\n 6: \"6.1 surround (front left, front center, front right, side left, side right, rear center, LFE)\"\n 7: \"7.1 surround (front left, front center, front right, side left, side right, rear left, rear right, LFE)\"\n */\n // additional channel mappings are user defined\n};\n\nconst silkOnly = \"SILK-only\";\nconst celtOnly = \"CELT-only\";\nconst hybrid = \"Hybrid\";\n\nconst narrowBand = \"narrowband\";\nconst mediumBand = \"medium-band\";\nconst wideBand = \"wideband\";\nconst superWideBand = \"super-wideband\";\nconst fullBand = \"fullband\";\n\n// 0 1 2 3 4 5 6 7\n// +-+-+-+-+-+-+-+-+\n// | config |s| c |\n// +-+-+-+-+-+-+-+-+\n// prettier-ignore\nconst configTable = {\n 0b00000000: { [mode]: silkOnly, [bandwidth]: narrowBand, [frameSize]: 10 },\n 0b00001000: { [mode]: silkOnly, [bandwidth]: narrowBand, [frameSize]: 20 },\n 0b00010000: { [mode]: silkOnly, [bandwidth]: narrowBand, [frameSize]: 40 },\n 0b00011000: { [mode]: silkOnly, [bandwidth]: narrowBand, [frameSize]: 60 },\n 0b00100000: { [mode]: silkOnly, [bandwidth]: mediumBand, [frameSize]: 10 },\n 0b00101000: { [mode]: silkOnly, [bandwidth]: mediumBand, [frameSize]: 20 },\n 0b00110000: { [mode]: silkOnly, [bandwidth]: mediumBand, [frameSize]: 40 },\n 0b00111000: { [mode]: silkOnly, [bandwidth]: mediumBand, [frameSize]: 60 },\n 0b01000000: { [mode]: silkOnly, [bandwidth]: wideBand, [frameSize]: 10 },\n 0b01001000: { [mode]: silkOnly, [bandwidth]: wideBand, [frameSize]: 20 },\n 0b01010000: { [mode]: silkOnly, [bandwidth]: wideBand, [frameSize]: 40 },\n 0b01011000: { [mode]: silkOnly, [bandwidth]: wideBand, [frameSize]: 60 },\n 0b01100000: { [mode]: hybrid, [bandwidth]: superWideBand, [frameSize]: 10 },\n 0b01101000: { [mode]: hybrid, [bandwidth]: superWideBand, [frameSize]: 20 },\n 0b01110000: { [mode]: hybrid, [bandwidth]: fullBand, [frameSize]: 10 },\n 0b01111000: { [mode]: hybrid, [bandwidth]: fullBand, [frameSize]: 20 },\n 0b10000000: { [mode]: celtOnly, [bandwidth]: narrowBand, [frameSize]: 2.5 },\n 0b10001000: { [mode]: celtOnly, [bandwidth]: narrowBand, [frameSize]: 5 },\n 0b10010000: { [mode]: celtOnly, [bandwidth]: narrowBand, [frameSize]: 10 },\n 0b10011000: { [mode]: celtOnly, [bandwidth]: narrowBand, [frameSize]: 20 },\n 0b10100000: { [mode]: celtOnly, [bandwidth]: wideBand, [frameSize]: 2.5 },\n 0b10101000: { [mode]: celtOnly, [bandwidth]: wideBand, [frameSize]: 5 },\n 0b10110000: { [mode]: celtOnly, [bandwidth]: wideBand, [frameSize]: 10 },\n 0b10111000: { [mode]: celtOnly, [bandwidth]: wideBand, [frameSize]: 20 },\n 0b11000000: { [mode]: celtOnly, [bandwidth]: superWideBand, [frameSize]: 2.5 },\n 0b11001000: { [mode]: celtOnly, [bandwidth]: superWideBand, [frameSize]: 5 },\n 0b11010000: { [mode]: celtOnly, [bandwidth]: superWideBand, [frameSize]: 10 },\n 0b11011000: { [mode]: celtOnly, [bandwidth]: superWideBand, [frameSize]: 20 },\n 0b11100000: { [mode]: celtOnly, [bandwidth]: fullBand, [frameSize]: 2.5 },\n 0b11101000: { [mode]: celtOnly, [bandwidth]: fullBand, [frameSize]: 5 },\n 0b11110000: { [mode]: celtOnly, [bandwidth]: fullBand, [frameSize]: 10 },\n 0b11111000: { [mode]: celtOnly, [bandwidth]: fullBand, [frameSize]: 20 },\n};\n\nexport default class OpusHeader extends CodecHeader {\n static [getHeaderFromUint8Array](dataValue, packetData, headerCache) {\n const header = {};\n\n // get length of header\n // Byte (10 of 19)\n // * `CCCCCCCC`: Channel Count\n header[channels] = dataValue[9];\n // Byte (19 of 19)\n // * `GGGGGGGG`: Channel Mapping Family\n header[channelMappingFamily] = dataValue[18];\n\n header[length] =\n header[channelMappingFamily] !== 0 ? 21 + header[channels] : 19;\n\n if (dataValue[length] < header[length])\n throw new Error(\"Out of data while inside an Ogg Page\");\n\n // Page Segment Bytes (1-2)\n // * `AAAAA...`: Packet config\n // * `.....B..`:\n // * `......CC`: Packet code\n const packetMode = packetData[0] & 0b00000011;\n const packetLength = packetMode === 3 ? 2 : 1;\n\n // Check header cache\n const key =\n bytesToString(dataValue[subarray](0, header[length])) +\n bytesToString(packetData[subarray](0, packetLength));\n const cachedHeader = headerCache[getHeader](key);\n\n if (cachedHeader) return new OpusHeader(cachedHeader);\n\n // Bytes (1-8 of 19): OpusHead - Magic Signature\n if (key.substr(0, 8) !== \"OpusHead\") {\n return null;\n }\n\n // Byte (9 of 19)\n // * `00000001`: Version number\n if (dataValue[8] !== 1) return null;\n\n header[data] = uint8Array.from(dataValue[subarray](0, header[length]));\n\n const view = new dataView(header[data][buffer]);\n\n header[bitDepth] = 16;\n\n // Byte (10 of 19)\n // * `CCCCCCCC`: Channel Count\n // set earlier to determine length\n\n // Byte (11-12 of 19)\n // * `DDDDDDDD|DDDDDDDD`: Pre skip\n header[preSkip] = view.getUint16(10, true);\n\n // Byte (13-16 of 19)\n // * `EEEEEEEE|EEEEEEEE|EEEEEEEE|EEEEEEEE`: Sample Rate\n header[inputSampleRate] = view.getUint32(12, true);\n // Opus is always decoded at 48kHz\n header[sampleRate] = rate48000;\n\n // Byte (17-18 of 19)\n // * `FFFFFFFF|FFFFFFFF`: Output Gain\n header[outputGain] = view.getInt16(16, true);\n\n // Byte (19 of 19)\n // * `GGGGGGGG`: Channel Mapping Family\n // set earlier to determine length\n if (header[channelMappingFamily] in channelMappingFamilies) {\n header[channelMode] =\n channelMappingFamilies[header[channelMappingFamily]][\n header[channels] - 1\n ];\n if (!header[channelMode]) return null;\n }\n\n if (header[channelMappingFamily] !== 0) {\n // * `HHHHHHHH`: Stream count\n header[streamCount] = dataValue[19];\n\n // * `IIIIIIII`: Coupled Stream count\n header[coupledStreamCount] = dataValue[20];\n\n // * `JJJJJJJJ|...` Channel Mapping table\n header[channelMappingTable] = [\n ...dataValue[subarray](21, header[channels] + 21),\n ];\n }\n\n const packetConfig = configTable[0b11111000 & packetData[0]];\n header[mode] = packetConfig[mode];\n header[bandwidth] = packetConfig[bandwidth];\n header[frameSize] = packetConfig[frameSize];\n\n // https://tools.ietf.org/html/rfc6716#appendix-B\n switch (packetMode) {\n case 0:\n // 0: 1 frame in the packet\n header[frameCount] = 1;\n break;\n case 1:\n // 1: 2 frames in the packet, each with equal compressed size\n case 2:\n // 2: 2 frames in the packet, with different compressed sizes\n header[frameCount] = 2;\n break;\n case 3:\n // 3: an arbitrary number of frames in the packet\n header[isVbr] = !!(0b10000000 & packetData[1]);\n header[hasOpusPadding] = !!(0b01000000 & packetData[1]);\n header[frameCount] = 0b00111111 & packetData[1];\n break;\n default:\n return null;\n }\n\n // set header cache\n {\n const {\n length,\n data: headerData,\n channelMappingFamily,\n ...codecUpdateFields\n } = header;\n\n headerCache[setHeader](key, header, codecUpdateFields);\n }\n\n return new OpusHeader(header);\n }\n\n /**\n * @private\n * Call OpusHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n super(header);\n\n this[data] = header[data];\n this[bandwidth] = header[bandwidth];\n this[channelMappingFamily] = header[channelMappingFamily];\n this[channelMappingTable] = header[channelMappingTable];\n this[coupledStreamCount] = header[coupledStreamCount];\n this[frameCount] = header[frameCount];\n this[frameSize] = header[frameSize];\n this[hasOpusPadding] = header[hasOpusPadding];\n this[inputSampleRate] = header[inputSampleRate];\n this[isVbr] = header[isVbr];\n this[mode] = header[mode];\n this[outputGain] = header[outputGain];\n this[preSkip] = header[preSkip];\n this[streamCount] = header[streamCount];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore } from \"../../globals.js\";\nimport {\n codecFrames,\n data,\n pageSequenceNumber,\n codec,\n segments,\n logError,\n parseOggPage,\n enable,\n getHeaderFromUint8Array,\n} from \"../../constants.js\";\nimport Parser from \"../Parser.js\";\nimport OpusFrame from \"./OpusFrame.js\";\nimport OpusHeader from \"./OpusHeader.js\";\n\nexport default class OpusParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n this.Frame = OpusFrame;\n this.Header = OpusHeader;\n\n onCodec(this[codec]);\n this._identificationHeader = null;\n }\n\n get [codec]() {\n return \"opus\";\n }\n\n /**\n * @todo implement continued page support\n */\n [parseOggPage](oggPage) {\n if (oggPage[pageSequenceNumber] === 0) {\n // Identification header\n\n this._headerCache[enable]();\n this._identificationHeader = oggPage[data];\n } else if (oggPage[pageSequenceNumber] === 1) {\n // OpusTags\n } else {\n oggPage[codecFrames] = frameStore\n .get(oggPage)\n [segments].map((segment) => {\n const header = OpusHeader[getHeaderFromUint8Array](\n this._identificationHeader,\n segment,\n this._headerCache,\n );\n\n if (header) return new OpusFrame(segment, header);\n\n this._codecParser[logError](\n \"Failed to parse Ogg Opus Header\",\n \"Not a valid Ogg Opus file\",\n );\n });\n }\n\n return oggPage;\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport CodecFrame from \"../CodecFrame.js\";\n\nexport default class VorbisFrame extends CodecFrame {\n constructor(data, header, samples) {\n super(header, data, samples);\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\n/*\n\n1 1) [packet_type] : 8 bit value\n2 2) 0x76, 0x6f, 0x72, 0x62, 0x69, 0x73: the characters ’v’,’o’,’r’,’b’,’i’,’s’ as six octets\n\nLetter bits Description\nA 8 Packet type\nB 48 Magic signature (vorbis)\nC 32 Version number\nD 8 Channels\nE 32 Sample rate\nF 32 Bitrate Maximum (signed)\nG 32 Bitrate Nominal (signed)\nH 32 Bitrate Minimum (signed)\nI 4 blocksize 1\nJ 4 blocksize 0\nK 1 Framing flag\n*/\n\nimport {\n vorbisOpusChannelMapping,\n bitDepth,\n channelMode,\n sampleRate,\n channels,\n length,\n bitrateMaximum,\n bitrateMinimum,\n bitrateNominal,\n blocksize0,\n blocksize1,\n data,\n vorbisComments,\n vorbisSetup,\n version,\n buffer,\n subarray,\n getHeader,\n setHeader,\n getHeaderFromUint8Array,\n uint8Array,\n dataView,\n} from \"../../constants.js\";\nimport { bytesToString } from \"../../utilities.js\";\n\nimport CodecHeader from \"../CodecHeader.js\";\n\nconst blockSizes = {\n // 0b0110: 64,\n // 0b0111: 128,\n // 0b1000: 256,\n // 0b1001: 512,\n // 0b1010: 1024,\n // 0b1011: 2048,\n // 0b1100: 4096,\n // 0b1101: 8192\n};\nfor (let i = 0; i < 8; i++) blockSizes[i + 6] = 2 ** (6 + i);\n\nexport default class VorbisHeader extends CodecHeader {\n static [getHeaderFromUint8Array](\n dataValue,\n headerCache,\n vorbisCommentsData,\n vorbisSetupData,\n ) {\n // Must be at least 30 bytes.\n if (dataValue[length] < 30)\n throw new Error(\"Out of data while inside an Ogg Page\");\n\n // Check header cache\n const key = bytesToString(dataValue[subarray](0, 30));\n const cachedHeader = headerCache[getHeader](key);\n if (cachedHeader) return new VorbisHeader(cachedHeader);\n\n const header = { [length]: 30 };\n\n // Bytes (1-7 of 30): /01vorbis - Magic Signature\n if (key.substr(0, 7) !== \"\\x01vorbis\") {\n return null;\n }\n\n header[data] = uint8Array.from(dataValue[subarray](0, 30));\n const view = new dataView(header[data][buffer]);\n\n // Byte (8-11 of 30)\n // * `CCCCCCCC|CCCCCCCC|CCCCCCCC|CCCCCCCC`: Version number\n header[version] = view.getUint32(7, true);\n if (header[version] !== 0) return null;\n\n // Byte (12 of 30)\n // * `DDDDDDDD`: Channel Count\n header[channels] = dataValue[11];\n header[channelMode] =\n vorbisOpusChannelMapping[header[channels] - 1] || \"application defined\";\n\n // Byte (13-16 of 30)\n // * `EEEEEEEE|EEEEEEEE|EEEEEEEE|EEEEEEEE`: Sample Rate\n header[sampleRate] = view.getUint32(12, true);\n\n // Byte (17-20 of 30)\n // * `FFFFFFFF|FFFFFFFF|FFFFFFFF|FFFFFFFF`: Bitrate Maximum\n header[bitrateMaximum] = view.getInt32(16, true);\n\n // Byte (21-24 of 30)\n // * `GGGGGGGG|GGGGGGGG|GGGGGGGG|GGGGGGGG`: Bitrate Nominal\n header[bitrateNominal] = view.getInt32(20, true);\n\n // Byte (25-28 of 30)\n // * `HHHHHHHH|HHHHHHHH|HHHHHHHH|HHHHHHHH`: Bitrate Minimum\n header[bitrateMinimum] = view.getInt32(24, true);\n\n // Byte (29 of 30)\n // * `IIII....` Blocksize 1\n // * `....JJJJ` Blocksize 0\n header[blocksize1] = blockSizes[(dataValue[28] & 0b11110000) >> 4];\n header[blocksize0] = blockSizes[dataValue[28] & 0b00001111];\n if (header[blocksize0] > header[blocksize1]) return null;\n\n // Byte (29 of 30)\n // * `00000001` Framing bit\n if (dataValue[29] !== 0x01) return null;\n\n header[bitDepth] = 32;\n header[vorbisSetup] = vorbisSetupData;\n header[vorbisComments] = vorbisCommentsData;\n\n {\n // set header cache\n const {\n length,\n data,\n version,\n vorbisSetup,\n vorbisComments,\n ...codecUpdateFields\n } = header;\n headerCache[setHeader](key, header, codecUpdateFields);\n }\n\n return new VorbisHeader(header);\n }\n\n /**\n * @private\n * Call VorbisHeader.getHeader(Array<Uint8>) to get instance\n */\n constructor(header) {\n super(header);\n\n this[bitrateMaximum] = header[bitrateMaximum];\n this[bitrateMinimum] = header[bitrateMinimum];\n this[bitrateNominal] = header[bitrateNominal];\n this[blocksize0] = header[blocksize0];\n this[blocksize1] = header[blocksize1];\n this[data] = header[data];\n this[vorbisComments] = header[vorbisComments];\n this[vorbisSetup] = header[vorbisSetup];\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { frameStore } from \"../../globals.js\";\nimport { BitReader, reverse } from \"../../utilities.js\";\nimport {\n data,\n codec,\n blocksize0,\n blocksize1,\n codecFrames,\n segments,\n vorbis,\n logWarning,\n parseOggPage,\n enable,\n getHeaderFromUint8Array,\n} from \"../../constants.js\";\n\nimport Parser from \"../Parser.js\";\nimport VorbisFrame from \"./VorbisFrame.js\";\nimport VorbisHeader from \"./VorbisHeader.js\";\n\nexport default class VorbisParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n this.Frame = VorbisFrame;\n\n onCodec(this[codec]);\n\n this._identificationHeader = null;\n this._setupComplete = false;\n\n this._prevBlockSize = null;\n }\n\n get [codec]() {\n return vorbis;\n }\n\n [parseOggPage](oggPage) {\n oggPage[codecFrames] = [];\n\n for (const oggPageSegment of frameStore.get(oggPage)[segments]) {\n if (oggPageSegment[0] === 1) {\n // Identification header\n\n this._headerCache[enable]();\n this._identificationHeader = oggPage[data];\n this._setupComplete = false;\n } else if (oggPageSegment[0] === 3) {\n // comment header\n\n this._vorbisComments = oggPageSegment;\n } else if (oggPageSegment[0] === 5) {\n // setup header\n\n this._vorbisSetup = oggPageSegment;\n this._mode = this._parseSetupHeader(oggPageSegment);\n this._setupComplete = true;\n } else if (this._setupComplete) {\n const header = VorbisHeader[getHeaderFromUint8Array](\n this._identificationHeader,\n this._headerCache,\n this._vorbisComments,\n this._vorbisSetup,\n );\n\n if (header) {\n oggPage[codecFrames].push(\n new VorbisFrame(\n oggPageSegment,\n header,\n this._getSamples(oggPageSegment, header),\n ),\n );\n } else {\n this._codecParser[logError](\n \"Failed to parse Ogg Vorbis Header\",\n \"Not a valid Ogg Vorbis file\",\n );\n }\n }\n }\n\n return oggPage;\n }\n\n _getSamples(segment, header) {\n const blockFlag =\n this._mode.blockFlags[(segment[0] >> 1) & this._mode.mask];\n\n const currentBlockSize = blockFlag\n ? header[blocksize1]\n : header[blocksize0];\n\n // data is not returned on the first frame, but is used to prime the decoder\n // https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-590004\n const samplesValue =\n this._prevBlockSize === null\n ? 0\n : (this._prevBlockSize + currentBlockSize) / 4;\n\n this._prevBlockSize = currentBlockSize;\n\n return samplesValue;\n }\n\n // https://gitlab.xiph.org/xiph/liboggz/-/blob/master/src/liboggz/oggz_auto.c#L911\n // https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/vorbis_parser.c\n /*\n * This is the format of the mode data at the end of the packet for all\n * Vorbis Version 1 :\n *\n * [ 6:number_of_modes ]\n * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]\n * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]\n * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]\n * [ 1:framing(1) ]\n *\n * e.g.:\n *\n * MsB LsB\n * <-\n * 0 0 0 0 0 1 0 0\n * 0 0 1 0 0 0 0 0\n * 0 0 1 0 0 0 0 0\n * 0 0 1|0 0 0 0 0\n * 0 0 0 0|0|0 0 0\n * 0 0 0 0 0 0 0 0\n * 0 0 0 0|0 0 0 0\n * 0 0 0 0 0 0 0 0\n * 0 0 0 0|0 0 0 0\n * 0 0 0|1|0 0 0 0 |\n * 0 0 0 0 0 0 0 0 V\n * 0 0 0|0 0 0 0 0\n * 0 0 0 0 0 0 0 0\n * 0 0|1 0 0 0 0 0\n *\n * The simplest way to approach this is to start at the end\n * and read backwards to determine the mode configuration.\n *\n * liboggz and ffmpeg both use this method.\n */\n _parseSetupHeader(setup) {\n const bitReader = new BitReader(setup);\n const mode = {\n count: 0,\n blockFlags: [],\n };\n\n // sync with the framing bit\n while ((bitReader.read(1) & 0x01) !== 1) {}\n\n let modeBits;\n // search in reverse to parse out the mode entries\n // limit mode count to 63 so previous block flag will be in first packet byte\n while (mode.count < 64 && bitReader.position > 0) {\n reverse(bitReader.read(8)); // read mapping\n\n // 16 bits transform type, 16 bits window type, all values must be zero\n let currentByte = 0;\n while (bitReader.read(8) === 0x00 && currentByte++ < 3) {} // a non-zero value may indicate the end of the mode entries, or invalid data\n\n if (currentByte === 4) {\n // transform type and window type were all zeros\n modeBits = bitReader.read(7); // modeBits may need to be used in the next iteration if this is the last mode entry\n mode.blockFlags.unshift(modeBits & 0x01); // read and store mode number -> block flag\n bitReader.position += 6; // go back 6 bits so next iteration starts right after the block flag\n mode.count++;\n } else {\n // transform type and window type were not all zeros\n // check for mode count using previous iteration modeBits\n if (((reverse(modeBits) & 0b01111110) >> 1) + 1 !== mode.count) {\n this._codecParser[logWarning](\n \"vorbis derived mode count did not match actual mode count\",\n );\n }\n\n break;\n }\n }\n\n // xxxxxxxa packet type\n // xxxxxxbx mode count (number of mode count bits)\n // xxxxxcxx previous window flag\n // xxxxdxxx next window flag\n mode.mask = (1 << Math.log2(mode.count)) - 1;\n\n return mode;\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { headerStore, frameStore } from \"../../globals.js\";\nimport { bytesToString, concatBuffers } from \"../../utilities.js\";\nimport {\n header,\n pageSequenceNumber,\n pageSegmentBytes,\n pageSegmentTable,\n codec,\n data,\n length,\n segments,\n subarray,\n vorbis,\n mapFrameStats,\n logWarning,\n fixedLengthFrameSync,\n parseFrame,\n parseOggPage,\n reset,\n uint8Array,\n isLastPage,\n streamSerialNumber,\n} from \"../../constants.js\";\n\nimport Parser from \"../../codecs/Parser.js\";\nimport OggPage from \"./OggPage.js\";\nimport OggPageHeader from \"./OggPageHeader.js\";\n\nimport FLACParser from \"../../codecs/flac/FLACParser.js\";\nimport OpusParser from \"../../codecs/opus/OpusParser.js\";\nimport VorbisParser from \"../../codecs/vorbis/VorbisParser.js\";\n\nclass OggStream {\n constructor(codecParser, headerCache, onCodec) {\n this._codecParser = codecParser;\n this._headerCache = headerCache;\n this._onCodec = onCodec;\n\n this._continuedPacket = new uint8Array();\n this._codec = null;\n this._isSupported = null;\n }\n\n get [codec]() {\n return this._codec || \"\";\n }\n\n _updateCodec(codec, Parser) {\n if (this._codec !== codec) {\n this._headerCache[reset]();\n this._parser = new Parser(\n this._codecParser,\n this._headerCache,\n this._onCodec,\n );\n this._codec = codec;\n }\n }\n\n _checkCodecSupport({ data }) {\n const idString = bytesToString(data[subarray](0, 8));\n\n switch (idString) {\n case \"fishead\\0\":\n return false; // ignore ogg skeleton packets\n case \"OpusHead\":\n this._updateCodec(\"opus\", OpusParser);\n return true;\n case /^\\x7fFLAC/.test(idString) && idString:\n this._updateCodec(\"flac\", FLACParser);\n return true;\n case /^\\x01vorbis/.test(idString) && idString:\n this._updateCodec(vorbis, VorbisParser);\n return true;\n default:\n return false;\n }\n }\n\n _checkPageSequenceNumber(oggPage) {\n if (\n oggPage[pageSequenceNumber] !== this._pageSequenceNumber + 1 &&\n this._pageSequenceNumber > 1 &&\n oggPage[pageSequenceNumber] > 1\n ) {\n this._codecParser[logWarning](\n \"Unexpected gap in Ogg Page Sequence Number.\",\n `Expected: ${this._pageSequenceNumber + 1}, Got: ${\n oggPage[pageSequenceNumber]\n }`,\n );\n }\n\n this._pageSequenceNumber = oggPage[pageSequenceNumber];\n }\n\n _parsePage(oggPage) {\n if (this._isSupported === null) {\n this._pageSequenceNumber = oggPage[pageSequenceNumber];\n this._isSupported = this._checkCodecSupport(oggPage);\n }\n\n this._checkPageSequenceNumber(oggPage);\n\n const oggPageStore = frameStore.get(oggPage);\n const headerData = headerStore.get(oggPageStore[header]);\n\n let offset = 0;\n oggPageStore[segments] = headerData[pageSegmentTable].map((segmentLength) =>\n oggPage[data][subarray](offset, (offset += segmentLength)),\n );\n\n // prepend any existing continued packet data\n if (this._continuedPacket[length]) {\n oggPageStore[segments][0] = concatBuffers(\n this._continuedPacket,\n oggPageStore[segments][0],\n );\n\n this._continuedPacket = new uint8Array();\n }\n\n // save any new continued packet data\n if (\n headerData[pageSegmentBytes][headerData[pageSegmentBytes][length] - 1] ===\n 0xff\n ) {\n this._continuedPacket = concatBuffers(\n this._continuedPacket,\n oggPageStore[segments].pop(),\n );\n }\n\n if (this._isSupported) {\n const frame = this._parser[parseOggPage](oggPage);\n this._codecParser[mapFrameStats](frame);\n\n return frame;\n } else {\n return oggPage;\n }\n }\n}\n\nexport default class OggParser extends Parser {\n constructor(codecParser, headerCache, onCodec) {\n super(codecParser, headerCache);\n\n this._onCodec = onCodec;\n this.Frame = OggPage;\n this.Header = OggPageHeader;\n\n this._streams = new Map();\n this._currentSerialNumber = null;\n }\n\n get [codec]() {\n const oggStream = this._streams.get(this._currentSerialNumber);\n\n return oggStream ? oggStream.codec : \"\";\n }\n\n *[parseFrame]() {\n const oggPage = yield* this[fixedLengthFrameSync](true);\n this._currentSerialNumber = oggPage[streamSerialNumber];\n\n let oggStream = this._streams.get(this._currentSerialNumber);\n if (!oggStream) {\n oggStream = new OggStream(\n this._codecParser,\n this._headerCache,\n this._onCodec,\n );\n this._streams.set(this._currentSerialNumber, oggStream);\n }\n\n if (oggPage[isLastPage]) this._streams.delete(this._currentSerialNumber);\n\n return oggStream._parsePage(oggPage);\n }\n}\n","/* Copyright 2020-2023 Ethan Halsall\n \n This file is part of codec-parser.\n \n codec-parser is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n codec-parser is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport { crc32Function, concatBuffers } from \"./utilities.js\";\nimport {\n header,\n sampleRate,\n bitrate,\n length,\n frameNumber,\n data,\n samples,\n codec,\n codecFrames,\n totalBytesOut,\n totalSamples,\n totalDuration,\n crc32,\n duration,\n subarray,\n readRawData,\n incrementRawData,\n mapCodecFrameStats,\n mapFrameStats,\n logWarning,\n logError,\n parseFrame,\n checkCodecUpdate,\n reset,\n} from \"./constants.js\";\nimport HeaderCache from \"./codecs/HeaderCache.js\";\nimport MPEGParser from \"./codecs/mpeg/MPEGParser.js\";\nimport AACParser from \"./codecs/aac/AACParser.js\";\nimport FLACParser from \"./codecs/flac/FLACParser.js\";\nimport OggParser from \"./containers/ogg/OggParser.js\";\n\nconst noOp = () => {};\n\nexport default class CodecParser {\n constructor(\n mimeType,\n {\n onCodec,\n onCodecHeader,\n onCodecUpdate,\n enableLogging = false,\n enableFrameCRC32 = true,\n } = {},\n ) {\n this._inputMimeType = mimeType;\n this._onCodec = onCodec || noOp;\n this._onCodecHeader = onCodecHeader || noOp;\n this._onCodecUpdate = onCodecUpdate;\n this._enableLogging = enableLogging;\n this._crc32 = enableFrameCRC32 ? crc32Function : noOp;\n\n this[reset]();\n }\n\n /**\n * @public\n * @returns The detected codec\n */\n get [codec]() {\n return this._parser ? this._parser[codec] : \"\";\n }\n\n [reset]() {\n this._headerCache = new HeaderCache(\n this._onCodecHeader,\n this._onCodecUpdate,\n );\n\n this._generator = this._getGenerator();\n this._generator.next();\n }\n\n /**\n * @public\n * @description Generator function that yields any buffered CodecFrames and resets the CodecParser\n * @returns {Iterable<CodecFrame|OggPage>} Iterator that operates over the codec data.\n * @yields {CodecFrame|OggPage} Parsed codec or ogg page data\n */\n *flush() {\n this._flushing = true;\n\n for (let i = this._generator.next(); i.value; i = this._generator.next()) {\n yield i.value;\n }\n\n this._flushing = false;\n\n this[reset]();\n }\n\n /**\n * @public\n * @description Generator function takes in a Uint8Array of data and returns a CodecFrame from the data for each iteration\n * @param {Uint8Array} chunk Next chunk of codec data to read\n * @returns {Iterable<CodecFrame|OggPage>} Iterator that operates over the codec data.\n * @yields {CodecFrame|OggPage} Parsed codec or ogg page data\n */\n *parseChunk(chunk) {\n for (\n let i = this._generator.next(chunk);\n i.value;\n i = this._generator.next()\n ) {\n yield i.value;\n }\n }\n\n /**\n * @public\n * @description Parses an entire file and returns all of the contained frames.\n * @param {Uint8Array} fileData Coded data to read\n * @returns {Array<CodecFrame|OggPage>} CodecFrames\n */\n parseAll(fileData) {\n return [...this.parseChunk(fileData), ...this.flush()];\n }\n\n /**\n * @private\n */\n *_getGenerator() {\n if (this._inputMimeType.match(/aac/)) {\n this._parser = new AACParser(this, this._headerCache, this._onCodec);\n } else if (this._inputMimeType.match(/mpeg/)) {\n this._parser = new MPEGParser(this, this._headerCache, this._onCodec);\n } else if (this._inputMimeType.match(/flac/)) {\n this._parser = new FLACParser(this, this._headerCache, this._onCodec);\n } else if (this._inputMimeType.match(/ogg/)) {\n this._parser = new OggParser(this, this._headerCache, this._onCodec);\n } else {\n throw new Error(`Unsupported Codec ${mimeType}`);\n }\n\n this._frameNumber = 0;\n this._currentReadPosition = 0;\n this._totalBytesIn = 0;\n this._totalBytesOut = 0;\n this._totalSamples = 0;\n this._sampleRate = undefined;\n\n this._rawData = new Uint8Array(0);\n\n // start parsing out frames\n while (true) {\n const frame = yield* this._parser[parseFrame]();\n if (frame) yield frame;\n }\n }\n\n /**\n * @protected\n * @param {number} minSize Minimum bytes to have present in buffer\n * @returns {Uint8Array} rawData\n */\n *[readRawData](minSize = 0, readOffset = 0) {\n let rawData;\n\n while (this._rawData[length] <= minSize + readOffset) {\n rawData = yield;\n\n if (this._flushing) return this._rawData[subarray](readOffset);\n\n if (rawData) {\n this._totalBytesIn += rawData[length];\n this._rawData = concatBuffers(this._rawData, rawData);\n }\n }\n\n return this._rawData[subarray](readOffset);\n }\n\n /**\n * @protected\n * @param {number} increment Bytes to increment codec data\n */\n [incrementRawData](increment) {\n this._currentReadPosition += increment;\n this._rawData = this._rawData[subarray](increment);\n }\n\n /**\n * @protected\n */\n [mapCodecFrameStats](frame) {\n this._sampleRate = frame[header][sampleRate];\n\n frame[header][bitrate] =\n frame[duration] > 0\n ? Math.round(frame[data][length] / frame[duration]) * 8\n : 0;\n frame[frameNumber] = this._frameNumber++;\n frame[totalBytesOut] = this._totalBytesOut;\n frame[totalSamples] = this._totalSamples;\n frame[totalDuration] = (this._totalSamples / this._sampleRate) * 1000;\n frame[crc32] = this._crc32(frame[data]);\n\n this._headerCache[checkCodecUpdate](\n frame[header][bitrate],\n frame[totalDuration],\n );\n\n this._totalBytesOut += frame[data][length];\n this._totalSamples += frame[samples];\n }\n\n /**\n * @protected\n */\n [mapFrameStats](frame) {\n if (frame[codecFrames]) {\n // Ogg container\n frame[codecFrames].forEach((codecFrame) => {\n frame[duration] += codecFrame[duration];\n frame[samples] += codecFrame[samples];\n this[mapCodecFrameStats](codecFrame);\n });\n\n frame[totalSamples] = this._totalSamples;\n frame[totalDuration] =\n (this._totalSamples / this._sampleRate) * 1000 || 0;\n frame[totalBytesOut] = this._totalBytesOut;\n } else {\n this[mapCodecFrameStats](frame);\n }\n }\n\n /**\n * @private\n */\n _log(logger, messages) {\n if (this._enableLogging) {\n const stats = [\n `${codec}: ${this[codec]}`,\n `inputMimeType: ${this._inputMimeType}`,\n `readPosition: ${this._currentReadPosition}`,\n `totalBytesIn: ${this._totalBytesIn}`,\n `${totalBytesOut}: ${this._totalBytesOut}`,\n ];\n\n const width = Math.max(...stats.map((s) => s[length]));\n\n messages.push(\n `--stats--${\"-\".repeat(width - 9)}`,\n ...stats,\n \"-\".repeat(width),\n );\n\n logger(\n \"codec-parser\",\n messages.reduce((acc, message) => acc + \"\\n \" + message, \"\"),\n );\n }\n }\n\n /**\n * @protected\n */\n [logWarning](...messages) {\n this._log(console.warn, messages);\n }\n\n /**\n * @protected\n */\n [logError](...messages) {\n this._log(console.error, messages);\n }\n}\n","import CodecParser from \"./src/CodecParser.js\";\nimport * as constants from \"./src/constants.js\";\n\nexport default CodecParser;\n\nexport const absoluteGranulePosition = constants.absoluteGranulePosition;\nexport const bandwidth = constants.bandwidth;\nexport const bitDepth = constants.bitDepth;\nexport const bitrate = constants.bitrate;\nexport const bitrateMaximum = constants.bitrateMaximum;\nexport const bitrateMinimum = constants.bitrateMinimum;\nexport const bitrateNominal = constants.bitrateNominal;\nexport const buffer = constants.buffer;\nexport const bufferFullness = constants.bufferFullness;\nexport const codec = constants.codec;\nexport const codecFrames = constants.codecFrames;\nexport const coupledStreamCount = constants.coupledStreamCount;\nexport const crc = constants.crc;\nexport const crc16 = constants.crc16;\nexport const crc32 = constants.crc32;\nexport const data = constants.data;\nexport const description = constants.description;\nexport const duration = constants.duration;\nexport const emphasis = constants.emphasis;\nexport const hasOpusPadding = constants.hasOpusPadding;\nexport const header = constants.header;\nexport const isContinuedPacket = constants.isContinuedPacket;\nexport const isCopyrighted = constants.isCopyrighted;\nexport const isFirstPage = constants.isFirstPage;\nexport const isHome = constants.isHome;\nexport const isLastPage = constants.isLastPage;\nexport const isOriginal = constants.isOriginal;\nexport const isPrivate = constants.isPrivate;\nexport const isVbr = constants.isVbr;\nexport const layer = constants.layer;\nexport const length = constants.length;\nexport const mode = constants.mode;\nexport const modeExtension = constants.modeExtension;\nexport const mpeg = constants.mpeg;\nexport const mpegVersion = constants.mpegVersion;\nexport const numberAACFrames = constants.numberAACFrames;\nexport const outputGain = constants.outputGain;\nexport const preSkip = constants.preSkip;\nexport const profile = constants.profile;\nexport const protection = constants.protection;\nexport const rawData = constants.rawData;\nexport const segments = constants.segments;\nexport const subarray = constants.subarray;\nexport const version = constants.version;\nexport const vorbis = constants.vorbis;\nexport const vorbisComments = constants.vorbisComments;\nexport const vorbisSetup = constants.vorbisSetup;\nexport const blockingStrategy = constants.blockingStrategy;\nexport const blockSize = constants.blockSize;\nexport const blocksize0 = constants.blocksize0;\nexport const blocksize1 = constants.blocksize1;\nexport const channelMappingFamily = constants.channelMappingFamily;\nexport const channelMappingTable = constants.channelMappingTable;\nexport const channelMode = constants.channelMode;\nexport const channels = constants.channels;\nexport const copyrightId = constants.copyrightId;\nexport const copyrightIdStart = constants.copyrightIdStart;\nexport const frame = constants.frame;\nexport const frameCount = constants.frameCount;\nexport const frameLength = constants.frameLength;\nexport const frameNumber = constants.frameNumber;\nexport const framePadding = constants.framePadding;\nexport const frameSize = constants.frameSize;\nexport const inputSampleRate = constants.inputSampleRate;\nexport const pageChecksum = constants.pageChecksum;\nexport const pageSegmentTable = constants.pageSegmentTable;\nexport const pageSequenceNumber = constants.pageSequenceNumber;\nexport const sampleNumber = constants.sampleNumber;\nexport const sampleRate = constants.sampleRate;\nexport const samples = constants.samples;\nexport const streamCount = constants.streamCount;\nexport const streamInfo = constants.streamInfo;\nexport const streamSerialNumber = constants.streamSerialNumber;\nexport const streamStructureVersion = constants.streamStructureVersion;\nexport const totalBytesOut = constants.totalBytesOut;\nexport const totalDuration = constants.totalDuration;\nexport const totalSamples = constants.totalSamples;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.F = {};\n__webpack_require__.E = (chunkId) => {\n\tObject.keys(__webpack_require__.F).map((key) => {\n\t\t__webpack_require__.F[key](chunkId);\n\t});\n}","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = (chunkId) => {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = (chunkId) => {\n\t// return url for filenames not based on template\n\tif (chunkId === 385) return \"icecast-metadata-player-1.17.3.common.min.js\";\n\t// return url for filenames based on template\n\treturn \"icecast-metadata-player-1.17.3.\" + {\"88\":\"mpeg\",\"398\":\"vorbis\",\"694\":\"opus\",\"731\":\"synaudio\",\"762\":\"mediasource\",\"993\":\"flac\"}[chunkId] + \".min.js\";\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","var scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nvar document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript)\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tvar i = scripts.length - 1;\n\t\t\twhile (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t792: 0\n};\n\n__webpack_require__.f.j = (chunkId, promises) => {\n\t\t// JSONP chunk loading for javascript\n\t\tvar installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tvar promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tvar url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tvar error = new Error();\n\t\t\t\t\tvar loadingEnded = (event) => {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n__webpack_require__.F.j = (chunkId) => {\n\tif((!__webpack_require__.o(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && true) {\n\t\tinstalledChunks[chunkId] = null;\n\t\tvar link = document.createElement('link');\n\n\t\tif (__webpack_require__.nc) {\n\t\t\tlink.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tlink.rel = \"prefetch\";\n\t\tlink.as = \"script\";\n\t\tlink.href = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\tdocument.head.appendChild(link);\n\t}\n};\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkIcecastMetadataPlayer\"] = self[\"webpackChunkIcecastMetadataPlayer\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.O(0, [792], () => {\n\t__webpack_require__.E(731);\n\t__webpack_require__.E(762);\n}, 5);","export const noOp = () => {};\nexport const p = new WeakMap();\n\nexport const state = {\n LOADING: \"loading\",\n PLAYING: \"playing\",\n STOPPING: \"stopping\",\n STOPPED: \"stopped\",\n RETRYING: \"retrying\",\n SWITCHING: \"switching\",\n};\n\nexport const event = {\n BUFFER: \"buffer\",\n PLAY: \"play\",\n PLAY_READY: \"playready\", // internal\n LOAD: \"load\",\n STREAM_START: \"streamstart\",\n STREAM: \"stream\",\n STREAM_END: \"streamend\",\n METADATA: \"metadata\",\n METADATA_ENQUEUE: \"metadataenqueue\",\n CODEC_UPDATE: \"codecupdate\",\n STOP: \"stop\",\n RETRY: \"retry\",\n RETRY_TIMEOUT: \"retrytimeout\",\n SWITCH: \"switch\",\n WARN: \"warn\",\n ERROR: \"error\",\n PLAYBACK_ERROR: \"playbackerror\",\n};\n\n// options\nexport const endpoints = Symbol();\nexport const endpointOrder = Symbol();\nexport const metadataTypes = Symbol();\nexport const playbackMethod = Symbol();\nexport const audioContext = Symbol();\nexport const audioElement = Symbol();\nexport const bufferLength = Symbol();\nexport const icyMetaInt = Symbol();\nexport const icyCharacterEncoding = Symbol();\nexport const icyDetectionTimeout = Symbol();\nexport const enableLogging = Symbol();\nexport const retryDelayRate = Symbol();\nexport const retryDelayMin = Symbol();\nexport const retryDelayMax = Symbol();\nexport const retryTimeout = Symbol();\nexport const enableCodecUpdate = Symbol();\nexport const authentication = Symbol();\n\n// methods\nexport const getNextEndpointGenerator = Symbol();\nexport const getOptions = Symbol();\nexport const fireEvent = Symbol();\nexport const attachAudioElement = Symbol();\nexport const shouldRetry = Symbol();\nexport const logError = Symbol();\n\n// variables\nexport const endpointGenerator = Symbol();\nexport const hasIcy = Symbol();\nexport const abortController = Symbol();\nexport const playerState = Symbol();\n\n// sync state\nexport const SYNCED = Symbol(\"synced\");\nexport const SYNCING = Symbol(\"syncing\");\nexport const PCM_SYNCED = Symbol(\"pcm_synced\");\nexport const NOT_SYNCED = Symbol(\"not_synced\");\n\nexport const concatBuffers = (buffers) => {\n const buffer = new Uint8Array(\n buffers.reduce((acc, buf) => acc + buf.length, 0),\n );\n\n buffers.reduce((offset, buf) => {\n buffer.set(buf, offset);\n return offset + buf.length;\n }, 0);\n\n return buffer;\n};\n","// support for Safari 13\n// https://stackoverflow.com/a/58209729/14911733\n\nexport default class EventTargetPolyfill {\n constructor() {\n this._listeners = [];\n }\n\n hasEventListener(type, listener) {\n return this._listeners.some(\n (item) => item.type === type && item.listener === listener,\n );\n }\n\n addEventListener(type, listener, options = {}) {\n if (!this.hasEventListener(type, listener)) {\n this._listeners.push({ type, listener, options });\n }\n // console.log(`${this}-listeners:`,this._listeners);\n return this;\n }\n\n removeEventListener(type, listener) {\n const index = this._listeners.findIndex(\n (item) => item.type === type && item.listener === listener,\n );\n if (index >= 0) this._listeners.splice(index, 1);\n return this;\n }\n\n removeEventListeners() {\n this._listeners = [];\n return this;\n }\n\n dispatchEvent(evt) {\n this._listeners\n .filter((item) => item.type === evt.type)\n .forEach((item) => {\n const {\n type,\n listener,\n options: { once },\n } = item;\n listener.call(this, evt);\n if (once === true) this.removeEventListener(type, listener);\n });\n return this;\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nexport default class Stats {\n constructor() {\n this._totalBytesRead = 0;\n this._streamBytesRead = 0;\n this._metadataLengthBytesRead = 0;\n this._metadataBytesRead = 0;\n\n this._currentBytesRemaining = 0;\n this._currentStreamBytesRemaining = 0;\n this._currentMetadataBytesRemaining = 0;\n }\n\n get stats() {\n return {\n totalBytesRead: this._totalBytesRead,\n streamBytesRead: this._streamBytesRead,\n metadataLengthBytesRead: this._metadataLengthBytesRead,\n metadataBytesRead: this._metadataBytesRead,\n currentBytesRemaining: this._currentBytesRemaining,\n currentStreamBytesRemaining: this._currentStreamBytesRemaining,\n currentMetadataBytesRemaining: this._currentMetadataBytesRemaining,\n };\n }\n\n set currentStreamBytesRemaining(bytes) {\n this._currentStreamBytesRemaining += bytes;\n }\n\n set currentMetadataBytesRemaining(bytes) {\n this._currentMetadataBytesRemaining = bytes;\n }\n\n addBytes(bytes) {\n this._totalBytesRead += bytes;\n this._currentBytesRemaining -= bytes;\n }\n\n addStreamBytes(bytes) {\n this._streamBytesRead += bytes;\n this._currentStreamBytesRemaining -= bytes;\n }\n\n addMetadataLengthBytes(bytes) {\n this._metadataLengthBytesRead += bytes;\n }\n\n addMetadataBytes(bytes) {\n this._metadataBytesRead += bytes;\n this._currentMetadataBytesRemaining -= bytes;\n }\n\n addCurrentBytesRemaining(bytes) {\n this._currentBytesRemaining += bytes;\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport Stats from \"./Stats.js\";\n\nconst noOp = () => {};\n\n/**\n * @description Passthrough parser\n * @protected\n * @see IcecastMetadataReader\n */\n\nexport default class MetadataParser {\n constructor(params) {\n this._remainingData = 0;\n this._currentPosition = 0;\n this._buffer = new Uint8Array(0);\n this._streamBuffer = [];\n this._streamBufferLength = 0;\n this._stats = new Stats();\n\n this._onStream = params.onStream || noOp;\n this._onMetadata = params.onMetadata || noOp;\n this._onMetadataFailed = params.onMetadataFailed || noOp;\n this._onError = params.onError || noOp;\n this._enableLogging = params.enableLogging || false;\n\n this._onStreamPromise = Promise.resolve();\n this._onMetadataPromise = Promise.resolve();\n this._generator = this._passThroughParser();\n this._generator.next();\n }\n\n *_passThroughParser() {\n this._remainingData = Infinity;\n while (true) {\n this._addStream(yield* this._getNextValue());\n yield* this._sendStream();\n }\n }\n\n static _concatBuffers(...buffers) {\n const length = buffers.reduce((acc, buf) => acc + buf.length, 0);\n\n return this._concatBuffersKnownLength(buffers, length);\n }\n\n static _concatBuffersKnownLength(buffers, length) {\n const buffer = new Uint8Array(length);\n\n buffers.reduce((offset, buf) => {\n buffer.set(buf, offset);\n return offset + buf.length;\n }, 0);\n\n return buffer;\n }\n\n *iterator(chunk) {\n for (\n let i = this._generator.next(chunk);\n i.value;\n i = this._generator.next()\n ) {\n yield i.value;\n }\n }\n\n readAll(chunk) {\n for (\n let i = this._generator.next(chunk);\n i.value;\n i = this._generator.next()\n ) {}\n }\n\n async *asyncIterator(chunk) {\n for (\n let i = this._generator.next(chunk);\n i.value;\n i = this._generator.next()\n ) {\n await this._onStreamPromise;\n await this._onMetadataPromise;\n yield i.value;\n }\n }\n\n async asyncReadAll(chunk) {\n for (\n let i = this._generator.next(chunk);\n i.value;\n i = this._generator.next()\n ) {\n await this._onStreamPromise;\n await this._onMetadataPromise;\n }\n }\n\n _logError(...messages) {\n if (this._enableLogging) {\n console.warn(\n \"icecast-metadata-js\",\n messages.reduce((acc, message) => acc + \"\\n \" + message, \"\"),\n );\n }\n this._onError(...messages);\n }\n\n _addStream(stream) {\n this._streamBuffer.push(stream);\n this._streamBufferLength += stream.length;\n }\n\n *_sendStream() {\n if (this._streamBuffer.length) {\n const stream = MetadataParser._concatBuffersKnownLength(\n this._streamBuffer,\n this._streamBufferLength,\n );\n this._streamBuffer = [];\n this._streamBufferLength = 0;\n\n this._stats.addStreamBytes(stream.length);\n\n const streamPayload = { stream, stats: this._stats.stats };\n\n this._onStreamPromise = this._onStream(streamPayload);\n yield streamPayload;\n }\n }\n\n *_sendMetadata(metadata) {\n yield* this._sendStream();\n\n const metadataPayload = {\n metadata,\n stats: this._stats.stats,\n };\n\n this._onMetadataPromise = this._onMetadata(metadataPayload);\n yield metadataPayload;\n }\n\n *_getNextValue(minLength = 0) {\n if (this._currentPosition === this._buffer.length) {\n this._buffer = yield* this._readData();\n this._currentPosition = 0;\n }\n\n while (this._buffer.length - this._currentPosition < minLength) {\n this._buffer = MetadataParser._concatBuffers(\n this._buffer,\n yield* this._readData(),\n );\n }\n\n const value = this._buffer.subarray(\n this._currentPosition,\n (minLength || this._remainingData) + this._currentPosition,\n );\n\n this._stats.addBytes(value.length);\n this._remainingData =\n value.length < this._remainingData\n ? this._remainingData - value.length\n : 0;\n\n this._currentPosition += value.length;\n\n return value;\n }\n\n *_readData() {\n yield* this._sendStream();\n\n let data;\n\n do {\n data = yield; // if out of data, accept new data in the .next() call\n } while (!data || data.length === 0);\n\n this._stats.addCurrentBytesRemaining(data.length);\n return data;\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport MetadataParser from \"./MetadataParser.js\";\n\n/**\n * @description Parses ICY metadata from an Icecast stream\n * @protected\n * @see IcecastMetadataReader\n */\n\nexport default class IcyMetadataParser extends MetadataParser {\n constructor({\n icyMetaInt,\n icyDetectionTimeout = 2000,\n icyCharacterEncoding = \"utf-8\",\n ...rest\n }) {\n super(rest);\n\n this._decoder = new globalThis.TextDecoder(icyCharacterEncoding);\n this._icyMetaInt = icyMetaInt;\n this._icyDetectionTimeout = icyDetectionTimeout;\n\n this._generator = this._icyParser();\n this._generator.next();\n }\n\n *_icyParser() {\n if (yield* this._hasIcyMetadata()) {\n do {\n this._remainingData = this._icyMetaInt;\n yield* this._getStream();\n yield* this._getMetadataLength();\n if (this._remainingData) yield* this._getMetadata();\n } while (true);\n }\n\n this._remainingData = Infinity;\n yield* this._getStream();\n }\n\n static parseIcyMetadata(metadataString) {\n /**\n * Metadata is a string of key='value' pairs delimited by a semicolon.\n * The string is a fixed length and any unused bytes at the end are 0x00.\n * i.e. \"StreamTitle='The Stream Title';StreamUrl='https://example.com';\\0\\0\\0\\0\\0\\0\"\n */\n\n const metadataRegex = /(?<key>[^\\0]+?)='(?<val>[^\\0]*?)(;$|';|'$|$)/;\n const metadata = {};\n\n // [{key: \"StreamTitle\", val: \"The Stream Title\"}, {key: \"StreamUrl\", val: \"https://example.com\"}]\n for (const metadataElement of metadataString.match(\n new RegExp(metadataRegex, \"g\"),\n ) || []) {\n const match = metadataElement.match(metadataRegex);\n if (match) metadata[match[\"groups\"][\"key\"]] = match[\"groups\"][\"val\"];\n }\n\n // {StreamTitle: \"The Stream Title\", StreamUrl: \"https://example.com\"}\n return metadata;\n }\n\n get icyMetaInt() {\n return this._icyMetaInt;\n }\n\n *_hasIcyMetadata() {\n if (this._icyMetaInt > 0) return true;\n if (!this._icyDetectionTimeout) return false;\n\n this._logError(\n \"Passed in Icy-MetaInt is invalid. Attempting to detect ICY Metadata.\",\n \"See https://github.com/eshaz/icecast-metadata-js for information on how to properly request ICY Metadata.\",\n );\n\n // prettier-ignore\n const METADATA_SEARCH = [null,83,116,114,101,97,109,84,105,116,108,101,61]; // StreamTitle=\n const startTime = Date.now();\n let metaInt = 0;\n\n while (startTime + this._icyDetectionTimeout > Date.now()) {\n this._buffer = MetadataParser._concatBuffers(\n this._buffer,\n yield* this._readData(),\n );\n\n // search for metadata\n detectMetadata: while (\n metaInt <\n this._buffer.length - METADATA_SEARCH.length\n ) {\n for (let i = 1; i < METADATA_SEARCH.length; i++) {\n if (this._buffer[i + metaInt] !== METADATA_SEARCH[i]) {\n metaInt++;\n continue detectMetadata;\n }\n }\n\n // found metadata\n // prettier-ignore\n this._logError(`Found ICY Metadata! Setting Icy-MetaInt to ${metaInt}.`);\n this._icyMetaInt = metaInt;\n\n return true;\n }\n }\n\n // prettier-ignore\n this._logError(\n \"ICY Metadata not detected, but continuing anyway. Audio errors will occur if there is ICY metadata.\",\n `Searched ${this._buffer.length} bytes for ${(Date.now() - startTime) / 1000} seconds.`,\n \"Try increasing the `icyDetectionTimeout` value if ICY metadata is present in the stream.\"\n );\n this._onMetadataFailed(\"icy\");\n\n return false;\n }\n\n *_getStream() {\n this._stats.currentStreamBytesRemaining = this._remainingData;\n\n while (this._remainingData) {\n this._addStream(yield* super._getNextValue());\n }\n }\n\n *_getMetadataLength() {\n this._remainingData = 1;\n\n do {\n this._remainingData = (yield* this._getNextValue())[0] * 16;\n } while (this._remainingData === 1);\n\n this._stats.addMetadataLengthBytes(1);\n }\n\n *_getMetadata() {\n this._stats.currentMetadataBytesRemaining = this._remainingData;\n\n const metadata = yield* this._getNextValue(this._remainingData);\n this._stats.addMetadataBytes(metadata.length);\n\n yield* this._sendMetadata(\n IcyMetadataParser.parseIcyMetadata(this._decoder.decode(metadata)),\n );\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport MetadataParser from \"./MetadataParser.js\";\n\n/**\n * @description Parses Ogg metadata from an Icecast stream\n * @protected\n * @see IcecastMetadataReader\n */\nexport default class OggMetadataParser extends MetadataParser {\n constructor(params) {\n super(params);\n\n this._decoder = new globalThis.TextDecoder(\"utf-8\");\n this._generator = this._oggParser();\n this._generator.next();\n this._isContinuePacket = false;\n }\n\n *_oggParser() {\n if (yield* this._hasOggPage()) {\n const codecMatcher = yield* this._identifyCodec();\n if (codecMatcher) {\n while (yield* this._hasOggPage()) {\n if (!this._isContinuePacket) yield* this._getMetadata(codecMatcher);\n yield* this._getStream();\n }\n }\n }\n\n this._remainingData = Infinity;\n yield* this._getStream();\n }\n\n _getUint32(data, offset = 0) {\n return new DataView(\n Uint8Array.from([...data.subarray(offset, offset + 4)]).buffer,\n ).getUint32(0, true);\n }\n\n _matchBytes(matchString, bytes) {\n return String.fromCharCode(...bytes).match(matchString);\n }\n\n *_hasOggPage() {\n // Bytes (1-4 of 28)\n // Frame sync (must equal OggS): `AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA`:\n // Byte (5 of 28) stream_structure_version\n // Byte (6 of 28)\n // * `00000...`: All zeros\n // * `.....C..`: (0 no, 1 yes) last page of logical bitstream (eos)\n // * `......D.`: (0 no, 1 yes) first page of logical bitstream (bos)\n // * `.......E`: (0 no, 1 yes) continued packet\n let syncBytes = [];\n while (syncBytes.length <= 65307) {\n // max ogg page size\n const bytes = yield* super._getNextValue(6); // Sync with Ogg page without sending stream data\n if (\n bytes[0] === 0x4f &&\n bytes[1] === 0x67 &&\n bytes[2] === 0x67 &&\n bytes[3] === 0x53 &&\n !(bytes[5] & 0b11111000)\n ) {\n this._isContinuePacket = bytes[5] & 0b00000001;\n this._currentPosition -= 6;\n this._remainingData += 6;\n this._stats._totalBytesRead -= 6;\n this._stats._currentBytesRemaining += 6;\n break;\n }\n // not synced, rewind to the next offset to continue syncing\n syncBytes.push(bytes[0]);\n\n this._currentPosition -= 5;\n this._stats._totalBytesRead -= 5;\n this._stats._currentBytesRemaining += 5;\n }\n\n if (syncBytes.length) this._addStream(Uint8Array.from(syncBytes));\n\n if (syncBytes.length > 65307) {\n this._logError(\n \"This stream is not an Ogg stream. No Ogg metadata will be returned.\",\n \"See https://github.com/eshaz/icecast-metadata-js for information on Ogg metadata.\",\n );\n this._onMetadataFailed(\"ogg\");\n return false;\n }\n\n const baseOggPage = yield* this._getNextValue(27);\n // Byte (27 of 28)\n // * `JJJJJJJJ`: Number of page segments in the segment table\n const oggPageSegments = yield* this._getNextValue(baseOggPage[26]);\n\n this._remainingData = oggPageSegments.reduce(\n (acc, octet) => acc + octet,\n 0,\n );\n return true;\n }\n\n *_identifyCodec() {\n const data = yield* this._getNextValue(8);\n\n yield* this._getStream();\n\n if (this._matchBytes(/\\x7fFLAC/, data.subarray(0, 5))) {\n return { regex: /^[\\x84|\\x04]/, length: 4 };\n } else if (this._matchBytes(/OpusHead/, data.subarray(0, 8))) {\n return { regex: /OpusTags/, length: 8 };\n } else if (this._matchBytes(/\\x01vorbis/, data.subarray(0, 7))) {\n return { regex: /\\x03vorbis/, length: 7 };\n }\n }\n\n *_getMetadata({ regex, length }) {\n if (this._matchBytes(regex, yield* this._getNextValue(length))) {\n yield* this._sendMetadata(yield* this._readVorbisComment());\n }\n }\n\n *_getStream() {\n while (this._remainingData) {\n yield* this._getNextValue();\n }\n }\n\n *_getNextValue(length) {\n const value = yield* super._getNextValue(length);\n\n this._addStream(value);\n return value;\n }\n\n *_readData() {\n const data = yield* super._readData();\n this._stats.currentStreamBytesRemaining = data.length;\n return data;\n }\n\n *_readVorbisComment() {\n /*\n 1) [vendor_length] = read an unsigned integer of 32 bits\n 2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets\n 3) [user_comment_list_length] = read an unsigned integer of 32 bits\n 4) iterate [user_comment_list_length] times {\n 5) [length] = read an unsigned integer of 32 bits\n 6) this iteration's user comment = read a UTF-8 vector as [length] octets\n }\n 7) [framing_bit] = read a single bit as boolean\n 8) if ( [framing_bit] unset or end of packet ) then ERROR\n 9) done.\n */\n const vendorStringLength = this._getUint32(yield* this._getNextValue(4));\n this._stats.addMetadataBytes(4);\n\n const vendorString = this._decoder.decode(\n yield* this._getNextValue(vendorStringLength),\n );\n this._stats.addMetadataBytes(vendorStringLength);\n\n const commentListLength = this._getUint32(yield* this._getNextValue(4));\n this._stats.addMetadataBytes(4);\n\n const comments = [];\n for (let i = 0; i < commentListLength; i++) {\n const commentLength = yield* this._getNextValue(4);\n this._stats.addMetadataBytes(4);\n\n comments.push(yield* this._getNextValue(this._getUint32(commentLength)));\n this._stats.addMetadataBytes(comments[comments.length - 1].length);\n }\n\n this._stats.currentMetadataBytesRemaining = 0;\n\n return comments.reduce(\n (metadata, comment) => {\n const delimiter = comment.indexOf(0x3d);\n // prettier-ignore\n const key = String.fromCharCode(...comment.subarray(0, delimiter)).toUpperCase();\n const val = this._decoder.decode(comment.subarray(delimiter + 1));\n\n metadata[key] = metadata[key] ? `${metadata[key]}; ${val}` : val;\n return metadata;\n },\n { VENDOR_STRING: vendorString },\n );\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport IcyMetadataParser from \"./IcyMetadataParser.js\";\nimport OggMetadataParser from \"./OggMetadataParser.js\";\n\n/**\n * @description Parses ICY and Ogg metadata from an Icecast stream\n * @protected\n * @see IcecastMetadataReader\n */\n\nexport default class DualMetadataParser {\n constructor(params) {\n const { onStream, ...rest } = params;\n this._oggMetadataParser = new OggMetadataParser(params);\n this._icyMetadataParser = new IcyMetadataParser(rest);\n }\n\n get icyMetaInt() {\n return this._icyMetadataParser.icyMetaInt;\n }\n\n *iterator(chunk) {\n for (const value of this._icyMetadataParser.iterator(chunk)) {\n if (value.stream) {\n yield* this._oggMetadataParser.iterator(value.stream);\n } else {\n yield value;\n }\n }\n }\n\n readAll(chunk) {\n for (const value of this._icyMetadataParser.iterator(chunk)) {\n if (value.stream) {\n this._oggMetadataParser.readAll(value.stream);\n }\n }\n }\n\n async *asyncIterator(chunk) {\n for await (const value of this._icyMetadataParser.asyncIterator(chunk)) {\n if (value.stream) {\n for await (const oggValue of this._oggMetadataParser.asyncIterator(\n value.stream,\n )) {\n yield oggValue;\n }\n } else {\n yield value;\n }\n }\n }\n\n async asyncReadAll(chunk) {\n for await (const value of this._icyMetadataParser.iterator(chunk)) {\n if (value.stream) {\n await this._oggMetadataParser.asyncReadAll(value.stream);\n }\n }\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport MetadataParser from \"./MetadataParser/MetadataParser.js\";\nimport IcyMetadataParser from \"./MetadataParser/IcyMetadataParser.js\";\nimport OggMetadataParser from \"./MetadataParser/OggMetadataParser.js\";\nimport DualMetadataParser from \"./MetadataParser/DualMetadataParser.js\";\n\nexport default class IcecastMetadataReader {\n /**\n * @description Splits Icecast raw response into stream bytes and metadata key / value pairs.\n * @param {number} IcecastMetadataReader.icyMetaInt Interval in bytes of metadata updates returned by the Icecast server\n * @param {number} IcecastMetadataReader.icyCharacterEncoding Character encoding to use for ICY metadata (defaults to \"utf-8\")\n * @param {number} IcecastMetadataReader.icyDetectionTimeout Duration in milliseconds to search for metadata if icyMetaInt isn't passed in\n * @param {Array} IcecastMetadataReader.metadataTypes Types of metadata to capture: \"icy\" and/or \"ogg\"\n *\n * @callback onMetadata\n * @param {object} value Object containing Metadata and Statistics\n * @param {object} metadata Object containing the metadata received.\n * @param {string} [metadata.StreamTitle] (ICY) Title of the metadata update.\n * @param {string} [metadata.StreamUrl] (ICY) Url (usually album art) of the metadata update.\n * @param {string} [metadata.TITLE] (Ogg) Url Title of the metadata update.\n * @param {object} stats Object containing statistics on how many bytes were read and the current read position.\n *\n * @callback onStream\n * @param {object} value Object containing Stream data and Statistics\n * @param {Uint8Array} stream Object containing the stream buffer.\n * @param {object} stats Object containing statistics on how many bytes were read and the current read position.\n *\n * @callback onMetadataFailed Called when metadata detection has failed and no metadata will be returned\n * @param {string} metadataType Metadata type that failed (\"icy\" or \"ogg\")\n *\n * @callback onError Called when an error is encountered\n * @param {string} message Error message\n */\n constructor({ metadataTypes = [\"icy\"], ...rest } = {}) {\n const hasIcy = metadataTypes.includes(\"icy\");\n const hasOgg = metadataTypes.includes(\"ogg\");\n\n if (hasIcy && hasOgg) this._metadataParser = new DualMetadataParser(rest);\n else if (hasOgg) this._metadataParser = new OggMetadataParser(rest);\n else if (hasIcy) this._metadataParser = new IcyMetadataParser(rest);\n else this._metadataParser = new MetadataParser(rest);\n }\n\n /**\n * @description Parses an already decoded ICY metadata string into key value pairs.\n * @param {string} metadataString ICY formatted metadata string. (i.e. \"StreamTitle='A Title';\")\n * @returns {object} Parsed metadata key value pairs. (i.e. {StreamTitle: \"A Title\"})\n */\n static parseIcyMetadata(string) {\n return IcyMetadataParser.parseIcyMetadata(string);\n }\n\n /**\n * @description Gets the ICY metadata interval for this instance.\n * @returns {number} ICY metadata interval in bytes.\n */\n get icyMetaInt() {\n return this._metadataParser.icyMetaInt;\n }\n\n /**\n * @description Returns an iterator that yields stream or metadata.\n * @param {Uint8Array} chunk Next chunk of data to read\n * @returns {Iterator} Iterator that operates over a raw icecast response.\n * @yields {object} Object containing stream or metadata.\n */\n *iterator(chunk) {\n yield* this._metadataParser.iterator(chunk);\n }\n\n /**\n * @description Reads all data in the passed in chunk and calls the onStream and onMetadata callbacks.\n * @param {Uint8Array} chunk Next chunk of data to read\n */\n readAll(chunk) {\n this._metadataParser.readAll(chunk);\n }\n\n /**\n * @description Returns an async iterator that yields stream or metadata and awaits the onStream and onMetadata callbacks.\n * @param {Uint8Array} chunk Next chunk of data to read\n * @returns {IterableIterator} Iterator that operates over a raw icecast response.\n * @yields {object} Object containing stream or metadata.\n */\n async *asyncIterator(chunk) {\n return yield* this._metadataParser.asyncIterator(chunk);\n }\n\n /**\n * @description Reads all data in the chunk and awaits the onStream and onMetadata callbacks.\n * @param {Uint8Array} chunk Next chunk of data to read\n */\n async asyncReadAll(chunk) {\n return this._metadataParser.asyncReadAll(chunk);\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nimport IcecastMetadataReader from \"./IcecastMetadataReader.js\";\n\nconst noOp = () => {};\n\n/**\n * @description Browser ReadableStream wrapper for IcecastMetadataReader\n */\nexport default class IcecastReadableStream {\n /**\n * @param {ReadableStream} response ReadableStream for raw Icecast response data\n * @param {object} options Configuration options for IcecastMetadataReader\n * @see IcecastMetadataReader for information on the options parameter\n */\n constructor(response, { onStream = noOp, ...rest }) {\n let icecast;\n\n this._readableStream = new ReadableStream({\n async start(controller) {\n icecast = new IcecastMetadataReader({\n icyMetaInt: parseInt(response.headers.get(\"Icy-MetaInt\")),\n ...rest,\n onStream: async (value) => {\n controller.enqueue(value.stream);\n return onStream(value);\n },\n });\n\n for await (const chunk of IcecastReadableStream.asyncIterator(\n response.body,\n )) {\n await icecast.asyncReadAll(chunk);\n }\n\n controller.close();\n },\n });\n\n this._icecast = icecast;\n }\n\n /**\n * @returns Icecast Metadata Interval if it is present on this stream\n */\n get icyMetaInt() {\n return this._icecast.icyMetaInt;\n }\n\n /**\n * @returns The ReadableStream instance\n */\n get readableStream() {\n return this._readableStream;\n }\n\n /**\n * @description Starts reading from the response and processing stream and metadata.\n */\n async startReading() {\n try {\n for await (const i of IcecastReadableStream.asyncIterator(\n this._readableStream,\n )) {\n }\n } catch (e) {\n if (e.name !== \"AbortError\") throw e;\n }\n }\n\n /**\n * @description Wraps a ReadableStream as an Async Iterator.\n * @param {ReadableStream} readableStream ReadableStream to convert to AsyncIterator\n * @returns {Symbol.asyncIterator} Async Iterator that wraps the ReadableStream\n */\n static asyncIterator(readableStream) {\n const reader = readableStream.getReader();\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => reader.read(),\n }),\n };\n }\n}\n","/* Copyright 2020-2021 Ethan Halsall\n This file is part of icecast-metadata-js.\n\n icecast-metadata-js free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n icecast-metadata-js distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with this program. If not, see <https://www.gnu.org/licenses/>\n*/\n\nconst noOp = () => {};\n\nexport default class IcecastMetadataQueue {\n /**\n * @description Schedules updates up to the millisecond for Icecast Metadata from the response body of an Icecast stream mountpoint\n * @description The accuracy of metadata updates is a direct relationship of the icyMetaInt\n * @param {Object} IcecastMetadataQueue constructor parameter\n * @param {number} [IcecastMetadataQueue.icyBr] Bitrate of audio stream used to increase accuracy when to updating metadata\n * @param {onMetadataUpdate} [IcecastMetadataQueue.onMetadataUpdate] Callback executed when metadata is scheduled to update\n * @param {onMetadataEnqueue} [IcecastMetadataQueue.onMetadataEnqueue] Callback executed when metadata is enqueued\n * @param {boolean} [IcecastMetadataQueue.paused] Set to true to start the queue in a paused mode\n *\n * @callback onMetadataUpdate\n * @param {Object} metadata Object containing all metadata received.\n * @param {string} [metadata.StreamTitle] Title of the metadata update.\n * @param {string} [metadata.StreamUrl] Url (usually album art) of the metadata update.\n * @param {number} timestampOffset Total time buffered when the metadata was added\n * @param {number} timestamp Current time of the audio player when the metadata was added\n *\n * @callback onMetadataEnqueue\n * @param {Object} metadata Object containing all metadata received.\n * @param {string} [metadata.StreamTitle] Title of the metadata update.\n * @param {string} [metadata.StreamUrl] Url (usually album art) of the metadata update.\n * @param {number} timestampOffset Total time buffered when the metadata was added\n * @param {number} timestamp Current time of the audio player when the metadata was added\n *\n */\n constructor({\n icyBr,\n onMetadataUpdate = noOp,\n onMetadataEnqueue = noOp,\n paused = false,\n }) {\n this._icyBr = icyBr;\n this._onMetadataUpdate = onMetadataUpdate;\n this._onMetadataEnqueue = onMetadataEnqueue;\n this._initialPaused = paused;\n this._paused = paused;\n this._isInitialMetadata = true;\n this._pendingMetadata = [];\n this._metadataQueue = [];\n }\n\n /**\n * @description Returns the metadata queued for updates\n * @type {{metadata: string, time: number}[]} Queued metadata\n */\n get metadataQueue() {\n return this._metadataQueue.map(({ _timeoutId, ...rest }) => rest);\n }\n\n /**\n *\n * @param {object} metadata Metadata object returned from IcecastMetadataReader\n * @param {number} timestampOffset Total buffered audio in seconds\n * @param {number} [timestamp] Current time in the audio player\n */\n addMetadata({ metadata, stats }, timestampOffset, timestamp = 0) {\n /**\n * Metadata time is derived from the total number of stream bytes read\n * since the latest buffer input. The buffer offset should be the total\n * seconds of audio in the player buffer when the metadata was read.\n */\n timestamp += stats ? this.getTimeByBytes(stats.currentStreamPosition) : 0;\n\n const metadataPayload = {\n metadata,\n timestampOffset,\n timestamp,\n };\n\n this._paused\n ? this._pendingMetadata.push(metadataPayload)\n : this._enqueueMetadata(metadataPayload);\n }\n\n /**\n * @description Calculates audio stream length based on bitrate\n * @param {number} bytesRead Number of bytes\n * @type {number} Seconds\n */\n getTimeByBytes(bytesRead) {\n return this._icyBr ? bytesRead / (this._icyBr * 125) : 0;\n }\n\n /**\n * @description Starts the metadata queue if it was paused\n * @param {number} [timestamp] Current time of the audio player\n */\n startQueue(timestamp) {\n if (this._paused) {\n this._pendingMetadata.forEach((u) => {\n if (timestamp !== undefined) u.timestamp = timestamp;\n\n // remove any metadata that has already elapsed\n if (timestamp === undefined || u.timestampOffset >= u.timestamp)\n this._enqueueMetadata(u);\n });\n this._pendingMetadata = [];\n this._paused = false;\n }\n }\n\n /**\n * @description Clears all metadata updates and empties the queue\n */\n purgeMetadataQueue() {\n this._metadataQueue.forEach((i) => clearTimeout(i._timeoutId));\n this._metadataQueue = [];\n this._pendingMetadata = [];\n this._paused = this._initialPaused;\n this._isInitialMetadata = true;\n }\n\n _enqueueMetadata(payload) {\n this._metadataQueue.push(payload);\n\n this._onMetadataEnqueue(\n payload.metadata,\n payload.timestampOffset,\n payload.timestamp,\n );\n\n if (this._isInitialMetadata) {\n this._dequeueMetadata();\n this._isInitialMetadata = false;\n } else {\n payload._timeoutId = setTimeout(\n () => {\n this._dequeueMetadata();\n },\n (payload.timestampOffset - payload.timestamp) * 1000,\n ); // trigger timeout relative to play position\n }\n }\n\n _dequeueMetadata() {\n // purging the queue is an async operation, some timeouts may still be queued in the event loop _after_ the purge call has happened\n if (this._metadataQueue.length) {\n const { metadata, timestampOffset, timestamp } =\n this._metadataQueue.shift();\n this._onMetadataUpdate(metadata, timestampOffset, timestamp);\n }\n }\n}\n","import {\n audioContext,\n concatBuffers,\n event,\n state,\n fireEvent,\n SYNCED,\n PCM_SYNCED,\n SYNCING,\n NOT_SYNCED,\n noOp,\n} from \"./global.js\";\n\n// test if worker can spawn a worker for (i.e. everything but iOS)\nlet canSpawnWorker;\nconst spawnWorkerTest = new Worker(\n URL.createObjectURL(\n new Blob([\"self.onmessage = () => self.postMessage(!!self.Worker)\"], {\n type: \"text/javascript\",\n }),\n ),\n);\nspawnWorkerTest.onmessage = (r) => {\n canSpawnWorker = r.data;\n spawnWorkerTest.terminate();\n};\nspawnWorkerTest.postMessage(null);\n\nexport default class FrameQueue {\n constructor(icecast, player) {\n this.CRC_DURATION = 300000; // milliseconds to cache for crc syncing\n this.PCM_DURATION = 60000; // milliseconds to cache for pcm syncing\n\n this._icecast = icecast;\n this._player = player;\n\n this.initSync();\n this.initQueue();\n }\n\n initSync() {\n clearTimeout(this._syncTimeout);\n this._syncTimeout = null;\n this._syncTimeoutReason = null;\n this._crcSyncPending = true;\n\n this._syncQueue = [];\n this._syncQueueDuration = 0;\n\n this._synAudioResult = null;\n this._a = null;\n this._b = null;\n }\n\n initQueue() {\n this._queueIndex = 0;\n this._queueSamples = 0;\n this._queueSampleRate = 0;\n\n this._crcQueue = [];\n this._crcQueueDuration = 0;\n this._crcQueueIndexes = {};\n\n this._pcmQueue = [];\n this._pcmQueueDuration = 0;\n }\n\n get buffered() {\n return (\n this._queueSamples / this._queueSampleRate - this._player.currentTime || 0\n );\n }\n\n add(frame) {\n // crc queue\n const { crc32, duration, samples } = frame;\n this._queueSamples += samples;\n this._queueSampleRate = frame.header.sampleRate;\n\n this._crcQueue.push({ crc32, duration });\n this._crcQueueDuration += duration;\n\n // update queue index\n let indexes = this._crcQueueIndexes[crc32];\n if (!indexes) {\n indexes = [];\n this._crcQueueIndexes[crc32] = indexes;\n }\n indexes.push(this._queueIndex++);\n\n if (this._crcQueueDuration >= this.CRC_DURATION) {\n const { crc32, duration } = this._crcQueue.shift();\n this._crcQueueDuration -= duration;\n\n // remove the oldest index\n const indexes = this._crcQueueIndexes[crc32];\n indexes.shift();\n // remove the key if there are no indexes left\n if (!indexes.length) delete this._crcQueueIndexes[crc32];\n }\n\n // pcm queue\n this._pcmQueue.push(frame);\n this._pcmQueueDuration += duration;\n\n if (this._pcmQueueDuration >= this.PCM_DURATION) {\n this._pcmQueueDuration -= this._pcmQueue.shift().duration;\n }\n }\n\n addAll(frames) {\n frames.forEach((frame) => this.add(frame));\n }\n\n _addAllSyncQueue(frames) {\n for (const frame of frames) {\n this._syncQueueDuration += frame.duration;\n this._syncQueue.push(frame);\n }\n }\n\n /**\n *\n * @param {Array<CodecFrame|OggPage>} frames\n */\n async sync(frames) {\n // stop syncing if the buffer runs out\n if (this._syncTimeout === null) {\n const currentBuffered = this.buffered;\n\n this._syncReject = noOp;\n this._syncTimeout = setTimeout(() => {\n this._syncTimeoutReason = `Buffer underrun after syncing for ${currentBuffered.toFixed(\n 2,\n )} seconds.`;\n this._syncReject(this._syncTimeoutReason);\n }, currentBuffered * 1000);\n }\n\n this._addAllSyncQueue(frames);\n\n return new Promise(async (resolve, reject) => {\n if (this._syncTimeoutReason !== null) reject(this._syncTimeoutReason);\n else this._syncReject = reject;\n\n let syncState;\n // try syncing using crc32 hashes (if the stream data matches exactly)\n if (this._crcSyncPending) syncState = this._crcSync();\n\n // try syncing using decoded audio and corelation (if audio data matches)\n if (!syncState) {\n this._crcSyncPending = false;\n syncState = await this._pcmSync();\n }\n\n // streams do not match (not synced)\n if (!syncState) reject(\"Old and new request do not match.\");\n else resolve(syncState);\n })\n .catch((e) => {\n if (\n this._icecast.state !== state.STOPPING &&\n this._icecast.state !== state.STOPPED\n )\n this._icecast[fireEvent](\n event.WARN,\n `Reconnected successfully after ${this._icecast.state}.`,\n \"Unable to sync old and new request.\",\n e,\n );\n\n const syncQueue = this._syncQueue;\n this.initSync();\n this.initQueue();\n return [syncQueue, NOT_SYNCED];\n })\n .then((syncState) => {\n if ([SYNCED, PCM_SYNCED].includes(syncState[1])) {\n this.initSync();\n }\n\n return syncState;\n });\n }\n\n /*\n Aligns the queue with a new incoming data by aligning the crc32 hashes \n and then returning only the frames that do not existing on the queue.\n \n old data | common data | new data\n (old connection) ------------------------|\n (new connection) |------------------>\n ^^^^^^^^^^^^^^ ^^^^\n (sync) (frames to return)\n */\n _crcSync() {\n // get all indexed matches for crc and check\n if (!this._syncQueue.length) return [[], SYNCING];\n\n const syncQueueStartIndex = 0;\n const syncQueueCrc = this._syncQueue[syncQueueStartIndex].crc32;\n const crcSyncPoints = this._crcQueueIndexes[syncQueueCrc];\n\n let matched, outOfFrames, syncPoint;\n\n if (crcSyncPoints) {\n align_queues: for (const absoluteSyncPoint of crcSyncPoints) {\n syncPoint =\n absoluteSyncPoint - (this._queueIndex - this._crcQueue.length);\n\n for (\n let i = syncQueueStartIndex;\n i < this._syncQueue.length && syncPoint + i < this._crcQueue.length;\n i++\n )\n if (this._crcQueue[syncPoint + i].crc32 !== this._syncQueue[i].crc32)\n continue align_queues; // failed to match\n\n outOfFrames =\n syncPoint + this._syncQueue.length <= this._crcQueue.length;\n matched = true;\n break; // full match\n }\n\n // have some overlapping frames, but none are new frames\n if (outOfFrames) return [[], SYNCING];\n\n if (matched) {\n const sliceIndex = this._crcQueue.length - syncPoint;\n // prettier-ignore\n this._icecast[fireEvent](\n event.WARN,\n `Reconnected successfully after ${this._icecast.state}.`,\n `Found ${sliceIndex} frames (${(this._crcQueue\n .slice(syncPoint)\n .reduce((acc, { duration }) => acc + duration, 0) / 1000).toFixed(3)} seconds) of overlapping audio data in new request.`,\n \"Synchronized old and new request.\"\n );\n\n return [this._syncQueue.slice(sliceIndex), SYNCED];\n }\n }\n }\n\n /*\n Syncs the old and new data using correlation between decoded audio.\n A new player will be constructed after this sync is completed.\n\n old data | common data | new data\n \n (time scale) -2 -1 0 +1 +2\n (old connection) -----------------------------|\n ^^^^^|^^^^^^^^^| |\n | sampleOffsetFromEnd buffered (metadataTimestamp)\n \n (time scale) -2 -1 0 +1 +2\n (new connection) |-----------|--->\n | ^^^^^^^^^^^^|^^^^\n delay syncLength\n */\n async _pcmSync() {\n try {\n const correlationSyncLength = 1; // seconds\n const initialGranularity = 16;\n\n const samplesToDuration = (samples, rate) => samples / rate;\n\n if (!this._synAudioResult) {\n let SynAudio;\n try {\n SynAudio = (\n await import(\n /* webpackChunkName: \"synaudio\", webpackPrefetch: true */\n \"synaudio\"\n )\n ).default;\n } catch (e) {\n this._icecast[fireEvent](\n event.WARN,\n \"Failed to synchronize old and new stream\",\n \"Missing `synaudio` dependency.\",\n );\n\n return;\n }\n\n const [pcmQueueDecoded, syncQueueDecoded, sampleRate] =\n await this._decodeQueues();\n\n const correlationSampleSize = sampleRate * correlationSyncLength;\n\n // more data is needed to meet the correlationSampleSize\n if (syncQueueDecoded.samplesDecoded <= correlationSampleSize)\n return [[], SYNCING];\n\n const synAudio = new SynAudio({\n correlationSampleSize,\n initialGranularity,\n });\n\n this._synAudioResult = await (canSpawnWorker\n ? synAudio.syncWorkerConcurrent(\n pcmQueueDecoded,\n syncQueueDecoded,\n Math.max(navigator.hardwareConcurrency - 1, 1),\n )\n : synAudio.syncWorker(pcmQueueDecoded, syncQueueDecoded));\n\n this._synAudioResult.offsetFromEnd = samplesToDuration(\n pcmQueueDecoded.samplesDecoded - this._synAudioResult.sampleOffset,\n sampleRate,\n ); // total queue samples decoded - sample offset (sampleOffset from end of buffer)\n }\n\n // anything lower than .5 is likely not synced, but it might sound better than some random sync point\n const { correlation, offsetFromEnd } = this._synAudioResult;\n\n let delay = (this.buffered - offsetFromEnd) * 1000; // if negative, sync is before playback position, positive, sync after playback position\n\n // more frames need to be cut than exist on the sync queue\n if (-delay > this._syncQueueDuration) return [[], SYNCING];\n\n const frameOverlap = 0;\n if (delay < 0) {\n // slice the sync frame with 'n' frame overlap and start immediately\n let sliceIndex = 0;\n for (\n let t = 0;\n sliceIndex < this._syncQueue.length - frameOverlap && t > delay;\n sliceIndex++\n )\n t -= this._syncQueue[sliceIndex].duration;\n\n this._syncQueue = this._syncQueue.slice(sliceIndex - frameOverlap);\n } else {\n // delay start with 'n' frame overlap\n for (let i = 0; i < frameOverlap && i < this._syncQueue.length; i++)\n delay -= this._syncQueue[i].duration;\n }\n\n // prettier-ignore\n this._icecast[fireEvent](\n event.WARN,\n `Reconnected successfully after ${this._icecast.state}.`,\n `Synchronized old and new request with ${(Math.round(correlation * 10000) / 100).toFixed(2)}% confidence.`\n );\n\n this.initQueue();\n return [this._syncQueue, PCM_SYNCED, delay];\n } catch {}\n }\n\n async _decodeQueues() {\n const decode = (queue, timeFromEnd) => {\n let sliceIndex = queue.length - 1;\n\n for (\n let duration = 0;\n duration < timeFromEnd && sliceIndex > 0;\n sliceIndex--\n )\n duration += queue[sliceIndex].duration;\n\n return this._icecast[audioContext].decodeAudioData(\n concatBuffers(queue.slice(sliceIndex).map(({ data }) => data)).buffer,\n );\n };\n\n [this._a, this._b] = await Promise.all([\n // decode the pcm queue only once, decode only up to twice the amount of buffered audio\n this._a ? this._a : decode(this._pcmQueue, this.buffered * 2000),\n decode(this._syncQueue, Infinity),\n ]);\n\n const getDecodedAudio = (decodedAudioData) => {\n const decoded = {\n channelData: [],\n samplesDecoded: decodedAudioData.length,\n };\n\n for (let i = 0; i < decodedAudioData.numberOfChannels; i++)\n decoded.channelData.push(\n Float32Array.from(decodedAudioData.getChannelData(i)),\n );\n\n return decoded;\n };\n\n return [\n getDecodedAudio(this._a),\n getDecodedAudio(this._b),\n this._a.sampleRate,\n ];\n }\n}\n","import {\n p,\n event,\n state,\n audioElement,\n bufferLength,\n SYNCED,\n NOT_SYNCED,\n} from \"../global.js\";\nimport FrameQueue from \"../FrameQueue.js\";\n\nexport default class Player {\n constructor(icecast, endpoint, inputMimeType, codec, codecHeader) {\n this._icecast = icecast;\n this._endpoint = endpoint;\n this._inputMimeType = inputMimeType;\n this._codec = codec;\n this._codecHeader = codecHeader;\n\n const instanceVariables = p.get(this._icecast);\n\n this._audioElement = instanceVariables[audioElement];\n this._bufferLength = instanceVariables[bufferLength];\n\n this._codecUpdateTimestamp = 0;\n this._codecUpdateOffset = 0;\n\n this._notSyncedHandler = () => {\n this.syncState = NOT_SYNCED;\n };\n }\n\n static parseMimeType(mimeType) {\n return mimeType.match(\n /^(?:application\\/|audio\\/|)(?<mime>[a-zA-Z]+)(?:$|;[ ]*codecs=(?:\\'|\\\")(?<codecs>[a-zA-Z,]+)(?:\\'|\\\"))/,\n );\n }\n\n static canPlayType(codecChecker, mimeType, mapping) {\n const matches = Player.parseMimeType(mimeType);\n\n const checkCodecs = (codecs) =>\n codecs.reduce((acc, codec) => {\n if (acc === \"\") return \"\";\n\n const result = codecChecker(codec);\n\n if (!result) return \"\";\n if (result === \"maybe\" || acc === \"maybe\") return \"maybe\";\n if (result === true || result === \"probably\") return \"probably\";\n }, null);\n\n if (matches) {\n const { mime, codecs } = matches.groups;\n\n const mimeMapping = mapping && mapping[mime];\n\n // mapping is a raw codec\n if (!mimeMapping || Array.isArray(mimeMapping)) {\n return (\n checkCodecs(mimeMapping || [mimeType]) || // check with the codec\n checkCodecs([`audio/${mime}`]) // check as a raw mimetype\n );\n }\n\n // mapping ia a container\n if (typeof mimeMapping === \"object\") {\n if (codecs) {\n const mimeCodecs = codecs.split(\",\");\n\n // multiple codecs are not supported\n if (mimeCodecs.length > 1) return \"\";\n if (!mimeMapping[mimeCodecs[0]]) return \"\";\n\n return checkCodecs(mimeMapping[mimeCodecs[0]]);\n }\n // container exists in list but no codecs were specified\n return \"maybe\";\n }\n }\n\n // codec not in the list\n return \"\";\n }\n\n enablePlayButton(supportedSources) {\n // set the audio element an empty source to enable the play button\n this._audioElement.removeAttribute(\"src\");\n this._audioElement.srcObject = null;\n\n if (supportedSources.includes(\"mediasource\")) {\n // MediaSourcePlayer\n this._audioElement.src = URL.createObjectURL(new MediaSource());\n } else if (supportedSources.includes(\"webaudio\")) {\n this._mediaStream = new MediaStream();\n this._audioElement.srcObject = this._mediaStream;\n } else if (supportedSources.includes(\"html5\")) {\n // HTML5Player\n // mp3 32kbs silence\n this._audioElement.src =\n \"data:audio/mpeg;base64,//sQxAAABFgC/SCEYACCgB9AAAAAppppVCAHBAEIgBByw9WD5+J8ufwxiDED\" +\n \"sMfE+D4fwG/RUGCx6VO4awVxV3qDtQNPiXKnZUNSwKuUDR6IgaeoGg7Fg6pMQU1FMy4xMDCqqqqqqqr/+xL\" +\n \"EB4PAAAGkAAAAIAAANIAAAASqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\" +\n \"qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqo=\";\n\n this._audioElement.loop = true;\n }\n }\n\n get syncStateUpdate() {\n return this._syncStatePromise;\n }\n\n get syncState() {\n return this._syncState;\n }\n\n set syncState(newState) {\n this._syncState = newState;\n\n if (this._syncStateResolve) this._syncStateResolve(newState);\n\n this._syncStatePromise = new Promise((resolve) => {\n this._syncStateResolve = resolve;\n });\n }\n\n /**\n * @abstract\n */\n get isSupported() {\n return false;\n }\n\n /**\n * @abstract\n */\n get isAudioPlayer() {\n return false;\n }\n\n /**\n * @interface\n */\n get metadataTimestamp() {\n return 0;\n }\n\n /**\n * @interface\n */\n get currentTime() {\n return 0;\n }\n\n get waiting() {\n return Promise.resolve();\n }\n\n get icecastMetadataQueue() {\n return this._icecastMetadataQueue;\n }\n\n set icecastMetadataQueue(icecastMetadataQueue) {\n this._icecastMetadataQueue = icecastMetadataQueue;\n }\n\n get codecUpdateQueue() {\n return this._codecUpdateQueue;\n }\n\n set codecUpdateQueue(codecUpdateQueue) {\n this._codecUpdateQueue = codecUpdateQueue;\n }\n\n get metadataQueue() {\n return this._icecastMetadataQueue\n ? this._icecastMetadataQueue.metadataQueue\n : [];\n }\n\n _startMetadataQueues() {\n this._icecastMetadataQueue.startQueue(this._metadataOffset);\n this._codecUpdateQueue.startQueue(this._metadataOffset);\n }\n\n /**\n * @abstract\n */\n async _init() {\n this.syncState = SYNCED;\n this.syncFrames = [];\n this.syncDelay = null;\n this._frameQueue = new FrameQueue(this._icecast, this);\n }\n\n /**\n * @abstract\n */\n async start(metadataOffset) {\n this._metadataOffset = metadataOffset;\n\n [event.RETRY, event.SWITCH].forEach((e) =>\n this._icecast.addEventListener(e, this._notSyncedHandler),\n );\n\n let resolve;\n const playing = new Promise((r) => {\n resolve = r;\n [state.PLAYING, state.STOPPING].forEach((s) =>\n this._icecast.addEventListener(s, resolve, { once: true }),\n );\n }).finally(() => {\n [state.PLAYING, state.STOPPING].forEach((s) =>\n this._icecast.removeEventListener(s, resolve),\n );\n });\n\n await playing;\n }\n\n /**\n * @abstract\n */\n async end() {\n [event.RETRY, event.SWITCH].forEach((e) =>\n this._icecast.removeEventListener(e, this._notSyncedHandler),\n );\n\n this._icecastMetadataQueue.purgeMetadataQueue();\n this._codecUpdateQueue.purgeMetadataQueue();\n }\n\n /**\n * @abstract\n */\n onStream(frames) {\n return frames;\n }\n\n /**\n * @abstract\n */\n onMetadata(metadata) {\n this._icecastMetadataQueue.addMetadata(\n metadata,\n this.metadataTimestamp,\n this.currentTime,\n );\n }\n\n /**\n * @abstract\n */\n onCodecUpdate(metadata, updateTimestamp) {\n const currentTime = this.currentTime;\n\n // add previous offset when reconnecting\n if (updateTimestamp < currentTime)\n this._codecUpdateOffset += this._codecUpdateTimestamp;\n\n this._codecUpdateTimestamp = updateTimestamp;\n\n this._codecUpdateQueue.addMetadata(\n { metadata },\n (updateTimestamp + this._codecUpdateOffset) / 1000,\n currentTime,\n );\n }\n}\n","import { state, event, fireEvent, NOT_SYNCED } from \"../global.js\";\nimport Player from \"./Player.js\";\n\nexport default class HTML5Player extends Player {\n constructor(icecast, endpoint) {\n super(icecast, endpoint);\n\n this._audioElement.crossOrigin = \"anonymous\";\n this._audioElement.loop = false;\n this._audioElement.preload = \"none\";\n\n this._icecast.addEventListener(event.STREAM_START, () => {\n if (!this._playReady) this.end();\n });\n\n this._init();\n }\n\n static canPlayType(mimeType) {\n if (!HTML5Player.isSupported) return \"\";\n\n return super.canPlayType((type) => new Audio().canPlayType(type), mimeType);\n }\n\n static get isSupported() {\n return Boolean(window.Audio);\n }\n\n static get name() {\n return \"html5\";\n }\n\n get isAudioPlayer() {\n return true;\n }\n\n get metadataTimestamp() {\n return this._frame\n ? (this._frame.totalDuration + this._metadataTimestampOffset) / 1000\n : 0;\n }\n\n get currentTime() {\n return (\n this._audioLoadedTimestamp &&\n (performance.now() - this._audioLoadedTimestamp) / 1000\n );\n }\n\n get waiting() {\n return new Promise((resolve) => {\n this._audioElement.addEventListener(\"waiting\", resolve, { once: true });\n });\n }\n\n async _init() {\n super._init();\n\n this._frame = null;\n this._audioLoadedTimestamp = 0;\n this._metadataTimestampOffset = 0;\n this._playReady = false;\n }\n\n async start(metadataOffset) {\n const playing = super.start(metadataOffset);\n\n this._metadataLoadedTimestamp = performance.now();\n this._audioElement.src = null;\n this._audioElement.srcObject = null;\n this._audioElement.src = this._endpoint;\n\n if (\n this._icecast.state !== state.STOPPING &&\n this._icecast.state !== state.STOPPED\n ) {\n this._audioElement.addEventListener(\n \"playing\",\n () => {\n this._audioLoadedTimestamp = performance.now();\n this._metadataTimestampOffset =\n performance.now() - this._metadataLoadedTimestamp;\n\n this._startMetadataQueues();\n this._icecast[fireEvent](event.PLAY);\n },\n { once: true },\n );\n\n this._icecast[fireEvent](event.PLAY_READY);\n this._playReady = true;\n }\n\n await playing;\n }\n\n async end() {\n super.end();\n\n this._audioElement.src = null;\n this._audioElement.srcObject = null;\n\n this._init();\n }\n\n onStream(frames) {\n this._frame = frames[frames.length - 1] || this._frame;\n\n if (this.syncState === NOT_SYNCED) {\n // syncing not implemented in html5 playback method\n this.syncState = NOT_SYNCED;\n }\n }\n}\n","import {\n state,\n event,\n fireEvent,\n concatBuffers,\n SYNCED,\n PCM_SYNCED,\n SYNCING,\n NOT_SYNCED,\n} from \"../global.js\";\nimport Player from \"./Player.js\";\n\nconst BUFFER = 5; // seconds of audio to store in SourceBuffer\nconst BUFFER_INTERVAL = 5; // seconds before removing from SourceBuffer\n\nexport default class MediaSourcePlayer extends Player {\n constructor(icecast, endpoint, inputMimeType, codec, codecHeader) {\n super(icecast, endpoint, inputMimeType, codec, codecHeader);\n\n this._MSEAudioWrapper = import(\n /* webpackChunkName: \"mediasource\", webpackPrefetch: true */\n \"mse-audio-wrapper\"\n );\n\n this._init();\n }\n\n static canPlayType(mimeType) {\n const mapping = {\n mpeg: ['audio/mp4;codecs=\"mp3\"'],\n aac: ['audio/mp4;codecs=\"mp4a.40.2\"'],\n aacp: ['audio/mp4;codecs=\"mp4a.40.2\"'],\n flac: ['audio/mp4;codecs=\"flac\"'],\n ogg: {\n flac: ['audio/mp4;codecs=\"flac\"'],\n opus: ['audio/mp4;codecs=\"opus\"', 'audio/webm;codecs=\"opus\"'],\n vorbis: ['audio/webm;codecs=\"vorbis\"'],\n },\n };\n\n if (!MediaSourcePlayer.isSupported) return \"\";\n\n if (MediaSource.isTypeSupported(mimeType)) return \"probably\";\n\n return super.canPlayType(MediaSource.isTypeSupported, mimeType, mapping);\n }\n\n static get isSupported() {\n return Boolean(window.MediaSource);\n }\n\n static get name() {\n return \"mediasource\";\n }\n\n get isAudioPlayer() {\n return true;\n }\n\n get metadataTimestamp() {\n return (\n (this._mediaSource &&\n this._mediaSource.sourceBuffers.length &&\n Math.max(\n // work-around for WEBM reporting a negative timestampOffset\n this._mediaSource.sourceBuffers[0].timestampOffset,\n this._mediaSource.sourceBuffers[0].buffered.length\n ? this._mediaSource.sourceBuffers[0].buffered.end(0)\n : 0,\n )) ||\n 0\n );\n }\n\n get currentTime() {\n return this._audioElement.currentTime;\n }\n\n get waiting() {\n return new Promise((resolve) => {\n this._audioElement.addEventListener(\"waiting\", resolve, { once: true });\n });\n }\n\n async _init() {\n super._init();\n\n this._sourceBufferQueue = [];\n this._playReady = false;\n this._processingLastPage = false;\n\n this._mediaSourceCreated = new Promise((resolve) => {\n this._mediaSourceCreatedNotify = resolve;\n });\n\n this._mediaSourceOpen = new Promise((resolve) => {\n this._mediaSourceOpenNotify = resolve;\n });\n\n this._addFrames = this._prepareMediaSource(\n this._inputMimeType,\n this._codec,\n );\n\n await this._mediaSourceOpen;\n }\n\n async start(metadataOffset) {\n const playing = super.start(metadataOffset);\n await this._mediaSourceCreated;\n await this._attachMediaSource();\n await playing;\n }\n\n async end() {\n super.end();\n\n await this._init();\n }\n\n async onStream(frames) {\n frames = frames.flatMap((frame) =>\n frame.codecFrames\n ? frame.codecFrames.map((codecFrame) => {\n codecFrame.isLastPage = frame.isLastPage;\n return codecFrame;\n })\n : frame,\n );\n\n if (frames.length) {\n switch (this.syncState) {\n case NOT_SYNCED:\n this._frameQueue.initSync();\n this.syncState = SYNCING;\n case SYNCING:\n [this.syncFrames, this.syncState, this.syncDelay] =\n await this._frameQueue.sync(frames);\n frames = this.syncFrames;\n }\n\n switch (this.syncState) {\n case PCM_SYNCED:\n break;\n case SYNCED:\n // when frames are present, we should already know the codec and have the mse audio mimetype determined\n await this._mediaSourceOpen;\n await this._addFrames(frames); // wait for the source buffer to be created\n\n this._frameQueue.addAll(frames);\n break;\n }\n }\n }\n\n _prepareMediaSource(inputMimeType, codec) {\n if (MediaSource.isTypeSupported(inputMimeType)) {\n // pass the audio directly to MSE\n this._createMediaSource(inputMimeType);\n\n return async (frames) =>\n this._appendSourceBuffer(concatBuffers(frames.map((f) => f.data)));\n }\n\n this._codecHeader\n .then((codecHeader) =>\n this._createMSEWrapper(inputMimeType, codec, codecHeader.channels),\n )\n .then(() => {\n this._createMediaSource(this._wrapper.mimeType);\n });\n\n return inputMimeType.match(/ogg/)\n ? async (codecFrames) => {\n let fragments = [];\n\n for await (const frame of codecFrames) {\n // handle new setup packet for continuous chain ogg vorbis streams\n if (this._processingLastPage !== frame.isLastPage) {\n if (frame.isLastPage) {\n this._processingLastPage = true;\n } else {\n await this._appendSourceBuffer(concatBuffers(fragments));\n fragments = [];\n\n const codecHeader = await this._codecHeader;\n await this._createMSEWrapper(\n inputMimeType,\n codec,\n codecHeader.channels,\n );\n\n this._processingLastPage = false;\n }\n }\n\n fragments.push(...this._wrapper.iterator([frame]));\n }\n\n await this._appendSourceBuffer(concatBuffers(fragments));\n }\n : async (codecFrames) =>\n this._appendSourceBuffer(\n concatBuffers([...this._wrapper.iterator(codecFrames)]),\n );\n }\n\n async _createMSEWrapper(inputMimeType, codec, channels) {\n // wrap the audio into fragments before passing to MSE\n this._wrapper = new (await this._MSEAudioWrapper).default(inputMimeType, {\n codec,\n preferredContainer: channels > 2 ? \"webm\" : \"fmp4\",\n });\n\n if (!MediaSource.isTypeSupported(this._wrapper.mimeType)) {\n this._icecast[fireEvent](\n event.PLAYBACK_ERROR,\n `Media Source Extensions API in your browser does not support ${inputMimeType} or ${this._wrapper.mimeType}.` +\n \"See: https://caniuse.com/mediasource and https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API\",\n );\n }\n }\n\n _createMediaSource(mimeType) {\n this._mediaSource = new MediaSource();\n this._mediaSourceCreatedNotify();\n\n this._mediaSource.addEventListener(\n \"sourceopen\",\n () => {\n if (\n this._icecast.state !== state.STOPPED &&\n this._icecast.state !== state.STOPPING\n )\n this._mediaSource.addSourceBuffer(mimeType).mode = \"sequence\";\n this._sourceBufferRemoved = 0;\n this._mediaSourceOpenNotify();\n },\n {\n once: true,\n },\n );\n }\n\n async _attachMediaSource() {\n this._audioElement.loop = false;\n this._audioElement.src = URL.createObjectURL(this._mediaSource);\n await this._mediaSourceOpen;\n }\n\n async _waitForSourceBuffer() {\n return new Promise((resolve) => {\n const sourceBuffer = this._mediaSource.sourceBuffers[0];\n\n if (!sourceBuffer.updating) {\n resolve();\n } else {\n sourceBuffer.addEventListener(\"updateend\", resolve, {\n once: true,\n });\n }\n });\n }\n\n async _appendSourceBuffer(chunk) {\n this._icecast[fireEvent](event.STREAM, chunk);\n\n if (!this._mediaSource.sourceBuffers.length) {\n this._icecast[fireEvent](\n event.WARN,\n \"Attempting to append audio, but MediaSource has not been or is no longer initialized\",\n \"Please be sure that `detachAudioElement()` was called and awaited before reusing the element with a new IcecastMetadataPlayer instance\",\n );\n }\n\n if (\n this._icecast.state !== state.STOPPING &&\n this._mediaSource.sourceBuffers.length\n ) {\n this._sourceBufferQueue.push(chunk);\n\n try {\n while (this._sourceBufferQueue.length) {\n this._mediaSource.sourceBuffers[0].appendBuffer(\n this._sourceBufferQueue.shift(),\n );\n await this._waitForSourceBuffer();\n }\n } catch (e) {\n if (e.name !== \"QuotaExceededError\") throw e;\n }\n\n if (!this._playReady) {\n if (this._bufferLength <= this.metadataTimestamp) {\n this._audioElement.addEventListener(\n \"playing\",\n () => {\n this._startMetadataQueues();\n this._icecast[fireEvent](event.PLAY);\n },\n { once: true },\n );\n this._icecast[fireEvent](event.PLAY_READY);\n this._playReady = true;\n } else {\n this._icecast[fireEvent](event.BUFFER, this.metadataTimestamp);\n }\n }\n\n if (\n this._audioElement.currentTime > BUFFER + this._bufferLength &&\n this._sourceBufferRemoved + BUFFER_INTERVAL * 1000 < performance.now()\n ) {\n this._sourceBufferRemoved = performance.now();\n this._mediaSource.sourceBuffers[0].remove(\n 0,\n this._audioElement.currentTime - BUFFER + this._bufferLength,\n );\n await this._waitForSourceBuffer();\n }\n }\n }\n}\n","import {\n audioContext,\n event,\n state,\n SYNCED,\n PCM_SYNCED,\n SYNCING,\n NOT_SYNCED,\n fireEvent,\n} from \"../global.js\";\nimport Player from \"./Player.js\";\n\nexport default class WebAudioPlayer extends Player {\n constructor(icecast, endpoint, inputMimeType, codec, codecHeader) {\n super(icecast, endpoint, inputMimeType, codec, codecHeader);\n\n this._audioContext = icecast[audioContext];\n\n this._init();\n }\n\n static canPlayType(mimeType) {\n const mapping = {\n flac: [\"audio/flac\"],\n mpeg: [\"audio/mpeg\"],\n ogg: {\n flac: ['audio/ogg;codecs=\"flac\"'],\n opus: ['audio/ogg;codecs=\"opus\"'],\n vorbis: ['audio/ogg;codecs=\"vorbis\"'],\n },\n };\n\n if (!WebAudioPlayer.isSupported) return \"\";\n\n return super.canPlayType(\n (codec) =>\n codec === 'audio/ogg;codecs=\"opus\"' ||\n codec === 'audio/ogg;codecs=\"flac\"' ||\n codec === 'audio/ogg;codecs=\"vorbis\"' ||\n codec === \"audio/mpeg\" ||\n codec === \"audio/flac\",\n mimeType,\n mapping,\n );\n }\n\n static get isSupported() {\n return Boolean(\n window.WebAssembly &&\n (window.AudioContext || window.webkitAudioContext) &&\n window.MediaStream,\n );\n }\n\n static get name() {\n return \"webaudio\";\n }\n\n get isAudioPlayer() {\n return true;\n }\n\n get metadataTimestamp() {\n return this._currentTime / 1000;\n }\n\n get currentTime() {\n return (performance.now() - this._playbackStartTime) / 1000 || 0;\n }\n\n get waiting() {\n return this._waitingPromise;\n }\n\n _updateWaiting(duration) {\n this._bufferedDuration += duration;\n\n let durationTimeout;\n durationTimeout = setTimeout(() => {\n this._bufferedDuration -= duration;\n this._durationTimeouts.delete(durationTimeout);\n\n if (!this._durationTimeouts.size) this._notifyWaiting();\n }, this._bufferedDuration);\n\n this._durationTimeouts.add(durationTimeout);\n }\n\n _notifyWaiting() {\n if (this._waitingResolve) this._waitingResolve();\n\n this._waitingPromise = new Promise((resolve) => {\n this._waitingResolve = resolve;\n });\n }\n\n _resetWaiting() {\n if (this._durationTimeouts)\n this._durationTimeouts.forEach((id) => clearTimeout(id));\n\n this._durationTimeouts = new Set();\n this._bufferedDuration = 0;\n this._notifyWaiting();\n }\n\n async _createDecoder() {\n let DecoderClass;\n\n this._loadingDecoder = new Promise((resolve) => {\n this._decoderLoaded = resolve;\n });\n\n try {\n switch (this._codec) {\n case \"mpeg\":\n const { MPEGDecoderWebWorker } = await import(\n /* webpackChunkName: \"mpeg\" */ \"mpg123-decoder\"\n );\n DecoderClass = MPEGDecoderWebWorker;\n break;\n case \"opus\":\n const { OpusDecoderWebWorker } = await import(\n /* webpackChunkName: \"opus\" */ \"opus-decoder\"\n );\n DecoderClass = OpusDecoderWebWorker;\n break;\n case \"flac\":\n const { FLACDecoderWebWorker } = await import(\n /* webpackChunkName: \"flac\" */ \"@wasm-audio-decoders/flac\"\n );\n DecoderClass = FLACDecoderWebWorker;\n break;\n case \"vorbis\":\n const { OggVorbisDecoderWebWorker } = await import(\n /* webpackChunkName: \"vorbis\" */ \"@wasm-audio-decoders/ogg-vorbis\"\n );\n DecoderClass = OggVorbisDecoderWebWorker;\n break;\n }\n } catch (e) {\n this._icecast[fireEvent](\n event.PLAYBACK_ERROR,\n `Missing \\`webaudio-${this._codec}\\` dependency.`,\n `Unable to playback playback \\`${this._codec}\\` audio.`,\n );\n return;\n }\n\n if (DecoderClass) {\n const codecHeader = await this._codecHeader;\n this._decoderLoaded();\n this._wasmDecoder = new DecoderClass(codecHeader);\n } else {\n this._icecast[fireEvent](\n event.PLAYBACK_ERROR,\n \"Unsupported `webaudio` playback codec: \" + this._codec,\n );\n }\n }\n\n async _init() {\n super._init();\n\n this._currentTime = 0;\n this._decodedSample = 0;\n this._startSampleOffset = 0;\n this._sampleRate = 0;\n this._playbackStartTime = undefined;\n this._playReady = false;\n\n this._resetWaiting();\n\n this._playPromise = new Promise((resolve) => {\n this._playStart = resolve;\n });\n }\n\n async start(metadataOffset) {\n if (!this._wasmDecoder) await this._createDecoder();\n\n const playing = super.start(metadataOffset);\n this._playStart();\n await playing;\n }\n\n async end() {\n super.end();\n\n if (this._wasmDecoder) {\n this._wasmDecoder.terminate();\n this._wasmDecoder = null;\n }\n\n if (this._mediaStream) {\n // disconnect the currently playing media stream\n this._mediaStream.stream\n .getTracks()\n .forEach((track) => this._mediaStream.stream.removeTrack(track));\n }\n\n this._init();\n }\n\n async onStream(frames) {\n if (this._codec !== \"vorbis\") {\n frames = frames.flatMap((oggPage) => oggPage.codecFrames || oggPage);\n\n switch (this.syncState) {\n case NOT_SYNCED:\n this._frameQueue.initSync();\n this.syncState = SYNCING;\n case SYNCING:\n [this.syncFrames, this.syncState, this.syncDelay] =\n await this._frameQueue.sync(frames);\n frames = this.syncFrames;\n }\n }\n\n switch (this.syncState) {\n case PCM_SYNCED:\n break;\n case SYNCED:\n if (frames.length) {\n this._currentTime = frames[frames.length - 1].totalDuration;\n\n this._decodeAndPlay(frames);\n }\n }\n }\n\n async _decodeAndPlay(frames) {\n await this._loadingDecoder;\n\n if (this._wasmDecoder) {\n await this._wasmDecoder.ready;\n\n let decodePromise;\n\n if (this._codec === \"vorbis\") {\n decodePromise = this._wasmDecoder.decodeOggPages(frames);\n } else {\n decodePromise = this._wasmDecoder.decodeFrames(\n frames.map((f) => f.data),\n );\n this._frameQueue.addAll(frames);\n }\n\n decodePromise.then((decoded) => this._play(decoded));\n }\n }\n\n async _play({ channelData, samplesDecoded, sampleRate }) {\n await this._playPromise;\n\n if (\n this._icecast.state !== state.STOPPING &&\n this._icecast.state !== state.STOPPED &&\n samplesDecoded\n ) {\n this._icecast[fireEvent](event.STREAM, {\n channelData,\n samplesDecoded,\n sampleRate,\n });\n\n if (!this._sampleRate) {\n this._sampleRate = sampleRate;\n\n this._mediaStream = this._audioContext.createMediaStreamDestination();\n this._mediaStream.channelCount =\n this._audioContext.destination.maxChannelCount;\n\n this._audioElement.srcObject = this._mediaStream.stream; // triggers canplay event\n }\n\n const audioBuffer = this._audioContext.createBuffer(\n channelData.length,\n samplesDecoded,\n this._sampleRate,\n );\n\n channelData.forEach((channel, idx) =>\n audioBuffer.getChannelData(idx).set(channel),\n );\n\n const source = this._audioContext.createBufferSource();\n source.buffer = audioBuffer;\n source.connect(this._mediaStream);\n\n const scalingFactor = 100;\n const startSamples =\n this._decodedSample * scalingFactor + this._startSampleOffset;\n const audioContextSamples = Math.round(\n this._audioContext.currentTime * this._sampleRate * scalingFactor,\n );\n\n if (startSamples < audioContextSamples) {\n // audio context time starts incrementing immediately when it's created\n // offset needs to be accounted for to prevent overlapping sources\n this._startSampleOffset += audioContextSamples - startSamples;\n }\n\n source.start(startSamples / this._sampleRate / scalingFactor);\n\n this._updateWaiting((samplesDecoded / this._sampleRate) * 1000);\n\n if (!this._playReady) {\n if (this._bufferLength <= this.metadataTimestamp) {\n this._icecast[fireEvent](event.PLAY_READY);\n this._playbackStartTime = performance.now();\n\n this._startMetadataQueues();\n this._icecast[fireEvent](event.PLAY);\n this._playReady = true;\n } else {\n this._icecast[fireEvent](event.BUFFER, this.metadataTimestamp);\n }\n }\n\n this._decodedSample += samplesDecoded;\n }\n }\n}\n","import {\n IcecastMetadataQueue,\n IcecastReadableStream,\n} from \"icecast-metadata-js\";\nimport CodecParser from \"codec-parser\";\n\nimport {\n p,\n state,\n event,\n audioElement,\n enableLogging,\n enableCodecUpdate,\n endpointGenerator,\n metadataTypes,\n icyMetaInt,\n icyCharacterEncoding,\n icyDetectionTimeout,\n playbackMethod,\n fireEvent,\n hasIcy,\n abortController,\n playerState,\n SYNCED,\n PCM_SYNCED,\n SYNCING,\n NOT_SYNCED,\n noOp,\n authentication,\n} from \"./global.js\";\n\nimport Player from \"./players/Player.js\";\nimport HTML5Player from \"./players/HTML5Player.js\";\nimport MediaSourcePlayer from \"./players/MediaSourcePlayer.js\";\nimport WebAudioPlayer from \"./players/WebAudioPlayer.js\";\n\nexport default class PlayerFactory {\n constructor(icecast) {\n const instanceVariables = p.get(icecast);\n\n this._icecast = icecast;\n this._audioElement = instanceVariables[audioElement];\n this._enableLogging = instanceVariables[enableLogging];\n this._enableCodecUpdate = instanceVariables[enableCodecUpdate];\n\n this._playbackMethod = \"\";\n\n this._newMetadataQueues();\n this._player = new Player(this._icecast);\n this._player.icecastMetadataQueue = this._icecastMetadataQueue;\n this._player.codecUpdateQueue = this._codecUpdateQueue;\n this._player.enablePlayButton(PlayerFactory.supportedPlaybackMethods);\n\n this._unprocessedFrames = [];\n this._codecParser = undefined;\n this._inputMimeType = \"\";\n this._codec = \"\";\n\n this._syncPromise = Promise.resolve();\n this._syncCancel = noOp;\n }\n\n static get supportedPlaybackMethods() {\n return [MediaSourcePlayer, WebAudioPlayer, HTML5Player].map((player) =>\n player.isSupported ? player.name : \"\",\n );\n }\n\n static canPlayType(type) {\n return {\n mediasource: MediaSourcePlayer.canPlayType(type),\n html5: HTML5Player.canPlayType(type),\n webaudio: WebAudioPlayer.canPlayType(type),\n };\n }\n\n get endpoint() {\n return this._endpoint;\n }\n\n get player() {\n return this._player;\n }\n\n get playbackMethod() {\n return this._playbackMethod;\n }\n\n get icyMetaInt() {\n return (\n this._icecastReadableStream && this._icecastReadableStream.icyMetaInt\n );\n }\n\n async playStream() {\n return this.fetchStream()\n .then(async (res) => {\n this._icecast[fireEvent](event.STREAM_START);\n\n return this.readIcecastResponse(res).finally(() => {\n this._icecast[fireEvent](event.STREAM_END);\n });\n })\n .catch((e) => {\n if (this._icecast.state !== state.SWITCHING) throw e;\n });\n }\n\n async switchStream() {\n if (this._icecast.state !== state.PLAYING) {\n this._syncCancel();\n await this._syncPromise;\n }\n\n const instance = p.get(this._icecast);\n\n instance[playerState] = state.SWITCHING;\n instance[abortController].abort();\n instance[abortController] = new AbortController();\n }\n\n async fetchStream() {\n const instanceVariables = p.get(this._icecast);\n this._endpoint = instanceVariables[endpointGenerator].next().value;\n\n const headers = instanceVariables[hasIcy] ? { \"Icy-MetaData\": 1 } : {};\n headers[\"Range\"] = \"bytes=0-\";\n\n if (instanceVariables[authentication]) {\n const auth = instanceVariables[authentication];\n headers[\"Authorization\"] =\n \"Basic \" + btoa(auth.user + \":\" + auth.password);\n }\n\n const res = await fetch(this._endpoint, {\n method: \"GET\",\n headers,\n signal: instanceVariables[abortController].signal,\n });\n\n if (!res.ok) {\n const error = new Error(`${res.status} received from ${res.url}`);\n error.name = \"HTTP Response Error\";\n throw error;\n }\n\n return res;\n }\n\n async readIcecastResponse(res) {\n const inputMimeType = res.headers.get(\"content-type\");\n const instanceVariables = p.get(this._icecast);\n\n let onCodecHeader;\n const codecHeaderPromise = new Promise((resolve) => {\n onCodecHeader = resolve;\n });\n\n const codecPromise = new Promise((onCodec) => {\n this._codecParser = new CodecParser(inputMimeType, {\n onCodec,\n onCodecHeader,\n onCodecUpdate:\n this._enableCodecUpdate &&\n ((...args) => this._player.onCodecUpdate(...args)),\n enableLogging: this._enableLogging,\n });\n });\n\n this._icecastReadableStream = new IcecastReadableStream(res, {\n onMetadata: async (metadata) => {\n this._player.onMetadata(metadata);\n },\n onStream: async ({ stream }) => {\n this._icecast[fireEvent](event.STREAM, stream);\n\n const frames = [...this._codecParser.parseChunk(stream)];\n\n if (this._player.isAudioPlayer) {\n const appendedFrames = [...this._unprocessedFrames, ...frames];\n this._unprocessedFrames = [];\n\n await this._player.onStream(appendedFrames);\n } else {\n this._unprocessedFrames.push(...frames);\n }\n },\n onError: (...args) => this._icecast[fireEvent](event.WARN, ...args),\n metadataTypes: instanceVariables[metadataTypes],\n icyCharacterEncoding: instanceVariables[icyCharacterEncoding],\n icyDetectionTimeout: instanceVariables[icyDetectionTimeout],\n ...(instanceVariables[icyMetaInt]\n ? { icyMetaInt: instanceVariables[icyMetaInt] }\n : {}),\n });\n\n const icecastPromise = this._icecastReadableStream.startReading();\n const codec = await codecPromise;\n\n if (!this._player.isAudioPlayer) {\n [this._player, this._playbackMethod] = this._buildPlayer(\n inputMimeType,\n codec,\n codecHeaderPromise,\n );\n }\n\n if (this._player.syncState === SYNCED) {\n this._player.start();\n } else {\n await this._syncPlayer(inputMimeType, codec, codecHeaderPromise);\n }\n\n await icecastPromise;\n }\n\n async _syncPlayer(inputMimeType, codec, codecHeaderPromise) {\n let delayTimeoutId,\n canceled = false,\n playerStarted = false,\n complete;\n\n const oldPlayer = this._player;\n const oldIcecastMetadataQueue = this._player.icecastMetadataQueue;\n const oldCodecUpdateQueue = this._player.codecUpdateQueue;\n\n this._newMetadataQueues();\n // intercept all new metadata updates\n oldPlayer.icecastMetadataQueue = this._icecastMetadataQueue;\n oldPlayer.codecUpdateQueue = this._codecUpdateQueue;\n\n const startNewPlayer = () => {\n playerStarted = true;\n if (\n this._icecast.state !== state.STOPPING ||\n this._icecast.state !== state.STOPPED\n ) {\n oldPlayer.icecastMetadataQueue.purgeMetadataQueue();\n oldPlayer.codecUpdateQueue.purgeMetadataQueue();\n this._player\n .start(Math.max(0, oldPlayer.syncDelay / 1000))\n .then(() => oldPlayer.end())\n .then(complete);\n }\n };\n\n this._syncCancel = () => {\n canceled = true;\n\n this._icecastMetadataQueue.purgeMetadataQueue();\n this._codecUpdateQueue.purgeMetadataQueue();\n\n this._player.icecastMetadataQueue = oldIcecastMetadataQueue;\n this._player.codecUpdateQueue = oldCodecUpdateQueue;\n\n if (delayTimeoutId !== undefined && !playerStarted) {\n clearTimeout(delayTimeoutId);\n startNewPlayer();\n }\n };\n\n const handleSyncEvent = () => {\n return this._player.syncStateUpdate.then((syncState) => {\n if (canceled) complete();\n else\n switch (syncState) {\n case SYNCING:\n return handleSyncEvent();\n case SYNCED: // synced on crc32 hashes\n // put old queues back since audio data is crc synced\n this._icecastMetadataQueue.purgeMetadataQueue();\n this._codecUpdateQueue.purgeMetadataQueue();\n this._player.icecastMetadataQueue = oldIcecastMetadataQueue;\n this._player.codecUpdateQueue = oldCodecUpdateQueue;\n\n if (\n this._icecast.state !== state.STOPPING ||\n this._icecast.state !== state.STOPPED\n )\n this._icecast[playerState] = state.PLAYING;\n\n complete();\n break;\n case PCM_SYNCED:\n case NOT_SYNCED:\n // put old queues back so they can be purged when the player is ended\n oldPlayer.icecastMetadataQueue = oldIcecastMetadataQueue;\n oldPlayer.codecUpdateQueue = oldCodecUpdateQueue;\n\n [this._player, this._playbackMethod] = this._buildPlayer(\n inputMimeType,\n codec,\n codecHeaderPromise,\n );\n\n this._unprocessedFrames.push(...oldPlayer.syncFrames);\n\n // start player after delay or immediately\n delayTimeoutId = setTimeout(\n startNewPlayer,\n Math.max(oldPlayer.syncDelay, 0),\n );\n }\n });\n };\n\n let stoppingHandler;\n\n this._syncPromise = new Promise((resolve) => {\n complete = resolve;\n\n // cancel switch event if stop is called\n stoppingHandler = () => {\n this._syncCancel();\n complete();\n };\n\n this._icecast.addEventListener(state.STOPPING, stoppingHandler, {\n once: true,\n });\n\n handleSyncEvent();\n }).finally(() => {\n this._icecast.removeEventListener(state.STOPPING, stoppingHandler);\n });\n }\n\n _newMetadataQueues() {\n this._icecastMetadataQueue = new IcecastMetadataQueue({\n onMetadataUpdate: (...args) =>\n this._icecast[fireEvent](event.METADATA, ...args),\n onMetadataEnqueue: (...args) =>\n this._icecast[fireEvent](event.METADATA_ENQUEUE, ...args),\n paused: true,\n });\n\n this._codecUpdateQueue = new IcecastMetadataQueue({\n onMetadataUpdate: (...args) =>\n this._icecast[fireEvent](event.CODEC_UPDATE, ...args),\n paused: true,\n });\n }\n\n _buildPlayer(inputMimeType, codec, codecHeader) {\n // in order of preference\n const { [p.get(this._icecast)[playbackMethod]]: firstMethod, ...rest } = {\n mediasource: MediaSourcePlayer,\n webaudio: WebAudioPlayer,\n html5: HTML5Player,\n };\n\n let player, method;\n\n for (const Player of Object.values({ firstMethod, ...rest })) {\n const support = Player.canPlayType(`${inputMimeType};codecs=\"${codec}\"`);\n\n if (support === \"probably\" || support === \"maybe\") {\n method = Player.name;\n player = new Player(\n this._icecast,\n this._endpoint,\n inputMimeType,\n codec,\n codecHeader,\n );\n player.icecastMetadataQueue = this._icecastMetadataQueue;\n player.codecUpdateQueue = this._codecUpdateQueue;\n break;\n }\n }\n\n if (!player) {\n throw new Error(\n `Your browser does not support this audio codec ${inputMimeType}${\n codec && `;codecs=\"${codec}\"`\n }`,\n );\n }\n\n return [player, method];\n }\n}\n","/**\n * @license\n * @see https://github.com/eshaz/icecast-metadata-js\n * @copyright 2021-2024 Ethan Halsall\n * This file is part of icecast-metadata-player.\n *\n * icecast-metadata-player free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * icecast-metadata-player distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public License\n * along with this program. If not, see <https://www.gnu.org/licenses/>\n */\n\nimport {\n p,\n noOp,\n state,\n event,\n // options,\n endpoints,\n metadataTypes,\n playbackMethod,\n audioContext,\n audioElement,\n bufferLength,\n icyMetaInt,\n icyCharacterEncoding,\n icyDetectionTimeout,\n enableLogging,\n enableCodecUpdate,\n retryDelayMin,\n retryDelayMax,\n retryDelayRate,\n endpointOrder,\n retryTimeout,\n authentication,\n // methods\n fireEvent,\n attachAudioElement,\n shouldRetry,\n logError,\n getOptions,\n getNextEndpointGenerator,\n // variables\n endpointGenerator,\n hasIcy,\n abortController,\n playerState,\n} from \"./global.js\";\n\nimport EventTargetPolyfill from \"./EventTargetPolyfill.js\";\nimport PlayerFactory from \"./PlayerFactory.js\";\n\nlet EventClass;\n\ntry {\n new window.EventTarget();\n EventClass = window.EventTarget;\n} catch {\n EventClass = EventTargetPolyfill;\n}\n\nconst playerFactory = Symbol();\nconst playerResetPromise = Symbol();\nconst events = Symbol();\n\nconst onAudioPause = Symbol();\nconst onAudioPlay = Symbol();\nconst onPlayReady = Symbol();\nconst onAudioError = Symbol();\nconst onAudioWaiting = Symbol();\n\nconst stopPlayback = Symbol();\nconst endPlayback = Symbol();\nconst retryAttempt = Symbol();\nconst retryTimeoutId = Symbol();\n\nexport default class IcecastMetadataPlayer extends EventClass {\n static *[getNextEndpointGenerator](instance) {\n while (true) {\n const currentEndpoints = p.get(instance)[endpoints];\n for (const endpoint of currentEndpoints) {\n yield endpoint;\n if (p.get(instance)[endpoints] !== currentEndpoints) break;\n }\n }\n }\n\n static [getOptions](urls, options, instance = {}) {\n const newOptions = {\n [endpoints]:\n (urls && (Array.isArray(urls) ? urls : [urls])) ?? instance[endpoints],\n [bufferLength]: options.bufferLength ?? instance[bufferLength] ?? 1,\n [icyMetaInt]: options.icyMetaInt ?? instance[icyMetaInt],\n [icyCharacterEncoding]:\n options.icyCharacterEncoding ?? instance[icyCharacterEncoding],\n [icyDetectionTimeout]:\n options.icyDetectionTimeout ?? instance[icyDetectionTimeout],\n [metadataTypes]: (options.metadataTypes ?? instance[metadataTypes]) || [\n \"icy\",\n ],\n [hasIcy]: (\n (options.metadataTypes ?? instance[metadataTypes]) || [\"icy\"]\n ).includes(\"icy\"),\n [enableLogging]:\n options.enableLogging ?? instance[enableLogging] ?? false,\n [enableCodecUpdate]: Boolean(\n options.enableCodecUpdate ??\n instance[enableCodecUpdate] ??\n options.onCodecUpdate,\n ),\n [endpointOrder]:\n options.endpointOrder ?? instance[endpointOrder] ?? \"ordered\",\n [retryDelayRate]:\n options.retryDelayRate ?? instance[retryDelayRate] ?? 0.1,\n [retryDelayMin]: options.retryDelayMin ?? instance[retryDelayMin] ?? 0.5,\n [retryDelayMax]: options.retryDelayMax ?? instance[retryDelayMax] ?? 2,\n [retryTimeout]: options.retryTimeout ?? instance[retryTimeout] ?? 30,\n [playbackMethod]:\n (options.playbackMethod ?? instance[playbackMethod]) || \"mediasource\",\n [authentication]: options.authentication ?? instance[authentication],\n };\n\n if (\n newOptions[endpoints] !== instance[endpoints] &&\n newOptions[endpointOrder] === \"random\"\n )\n newOptions[endpoints] = newOptions[endpoints].sort(\n () => 0.5 - Math.random(),\n );\n\n return newOptions;\n }\n\n /**\n * @constructor\n * @param {string|string[]} endpoint Endpoint(s) of the Icecast compatible stream\n * @param {object} options Options object\n * @param {HTMLAudioElement} options.audioElement Audio element to play the stream\n * @param {Array} options.metadataTypes Array of metadata types to parse\n * @param {number} options.bufferLength Seconds of audio to buffer before starting playback\n * @param {number} options.icyMetaInt ICY metadata interval\n * @param {string} options.icyCharacterEncoding Character encoding to use for ICY metadata (defaults to \"utf-8\")\n * @param {number} options.icyDetectionTimeout ICY metadata detection timeout\n * @param {string} options.endpointOrder Order that a stream endpoint will be chosen when multiple endpoints are passed in.\n * @param {number} options.retryTimeout Number of seconds to wait before giving up on retries\n * @param {number} options.retryDelayRate Percentage of seconds to increment after each retry (how quickly to increase the back-off)\n * @param {number} options.retryDelayMin Minimum number of seconds between retries (start of the exponential back-off curve)\n * @param {number} options.retryDelayMax Maximum number of seconds between retries (end of the exponential back-off curve)\n * @param {boolean} options.enableLogging Set to `true` to enable warning and error logging to the console\n * @param {string} options.playbackMethod Sets the preferred playback method (mediasource (default), html5, webaudio)\n *\n * @callback options.onMetadata Called with metadata when synchronized with the audio\n * @callback options.onMetadataEnqueue Called with metadata when discovered on the response\n * @callback options.onError Called with message(s) when a fallback or error condition is met\n * @callback options.onWarn Called with message(s) when a warning condition is met\n * @callback options.onPlay Called when the audio element begins playing\n * @callback options.onLoad Called when stream request is started\n * @callback options.onStreamStart Called when stream requests begins to return data\n * @callback options.onBuffer Called when the audio buffer is being filled\n * @callback options.onStream Called when stream data is sent to the audio element\n * @callback options.onStreamEnd Called when the stream request completes\n * @callback options.onStop Called when the stream is completely stopped and all cleanup operations are complete\n * @callback options.onRetry Called when a connection retry is attempted\n * @callback options.onRetryTimeout Called when connections attempts have timed out\n * @callback options.onSwitch Called when a switch event is triggered\n * @callback options.onCodecUpdate Called when the audio codec information has changed\n */\n constructor(urls, options = {}) {\n super();\n\n p.set(this, {\n // options\n [endpointGenerator]:\n IcecastMetadataPlayer[getNextEndpointGenerator](this),\n [audioElement]: options.audioElement || new Audio(),\n ...IcecastMetadataPlayer[getOptions](urls, options),\n // callbacks\n [events]: {\n [event.PLAY]: options.onPlay || noOp,\n [event.PLAY_READY]: noOp,\n [event.LOAD]: options.onLoad || noOp,\n [event.STREAM_START]: options.onStreamStart || noOp,\n [event.BUFFER]: options.onBuffer || noOp,\n [event.STREAM]: options.onStream || noOp,\n [event.STREAM_END]: options.onStreamEnd || noOp,\n [event.METADATA]: options.onMetadata || noOp,\n [event.METADATA_ENQUEUE]: options.onMetadataEnqueue || noOp,\n [event.CODEC_UPDATE]: options.onCodecUpdate || noOp,\n [event.STOP]: options.onStop || noOp,\n [event.RETRY]: options.onRetry || noOp,\n [event.RETRY_TIMEOUT]: options.onRetryTimeout || noOp,\n [event.SWITCH]: options.onSwitch || noOp,\n [event.WARN]: (...messages) => {\n this[logError](console.warn, options.onWarn, messages);\n },\n [event.ERROR]: (...messages) => {\n this[logError](console.error, options.onError, messages);\n },\n [event.PLAYBACK_ERROR]: (...messages) => {\n if (this.state !== state.RETRYING) {\n this[fireEvent](event.ERROR, ...messages);\n\n this.stop();\n } else {\n p.get(this)[endPlayback]();\n }\n },\n },\n // variables\n [endPlayback]: () => {\n clearTimeout(p.get(this)[retryTimeoutId]);\n this.removeEventListener(event.STREAM_START, p.get(this)[endPlayback]);\n p.get(this)[audioElement].removeEventListener(\n \"waiting\",\n p.get(this)[onAudioWaiting],\n );\n\n try {\n p.get(this)[audioElement].pause();\n } catch (e) {\n p.get(this)[onAudioError](e);\n }\n\n try {\n p.get(this)[playerResetPromise] = p\n .get(this)\n [playerFactory].player.end();\n } catch {}\n },\n // audio element event handlers\n [onAudioPlay]: () => {\n this.play();\n },\n [onAudioPause]: () => {\n this.stop();\n },\n [onAudioError]: (e) => {\n const errors = {\n 1: \" MEDIA_ERR_ABORTED The fetching of the associated resource was aborted by the user's request.\",\n 2: \" MEDIA_ERR_NETWORK Some kind of network error occurred which prevented the media from being successfully fetched, despite having previously been available.\",\n 3: \" MEDIA_ERR_DECODE Despite having previously been determined to be usable, an error occurred while trying to decode the media resource, resulting in an error.\",\n 4: \" MEDIA_ERR_SRC_NOT_SUPPORTED The associated resource or media provider object (such as a MediaStream) has been found to be unsuitable.\",\n 5: \" MEDIA_ERR_ENCRYPTED\",\n };\n\n const error = e?.target?.error || e;\n\n this[fireEvent](\n event.PLAYBACK_ERROR,\n \"The audio element encountered an error.\" +\n (errors[error?.code] || \"\"),\n );\n },\n [onPlayReady]: () => {\n const audio = p.get(this)[audioElement];\n\n if (\n this.state === state.LOADING ||\n (!audio.loop &&\n this.state !== state.STOPPING &&\n this.state !== state.STOPPED)\n ) {\n audio\n .play()\n .then(() => {\n this[playerState] = state.PLAYING;\n })\n .catch((e) => {\n this[fireEvent](event.PLAYBACK_ERROR, e, \"Playback failed.\");\n });\n }\n },\n [stopPlayback]: noOp,\n });\n\n this[attachAudioElement]();\n this[playerState] = state.STOPPED;\n\n p.get(this)[playerFactory] = new PlayerFactory(this);\n }\n\n /**\n * @description Checks for MediaSource, WebAudio, and HTML5 support for a given codec\n * @param {string} type Codec / mime-type to check\n * @returns {mediasource: string, webaudio: string, html5: string} Object indicating if the codec is supported by the playback method\n */\n static canPlayType(type) {\n return PlayerFactory.canPlayType(type);\n }\n\n /**\n * @returns {HTMLAudioElement} The audio element associated with this instance\n */\n get audioElement() {\n return p.get(this)[audioElement];\n }\n\n /**\n * @returns {AudioContext} Statically initialized internal AudioContext\n */\n get [audioContext]() {\n return IcecastMetadataPlayer.constructor[audioContext];\n }\n\n /**\n * @returns {string} Current endpoint that is being played\n */\n get endpoint() {\n return p.get(this)[playerFactory].endpoint;\n }\n\n /**\n * @returns {number} The ICY metadata interval in number of bytes for this instance\n */\n get icyMetaInt() {\n return p.get(this)[playerFactory].icyMetaInt;\n }\n\n /**\n * @returns {Array<Metadata>} Array of enqueued metadata objects in FILO order\n */\n get metadataQueue() {\n return p.get(this)[playerFactory].player.metadataQueue;\n }\n\n /**\n * @returns {string} The current state (\"loading\", \"playing\", \"stopping\", \"stopped\", \"retrying\", \"switching\")\n */\n get state() {\n return p.get(this)[playerState];\n }\n\n /**\n * @returns {string} The playback method (\"mediasource\", \"webaudio\", \"html5\")\n */\n get playbackMethod() {\n return p.get(this)[playerFactory].playbackMethod;\n }\n\n set [playerState](_state) {\n this.dispatchEvent(new CustomEvent(_state));\n p.get(this)[playerState] = _state;\n }\n\n [attachAudioElement]() {\n // audio events\n const audio = p.get(this)[audioElement];\n audio.addEventListener(\"pause\", p.get(this)[onAudioPause]);\n audio.addEventListener(\"play\", p.get(this)[onAudioPlay]);\n audio.addEventListener(\"error\", p.get(this)[onAudioError]);\n\n this.addEventListener(event.PLAY_READY, p.get(this)[onPlayReady]);\n }\n\n /**\n * @description Remove event listeners from the audio element and this instance and stops playback\n */\n async detachAudioElement() {\n const audio = p.get(this)[audioElement];\n audio.removeEventListener(\"pause\", p.get(this)[onAudioPause]);\n audio.removeEventListener(\"play\", p.get(this)[onAudioPlay]);\n audio.removeEventListener(\"error\", p.get(this)[onAudioError]);\n\n this.removeEventListener(event.PLAY_READY, p.get(this)[onPlayReady]);\n await this.stop();\n }\n\n /**\n * @description Plays the Icecast stream\n * @async Resolves when the audio element is playing\n */\n async play() {\n if (this.state === state.STOPPED) {\n const playing = new Promise((resolve) => {\n this.addEventListener(event.PLAY, resolve, { once: true });\n });\n\n const streamEnd = new Promise((resolve) => {\n this.addEventListener(event.STREAM_END, resolve, { once: true });\n });\n\n p.get(this)[abortController] = new AbortController();\n this[playerState] = state.LOADING;\n this[fireEvent](event.LOAD);\n\n // prettier-ignore\n const tryFetching = async () =>\n p.get(this)[playerFactory].playStream()\n .then(async () => {\n if (this.state === state.SWITCHING) {\n this[fireEvent](event.SWITCH);\n return tryFetching();\n } else if (\n this.state !== state.STOPPING &&\n this.state !== state.STOPPED\n ) {\n // wait for any remaining audio to play through\n await playing;\n await streamEnd;\n await p.get(this)[playerFactory].player.waiting;\n }\n })\n .catch(async (e) => {\n if (e && e.name !== \"AbortError\") {\n if (await this[shouldRetry](e)) {\n this[fireEvent](event.RETRY);\n return tryFetching();\n }\n\n p.get(this)[abortController].abort(); // stop fetch if is wasn't aborted\n\n if (\n this.state !== state.STOPPING &&\n this.state !== state.STOPPED\n ) {\n this[fireEvent](\n event.ERROR,\n e.message.match(/network|fetch|offline|codec/i) ? e : e.stack,\n e\n );\n }\n }\n });\n\n new Promise((resolve, reject) => {\n // stop any pending playback operation when stop is called\n p.get(this)[stopPlayback] = reject;\n\n tryFetching().then(resolve);\n })\n .catch((e) => {\n if (this.state !== state.STOPPING) throw e;\n })\n .finally(() => {\n p.get(this)[endPlayback]();\n\n this[fireEvent](event.STOP);\n this[playerState] = state.STOPPED;\n });\n\n await playing;\n }\n }\n\n /**\n * @description Stops playing the Icecast stream\n * @async Resolves when the icecast stream has stopped\n */\n async stop() {\n if (this.state !== state.STOPPED && this.state !== state.STOPPING) {\n this[playerState] = state.STOPPING;\n p.get(this)[abortController].abort();\n p.get(this)[stopPlayback]();\n\n await new Promise((resolve) => {\n this.addEventListener(event.STOP, resolve, { once: true });\n });\n }\n }\n\n /**\n * @description Switches the Icecast stream endpoint during playback\n * @async Resolves when playback begins from the new source\n */\n async switchEndpoint(newEndpoints, newOptions) {\n if (this.state !== state.STOPPED && this.state !== state.STOPPING) {\n const instance = p.get(this);\n Object.assign(\n instance,\n IcecastMetadataPlayer[getOptions](newEndpoints, newOptions, instance),\n );\n\n return instance[playerFactory].switchStream();\n }\n }\n\n async [shouldRetry](error) {\n if (p.get(this)[retryTimeout] === 0) return false;\n\n if (p.get(this)[playerState] === state.RETRYING) {\n // wait for retry interval\n await new Promise((resolve) => {\n this.addEventListener(state.STOPPING, resolve, { once: true });\n\n const delay = Math.min(\n p.get(this)[retryDelayMin] *\n 1000 *\n (p.get(this)[retryDelayRate] + 1) ** p.get(this)[retryAttempt]++,\n p.get(this)[retryDelayMax] * 1000,\n ); // exponential backoff\n\n setTimeout(\n () => {\n this.removeEventListener(state.STOPPING, resolve);\n resolve();\n },\n delay + delay * 0.3 * Math.random(),\n ); // jitter\n });\n\n // ensure the retry hasn't been cancelled while waiting\n return p.get(this)[playerState] === state.RETRYING;\n }\n\n if (\n p.get(this)[playerState] !== state.STOPPING &&\n p.get(this)[playerState] !== state.STOPPED &&\n (error.message.match(/network|fetch|offline|Error in body stream/i) ||\n error.name === \"HTTP Response Error\")\n ) {\n this[fireEvent](event.ERROR, error.name, error);\n this[playerState] = state.RETRYING;\n\n if (p.get(this)[hasIcy]) {\n this[fireEvent](\n event.WARN,\n \"This stream was requested with ICY metadata.\",\n 'If there is a CORS preflight failure, try removing \"icy\" from the metadataTypes option.',\n \"See https://github.com/eshaz/icecast-metadata-js#cors for more details.\",\n );\n }\n\n const audioWaiting = new Promise((resolve) => {\n p.get(this)[onAudioWaiting] = resolve;\n p.get(this)[audioElement].addEventListener(\n \"waiting\",\n p.get(this)[onAudioWaiting],\n {\n once: true,\n },\n );\n });\n\n // wait for whichever is longer, audio element waiting or retry timeout\n p.get(this)[retryTimeoutId] = setTimeout(\n () => {\n audioWaiting.then(() => {\n if (p.get(this)[playerState] === state.RETRYING) {\n this[fireEvent](event.RETRY_TIMEOUT);\n this.stop();\n }\n });\n },\n p.get(this)[retryTimeout] * 1000,\n );\n\n p.get(this)[retryAttempt] = 0;\n return true;\n }\n\n return false;\n }\n\n [fireEvent](event, ...args) {\n this.dispatchEvent(new CustomEvent(event, { detail: args }));\n p.get(this)[events][event](...args);\n }\n\n [logError](consoleFunction, callback, messages) {\n if (p.get(this)[enableLogging]) {\n consoleFunction(\n \"icecast-metadata-js\",\n messages.reduce((acc, message) => acc + \"\\n \" + message, \"\"),\n );\n }\n if (callback) callback(...messages);\n }\n}\n\nconst AudioContext = window.AudioContext || window.webkitAudioContext;\n\n// statically initialize audio context and start using a DOM event\nif (AudioContext && !IcecastMetadataPlayer.constructor[audioContext]) {\n IcecastMetadataPlayer.constructor[audioContext] = \"audio context pending\";\n\n const audioCtxErrorHandler = (e) => {\n console.error(\n \"icecast-metadata-js\",\n \"Failed to start the AudioContext. WebAudio playback will not be possible.\",\n e,\n );\n };\n\n // hack for iOS Audio element controls support\n // iOS will only enable AudioContext.resume() when called directly from a UI event\n // https://stackoverflow.com/questions/57510426\n const events = [\"touchstart\", \"touchend\", \"mousedown\", \"keydown\"];\n\n const unlock = () => {\n events.forEach((e) => document.removeEventListener(e, unlock));\n\n const audioCtx = new AudioContext({\n latencyHint: \"interactive\",\n });\n\n audioCtx.destination.channelCount = audioCtx.destination.maxChannelCount;\n\n audioCtx\n .resume()\n .then(() => {\n // hack for iOS to continue playing while locked\n audioCtx\n .createScriptProcessor(2 ** 14, 2, 2)\n .connect(audioCtx.destination);\n\n audioCtx.onstatechange = () => {\n if (audioCtx.state !== \"running\")\n audioCtx.resume().catch(audioCtxErrorHandler);\n };\n })\n .catch(audioCtxErrorHandler);\n\n IcecastMetadataPlayer.constructor[audioContext] = audioCtx;\n };\n\n events.forEach((e) => document.addEventListener(e, unlock));\n}\n"],"names":["deferred","inProgress","dataWebpackPrefix","symbol","Symbol","channelMappings","left","center","right","front","side","rear","map","x","flatMap","y","z","join","lfe","monophonic","stereo","surround","getChannelMapping","channelCount","mappings","vorbisOpusChannelMapping","rate48000","rate44100","rate32000","rate24000","rate22050","rate16000","rate8000","absoluteGranulePosition","bandwidth","bitDepth","bitrate","bitrateMaximum","bitrateMinimum","bitrateNominal","buffer","bufferFullness","codec","codecFrames","coupledStreamCount","crc","crc16","crc32","data","description","duration","emphasis","hasOpusPadding","header","isContinuedPacket","isCopyrighted","isFirstPage","isHome","isLastPage","isOriginal","isPrivate","isVbr","mode","modeExtension","mpeg","mpegVersion","numberAACFrames","outputGain","preSkip","profile","profileBits","protection","rawData","segments","subarray","version","vorbis","vorbisComments","vorbisSetup","block","blockingStrategy","blockingStrategyBits","blockSize","blocksize0","blocksize1","blockSizeBits","channel","channelMappingFamily","channelMappingTable","channelMode","channelModeBits","channels","copyright","copyrightId","copyrightIdStart","frameCount","frameLength","frameNumber","framePadding","frameSize","Rate","inputSampleRate","page","pageChecksum","pageSegmentBytes","pageSegmentTable","pageSequenceNumber","sample","sampleNumber","sampleRate","sampleRateBits","samples","stream","streamCount","streamInfo","streamSerialNumber","streamStructureVersion","total","totalBytesOut","totalDuration","totalSamples","readRawData","incrementRawData","mapCodecFrameStats","mapFrameStats","logWarning","syncFrame","fixedLengthFrameSync","getHeader","setHeader","getFrame","parseFrame","parseOggPage","checkCodecUpdate","enable","getHeaderFromUint8Array","checkFrameFooterCrc16","uint8Array","Uint8Array","dataView","DataView","reserved","bad","free","none","sixteenBitCRC","getCrcTable","crcTable","crcInitialValueFunction","crcFunction","byte","bit","crc8Table","b","flacCrc16Table","Uint16Array","crc32Table","Uint32Array","i","push","j","crc32Function","dataLength","crcChunkSize","concatBuffers","buffers","reduce","acc","buf","offset","set","bytesToString","bytes","String","fromCharCode","reverseTable","reverse","val","BitReader","constructor","this","_data","_pos","position","read","bits","Math","floor","HeaderCache","onCodecHeader","onCodecUpdate","_onCodecHeader","_onCodecUpdate","_isEnabled","_headerCache","Map","_codecUpdateData","WeakMap","_codecHeaderSent","_codecShouldUpdate","_bitrate","codecData","get","_currentHeader","key","_updateCurrentHeader","codecUpdateFields","headerStore","frameStore","Parser","codecParser","headerCache","_codecParser","frameData","Frame","ignoreNextFrame","_flushing","Header","headerValue","dataValue","CodecFrame","readOffset","frameLengthValue","samplesValue","super","unsynchronizationFlag","extendedHeaderFlag","experimentalFlag","footerPresent","ID3v2","getID3v2Header","CodecHeader","bitrateMatrix","calcBitrate","idx","interval","intervalOffset","bands","to31","layer12ModeExtensions","bitrateIndex","v2","v1","intensityStereo","msStereo","on","off","layer3ModeExtensions","layersValues","mpegVersionDescription","isoIec","mpegVersions","length","protectionValues","emphasisValues","channelModes","MPEGHeader","id3v2Header","cachedHeader","mpegVersionValues","layerBits","layerValues","MPEGFrame","frame","MPEGParser","onCodec","profileValues","sampleRates","channelModeValues","AACHeader","Object","assign","protectionBit","privateBit","bufferFullnessBits","audioSpecificConfig","setUint16","AACFrame","AACParser","FLACFrame","_getFrameFooterCrc16","expectedCrc16","actualCrc16","flacCrc16","streamInfoValue","getFromStreamInfo","blockingStrategyValues","blockSizeValues","sampleRateValues","channelAssignments","bitDepthValues","FLACHeader","_decodeUTF8Int","value","zeroMask","shift","codecParserStub","next","channelAssignment","decodedUtf8","crc8","FLACParser","_getNextFrameSyncOffset","secondByte","nextHeaderOffset","oggPage","_streamInfo","segment","filter","OggPageHeader","view","from","getBigInt64","getInt32","pageSegmentTableLength","segmentLength","segmentByte","OggPage","headerLength","totalLength","rawDataValue","OpusFrame","channelMappingFamilies","slice","silkOnly","celtOnly","hybrid","narrowBand","mediumBand","wideBand","superWideBand","fullBand","configTable","OpusHeader","packetData","Error","packetMode","packetLength","substr","getUint16","getUint32","getInt16","packetConfig","headerData","OpusParser","_identificationHeader","VorbisFrame","blockSizes","VorbisHeader","vorbisCommentsData","vorbisSetupData","VorbisParser","_setupComplete","_prevBlockSize","oggPageSegment","_vorbisComments","_vorbisSetup","_mode","_parseSetupHeader","_getSamples","logError","currentBlockSize","blockFlags","mask","setup","bitReader","count","modeBits","currentByte","unshift","log2","OggStream","_onCodec","_continuedPacket","_codec","_isSupported","_updateCodec","_parser","_checkCodecSupport","idString","test","_checkPageSequenceNumber","_pageSequenceNumber","_parsePage","oggPageStore","pop","OggParser","_streams","_currentSerialNumber","oggStream","delete","noOp","mimeType","enableLogging","enableFrameCRC32","_inputMimeType","_enableLogging","_crc32","_generator","_getGenerator","flush","parseChunk","chunk","parseAll","fileData","match","_frameNumber","_currentReadPosition","_totalBytesIn","_totalBytesOut","_totalSamples","_sampleRate","undefined","_rawData","minSize","increment","round","forEach","codecFrame","_log","logger","messages","stats","width","max","s","repeat","message","console","warn","error","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","m","O","result","chunkIds","fn","priority","notFulfilled","Infinity","fulfilled","keys","every","splice","r","F","E","chunkId","d","definition","o","defineProperty","enumerable","f","e","Promise","all","promises","u","g","globalThis","Function","window","obj","prop","prototype","hasOwnProperty","call","l","url","done","script","needAttach","scripts","document","getElementsByTagName","getAttribute","createElement","charset","timeout","nc","setAttribute","src","onScriptComplete","prev","event","onerror","onload","clearTimeout","doneFns","parentNode","removeChild","setTimeout","bind","type","target","head","appendChild","toStringTag","scriptUrl","importScripts","location","currentScript","replace","p","installedChunks","installedChunkData","promise","resolve","reject","errorType","realSrc","name","request","link","rel","as","href","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","id","chunkLoadingGlobal","self","state","LOADING","PLAYING","STOPPING","STOPPED","RETRYING","SWITCHING","BUFFER","PLAY","PLAY_READY","LOAD","STREAM_START","STREAM","STREAM_END","METADATA","METADATA_ENQUEUE","CODEC_UPDATE","STOP","RETRY","RETRY_TIMEOUT","SWITCH","WARN","ERROR","PLAYBACK_ERROR","endpoints","endpointOrder","metadataTypes","playbackMethod","audioContext","audioElement","bufferLength","icyMetaInt","icyCharacterEncoding","icyDetectionTimeout","retryDelayRate","retryDelayMin","retryDelayMax","retryTimeout","enableCodecUpdate","authentication","getNextEndpointGenerator","getOptions","fireEvent","attachAudioElement","shouldRetry","endpointGenerator","hasIcy","abortController","playerState","SYNCED","SYNCING","PCM_SYNCED","NOT_SYNCED","EventTargetPolyfill","_listeners","hasEventListener","listener","item","addEventListener","options","removeEventListener","index","findIndex","removeEventListeners","dispatchEvent","evt","once","Stats","_totalBytesRead","_streamBytesRead","_metadataLengthBytesRead","_metadataBytesRead","_currentBytesRemaining","_currentStreamBytesRemaining","_currentMetadataBytesRemaining","totalBytesRead","streamBytesRead","metadataLengthBytesRead","metadataBytesRead","currentBytesRemaining","currentStreamBytesRemaining","currentMetadataBytesRemaining","addBytes","addStreamBytes","addMetadataLengthBytes","addMetadataBytes","addCurrentBytesRemaining","MetadataParser","params","_remainingData","_currentPosition","_buffer","_streamBuffer","_streamBufferLength","_stats","_onStream","onStream","_onMetadata","onMetadata","_onMetadataFailed","onMetadataFailed","_onError","onError","_onStreamPromise","_onMetadataPromise","_passThroughParser","_addStream","_getNextValue","_sendStream","_concatBuffers","_concatBuffersKnownLength","iterator","readAll","asyncIterator","asyncReadAll","_logError","streamPayload","_sendMetadata","metadata","metadataPayload","minLength","_readData","IcyMetadataParser","rest","_decoder","TextDecoder","_icyMetaInt","_icyDetectionTimeout","_icyParser","_hasIcyMetadata","_getStream","_getMetadataLength","_getMetadata","parseIcyMetadata","metadataString","metadataRegex","metadataElement","RegExp","METADATA_SEARCH","startTime","Date","now","metaInt","detectMetadata","decode","OggMetadataParser","_oggParser","_isContinuePacket","_hasOggPage","codecMatcher","_identifyCodec","_getUint32","_matchBytes","matchString","syncBytes","baseOggPage","oggPageSegments","octet","regex","_readVorbisComment","vendorStringLength","vendorString","commentListLength","comments","commentLength","comment","delimiter","indexOf","toUpperCase","VENDOR_STRING","DualMetadataParser","_oggMetadataParser","_icyMetadataParser","oggValue","IcecastMetadataReader","includes","hasOgg","_metadataParser","string","IcecastReadableStream","response","icecast","_readableStream","ReadableStream","start","controller","parseInt","headers","async","enqueue","body","close","_icecast","readableStream","startReading","reader","getReader","IcecastMetadataQueue","icyBr","onMetadataUpdate","onMetadataEnqueue","paused","_icyBr","_onMetadataUpdate","_onMetadataEnqueue","_initialPaused","_paused","_isInitialMetadata","_pendingMetadata","_metadataQueue","metadataQueue","_timeoutId","addMetadata","timestampOffset","timestamp","getTimeByBytes","currentStreamPosition","_enqueueMetadata","bytesRead","startQueue","purgeMetadataQueue","payload","_dequeueMetadata","canSpawnWorker","spawnWorkerTest","Worker","URL","createObjectURL","Blob","onmessage","terminate","postMessage","FrameQueue","player","CRC_DURATION","PCM_DURATION","_player","initSync","initQueue","_syncTimeout","_syncTimeoutReason","_crcSyncPending","_syncQueue","_syncQueueDuration","_synAudioResult","_a","_b","_queueIndex","_queueSamples","_queueSampleRate","_crcQueue","_crcQueueDuration","_crcQueueIndexes","_pcmQueue","_pcmQueueDuration","buffered","currentTime","add","indexes","addAll","frames","_addAllSyncQueue","sync","currentBuffered","_syncReject","toFixed","syncState","_crcSync","_pcmSync","catch","syncQueue","then","syncQueueCrc","crcSyncPoints","matched","outOfFrames","syncPoint","align_queues","absoluteSyncPoint","sliceIndex","correlationSyncLength","initialGranularity","samplesToDuration","rate","SynAudio","default","pcmQueueDecoded","syncQueueDecoded","_decodeQueues","correlationSampleSize","samplesDecoded","synAudio","syncWorkerConcurrent","navigator","hardwareConcurrency","syncWorker","offsetFromEnd","sampleOffset","correlation","delay","frameOverlap","t","queue","timeFromEnd","decodeAudioData","getDecodedAudio","decodedAudioData","decoded","channelData","numberOfChannels","Float32Array","getChannelData","Player","endpoint","inputMimeType","codecHeader","_endpoint","_codecHeader","instanceVariables","_audioElement","_bufferLength","_codecUpdateTimestamp","_codecUpdateOffset","_notSyncedHandler","parseMimeType","canPlayType","codecChecker","mapping","matches","checkCodecs","codecs","mime","groups","mimeMapping","Array","isArray","mimeCodecs","split","enablePlayButton","supportedSources","removeAttribute","srcObject","MediaSource","_mediaStream","MediaStream","loop","syncStateUpdate","_syncStatePromise","_syncState","newState","_syncStateResolve","isSupported","isAudioPlayer","metadataTimestamp","waiting","icecastMetadataQueue","_icecastMetadataQueue","codecUpdateQueue","_codecUpdateQueue","_startMetadataQueues","_metadataOffset","_init","syncFrames","syncDelay","_frameQueue","metadataOffset","playing","finally","end","updateTimestamp","HTML5Player","crossOrigin","preload","_playReady","Audio","Boolean","_frame","_metadataTimestampOffset","_audioLoadedTimestamp","performance","_metadataLoadedTimestamp","MediaSourcePlayer","_MSEAudioWrapper","isTypeSupported","aac","aacp","flac","ogg","opus","_mediaSource","sourceBuffers","_sourceBufferQueue","_processingLastPage","_mediaSourceCreated","_mediaSourceCreatedNotify","_mediaSourceOpen","_mediaSourceOpenNotify","_addFrames","_prepareMediaSource","_attachMediaSource","_createMediaSource","_appendSourceBuffer","_createMSEWrapper","_wrapper","fragments","preferredContainer","addSourceBuffer","_sourceBufferRemoved","_waitForSourceBuffer","sourceBuffer","updating","appendBuffer","BUFFER_INTERVAL","remove","WebAudioPlayer","_audioContext","WebAssembly","AudioContext","webkitAudioContext","_currentTime","_playbackStartTime","_waitingPromise","_updateWaiting","durationTimeout","_bufferedDuration","_durationTimeouts","size","_notifyWaiting","_waitingResolve","_resetWaiting","Set","_createDecoder","DecoderClass","_loadingDecoder","_decoderLoaded","MPEGDecoderWebWorker","OpusDecoderWebWorker","FLACDecoderWebWorker","OggVorbisDecoderWebWorker","_wasmDecoder","_decodedSample","_startSampleOffset","_playPromise","_playStart","getTracks","track","removeTrack","_decodeAndPlay","decodePromise","ready","decodeOggPages","decodeFrames","_play","createMediaStreamDestination","destination","maxChannelCount","audioBuffer","createBuffer","source","createBufferSource","connect","scalingFactor","startSamples","audioContextSamples","PlayerFactory","_enableCodecUpdate","_playbackMethod","_newMetadataQueues","supportedPlaybackMethods","_unprocessedFrames","_syncPromise","_syncCancel","mediasource","html5","webaudio","_icecastReadableStream","playStream","fetchStream","res","readIcecastResponse","switchStream","instance","abort","AbortController","auth","btoa","user","password","fetch","method","signal","ok","status","codecHeaderPromise","codecPromise","args","appendedFrames","icecastPromise","_buildPlayer","_syncPlayer","delayTimeoutId","complete","canceled","playerStarted","oldPlayer","oldIcecastMetadataQueue","oldCodecUpdateQueue","startNewPlayer","handleSyncEvent","stoppingHandler","firstMethod","values","support","EventClass","EventTarget","playerFactory","playerResetPromise","events","onAudioPause","onAudioPlay","onPlayReady","onAudioError","onAudioWaiting","stopPlayback","endPlayback","retryAttempt","retryTimeoutId","IcecastMetadataPlayer","currentEndpoints","urls","newOptions","sort","random","onPlay","onLoad","onStreamStart","onBuffer","onStreamEnd","onStop","onRetry","onRetryTimeout","onSwitch","onWarn","stop","pause","play","code","audio","_state","CustomEvent","detachAudioElement","streamEnd","tryFetching","stack","switchEndpoint","newEndpoints","min","audioWaiting","detail","consoleFunction","callback","audioCtxErrorHandler","unlock","audioCtx","latencyHint","resume","createScriptProcessor","onstatechange"],"sourceRoot":""} |