From 2bd7ebc5147041c5b8e7d389c1be7567e60fd4ac Mon Sep 17 00:00:00 2001 From: erew123 <35898566+erew123@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:24:20 +0000 Subject: [PATCH 1/2] Delete templates/TTS_Input_Proof_of_concept.html --- templates/TTS_Input_Proof_of_concept.html | 593 ---------------------- 1 file changed, 593 deletions(-) delete mode 100644 templates/TTS_Input_Proof_of_concept.html diff --git a/templates/TTS_Input_Proof_of_concept.html b/templates/TTS_Input_Proof_of_concept.html deleted file mode 100644 index d3cbed2..0000000 --- a/templates/TTS_Input_Proof_of_concept.html +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - AllTalk TTS Generator - - - - -

AllTalk TTS Generator

- -
-
- - -
- -
- -
- - -
- -
- - -
- - -
- - -
- -
- - -
- -
- - - 3 -
- -
- - - 0.8 -
-
- - -
- - - - -
- - -
- - - - - - - - \ No newline at end of file From 332582baeac474d966c67e293437c7d8e6a02268 Mon Sep 17 00:00:00 2001 From: erew123 <35898566+erew123@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:26:05 +0000 Subject: [PATCH 2/2] AllTalk TTS Generator --- templates/admin.html | 91 +- templates/favicon.ico | Bin 0 -> 1150 bytes templates/tts_chunk_player/crunker.d.ts | 179 ++ templates/tts_chunk_player/crunker.esm.js | 2 + templates/tts_chunk_player/crunker.esm.js.map | 1 + templates/tts_chunk_player/favicon.ico | Bin 0 -> 1150 bytes templates/tts_chunk_player/howler.min.js | 4 + .../tts_chunk_player/tts_chunk_player.html | 1669 +++++++++++++++++ 8 files changed, 1943 insertions(+), 3 deletions(-) create mode 100644 templates/favicon.ico create mode 100644 templates/tts_chunk_player/crunker.d.ts create mode 100644 templates/tts_chunk_player/crunker.esm.js create mode 100644 templates/tts_chunk_player/crunker.esm.js.map create mode 100644 templates/tts_chunk_player/favicon.ico create mode 100644 templates/tts_chunk_player/howler.min.js create mode 100644 templates/tts_chunk_player/tts_chunk_player.html diff --git a/templates/admin.html b/templates/admin.html index f1c7ca0..d0a0c4b 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -2,7 +2,7 @@ - + AllTalk TTS for Text generation webUI @@ -218,6 +218,7 @@
  • Getting Started
  • Server Information
  • Demo/Test TTS output
  • +
  • AllTalk TTS Generator
  • Using Voice Samples
  • Text Not inside
  • Low VRAM
  • @@ -271,6 +272,8 @@ here
    Update instructions link here
    Help and issues link + here
    TTS Generator link here

    Text generation webUI
    Web interface link here
    Documentation Back to top of page

    Demo/Test TTS

    +

    If you are wanting to generate bulk quantites of TTS and have control over them, please see the AllTalk TTS Generator below.

    @@ -416,7 +420,7 @@ let cleanedText = textInput.replace(/ \- | \– /g, ' '); // Replace hyphens cleanedText = cleanedText.replace(/%/g, " percent"); //cleanedText = cleanedText.replace(/([!?.])\1+/g, '$1'); - cleanedText = cleanedText.replace(/[^a-zA-Z0-9\s\.,;:!?\-\'"À-ÿ\u0400-\u04FF\u0150\u0151\u0170\u0171]/g, ''); + cleanedText = cleanedText.replace(/[^a-zA-Z0-9\s\.,;:!?\-\'"À-ÿ\u0400-\u04FF]/g, ''); cleanedText = cleanedText.replace(/\n+/g, ' '); cleanedText = cleanedText.replace(/\.\s'/g, ".'"); // Remove space between period and single quote //cleanedText = cleanedText.replace(/'/g, ""); // Remove all single quotes @@ -452,6 +456,87 @@

    Back to top of page

    + + +

    AllTalk TTS Generator

    +

    AllTalk TTS Generator is the solution for converting large volumes of text into + speech using the voice of your choice. Whether you're creating audio content or just want to hear text read + aloud, the TTS Generator is equipped to handle it all efficiently.

    +

    The TTS Generator is available on this link

    +

    Quick Start

    + +

    Once you have sent text off to be generated, either as a stream or wav file + generation, the TTS server will remain busy until this process has competed. As such, think carefully as to how + much you want to send to the server.

    +

    If you are generating wav files and populating the queue, you can generate one lot of + text to speech, then input your next lot of text and it will continue adding to the list.

    +

    TTS Generation Modes

    + +

    With wav chunks you can either playback “In Browser” which is the web + page you are on, or “On Server” which is through the console/terminal where AllTalk is running from. + Only generation “In Browser” can play back smoothly and populate the Generated TTS List. Setting the + Volume will affect the volume level played back both “In Browser” and “On Server”.

    +

    Playback and List Management

    + +

    Exporting Your Audio

    + +

    Customization and Preferences

    + +

    Interface and Accessibility

    + +

    Notes on Usage

    + +

    Back to top of page

    + + +

    Using Voice Samples

    Where are the sample voices stored?

    Voice samples are stored in /alltalk_tts/voices/ @@ -1431,4 +1516,4 @@ - + \ No newline at end of file diff --git a/templates/favicon.ico b/templates/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1e0d7ff908da1cda264d9216a691cf85b1cef948 GIT binary patch literal 1150 zcmbW1Sx=is6o%(BgrzJ6nwYSOC8jou0Xx`0!0Z^>Kn%oehOz`vmKbo#5=e*%!36>d zfkG08SY;`spjJewqBc@5dXZL@s!II>y>EX&@1IUU{R7qL%+dGGyze4cDLZ^KXRdbyq)uL(f>Fkb_ZK7w3DUzQPp!gmRzVvqNC;4o5E?~UY7mz*{ixNeu;(h+3<{U^ z3RPN#5~-CUxf$=vd?Zg7Du{V6jD$2R7i+pHZ>hqR7I|{6oH!NjmNRshs_3vNG?^8y zWGke-i+fgTM2C}-l8e#W&+M|7{XH+cTSKfb-(qImNsrx3X@)-?m4WnGL+GmxrlZ&& z!#Rai889XmtS88$hB#|Db zqPbjPYt*y%$NcSj27?`>pw;xlG@k}=75 ztS^jYuqB^o4_0t?hBNZ1gDm;B^(E)I(Obxx=W~8Ia`5}lqkQ*b8_#$Si{q(0oU&k+ z{1Jzqv4K9e*B4lt3Z}`bMOSv4T%&;seH_$-3Jntp-b?imFt> zaBD8k4hsttcJ9x#(OQ|#){29_{`B$Y^)^?n7S)J>BbbO0{{(j2q!&Tg~PM+;A@#~K>9QuaY@La_x&tEL- zur^EK6N|tpa~tW(WOGi literal 0 HcmV?d00001 diff --git a/templates/tts_chunk_player/crunker.d.ts b/templates/tts_chunk_player/crunker.d.ts new file mode 100644 index 0000000..2f60147 --- /dev/null +++ b/templates/tts_chunk_player/crunker.d.ts @@ -0,0 +1,179 @@ +export interface CrunkerConstructorOptions { + /** + * Sample rate for Crunker's internal audio context. + * + * @default 44100 + */ + sampleRate: number; +} +export type CrunkerInputTypes = string | File | Blob; +/** + * An exported Crunker audio object. + */ +export interface ExportedCrunkerAudio { + blob: Blob; + url: string; + element: HTMLAudioElement; +} +/** + * Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API. + */ +export default class Crunker { + private readonly _sampleRate; + private readonly _context; + /** + * Creates a new instance of Crunker with the provided options. + * + * If `sampleRate` is not defined, it will auto-select an appropriate sample rate + * for the device being used. + */ + constructor({ sampleRate }?: Partial); + /** + * Creates Crunker's internal AudioContext. + * + * @internal + */ + private _createContext; + /** + * + * The internal AudioContext used by Crunker. + */ + get context(): AudioContext; + /** + * Asynchronously fetches multiple audio files and returns an array of AudioBuffers. + */ + fetchAudio(...filepaths: CrunkerInputTypes[]): Promise; + /** + * Merges (layers) multiple AudioBuffers into a single AudioBuffer. + * + * **Visual representation:** + * + * ![](https://user-images.githubusercontent.com/12958674/88806278-968f0680-d186-11ea-9cb5-8ef2606ffcc7.png) + */ + mergeAudio(buffers: AudioBuffer[]): AudioBuffer; + /** + * Concatenates multiple AudioBuffers into a single AudioBuffer. + * + * **Visual representation:** + * + * ![](https://user-images.githubusercontent.com/12958674/88806297-9d1d7e00-d186-11ea-8cd2-c64cb0324845.png) + */ + concatAudio(buffers: AudioBuffer[]): AudioBuffer; + /** + * Pads a specified AudioBuffer with silence from a specified start time, + * for a specified length of time. + * + * Accepts float values as well as whole integers. + * + * @param buffer AudioBuffer to pad + * @param padStart Time to start padding (in seconds) + * @param seconds Duration to pad for (in seconds) + */ + padAudio(buffer: AudioBuffer, padStart?: number, seconds?: number): AudioBuffer; + /** + * Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out. + * + * @param buffer AudioBuffer to slice + * @param start Start time (in seconds) + * @param end End time (in seconds) + * @param fadeIn Fade in duration (in seconds, default is 0) + * @param fadeOut Fade out duration (in seconds, default is 0) + */ + sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn?: number, fadeOut?: number): AudioBuffer; + /** + * Plays the provided AudioBuffer in an AudioBufferSourceNode. + */ + play(buffer: AudioBuffer): AudioBufferSourceNode; + /** + * Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement. + * + * Note that changing the MIME type does not change the actual file format. The + * file format will **always** be a WAVE file due to how audio is stored in the + * browser. + * + * @param buffer Buffer to export + * @param type MIME type (default: `audio/wav`) + */ + export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio; + /** + * Downloads the provided Blob. + * + * @param blob Blob to download + * @param filename An optional file name to use for the download (default: `crunker`) + */ + download(blob: Blob, filename?: string): HTMLAnchorElement; + /** + * Executes a callback if the browser does not support the Web Audio API. + * + * Returns the result of the callback, or `undefined` if the Web Audio API is supported. + * + * @param callback callback to run if the browser does not support the Web Audio API + */ + notSupported(callback: () => T): T | undefined; + /** + * Closes Crunker's internal AudioContext. + */ + close(): this; + /** + * Returns the largest duration of the longest AudioBuffer. + * + * @internal + */ + private _maxDuration; + /** + * Returns the largest number of channels in an array of AudioBuffers. + * + * @internal + */ + private _maxNumberOfChannels; + /** + * Returns the sum of the lengths of an array of AudioBuffers. + * + * @internal + */ + private _totalLength; + /** + * Returns whether the browser supports the Web Audio API. + * + * @internal + */ + private _isSupported; + /** + * Writes the WAV headers for the specified Float32Array. + * + * Returns a DataView containing the WAV headers and file content. + * + * @internal + */ + private _writeHeaders; + /** + * Converts a Float32Array to 16-bit PCM. + * + * @internal + */ + private _floatTo16BitPCM; + /** + * Writes a string to a DataView at the specified offset. + * + * @internal + */ + private _writeString; + /** + * Converts an AudioBuffer to a Float32Array. + * + * @internal + */ + private _interleave; + /** + * Creates an HTMLAudioElement whose source is the specified Blob. + * + * @internal + */ + private _renderAudioElement; + /** + * Creates an Object URL for the specified Blob. + * + * @internal + */ + private _renderURL; +} \ No newline at end of file diff --git a/templates/tts_chunk_player/crunker.esm.js b/templates/tts_chunk_player/crunker.esm.js new file mode 100644 index 0000000..80f7f81 --- /dev/null +++ b/templates/tts_chunk_player/crunker.esm.js @@ -0,0 +1,2 @@ +var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nu});var u=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.sampleRate;o(this,e),this._context=this._createContext(n),n||(n=this._context.sampleRate),this._sampleRate=n}var t,n,a;return t=e,n=[{key:"_createContext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:44100;return window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext,new AudioContext({sampleRate:e})}},{key:"context",get:function(){return this._context}},{key:"fetchAudio",value:async function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r=0;o--)r[o]+=a[o];t.getChannelData(n).set(r)}})),t}},{key:"concatAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._totalLength(e),this._sampleRate),n=0;return e.forEach((function(e){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(0===n)return e;if(t<0)throw new Error('Crunker: Parameter "padStart" in padAudio must be positive');if(n<0)throw new Error('Crunker: Parameter "seconds" in padAudio must be positive');for(var r=this._context.createBuffer(e.numberOfChannels,Math.ceil(e.length+n*e.sampleRate),e.sampleRate),a=0;a3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(t>=n)throw new Error('Crunker: "start" time should be less than "end" time in sliceAudio method');for(var o=Math.round((n-t)*this._sampleRate),i=Math.round(t*this._sampleRate),u=this._context.createBuffer(e.numberOfChannels,o,this._sampleRate),l=0;lo-a*this._sampleRate&&(c[f]*=(o-f)/(a*this._sampleRate));return u}},{key:"play",value:function(e){var t=this._context.createBufferSource();return t.buffer=e,t.connect(this._context.destination),t.start(),t}},{key:"export",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"audio/wav",n=this._interleave(e),r=this._writeHeaders(n,e.numberOfChannels,e.sampleRate),a=new Blob([r],{type:t});return{blob:a,url:this._renderURL(a),element:this._renderAudioElement(a)}}},{key:"download",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"crunker",n=document.createElement("a");return n.style.display="none",n.href=this._renderURL(e),n.download="".concat(t,".").concat(e.type.split("/")[1]),n.click(),n}},{key:"notSupported",value:function(e){return this._isSupported()?void 0:e()}},{key:"close",value:function(){return this._context.close(),this}},{key:"_maxDuration",value:function(e){return Math.max.apply(Math,r(e.map((function(e){return e.duration}))))}},{key:"_maxNumberOfChannels",value:function(e){return Math.max.apply(Math,r(e.map((function(e){return e.numberOfChannels}))))}},{key:"_totalLength",value:function(e){return e.map((function(e){return e.length})).reduce((function(e,t){return e+t}),0)}},{key:"_isSupported",value:function(){return"AudioContext"in window||"webkitAudioContext"in window||"mozAudioContext"in window}},{key:"_writeHeaders",value:function(e,t,n){var r=2*t,a=2*e.length,o=36+a,i=new ArrayBuffer(8+o),u=new DataView(i);return this._writeString(u,0,"RIFF"),u.setUint32(4,o,!0),this._writeString(u,8,"WAVE"),this._writeString(u,12,"fmt "),u.setUint32(16,16,!0),u.setUint16(20,1,!0),u.setUint16(22,t,!0),u.setUint32(24,n,!0),u.setUint32(28,n*r,!0),u.setUint16(32,r,!0),u.setUint16(34,16,!0),this._writeString(u,36,"data"),u.setUint32(40,a,!0),this._floatTo16BitPCM(u,e,44)}},{key:"_floatTo16BitPCM",value:function(e,t,n){for(var r=0;r {\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))","export interface CrunkerConstructorOptions {\n /**\n * Sample rate for Crunker's internal audio context.\n *\n * @default 44100\n */\n sampleRate: number;\n}\n\nexport type CrunkerInputTypes = string | File | Blob;\n\n/**\n * An exported Crunker audio object.\n */\nexport interface ExportedCrunkerAudio {\n blob: Blob;\n url: string;\n element: HTMLAudioElement;\n}\n\n/**\n * Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API.\n */\nexport default class Crunker {\n private readonly _sampleRate: number;\n private readonly _context: AudioContext;\n\n /**\n * Creates a new instance of Crunker with the provided options.\n *\n * If `sampleRate` is not defined, it will auto-select an appropriate sample rate\n * for the device being used.\n */\n constructor({ sampleRate }: Partial = {}) {\n this._context = this._createContext(sampleRate);\n\n sampleRate ||= this._context.sampleRate;\n\n this._sampleRate = sampleRate;\n }\n\n /**\n * Creates Crunker's internal AudioContext.\n *\n * @internal\n */\n private _createContext(sampleRate: number = 44_100): AudioContext {\n window.AudioContext = window.AudioContext || (window as any).webkitAudioContext || (window as any).mozAudioContext;\n return new AudioContext({ sampleRate });\n }\n\n /**\n *\n * The internal AudioContext used by Crunker.\n */\n get context(): AudioContext {\n return this._context;\n }\n\n /**\n * Asynchronously fetches multiple audio files and returns an array of AudioBuffers.\n */\n async fetchAudio(...filepaths: CrunkerInputTypes[]): Promise {\n return await Promise.all(\n filepaths.map(async (filepath) => {\n let buffer: ArrayBuffer;\n\n if (filepath instanceof File || filepath instanceof Blob) {\n buffer = await filepath.arrayBuffer();\n } else {\n buffer = await fetch(filepath).then((response) => {\n if (response.headers.has('Content-Type') && !response.headers.get('Content-Type')!.includes('audio/')) {\n console.warn(\n `Crunker: Attempted to fetch an audio file, but its MIME type is \\`${\n response.headers.get('Content-Type')!.split(';')[0]\n }\\`. We'll try and continue anyway. (file: \"${filepath}\")`\n );\n }\n\n return response.arrayBuffer();\n });\n }\n\n return await this._context.decodeAudioData(buffer);\n })\n );\n }\n\n /**\n * Merges (layers) multiple AudioBuffers into a single AudioBuffer.\n *\n * **Visual representation:**\n *\n * ![](https://user-images.githubusercontent.com/12958674/88806278-968f0680-d186-11ea-9cb5-8ef2606ffcc7.png)\n */\n mergeAudio(buffers: AudioBuffer[]): AudioBuffer {\n const output = this._context.createBuffer(\n this._maxNumberOfChannels(buffers),\n this._sampleRate * this._maxDuration(buffers),\n this._sampleRate\n );\n\n buffers.forEach((buffer) => {\n for (let channelNumber = 0; channelNumber < buffer.numberOfChannels; channelNumber++) {\n const outputData = output.getChannelData(channelNumber);\n const bufferData = buffer.getChannelData(channelNumber);\n\n for (let i = buffer.getChannelData(channelNumber).length - 1; i >= 0; i--) {\n outputData[i] += bufferData[i];\n }\n\n output.getChannelData(channelNumber).set(outputData);\n }\n });\n\n return output;\n }\n\n /**\n * Concatenates multiple AudioBuffers into a single AudioBuffer.\n *\n * **Visual representation:**\n *\n * ![](https://user-images.githubusercontent.com/12958674/88806297-9d1d7e00-d186-11ea-8cd2-c64cb0324845.png)\n */\n concatAudio(buffers: AudioBuffer[]): AudioBuffer {\n const output = this._context.createBuffer(\n this._maxNumberOfChannels(buffers),\n this._totalLength(buffers),\n this._sampleRate\n );\n let offset = 0;\n\n buffers.forEach((buffer) => {\n for (let channelNumber = 0; channelNumber < buffer.numberOfChannels; channelNumber++) {\n output.getChannelData(channelNumber).set(buffer.getChannelData(channelNumber), offset);\n }\n\n offset += buffer.length;\n });\n\n return output;\n }\n\n /**\n * Pads a specified AudioBuffer with silence from a specified start time,\n * for a specified length of time.\n *\n * Accepts float values as well as whole integers.\n *\n * @param buffer AudioBuffer to pad\n * @param padStart Time to start padding (in seconds)\n * @param seconds Duration to pad for (in seconds)\n */\n padAudio(buffer: AudioBuffer, padStart: number = 0, seconds: number = 0): AudioBuffer {\n if (seconds === 0) return buffer;\n\n if (padStart < 0) throw new Error('Crunker: Parameter \"padStart\" in padAudio must be positive');\n if (seconds < 0) throw new Error('Crunker: Parameter \"seconds\" in padAudio must be positive');\n\n const updatedBuffer = this._context.createBuffer(\n buffer.numberOfChannels,\n Math.ceil(buffer.length + seconds * buffer.sampleRate),\n buffer.sampleRate\n );\n\n for (let channelNumber = 0; channelNumber < buffer.numberOfChannels; channelNumber++) {\n const channelData = buffer.getChannelData(channelNumber);\n updatedBuffer\n .getChannelData(channelNumber)\n .set(channelData.subarray(0, Math.ceil(padStart * buffer.sampleRate) + 1), 0);\n\n updatedBuffer\n .getChannelData(channelNumber)\n .set(\n channelData.subarray(Math.ceil(padStart * buffer.sampleRate) + 2, updatedBuffer.length + 1),\n Math.ceil((padStart + seconds) * buffer.sampleRate)\n );\n }\n\n return updatedBuffer;\n }\n\n /**\n * Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out.\n *\n * @param buffer AudioBuffer to slice\n * @param start Start time (in seconds)\n * @param end End time (in seconds)\n * @param fadeIn Fade in duration (in seconds, default is 0)\n * @param fadeOut Fade out duration (in seconds, default is 0)\n */\n sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn: number = 0, fadeOut: number = 0): AudioBuffer {\n if (start >= end) throw new Error('Crunker: \"start\" time should be less than \"end\" time in sliceAudio method');\n\n const length = Math.round((end - start) * this._sampleRate);\n const offset = Math.round(start * this._sampleRate);\n const newBuffer = this._context.createBuffer(buffer.numberOfChannels, length, this._sampleRate);\n\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const inputData = buffer.getChannelData(channel);\n const outputData = newBuffer.getChannelData(channel);\n\n for (let i = 0; i < length; i++) {\n outputData[i] = inputData[offset + i];\n\n // Apply fade in\n if (i < fadeIn * this._sampleRate) {\n outputData[i] *= i / (fadeIn * this._sampleRate);\n }\n\n // Apply fade out\n if (i > length - fadeOut * this._sampleRate) {\n outputData[i] *= (length - i) / (fadeOut * this._sampleRate);\n }\n }\n }\n\n return newBuffer;\n }\n\n /**\n * Plays the provided AudioBuffer in an AudioBufferSourceNode.\n */\n play(buffer: AudioBuffer): AudioBufferSourceNode {\n const source = this._context.createBufferSource();\n\n source.buffer = buffer;\n source.connect(this._context.destination);\n source.start();\n\n return source;\n }\n\n /**\n * Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement.\n *\n * Note that changing the MIME type does not change the actual file format. The\n * file format will **always** be a WAVE file due to how audio is stored in the\n * browser.\n *\n * @param buffer Buffer to export\n * @param type MIME type (default: `audio/wav`)\n */\n export(buffer: AudioBuffer, type: string = 'audio/wav'): ExportedCrunkerAudio {\n const recorded = this._interleave(buffer);\n const dataview = this._writeHeaders(recorded, buffer.numberOfChannels, buffer.sampleRate);\n const audioBlob = new Blob([dataview], { type });\n\n return {\n blob: audioBlob,\n url: this._renderURL(audioBlob),\n element: this._renderAudioElement(audioBlob),\n };\n }\n\n /**\n * Downloads the provided Blob.\n *\n * @param blob Blob to download\n * @param filename An optional file name to use for the download (default: `crunker`)\n */\n download(blob: Blob, filename: string = 'crunker'): HTMLAnchorElement {\n const a = document.createElement('a');\n\n a.style.display = 'none';\n a.href = this._renderURL(blob);\n a.download = `${filename}.${blob.type.split('/')[1]}`;\n a.click();\n\n return a;\n }\n\n /**\n * Executes a callback if the browser does not support the Web Audio API.\n *\n * Returns the result of the callback, or `undefined` if the Web Audio API is supported.\n *\n * @param callback callback to run if the browser does not support the Web Audio API\n */\n notSupported(callback: () => T): T | undefined {\n return this._isSupported() ? undefined : callback();\n }\n\n /**\n * Closes Crunker's internal AudioContext.\n */\n close(): this {\n this._context.close();\n return this;\n }\n\n /**\n * Returns the largest duration of the longest AudioBuffer.\n *\n * @internal\n */\n private _maxDuration(buffers: AudioBuffer[]): number {\n return Math.max(...buffers.map((buffer) => buffer.duration));\n }\n\n /**\n * Returns the largest number of channels in an array of AudioBuffers.\n *\n * @internal\n */\n private _maxNumberOfChannels(buffers: AudioBuffer[]): number {\n return Math.max(...buffers.map((buffer) => buffer.numberOfChannels));\n }\n\n /**\n * Returns the sum of the lengths of an array of AudioBuffers.\n *\n * @internal\n */\n private _totalLength(buffers: AudioBuffer[]): number {\n return buffers.map((buffer) => buffer.length).reduce((a, b) => a + b, 0);\n }\n\n /**\n * Returns whether the browser supports the Web Audio API.\n *\n * @internal\n */\n private _isSupported(): boolean {\n return 'AudioContext' in window || 'webkitAudioContext' in window || 'mozAudioContext' in window;\n }\n\n /**\n * Writes the WAV headers for the specified Float32Array.\n *\n * Returns a DataView containing the WAV headers and file content.\n *\n * @internal\n */\n private _writeHeaders(buffer: Float32Array, numOfChannels: number, sampleRate: number): DataView {\n const bitDepth = 16;\n const bytesPerSample = bitDepth / 8;\n const sampleSize = numOfChannels * bytesPerSample;\n\n const fileHeaderSize = 8;\n const chunkHeaderSize = 36;\n const chunkDataSize = buffer.length * bytesPerSample;\n const chunkTotalSize = chunkHeaderSize + chunkDataSize;\n\n const arrayBuffer = new ArrayBuffer(fileHeaderSize + chunkTotalSize);\n const view = new DataView(arrayBuffer);\n\n this._writeString(view, 0, 'RIFF');\n view.setUint32(4, chunkTotalSize, true);\n this._writeString(view, 8, 'WAVE');\n this._writeString(view, 12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, numOfChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, sampleRate * sampleSize, true);\n view.setUint16(32, sampleSize, true);\n view.setUint16(34, bitDepth, true);\n this._writeString(view, 36, 'data');\n view.setUint32(40, chunkDataSize, true);\n\n return this._floatTo16BitPCM(view, buffer, fileHeaderSize + chunkHeaderSize);\n }\n\n /**\n * Converts a Float32Array to 16-bit PCM.\n *\n * @internal\n */\n private _floatTo16BitPCM(dataview: DataView, buffer: Float32Array, offset: number): DataView {\n for (let i = 0; i < buffer.length; i++, offset += 2) {\n const tmp = Math.max(-1, Math.min(1, buffer[i]));\n dataview.setInt16(offset, tmp < 0 ? tmp * 0x8000 : tmp * 0x7fff, true);\n }\n\n return dataview;\n }\n\n /**\n * Writes a string to a DataView at the specified offset.\n *\n * @internal\n */\n private _writeString(dataview: DataView, offset: number, header: string): void {\n for (let i = 0; i < header.length; i++) {\n dataview.setUint8(offset + i, header.charCodeAt(i));\n }\n }\n\n /**\n * Converts an AudioBuffer to a Float32Array.\n *\n * @internal\n */\n private _interleave(input: AudioBuffer): Float32Array {\n const channels = Array.from({ length: input.numberOfChannels }, (_, i) => i);\n const length = channels.reduce((prev, channelIdx) => prev + input.getChannelData(channelIdx).length, 0);\n const result = new Float32Array(length);\n\n let index = 0;\n let inputIndex = 0;\n\n // for 2 channels its like: [L[0], R[0], L[1], R[1], ... , L[n], R[n]]\n while (index < length) {\n channels.forEach((channelIdx) => {\n result[index++] = input.getChannelData(channelIdx)[inputIndex];\n });\n\n inputIndex++;\n }\n\n return result;\n }\n\n /**\n * Creates an HTMLAudioElement whose source is the specified Blob.\n *\n * @internal\n */\n private _renderAudioElement(blob: Blob): HTMLAudioElement {\n const audio = document.createElement('audio');\n\n audio.controls = true;\n audio.src = this._renderURL(blob);\n\n return audio;\n }\n\n /**\n * Creates an Object URL for the specified Blob.\n *\n * @internal\n */\n private _renderURL(blob: Blob): string {\n return (window.URL || window.webkitURL).createObjectURL(blob);\n }\n}\n"],"names":["__webpack_require__","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Crunker","sampleRate","this","_context","_createContext","_sampleRate","window","AudioContext","webkitAudioContext","mozAudioContext","async","filepaths","Promise","all","map","filepath","buffer","File","Blob","arrayBuffer","fetch","then","response","headers","has","includes","console","warn","split","decodeAudioData","buffers","output","createBuffer","_maxNumberOfChannels","_maxDuration","forEach","channelNumber","numberOfChannels","outputData","getChannelData","bufferData","i","length","set","_totalLength","offset","padStart","seconds","Error","updatedBuffer","Math","ceil","channelData","subarray","start","end","fadeIn","fadeOut","round","newBuffer","channel","inputData","source","createBufferSource","connect","destination","type","recorded","_interleave","dataview","_writeHeaders","audioBlob","blob","url","_renderURL","element","_renderAudioElement","filename","a","document","createElement","style","display","href","download","click","callback","_isSupported","undefined","close","max","duration","reduce","b","numOfChannels","sampleSize","bitDepth","chunkDataSize","chunkTotalSize","ArrayBuffer","view","DataView","_writeString","setUint32","setUint16","_floatTo16BitPCM","fileHeaderSize","tmp","min","setInt16","header","setUint8","charCodeAt","input","channels","Array","from","_","prev","channelIdx","result","Float32Array","index","inputIndex","audio","controls","src","URL","webkitURL","createObjectURL"],"sourceRoot":""} \ No newline at end of file diff --git a/templates/tts_chunk_player/favicon.ico b/templates/tts_chunk_player/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1e0d7ff908da1cda264d9216a691cf85b1cef948 GIT binary patch literal 1150 zcmbW1Sx=is6o%(BgrzJ6nwYSOC8jou0Xx`0!0Z^>Kn%oehOz`vmKbo#5=e*%!36>d zfkG08SY;`spjJewqBc@5dXZL@s!II>y>EX&@1IUU{R7qL%+dGGyze4cDLZ^KXRdbyq)uL(f>Fkb_ZK7w3DUzQPp!gmRzVvqNC;4o5E?~UY7mz*{ixNeu;(h+3<{U^ z3RPN#5~-CUxf$=vd?Zg7Du{V6jD$2R7i+pHZ>hqR7I|{6oH!NjmNRshs_3vNG?^8y zWGke-i+fgTM2C}-l8e#W&+M|7{XH+cTSKfb-(qImNsrx3X@)-?m4WnGL+GmxrlZ&& z!#Rai889XmtS88$hB#|Db zqPbjPYt*y%$NcSj27?`>pw;xlG@k}=75 ztS^jYuqB^o4_0t?hBNZ1gDm;B^(E)I(Obxx=W~8Ia`5}lqkQ*b8_#$Si{q(0oU&k+ z{1Jzqv4K9e*B4lt3Z}`bMOSv4T%&;seH_$-3Jntp-b?imFt> zaBD8k4hsttcJ9x#(OQ|#){29_{`B$Y^)^?n7S)J>BbbO0{{(j2q!&Tg~PM+;A@#~K>9QuaY@La_x&tEL- zur^EK6N|tpa~tW(WOGi literal 0 HcmV?d00001 diff --git a/templates/tts_chunk_player/howler.min.js b/templates/tts_chunk_player/howler.min.js new file mode 100644 index 0000000..40f9a2f --- /dev/null +++ b/templates/tts_chunk_player/howler.min.js @@ -0,0 +1,4 @@ +/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */ +!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length0?d._seek:t._sprite[e][0]/1e3),s=Math.max(0,(t._sprite[e][0]+t._sprite[e][1])/1e3-_),l=1e3*s/Math.abs(d._rate),c=t._sprite[e][0]/1e3,f=(t._sprite[e][0]+t._sprite[e][1])/1e3;d._sprite=e,d._ended=!1;var p=function(){d._paused=!1,d._seek=_,d._start=c,d._stop=f,d._loop=!(!d._loop&&!t._sprite[e][2])};if(_>=f)return void t._ended(d);var m=d._node;if(t._webAudio){var v=function(){t._playLock=!1,p(),t._refreshBuffer(d);var e=d._muted||t._muted?0:d._volume;m.gain.setValueAtTime(e,n.ctx.currentTime),d._playStart=n.ctx.currentTime,void 0===m.bufferSource.start?d._loop?m.bufferSource.noteGrainOn(0,_,86400):m.bufferSource.noteGrainOn(0,_,s):d._loop?m.bufferSource.start(0,_,86400):m.bufferSource.start(0,_,s),l!==1/0&&(t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l)),o||setTimeout(function(){t._emit("play",d._id),t._loadQueue()},0)};"running"===n.state&&"interrupted"!==n.ctx.state?v():(t._playLock=!0,t.once("resume",v),t._clearTimer(d._id))}else{var h=function(){m.currentTime=_,m.muted=d._muted||t._muted||n._muted||m.muted,m.volume=d._volume*n.volume(),m.playbackRate=d._rate;try{var r=m.play();if(r&&"undefined"!=typeof Promise&&(r instanceof Promise||"function"==typeof r.then)?(t._playLock=!0,p(),r.then(function(){t._playLock=!1,m._unlocked=!0,o?t._loadQueue():t._emit("play",d._id)}).catch(function(){t._playLock=!1,t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction."),d._ended=!0,d._paused=!0})):o||(t._playLock=!1,p(),t._emit("play",d._id)),m.playbackRate=d._rate,m.paused)return void t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.");"__default"!==e||d._loop?t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l):(t._endTimers[d._id]=function(){t._ended(d),m.removeEventListener("ended",t._endTimers[d._id],!1)},m.addEventListener("ended",t._endTimers[d._id],!1))}catch(e){t._emit("playerror",d._id,e)}};"data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA"===m.src&&(m.src=t._src,m.load());var y=window&&window.ejecta||!m.readyState&&n._navigator.isCocoonJS;if(m.readyState>=3||y)h();else{t._playLock=!0,t._state="loading";var g=function(){t._state="loaded",h(),m.removeEventListener(n._canPlayEvent,g,!1)};m.addEventListener(n._canPlayEvent,g,!1),t._clearTimer(d._id)}}return d._id},pause:function(e){var n=this;if("loaded"!==n._state||n._playLock)return n._queue.push({event:"pause",action:function(){n.pause(e)}}),n;for(var o=n._getSoundIds(e),t=0;t=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else r.length>=2&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var a;if(!(void 0!==e&&e>=0&&e<=1))return a=o?t._soundById(o):t._sounds[0],a?a._volume:0;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"volume",action:function(){t.volume.apply(t,r)}}),t;void 0===o&&(t._volume=e),o=t._getSoundIds(o);for(var u=0;u0?t/_:t),l=Date.now();e._fadeTo=o,e._interval=setInterval(function(){var r=(Date.now()-l)/t;l=Date.now(),d+=i*r,d=Math.round(100*d)/100,d=i<0?Math.max(o,d):Math.min(o,d),u._webAudio?e._volume=d:u.volume(d,e._id,!0),a&&(u._volume=d),(on&&d>=o)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,u.volume(o,e._id),u._emit("fade",e._id))},s)},_stopFade:function(e){var o=this,t=o._soundById(e);return t&&t._interval&&(o._webAudio&&t._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(t._interval),t._interval=null,o.volume(t._fadeTo,e),t._fadeTo=null,o._emit("fade",e)),o},loop:function(){var e,n,o,t=this,r=arguments;if(0===r.length)return t._loop;if(1===r.length){if("boolean"!=typeof r[0])return!!(o=t._soundById(parseInt(r[0],10)))&&o._loop;e=r[0],t._loop=e}else 2===r.length&&(e=r[0],n=parseInt(r[1],10));for(var a=t._getSoundIds(n),u=0;u=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var d;if("number"!=typeof e)return d=t._soundById(o),d?d._rate:t._rate;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"rate",action:function(){t.rate.apply(t,r)}}),t;void 0===o&&(t._rate=e),o=t._getSoundIds(o);for(var i=0;i=0?o=parseInt(r[0],10):t._sounds.length&&(o=t._sounds[0]._id,e=parseFloat(r[0]))}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));if(void 0===o)return 0;if("number"==typeof e&&("loaded"!==t._state||t._playLock))return t._queue.push({event:"seek",action:function(){t.seek.apply(t,r)}}),t;var d=t._soundById(o);if(d){if(!("number"==typeof e&&e>=0)){if(t._webAudio){var i=t.playing(o)?n.ctx.currentTime-d._playStart:0,_=d._rateSeek?d._rateSeek-d._seek:0;return d._seek+(_+i*Math.abs(d._rate))}return d._node.currentTime}var s=t.playing(o);s&&t.pause(o,!0),d._seek=e,d._ended=!1,t._clearTimer(o),t._webAudio||!d._node||isNaN(d._node.duration)||(d._node.currentTime=e);var l=function(){s&&t.play(o,!0),t._emit("seek",o)};if(s&&!t._webAudio){var c=function(){t._playLock?setTimeout(c,0):l()};setTimeout(c,0)}else l()}return t},playing:function(e){var n=this;if("number"==typeof e){var o=n._soundById(e);return!!o&&!o._paused}for(var t=0;t=0&&n._howls.splice(a,1);var u=!0;for(t=0;t=0){u=!1;break}return r&&u&&delete r[e._src],n.noAudio=!1,e._state="unloaded",e._sounds=[],e=null,null},on:function(e,n,o,t){var r=this,a=r["_on"+e];return"function"==typeof n&&a.push(t?{id:o,fn:n,once:t}:{id:o,fn:n}),r},off:function(e,n,o){var t=this,r=t["_on"+e],a=0;if("number"==typeof n&&(o=n,n=null),n||o)for(a=0;a=0;a--)r[a].id&&r[a].id!==n&&"load"!==e||(setTimeout(function(e){e.call(this,n,o)}.bind(t,r[a].fn),0),r[a].once&&t.off(e,r[a].fn,r[a].id));return t._loadQueue(e),t},_loadQueue:function(e){var n=this;if(n._queue.length>0){var o=n._queue[0];o.event===e&&(n._queue.shift(),n._loadQueue()),e||o.action()}return n},_ended:function(e){var o=this,t=e._sprite;if(!o._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;t--){if(o<=n)return;e._sounds[t]._ended&&(e._webAudio&&e._sounds[t]._node&&e._sounds[t]._node.disconnect(0),e._sounds.splice(t,1),o--)}}},_getSoundIds:function(e){var n=this;if(void 0===e){for(var o=[],t=0;t=0;if(!e.bufferSource)return o;if(n._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),t))try{e.bufferSource.buffer=n._scratchBuffer}catch(e){}return e.bufferSource=null,o},_clearSound:function(e){/MSIE |Trident\//.test(n._navigator&&n._navigator.userAgent)||(e.src="data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA")}};var t=function(e){this._parent=e,this.init()};t.prototype={init:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,o._sounds.push(e),e.create(),e},create:function(){var e=this,o=e._parent,t=n._muted||e._muted||e._parent._muted?0:e._volume;return o._webAudio?(e._node=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(t,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):n.noAudio||(e._node=n._obtainHtml5Audio(),e._errorFn=e._errorListener.bind(e),e._node.addEventListener("error",e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._endFn=e._endListener.bind(e),e._node.addEventListener("ended",e._endFn,!1),e._node.src=o._src,e._node.preload=!0===o._preload?"auto":o._preload,e._node.volume=t*n.volume(),e._node.load()),e},reset:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit("loaderror",e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener("error",e._errorFn,!1)},_loadListener:function(){var e=this,o=e._parent;o._duration=Math.ceil(10*e._node.duration)/10,0===Object.keys(o._sprite).length&&(o._sprite={__default:[0,1e3*o._duration]}),"loaded"!==o._state&&(o._state="loaded",o._emit("load"),o._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)},_endListener:function(){var e=this,n=e._parent;n._duration===1/0&&(n._duration=Math.ceil(10*e._node.duration)/10,n._sprite.__default[1]===1/0&&(n._sprite.__default[1]=1e3*n._duration),n._ended(e)),e._node.removeEventListener("ended",e._endFn,!1)}};var r={},a=function(e){var n=e._src;if(r[n])return e._duration=r[n].duration,void i(e);if(/^data:[^;]+;base64,/.test(n)){for(var o=atob(n.split(",")[1]),t=new Uint8Array(o.length),a=0;a0?(r[o._src]=e,i(o,e)):t()};"undefined"!=typeof Promise&&1===n.ctx.decodeAudioData.length?n.ctx.decodeAudioData(e).then(a).catch(t):n.ctx.decodeAudioData(e,a,t)},i=function(e,n){n&&!e._duration&&(e._duration=n.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue())},_=function(){if(n.usingWebAudio){try{"undefined"!=typeof AudioContext?n.ctx=new AudioContext:"undefined"!=typeof webkitAudioContext?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch(e){n.usingWebAudio=!1}n.ctx||(n.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),o=n._navigator&&n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),t=o?parseInt(o[1],10):null;if(e&&t&&t<9){var r=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());n._navigator&&!r&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.setValueAtTime(n._muted?0:n._volume,n.ctx.currentTime),n.masterGain.connect(n.ctx.destination)),n._setup()}};"function"==typeof define&&define.amd&&define([],function(){return{Howler:n,Howl:o}}),"undefined"!=typeof exports&&(exports.Howler=n,exports.Howl=o),"undefined"!=typeof global?(global.HowlerGlobal=e,global.Howler=n,global.Howl=o,global.Sound=t):"undefined"!=typeof window&&(window.HowlerGlobal=e,window.Howler=n,window.Howl=o,window.Sound=t)}(); +/*! Spatial Plugin */ +!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return n="number"!=typeof n?p[1]:n,t="number"!=typeof t?p[2]:t,r="number"!=typeof r?p[3]:r,o="number"!=typeof o?p[4]:o,i="number"!=typeof i?p[5]:i,"number"!=typeof e?p:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(o,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(i,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a + + + + + + + AllTalk TTS Generator + + + + + + + +

    AllTalk TTS Generator

    + +
    +
    + + +
    + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + + +
    + +
    + + 2 +
    +
    + +
    + +
    + + 0.8 +
    +
    +
    + +
    + + + + + + + + +

    Word Count: 0

    +

             Idle

    +
    + + + +
    + +
    +

    Generated TTS List

    + + + + + + + +
    + +
    +
    +
    + + + + + + + + + + \ No newline at end of file