interactive-player
Version:
A front-end interactive music audio player using AudioWorklet for javascript and typescript
146 lines • 4.5 kB
JavaScript
// src/interactive-player-processor.ts
var Fader = class {
constructor(fadeInSamples, fadeOutSamples) {
this.fadeInStart = 0;
this.useFadeIn = false;
this.fadeOutStart = 0;
this.useFadeOut = false;
this.fadeOutEvent = null;
this.fadeInSamples = fadeInSamples;
this.fadeOutSamples = fadeOutSamples;
}
startFadeIn(head) {
this.fadeInStart = head;
this.useFadeIn = true;
}
startFadeOut(head, event = null) {
this.fadeOutEvent = event;
this.fadeOutStart = head;
this.useFadeOut = true;
}
getFadeInStep(head) {
if (!this.useFadeIn) return 1;
if (head < this.fadeInStart) return 0;
if (this.fadeInStart + this.fadeInSamples < head) {
this.useFadeIn = false;
return 1;
}
;
const step = (head - this.fadeInStart) / this.fadeInSamples;
return Math.min(step, 1);
}
getFadeOutStep(head, isPause) {
if (!this.useFadeOut && !isPause) {
if (this.fadeOutEvent !== null) {
this.fadeOutEvent();
this.fadeOutEvent = null;
}
return 1;
}
if (!this.useFadeOut && isPause) return 0;
if (head < this.fadeOutStart) return 1;
if (this.fadeOutStart + this.fadeOutSamples < head) {
this.useFadeOut = false;
return 0;
}
;
const step = 1 - (head - this.fadeOutStart) / this.fadeOutSamples;
return Math.max(step, 0);
}
};
var InteractivePlayerProcessor = class extends AudioWorkletProcessor {
constructor() {
super();
this.tracks = [];
this.start = 0;
this.head = 0;
this.playing = false;
this.pause = false;
this.current = 0;
this.next = 0;
this.transitions = {};
this.fader = new Fader(440, 440);
this.port.onmessage = ({ data }) => {
switch (data.type) {
case "loadMulti":
this.tracks = data.tracks.map(
(track) => track.map((buf) => new Float32Array(buf))
);
this.head = 0;
this.start = data.start ?? 0;
this.current = this.start;
this.transitions = data.transitions ?? {};
this.next = this.transitions[this.current] ?? null;
break;
case "play":
if (!this.playing) this.playing = true;
break;
case "stop":
if (this.playing) {
this.playing = false;
this.head = 0;
this.current = this.start;
this.next = this.transitions[this.current] ?? null;
}
break;
case "pause":
if (!this.pause) {
this.pause = data.type === "pause";
this.fader.startFadeOut(this.head);
}
break;
case "resume":
if (this.pause) {
this.pause = false;
this.fader.startFadeIn(this.head);
}
break;
case "next":
if (data.currentIs === void 0 || data.currentIs === null || data.currentIs === this.current) {
this.next = data.next;
}
break;
case "setFadeIn":
this.fader.fadeInSamples = data.fadeInSamples;
break;
case "setFadeOut":
this.fader.fadeOutSamples = data.fadeOutSamples;
break;
}
};
}
process(_inputs, outputs) {
const out = outputs[0];
if ((!this.playing || this.pause || this.tracks.length === 0) && !this.fader.useFadeOut) {
out.forEach((ch) => ch.fill(0));
return true;
}
for (let i = 0; i < out[0].length; i++) {
if (this.tracks[this.current].length > 0 && this.head >= this.tracks[this.current][0].length && !this.fader.useFadeOut) {
this.head = 0;
if (this.next === null || this.next === void 0) {
this.playing = false;
this.current = this.start;
this.next = this.transitions[this.current] ?? null;
out.forEach((ch) => ch[i] = 0);
continue;
} else {
this.current = this.next;
this.next = this.transitions[this.current] ?? null;
}
}
const fadeInStep = this.fader.getFadeInStep(this.head);
const fadeOutStep = this.fader.getFadeOutStep(this.head, this.pause);
for (let ch = 0; ch < out.length; ch++) {
out[ch][i] = this.tracks[this.current][ch][this.head] * fadeInStep * fadeOutStep;
}
this.head++;
}
return true;
}
};
registerProcessor(
"interactive-player-processor",
InteractivePlayerProcessor
);
//# sourceMappingURL=interactive-player-processor.js.map