Spaces:
Running
Running
File size: 2,153 Bytes
6bcb42f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
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;
|