{"version":3,"file":"flacEncodeWorker.min.js","mappings":"mBACA,IAAIA,EAAsB,CAAC,E,wHCA3BA,EAAoBC,EAAI,CAACC,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXH,EAAoBK,EAAEF,EAAYC,KAASJ,EAAoBK,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDJ,EAAoBK,EAAI,CAACK,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCY3E,MAmBMI,EAAuB,uBAgCpC,IAAIC,EAdJC,KAAKC,qBAAuB,0BAE5BC,cAAc,gDAcd,MAAMC,EAAc,CAEhB,EAAG,0BAKH,EAAG,qCAGH,EAAG,iCAIH,EAAG,4CAIH,EAAG,qDAGH,EAAG,oCAGH,EAAG,gCAIH,EAAG,qCAGH,EAAG,gDAMDC,EAAef,OAAOgB,OAAO,CAI/BC,aAAc,gBAKdC,QAAS,UAKTC,SAAU,aAiCd,MAAMC,EAuDFC,YAAYC,GAA8C,IAAlCC,EAAkC,uDAAvB,GAAIC,EAAmB,uDAAN,KAChD,GADsD,oBAjD7C,GAiD6C,2GA1B3C,IA0B2C,qBArB5C,GAqB4C,gBAhBjDT,EAAaE,cAgBoC,eAXlD,MAWkD,+BAyKnC,UAxKdP,EAAKe,UACN,MAAM,IAAIC,MAAM,6BA2BpB,GAxBAC,KAAKC,YAAcN,EACnBK,KAAKE,UAAYN,EACjBI,KAAKG,YAAcN,EAGnBG,KAAKI,WAAarB,EAAKsB,qBACnBL,KAAKC,YAGL,EACAD,KAAKE,UAjGc,EAsGnB,GAGA,EAGA,GAGoB,IAApBF,KAAKI,WACL,MAAM,IAAIL,MAAM,qCAUpB,GAAmB,IANAhB,EAAKuB,oBACpBN,KAAKI,WACLJ,KAAKO,eAAeC,KAAKR,MACzBA,KAAKS,qBAAqBD,KAAKR,OAI/B,MAAM,IAAID,MAAM,yCAGpBC,KAAKU,OAAStB,EAAaG,OAC9B,CAQDoB,OAAOC,GACH,GAAIZ,KAAKU,SAAWtB,EAAaG,QAC7B,MAAM,IAAIQ,MAAM,yCAGpB,IAAKhB,EAAKe,UACN,MAAM,IAAIC,MAAM,kBAEpB,MAAMc,EAAeD,EAAUE,OAYzBC,EAAY,IAAIC,WAAWH,GAC3BI,EAAO,IAAIC,SAASH,EAAUI,QAEpC,IAAIC,EAAQ,EAEZ,IAAK,IAAIC,EAAI,EAAGA,EAAIR,EAAcQ,IAC9BJ,EAAKK,SAASF,EAAO,MAAAR,EAAUS,IAAwB,GACvDD,GAAS,EAUb,GAAe,IANArC,EAAKwC,yCAChBvB,KAAKI,WACLW,EACAA,EAAUD,QAGI,CAGd,MAAMU,EACAzC,EAAK0C,+BAA+BzB,KAAKI,YAE/CsB,QAAQC,MAAM,wBAAyBxC,EAAYqC,GACtD,CACJ,CAODI,SACI,GAAI5B,KAAKU,SAAWtB,EAAaG,QAAS,CACtCS,KAAKU,OAAStB,EAAaI,SAE3B,MAAMqC,EAAS9C,EAAK+C,4BAA4B9B,KAAKI,YAErDsB,QAAQK,IAAI,2BAA4BF,GAGxC9C,EAAKiD,4BAA4BhC,KAAKI,YAEtCJ,KAAKiC,MAAQjC,KAAKkC,iBACrB,CACJ,CAODC,UACI,OAAInC,KAAKU,SAAWtB,EAAaI,SACtBQ,KAAKiC,MAGT,IACV,CAQDC,kBACI,MAAME,EArNd,SAA0BC,EAAQC,GAC9B,MAAMC,EAAS,IAAIC,WAAWF,GAC9B,IAAIG,EAAS,EACb,MAAMC,EAAML,EAAOvB,OAEnB,IAAK,IAAIO,EAAI,EAAGA,EAAIqB,EAAKrB,IAAK,CAC1B,MAAMF,EAASkB,EAAOhB,GAEtBkB,EAAOI,IAAIxB,EAAQsB,GACnBA,GAAUtB,EAAOL,MACpB,CAED,OAAOyB,CACV,CAwMuBK,CAAiB5C,KAAK6C,aAAc7C,KAAK8C,aAIzD,OAFa,IAAIC,KAAK,CAAEX,GAAW,CAAEY,KAAM,cAG9C,CAYDzC,eAAeY,EAAQ8B,GACnBjD,KAAK6C,aAAaK,KAAK/B,GACvBnB,KAAK8C,aAAe3B,EAAOgC,UAC9B,EAeL,IAAIC,EAAU,KAEdpE,KAAKqE,UAAY,SAASC,GAEtB,OAAQA,EAAEC,KAAKC,SACf,IA9W4B,mBA+W5B,CACI,MAAMC,EAAMH,EAAEC,KAAKG,OAAOD,IACpB9D,EAAa2D,EAAEC,KAAKG,OAAO/D,WAE7BZ,EAAKe,WACLsD,EAAU,IAAI3D,EAAQE,EAAY8D,GAClCzE,KAAK2E,YAAY,CACbH,QAAS1E,KAGbC,EAAK6E,QAAU,WACXC,YAAW,KACPT,EAAU,IAAI3D,EAAQE,EAAY8D,GAClCzE,KAAK2E,YAAY,CACbH,QAAS1E,GADb,GAGD,EACN,EAEL,KACH,CAED,IA/XwC,+BAgYpB,OAAZsE,EACA1B,QAAQC,MAAM,kEAEdyB,EAAQzC,OAAO2C,EAAEC,KAAKO,KAE1B,MAEJ,IAnZ8B,qBAoZ1B,GAAgB,OAAZV,EAAkB,CAClBA,EAAQxB,SACR,MAAM2B,EAAOH,EAAQjB,UAErBnD,KAAK2E,YACD,CACIH,QAlYa,oBAmYbM,IAAKP,IAGbH,EAAU,IACb,EAGR,C","sources":["webpack://sariska-media-transport/webpack/bootstrap","webpack://sariska-media-transport/webpack/runtime/define property getters","webpack://sariska-media-transport/webpack/runtime/hasOwnProperty shorthand","webpack://sariska-media-transport/./modules/local-recording/recording/flac/flacEncodeWorker.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\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__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/**\n * Types of messages that are passed between the main thread and the WebWorker\n * ({@code flacEncodeWorker})\n */\n\n// Messages sent by the main thread\n\n/**\n * Message type that signals the termination of encoding,\n * after which no new audio bits should be sent to the\n * WebWorker.\n */\nexport const MAIN_THREAD_FINISH = 'MAIN_THREAD_FINISH';\n\n/**\n * Message type that carries initial parameters for\n * the WebWorker.\n */\nexport const MAIN_THREAD_INIT = 'MAIN_THREAD_INIT';\n\n/**\n * Message type that carries the newly received raw audio bits\n * for the WebWorker to encode.\n */\nexport const MAIN_THREAD_NEW_DATA_ARRIVED = 'MAIN_THREAD_NEW_DATA_ARRIVED';\n\n// Messages sent by the WebWorker\n\n/**\n * Message type that signals libflac is ready to receive audio bits.\n */\nexport const WORKER_LIBFLAC_READY = 'WORKER_LIBFLAC_READY';\n\n/**\n * Message type that carries the encoded FLAC file as a Blob.\n */\nexport const WORKER_BLOB_READY = 'WORKER_BLOB_READY';\n\n// Messages sent by either the main thread or the WebWorker\n\n/**\n * Debug messages.\n */\nexport const DEBUG = 'DEBUG';\n\n/**\n * WebWorker that does FLAC encoding using libflac.js\n */\n\nself.FLAC_SCRIPT_LOCATION = 'https://sdk.sariska.io/';\n/* eslint-disable */\nimportScripts('https://sdk.sariska.io/libflac4-1.3.2.min.js');\n/* eslint-enable */\n\n// There is a number of API calls to libflac.js, which does not conform\n// to the camalCase naming convention, but we cannot change it.\n// So we disable the ESLint rule `new-cap` in this file.\n/* eslint-disable new-cap */\n\n// Flow will complain about the number keys in `FLAC_ERRORS`,\n// ESLint will complain about the `declare` statement.\n// As the current workaround, add an exception for eslint.\n/* eslint-disable flowtype/no-types-missing-file-annotation */\nvar Flac;\n\nconst FLAC_ERRORS = {\n    // The encoder is in the normal OK state and samples can be processed.\n    0: 'FLAC__STREAM_ENCODER_OK',\n\n    // The encoder is in the uninitialized state one of the\n    // FLAC__stream_encoder_init_*() functions must be called before samples can\n    // be processed.\n    1: 'FLAC__STREAM_ENCODER_UNINITIALIZED',\n\n    // An error occurred in the underlying Ogg layer.\n    2: 'FLAC__STREAM_ENCODER_OGG_ERROR',\n\n    // An error occurred in the underlying verify stream decoder; check\n    // FLAC__stream_encoder_get_verify_decoder_state().\n    3: 'FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR',\n\n    // The verify decoder detected a mismatch between the original audio signal\n    // and the decoded audio signal.\n    4: 'FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA',\n\n    // One of the callbacks returned a fatal error.\n    5: 'FLAC__STREAM_ENCODER_CLIENT_ERROR',\n\n    // An I/O error occurred while opening/reading/writing a file. Check errno.\n    6: 'FLAC__STREAM_ENCODER_IO_ERROR',\n\n    // An error occurred while writing the stream; usually, the write_callback\n    // returned an error.\n    7: 'FLAC__STREAM_ENCODER_FRAMING_ERROR',\n\n    // Memory allocation failed.\n    8: 'FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR'\n};\n\n/**\n * States of the {@code Encoder}.\n */\nconst EncoderState = Object.freeze({\n    /**\n     * Initial state, when libflac.js is not initialized.\n     */\n    UNINTIALIZED: 'uninitialized',\n\n    /**\n     * Actively encoding new audio bits.\n     */\n    WORKING: 'working',\n\n    /**\n     * Encoding has finished and encoded bits are available.\n     */\n    FINISHED: 'finished'\n});\n\n/**\n * Default FLAC compression level.\n */\nconst FLAC_COMPRESSION_LEVEL = 5;\n\n/**\n * Concat multiple Uint8Arrays into one.\n *\n * @param {Uint8Array[]} arrays - Array of Uint8 arrays.\n * @param {number} totalLength - Total length of all Uint8Arrays.\n * @returns {Uint8Array}\n */\nfunction mergeUint8Arrays(arrays, totalLength) {\n    const result = new Uint8Array(totalLength);\n    let offset = 0;\n    const len = arrays.length;\n\n    for (let i = 0; i < len; i++) {\n        const buffer = arrays[i];\n\n        result.set(buffer, offset);\n        offset += buffer.length;\n    }\n\n    return result;\n}\n\n/**\n * Wrapper class around libflac API.\n */\nclass Encoder {\n\n    /**\n     * Flac encoder instance ID. (As per libflac.js API).\n     * @private\n     */\n    _encoderId = 0;\n\n    /**\n     * Sample rate.\n     * @private\n     */\n    _sampleRate;\n\n    /**\n     * Bit depth (bits per sample).\n     * @private\n     */\n    _bitDepth;\n\n    /**\n     * Buffer size.\n     * @private\n     */\n    _bufferSize;\n\n    /**\n     * Buffers to store encoded bits temporarily.\n     */\n    _flacBuffers = [];\n\n    /**\n     * Length of encoded FLAC bits.\n     */\n    _flacLength = 0;\n\n    /**\n     * The current state of the {@code Encoder}.\n     */\n    _state = EncoderState.UNINTIALIZED;\n\n    /**\n     * The ready-for-grab downloadable Blob.\n     */\n    _data = null;\n\n\n    /**\n     * Constructor.\n     * Note: Only create instance when Flac.isReady() returns true.\n     *\n     * @param {number} sampleRate - Sample rate of the raw audio data.\n     * @param {number} bitDepth - Bit depth (bit per sample).\n     * @param {number} bufferSize - The size of each batch.\n     */\n    constructor(sampleRate, bitDepth = 16, bufferSize = 4096) {\n        if (!Flac.isReady()) {\n            throw new Error('libflac is not ready yet!');\n        }\n\n        this._sampleRate = sampleRate;\n        this._bitDepth = bitDepth;\n        this._bufferSize = bufferSize;\n\n        // create the encoder\n        this._encoderId = Flac.init_libflac_encoder(\n            this._sampleRate,\n\n            // Mono channel\n            1,\n            this._bitDepth,\n\n            FLAC_COMPRESSION_LEVEL,\n\n            // Pass 0 in because of unknown total samples,\n            0,\n\n            // checksum, FIXME: double-check whether this is necessary\n            true,\n\n            // Auto-determine block size (samples per frame)\n            0\n        );\n\n        if (this._encoderId === 0) {\n            throw new Error('Failed to create libflac encoder.');\n        }\n\n        // initialize the encoder\n        const initResult = Flac.init_encoder_stream(\n            this._encoderId,\n            this._onEncodedData.bind(this),\n            this._onMetadataAvailable.bind(this)\n        );\n\n        if (initResult !== 0) {\n            throw new Error('Failed to initialise libflac encoder.');\n        }\n\n        this._state = EncoderState.WORKING;\n    }\n\n    /**\n     * Receive and encode new data.\n     *\n     * @param {Float32Array} audioData - Raw audio data.\n     * @returns {void}\n     */\n    encode(audioData) {\n        if (this._state !== EncoderState.WORKING) {\n            throw new Error('Encoder is not ready or has finished.');\n        }\n\n        if (!Flac.isReady()) {\n            throw new Error('Flac not ready');\n        }\n        const bufferLength = audioData.length;\n\n        // Convert sample to signed 32-bit integers.\n        // According to libflac documentation:\n        // each sample in the buffers should be a signed integer,\n        // right-justified to the resolution set by\n        // FLAC__stream_encoder_set_bits_per_sample().\n\n        // Here we are using 16 bits per sample, the samples should all be in\n        // the range [-32768,32767]. This is achieved by multipling Float32\n        // numbers with 0x7FFF.\n\n        const bufferI32 = new Int32Array(bufferLength);\n        const view = new DataView(bufferI32.buffer);\n        const volume = 1;\n        let index = 0;\n\n        for (let i = 0; i < bufferLength; i++) {\n            view.setInt32(index, audioData[i] * (0x7FFF * volume), true);\n            index += 4; // 4 bytes (32-bit)\n        }\n\n        // pass it to libflac\n        const status = Flac.FLAC__stream_encoder_process_interleaved(\n            this._encoderId,\n            bufferI32,\n            bufferI32.length\n        );\n\n        if (status !== 1) {\n            // gets error number\n\n            const errorNo\n                = Flac.FLAC__stream_encoder_get_state(this._encoderId);\n\n            console.error('Error during encoding', FLAC_ERRORS[errorNo]);\n        }\n    }\n\n    /**\n     * Signals the termination of encoding.\n     *\n     * @returns {void}\n     */\n    finish() {\n        if (this._state === EncoderState.WORKING) {\n            this._state = EncoderState.FINISHED;\n\n            const status = Flac.FLAC__stream_encoder_finish(this._encoderId);\n\n            console.log('Flac encoding finished: ', status);\n\n            // free up resources\n            Flac.FLAC__stream_encoder_delete(this._encoderId);\n\n            this._data = this._exportFlacBlob();\n        }\n    }\n\n    /**\n     * Gets the encoded flac file.\n     *\n     * @returns {Blob} - The encoded flac file.\n     */\n    getBlob() {\n        if (this._state === EncoderState.FINISHED) {\n            return this._data;\n        }\n\n        return null;\n    }\n\n    /**\n     * Converts flac buffer to a Blob.\n     *\n     * @private\n     * @returns {void}\n     */\n    _exportFlacBlob() {\n        const samples = mergeUint8Arrays(this._flacBuffers, this._flacLength);\n\n        const blob = new Blob([ samples ], { type: 'audio/flac' });\n\n        return blob;\n    }\n\n    /* eslint-disable no-unused-vars */\n    /**\n     * Callback function for saving encoded Flac data.\n     * This is invoked by libflac.\n     *\n     * @private\n     * @param {Uint8Array} buffer - The encoded Flac data.\n     * @param {number} bytes - Number of bytes in the data.\n     * @returns {void}\n     */\n    _onEncodedData(buffer, bytes) {\n        this._flacBuffers.push(buffer);\n        this._flacLength += buffer.byteLength;\n    }\n    /* eslint-enable no-unused-vars */\n\n    /**\n     * Callback function for receiving metadata.\n     *\n     * @private\n     * @returns {void}\n     */\n    _onMetadataAvailable = () => {\n        // reserved for future use\n    }\n}\n\n\nlet encoder = null;\n\nself.onmessage = function(e) {\n\n    switch (e.data.command) {\n    case MAIN_THREAD_INIT:\n    {\n        const bps = e.data.config.bps;\n        const sampleRate = e.data.config.sampleRate;\n\n        if (Flac.isReady()) {\n            encoder = new Encoder(sampleRate, bps);\n            self.postMessage({\n                command: WORKER_LIBFLAC_READY\n            });\n        } else {\n            Flac.onready = function() {\n                setTimeout(() => {\n                    encoder = new Encoder(sampleRate, bps);\n                    self.postMessage({\n                        command: WORKER_LIBFLAC_READY\n                    });\n                }, 0);\n            };\n        }\n        break;\n    }\n\n    case MAIN_THREAD_NEW_DATA_ARRIVED:\n        if (encoder === null) {\n            console.error('flacEncoderWorker received data when the encoder is not ready.');\n        } else {\n            encoder.encode(e.data.buf);\n        }\n        break;\n\n    case MAIN_THREAD_FINISH:\n        if (encoder !== null) {\n            encoder.finish();\n            const data = encoder.getBlob();\n\n            self.postMessage(\n                {\n                    command: WORKER_BLOB_READY,\n                    buf: data\n                }\n            );\n            encoder = null;\n        }\n        break;\n    }\n};"],"names":["__webpack_require__","d","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","WORKER_LIBFLAC_READY","Flac","self","FLAC_SCRIPT_LOCATION","importScripts","FLAC_ERRORS","EncoderState","freeze","UNINTIALIZED","WORKING","FINISHED","Encoder","constructor","sampleRate","bitDepth","bufferSize","isReady","Error","this","_sampleRate","_bitDepth","_bufferSize","_encoderId","init_libflac_encoder","init_encoder_stream","_onEncodedData","bind","_onMetadataAvailable","_state","encode","audioData","bufferLength","length","bufferI32","Int32Array","view","DataView","buffer","index","i","setInt32","FLAC__stream_encoder_process_interleaved","errorNo","FLAC__stream_encoder_get_state","console","error","finish","status","FLAC__stream_encoder_finish","log","FLAC__stream_encoder_delete","_data","_exportFlacBlob","getBlob","samples","arrays","totalLength","result","Uint8Array","offset","len","set","mergeUint8Arrays","_flacBuffers","_flacLength","Blob","type","bytes","push","byteLength","encoder","onmessage","e","data","command","bps","config","postMessage","onready","setTimeout","buf"],"sourceRoot":""}