Tone.js/Tone/core/context/ToneAudioBuffers.ts

159 lines
4 KiB
TypeScript
Raw Normal View History

2019-07-22 16:29:50 +00:00
import { Tone } from "../Tone";
import { optionsFromArguments } from "../util/Defaults";
import { noOp } from "../util/Interface";
import { isString } from "../util/TypeCheck";
import { ToneAudioBuffer } from "./ToneAudioBuffer";
export interface ToneAudioBuffersUrlMap {
[name: string]: string | AudioBuffer | ToneAudioBuffer;
[name: number]: string | AudioBuffer | ToneAudioBuffer;
2019-07-22 16:29:50 +00:00
}
interface ToneAudioBuffersOptions {
urls: ToneAudioBuffersUrlMap;
onload: () => void;
onerror?: (error: Error) => void;
baseUrl: string;
}
/**
* A data structure for holding multiple buffers in a Map-like datastructure.
*
* @example
* //load a whole bank of piano samples
* var pianoSamples = new ToneAudioBuffers({
2019-09-16 15:09:44 +00:00
* "C4" : "path/to/C4.mp3"
* "C#4" : "path/to/C#4.mp3"
* "D4" : "path/to/D4.mp3"
* "D#4" : "path/to/D#4.mp3"
2019-07-22 16:29:50 +00:00
* }, function(){
2019-09-16 15:09:44 +00:00
* //play one of the samples when they all load
* player.buffer = pianoSamples.get("C4");
* player.start();
2019-07-22 16:29:50 +00:00
* });
* @example
* //To pass in additional parameters in the second parameter
* var buffers = new ToneAudioBuffers(urls, {
2019-09-16 15:09:44 +00:00
* "onload" : callback,
* "baseUrl" : "../path/to/audio/"
2019-07-22 16:29:50 +00:00
* })
2019-08-21 20:01:12 +00:00
* @category Core
2019-07-22 16:29:50 +00:00
*/
export class ToneAudioBuffers extends Tone {
2019-09-04 23:18:44 +00:00
readonly name: string = "ToneAudioBuffers";
2019-07-22 16:29:50 +00:00
/**
2019-09-14 20:39:18 +00:00
* All of the buffers
2019-07-22 16:29:50 +00:00
*/
private _buffers: Map<string, ToneAudioBuffer> = new Map();
/**
2019-09-14 20:39:18 +00:00
* A path which is prefixed before every url.
2019-07-22 16:29:50 +00:00
*/
baseUrl: string;
/**
* Keep track of the number of loaded buffers
*/
private _loadingCount: number = 0;
2019-08-27 17:02:31 +00:00
/**
* @param urls An object literal or array of urls to load.
* @param onload The callback to invoke when the buffers are loaded.
* @param baseUrl A prefix url to add before all the urls
*/
2019-07-22 16:29:50 +00:00
constructor(
urls?: ToneAudioBuffersUrlMap,
onload?: () => void,
baseUrl?: string,
);
2019-07-22 16:29:50 +00:00
constructor(options?: Partial<ToneAudioBuffersOptions>);
constructor() {
super();
const options = optionsFromArguments(
ToneAudioBuffers.getDefaults(), arguments, ["urls", "onload", "baseUrl"], "urls",
);
2019-07-22 16:29:50 +00:00
this.baseUrl = options.baseUrl;
// add each one
Object.keys(options.urls).forEach(name => {
2019-07-22 16:29:50 +00:00
this._loadingCount++;
const url = options.urls[name];
this.add(name, url, this._bufferLoaded.bind(this, options.onload));
2019-07-22 16:29:50 +00:00
});
}
static getDefaults(): ToneAudioBuffersOptions {
return {
baseUrl: "",
onerror: noOp,
onload: noOp,
urls: {},
};
}
/**
2019-09-14 20:39:18 +00:00
* True if the buffers object has a buffer by that name.
* @param name The key or index of the buffer.
2019-07-22 16:29:50 +00:00
*/
has(name: string | number): boolean {
return this._buffers.has(name.toString());
2019-07-22 16:29:50 +00:00
}
/**
2019-09-14 20:39:18 +00:00
* Get a buffer by name. If an array was loaded,
* then use the array index.
* @param name The key or index of the buffer.
2019-07-22 16:29:50 +00:00
*/
get(name: string | number): ToneAudioBuffer {
2019-07-22 16:29:50 +00:00
this.assert(this.has(name), `ToneAudioBuffers has no buffer named: ${name}`);
return this._buffers.get(name.toString()) as ToneAudioBuffer;
2019-07-22 16:29:50 +00:00
}
/**
2019-09-14 20:39:18 +00:00
* A buffer was loaded. decrement the counter.
2019-07-22 16:29:50 +00:00
*/
private _bufferLoaded(callback: () => void): void {
this._loadingCount--;
if (this._loadingCount === 0 && callback) {
callback();
}
}
/**
* If the buffers are loaded or not
*/
get loaded(): boolean {
2019-09-10 04:06:52 +00:00
return Array.from(this._buffers).every(([_, buffer]) => buffer.loaded);
2019-07-22 16:29:50 +00:00
}
/**
2019-09-14 20:39:18 +00:00
* Add a buffer by name and url to the Buffers
* @param name A unique name to give the buffer
* @param url Either the url of the bufer, or a buffer which will be added with the given name.
* @param callback The callback to invoke when the url is loaded.
2019-07-22 16:29:50 +00:00
*/
add(
name: string | number,
2019-07-22 16:29:50 +00:00
url: string | AudioBuffer | ToneAudioBuffer,
callback: () => void = noOp,
): this {
if (isString(url)) {
this._buffers.set(name.toString(), new ToneAudioBuffer(this.baseUrl + url, callback));
} else {
this._buffers.set(name.toString(), new ToneAudioBuffer(url, callback));
2019-07-22 16:29:50 +00:00
}
return this;
}
dispose(): this {
super.dispose();
this._buffers.forEach(buffer => buffer.dispose());
this._buffers.clear();
2019-07-22 16:29:50 +00:00
return this;
}
}