From 7de3255a45e0dedcd74dff0a67f3d06a31025349 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Fri, 22 Dec 2023 03:47:38 +0000 Subject: [PATCH 1/3] fix: batch network requests in `fetchAudio` --- src/crunker.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/crunker.ts b/src/crunker.ts index 64c3725..8f990ce 100644 --- a/src/crunker.ts +++ b/src/crunker.ts @@ -58,9 +58,25 @@ export default class Crunker { } /** - * Asynchronously fetches multiple audio files and returns an array of AudioBuffers. + * Asynchronously fetches multiple audio files and returns an array of AudioBuffers, + * splitting into groups of 200 files to avoid resource exhaustion. */ async fetchAudio(...filepaths: CrunkerInputTypes[]): Promise { + const buffers: AudioBuffer[] = []; + const groups = Math.ceil(filepaths.length / 200); + + for (let i = 0; i < groups; i++) { + const group = filepaths.slice(i * 200, (i + 1) * 200); + buffers.push(...(await this._fetchAudio(...group))); + } + + return buffers; + } + + /** + * Asynchronously fetches multiple audio files and returns an array of AudioBuffers. + */ + private async _fetchAudio(...filepaths: CrunkerInputTypes[]): Promise { return await Promise.all( filepaths.map(async (filepath) => { let buffer: ArrayBuffer; From 11b2423975a0c7771e6f6d346b9ef98d75e179b2 Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 20 Jan 2024 10:45:13 +0000 Subject: [PATCH 2/3] Update crunker.ts --- src/crunker.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/crunker.ts b/src/crunker.ts index 8f990ce..8670591 100644 --- a/src/crunker.ts +++ b/src/crunker.ts @@ -5,6 +5,14 @@ export interface CrunkerConstructorOptions { * @default 44100 */ sampleRate: number; + /** + * Maximum number of concurrent network requests to use while fetching audio. Requests will be batched into groups of this size. + * + * Anything much higher than the default can cause issues in web browsers. You may wish to lower it for low-performance devices. + * + * @default 200 + */ + concurrentNetworkRequests: number; } export type CrunkerInputTypes = string | File | Blob; @@ -23,6 +31,7 @@ export interface ExportedCrunkerAudio { */ export default class Crunker { private readonly _sampleRate: number; + private readonly _concurrentNetworkRequests: number; private readonly _context: AudioContext; /** @@ -31,12 +40,13 @@ export default class Crunker { * If `sampleRate` is not defined, it will auto-select an appropriate sample rate * for the device being used. */ - constructor({ sampleRate }: Partial = {}) { + constructor({ sampleRate, concurrentNetworkRequests }: Partial = {}) { this._context = this._createContext(sampleRate); sampleRate ||= this._context.sampleRate; this._sampleRate = sampleRate; + this._concurrentNetworkRequests = concurrentNetworkRequests; } /** @@ -58,15 +68,16 @@ export default class Crunker { } /** - * Asynchronously fetches multiple audio files and returns an array of AudioBuffers, - * splitting into groups of 200 files to avoid resource exhaustion. + * Asynchronously fetches multiple audio files and returns an array of AudioBuffers. + * + * Network requests are batched, and the size of these batches can be configured with the `concurrentNetworkRequests` option in the Crunker constructor. */ async fetchAudio(...filepaths: CrunkerInputTypes[]): Promise { const buffers: AudioBuffer[] = []; - const groups = Math.ceil(filepaths.length / 200); + const groups = Math.ceil(filepaths.length / this._concurrentNetworkRequests); for (let i = 0; i < groups; i++) { - const group = filepaths.slice(i * 200, (i + 1) * 200); + const group = filepaths.slice(i * this._concurrentNetworkRequests, (i + 1) * this._concurrentNetworkRequests); buffers.push(...(await this._fetchAudio(...group))); } From 259170e7b8b75bc304d2a4ad99f623c730d835ce Mon Sep 17 00:00:00 2001 From: David Wheatley Date: Sat, 20 Jan 2024 12:03:47 +0000 Subject: [PATCH 3/3] fix: default value --- src/crunker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crunker.ts b/src/crunker.ts index 8670591..8c56307 100644 --- a/src/crunker.ts +++ b/src/crunker.ts @@ -40,7 +40,7 @@ export default class Crunker { * If `sampleRate` is not defined, it will auto-select an appropriate sample rate * for the device being used. */ - constructor({ sampleRate, concurrentNetworkRequests }: Partial = {}) { + constructor({ sampleRate, concurrentNetworkRequests = 200 }: Partial = {}) { this._context = this._createContext(sampleRate); sampleRate ||= this._context.sampleRate;