penguinmod-editor-2 / src /lib /audio /audio-buffer-player.js
soiz1's picture
Upload 2891 files
6bcb42f verified
import SharedAudioContext from './shared-audio-context.js';
class AudioBufferPlayer {
constructor (samples, sampleRate) {
this.audioContext = new SharedAudioContext();
this.buffer = this.audioContext.createBuffer(1, samples.length, sampleRate);
this.buffer.getChannelData(0).set(samples);
this.source = null;
this.startTime = null;
this.updateCallback = null;
this.trimStart = null;
this.trimEnd = null;
}
play (trimStart, trimEnd, onUpdate, onEnded) {
this.updateCallback = onUpdate;
this.trimStart = trimStart;
this.trimEnd = trimEnd;
this.startTime = Date.now();
const trimStartTime = this.buffer.duration * trimStart;
const trimmedDuration = (this.buffer.duration * trimEnd) - trimStartTime;
this.source = this.audioContext.createBufferSource();
this.source.onended = onEnded;
this.source.buffer = this.buffer;
this.source.connect(this.audioContext.destination);
this.source.start(0, trimStartTime, trimmedDuration);
this.update();
}
update () {
const timeSinceStart = (Date.now() - this.startTime) / 1000;
const percentage = timeSinceStart / this.buffer.duration;
if (percentage + this.trimStart < this.trimEnd && this.source.onended) {
requestAnimationFrame(this.update.bind(this));
this.updateCallback(percentage + this.trimStart);
} else {
this.updateCallback = null;
}
}
stop () {
if (this.source) {
this.source.onended = null; // Do not call onEnded callback if manually stopped
try {
this.source.stop();
} catch (e) {
// This is probably Safari, which dies when you call stop more than once
// which the spec says is allowed: https://developer.mozilla.org/en-US/docs/Web/API/AudioBufferSourceNode
console.log('Caught error while stopping buffer source node.'); // eslint-disable-line no-console
}
}
}
}
export default AudioBufferPlayer;