Hindi Support

This commit is contained in:
erew123 authored and GitHub committed 2024-04-18 18:43:25 +01:00
1 parent f18eb9a4a0
commit c3895b602c
6 files changed
+185 -180

No files matched your search

+2
View File
@@ -304,6 +304,7 @@
<option value="nl">Dutch</option> <option value="nl">Dutch</option>
<option value="fr">French</option> <option value="fr">French</option>
<option value="de">German</option> <option value="de">German</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option> <option value="hu">Hungarian</option>
<option value="it">Italian</option> <option value="it">Italian</option>
<option value="ja">Japanese</option> <option value="ja">Japanese</option>
@@ -2500,6 +2501,7 @@
<code>en</code> English<br> <code>en</code> English<br>
<code>fr</code> French<br> <code>fr</code> French<br>
<code>de</code> German<br> <code>de</code> German<br>
<code>hi</code> Hindi<br>
<code>hu</code> Hungarian<br> <code>hu</code> Hungarian<br>
<code>it</code> Italian<br> <code>it</code> Italian<br>
<code>ja</code> Japanese<br> <code>ja</code> Japanese<br>
+1
View File
@@ -124,6 +124,7 @@
<option value="English" {% if data.language=='English' %}selected{% endif %}>English</option> <option value="English" {% if data.language=='English' %}selected{% endif %}>English</option>
<option value="French" {% if data.language=='French' %}selected{% endif %}>French</option> <option value="French" {% if data.language=='French' %}selected{% endif %}>French</option>
<option value="German" {% if data.language=='German' %}selected{% endif %}>German</option> <option value="German" {% if data.language=='German' %}selected{% endif %}>German</option>
<option value="Hindi" {% if data.language=='Hindi' %}selected{% endif %}>Hindi</option>
<option value="Hungarian" {% if data.language=='Hungarian' %}selected{% endif %}>Hungarian</option> <option value="Hungarian" {% if data.language=='Hungarian' %}selected{% endif %}>Hungarian</option>
<option value="Italian" {% if data.language=='Italian' %}selected{% endif %}>Italian</option> <option value="Italian" {% if data.language=='Italian' %}selected{% endif %}>Italian</option>
<option value="Japanese" {% if data.language=='Japanese' %}selected{% endif %}>Japanese</option> <option value="Japanese" {% if data.language=='Japanese' %}selected{% endif %}>Japanese</option>
+1
View File
@@ -6,6 +6,7 @@
"English": "en", "English": "en",
"French": "fr", "French": "fr",
"German": "de", "German": "de",
"Hindi": "hi",
"Hungarian": "hu", "Hungarian": "hu",
"Italian": "it", "Italian": "it",
"Japanese": "ja", "Japanese": "ja",
+179 -179
View File
@@ -1,179 +1,179 @@
export interface CrunkerConstructorOptions { export interface CrunkerConstructorOptions {
/** /**
* Sample rate for Crunker's internal audio context. * Sample rate for Crunker's internal audio context.
* *
* @default 44100 * @default 44100
*/ */
sampleRate: number; sampleRate: number;
} }
export type CrunkerInputTypes = string | File | Blob; export type CrunkerInputTypes = string | File | Blob;
/** /**
* An exported Crunker audio object. * An exported Crunker audio object.
*/ */
export interface ExportedCrunkerAudio { export interface ExportedCrunkerAudio {
blob: Blob; blob: Blob;
url: string; url: string;
element: HTMLAudioElement; element: HTMLAudioElement;
} }
/** /**
* Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API. * Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API.
*/ */
export default class Crunker { export default class Crunker {
private readonly _sampleRate; private readonly _sampleRate;
private readonly _context; private readonly _context;
/** /**
* Creates a new instance of Crunker with the provided options. * Creates a new instance of Crunker with the provided options.
* *
* If `sampleRate` is not defined, it will auto-select an appropriate sample rate * If `sampleRate` is not defined, it will auto-select an appropriate sample rate
* for the device being used. * for the device being used.
*/ */
constructor({ sampleRate }?: Partial<CrunkerConstructorOptions>); constructor({ sampleRate }?: Partial<CrunkerConstructorOptions>);
/** /**
* Creates Crunker's internal AudioContext. * Creates Crunker's internal AudioContext.
* *
* @internal * @internal
*/ */
private _createContext; private _createContext;
/** /**
* *
* The internal AudioContext used by Crunker. * The internal AudioContext used by Crunker.
*/ */
get context(): AudioContext; get context(): AudioContext;
/** /**
* Asynchronously fetches multiple audio files and returns an array of AudioBuffers. * Asynchronously fetches multiple audio files and returns an array of AudioBuffers.
*/ */
fetchAudio(...filepaths: CrunkerInputTypes[]): Promise<AudioBuffer[]>; fetchAudio(...filepaths: CrunkerInputTypes[]): Promise<AudioBuffer[]>;
/** /**
* Merges (layers) multiple AudioBuffers into a single AudioBuffer. * Merges (layers) multiple AudioBuffers into a single AudioBuffer.
* *
* **Visual representation:** * **Visual representation:**
* *
* ![](https://user-images.githubusercontent.com/12958674/88806278-968f0680-d186-11ea-9cb5-8ef2606ffcc7.png) * ![](https://user-images.githubusercontent.com/12958674/88806278-968f0680-d186-11ea-9cb5-8ef2606ffcc7.png)
*/ */
mergeAudio(buffers: AudioBuffer[]): AudioBuffer; mergeAudio(buffers: AudioBuffer[]): AudioBuffer;
/** /**
* Concatenates multiple AudioBuffers into a single AudioBuffer. * Concatenates multiple AudioBuffers into a single AudioBuffer.
* *
* **Visual representation:** * **Visual representation:**
* *
* ![](https://user-images.githubusercontent.com/12958674/88806297-9d1d7e00-d186-11ea-8cd2-c64cb0324845.png) * ![](https://user-images.githubusercontent.com/12958674/88806297-9d1d7e00-d186-11ea-8cd2-c64cb0324845.png)
*/ */
concatAudio(buffers: AudioBuffer[]): AudioBuffer; concatAudio(buffers: AudioBuffer[]): AudioBuffer;
/** /**
* Pads a specified AudioBuffer with silence from a specified start time, * Pads a specified AudioBuffer with silence from a specified start time,
* for a specified length of time. * for a specified length of time.
* *
* Accepts float values as well as whole integers. * Accepts float values as well as whole integers.
* *
* @param buffer AudioBuffer to pad * @param buffer AudioBuffer to pad
* @param padStart Time to start padding (in seconds) * @param padStart Time to start padding (in seconds)
* @param seconds Duration to pad for (in seconds) * @param seconds Duration to pad for (in seconds)
*/ */
padAudio(buffer: AudioBuffer, padStart?: number, seconds?: number): AudioBuffer; 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. * Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out.
* *
* @param buffer AudioBuffer to slice * @param buffer AudioBuffer to slice
* @param start Start time (in seconds) * @param start Start time (in seconds)
* @param end End time (in seconds) * @param end End time (in seconds)
* @param fadeIn Fade in duration (in seconds, default is 0) * @param fadeIn Fade in duration (in seconds, default is 0)
* @param fadeOut Fade out 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; sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn?: number, fadeOut?: number): AudioBuffer;
/** /**
* Plays the provided AudioBuffer in an AudioBufferSourceNode. * Plays the provided AudioBuffer in an AudioBufferSourceNode.
*/ */
play(buffer: AudioBuffer): AudioBufferSourceNode; play(buffer: AudioBuffer): AudioBufferSourceNode;
/** /**
* Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement. * 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 * 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 * file format will **always** be a WAVE file due to how audio is stored in the
* browser. * browser.
* *
* @param buffer Buffer to export * @param buffer Buffer to export
* @param type MIME type (default: `audio/wav`) * @param type MIME type (default: `audio/wav`)
*/ */
export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio; export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio;
/** /**
* Downloads the provided Blob. * Downloads the provided Blob.
* *
* @param blob Blob to download * @param blob Blob to download
* @param filename An optional file name to use for the download (default: `crunker`) * @param filename An optional file name to use for the download (default: `crunker`)
*/ */
download(blob: Blob, filename?: string): HTMLAnchorElement; download(blob: Blob, filename?: string): HTMLAnchorElement;
/** /**
* Executes a callback if the browser does not support the Web Audio API. * 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. * 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 * @param callback callback to run if the browser does not support the Web Audio API
*/ */
notSupported<T>(callback: () => T): T | undefined; notSupported<T>(callback: () => T): T | undefined;
/** /**
* Closes Crunker's internal AudioContext. * Closes Crunker's internal AudioContext.
*/ */
close(): this; close(): this;
/** /**
* Returns the largest duration of the longest AudioBuffer. * Returns the largest duration of the longest AudioBuffer.
* *
* @internal * @internal
*/ */
private _maxDuration; private _maxDuration;
/** /**
* Returns the largest number of channels in an array of AudioBuffers. * Returns the largest number of channels in an array of AudioBuffers.
* *
* @internal * @internal
*/ */
private _maxNumberOfChannels; private _maxNumberOfChannels;
/** /**
* Returns the sum of the lengths of an array of AudioBuffers. * Returns the sum of the lengths of an array of AudioBuffers.
* *
* @internal * @internal
*/ */
private _totalLength; private _totalLength;
/** /**
* Returns whether the browser supports the Web Audio API. * Returns whether the browser supports the Web Audio API.
* *
* @internal * @internal
*/ */
private _isSupported; private _isSupported;
/** /**
* Writes the WAV headers for the specified Float32Array. * Writes the WAV headers for the specified Float32Array.
* *
* Returns a DataView containing the WAV headers and file content. * Returns a DataView containing the WAV headers and file content.
* *
* @internal * @internal
*/ */
private _writeHeaders; private _writeHeaders;
/** /**
* Converts a Float32Array to 16-bit PCM. * Converts a Float32Array to 16-bit PCM.
* *
* @internal * @internal
*/ */
private _floatTo16BitPCM; private _floatTo16BitPCM;
/** /**
* Writes a string to a DataView at the specified offset. * Writes a string to a DataView at the specified offset.
* *
* @internal * @internal
*/ */
private _writeString; private _writeString;
/** /**
* Converts an AudioBuffer to a Float32Array. * Converts an AudioBuffer to a Float32Array.
* *
* @internal * @internal
*/ */
private _interleave; private _interleave;
/** /**
* Creates an HTMLAudioElement whose source is the specified Blob. * Creates an HTMLAudioElement whose source is the specified Blob.
* *
* @internal * @internal
*/ */
private _renderAudioElement; private _renderAudioElement;
/** /**
* Creates an Object URL for the specified Blob. * Creates an Object URL for the specified Blob.
* *
* @internal * @internal
*/ */
private _renderURL; private _renderURL;
} }
+1 -1
View File
@@ -1,2 +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);n<t;n++)r[n]=e[n];return r}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(o=a.key,i=void 0,i=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(o,"string"),"symbol"===n(i)?i:String(i)),a)}var o,i}e.d(t,{Z:()=>u});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<t;r++)n[r]=arguments[r];return await Promise.all(n.map((async function(t){var n;return n=t instanceof File||t instanceof Blob?await t.arrayBuffer():await fetch(t).then((function(e){return e.headers.has("Content-Type")&&!e.headers.get("Content-Type").includes("audio/")&&console.warn("Crunker: Attempted to fetch an audio file, but its MIME type is `".concat(e.headers.get("Content-Type").split(";")[0],"`. We'll try and continue anyway. (file: \"").concat(t,'")')),e.arrayBuffer()})),await e._context.decodeAudioData(n)})))}},{key:"mergeAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._sampleRate*this._maxDuration(e),this._sampleRate);return e.forEach((function(e){for(var n=0;n<e.numberOfChannels;n++){for(var r=t.getChannelData(n),a=e.getChannelData(n),o=e.getChannelData(n).length-1;o>=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;r<e.numberOfChannels;r++)t.getChannelData(r).set(e.getChannelData(r),n);n+=e.length})),t}},{key:"padAudio",value:function(e){var t=arguments.length>1&&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;a<e.numberOfChannels;a++){var o=e.getChannelData(a);r.getChannelData(a).set(o.subarray(0,Math.ceil(t*e.sampleRate)+1),0),r.getChannelData(a).set(o.subarray(Math.ceil(t*e.sampleRate)+2,r.length+1),Math.ceil((t+n)*e.sampleRate))}return r}},{key:"sliceAudio",value:function(e,t,n){var r=arguments.length>3&&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;l<e.numberOfChannels;l++)for(var s=e.getChannelData(l),c=u.getChannelData(l),f=0;f<o;f++)c[f]=s[i+f],f<r*this._sampleRate&&(c[f]*=f/(r*this._sampleRate)),f>o-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(),Line truncated 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);n<t;n++)r[n]=e[n];return r}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(o=a.key,i=void 0,i=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(o,"string"),"symbol"===n(i)?i:String(i)),a)}var o,i}e.d(t,{Z:()=>u});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<t;r++)n[r]=arguments[r];return await Promise.all(n.map((async function(t){var n;return n=t instanceof File||t instanceof Blob?await t.arrayBuffer():await fetch(t).then((function(e){return e.headers.has("Content-Type")&&!e.headers.get("Content-Type").includes("audio/")&&console.warn("Crunker: Attempted to fetch an audio file, but its MIME type is `".concat(e.headers.get("Content-Type").split(";")[0],"`. We'll try and continue anyway. (file: \"").concat(t,'")')),e.arrayBuffer()})),await e._context.decodeAudioData(n)})))}},{key:"mergeAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._sampleRate*this._maxDuration(e),this._sampleRate);return e.forEach((function(e){for(var n=0;n<e.numberOfChannels;n++){for(var r=t.getChannelData(n),a=e.getChannelData(n),o=e.getChannelData(n).length-1;o>=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;r<e.numberOfChannels;r++)t.getChannelData(r).set(e.getChannelData(r),n);n+=e.length})),t}},{key:"padAudio",value:function(e){var t=arguments.length>1&&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;a<e.numberOfChannels;a++){var o=e.getChannelData(a);r.getChannelData(a).set(o.subarray(0,Math.ceil(t*e.sampleRate)+1),0),r.getChannelData(a).set(o.subarray(Math.ceil(t*e.sampleRate)+2,r.length+1),Math.ceil((t+n)*e.sampleRate))}return r}},{key:"sliceAudio",value:function(e,t,n){var r=arguments.length>3&&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;l<e.numberOfChannels;l++)for(var s=e.getChannelData(l),c=u.getChannelData(l),f=0;f<o;f++)c[f]=s[i+f],f<r*this._sampleRate&&(c[f]*=f/(r*this._sampleRate)),f>o-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(),Line truncated
//# sourceMappingURL=crunker.esm.js.map //# sourceMappingURL=crunker.esm.js.map
+1
View File
@@ -532,6 +532,7 @@
<option value="en" selected>English</option> <option value="en" selected>English</option>
<option value="fr">French</option> <option value="fr">French</option>
<option value="de">German</option> <option value="de">German</option>
<option value="hi">Hindi</option>
<option value="hu">Hungarian</option> <option value="hu">Hungarian</option>
<option value="it">Italian</option> <option value="it">Italian</option>
<option value="ja">Japanese</option> <option value="ja">Japanese</option>