Skip to content

Commit

Permalink
player POC
Browse files Browse the repository at this point in the history
  • Loading branch information
nknapp committed Apr 6, 2024
1 parent 5948ccf commit fd750c4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 14 deletions.
41 changes: 30 additions & 11 deletions src/components/solid/organisms/Reader/Reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,66 @@ import speechPack from "@/data/speechpacks/default";
import { SINGLE_DIRECTION, type Technique } from "$core/model";
import { SimpleButton } from "@/components/solid/atoms/SimpleButton.tsx";
import { ExamScroll } from "@/components/solid/organisms/Reader/ExamScroll.tsx";
import { IconAutoMode, IconPlay, IconSkipNext, IconSkipPrevious } from "@/icons";
import { IconAutoMode, IconPause, IconPlay, IconSkipNext, IconSkipPrevious } from "@/icons";
import { CheckButton } from "@/components/solid/atoms/CheckButton.tsx";
import { type Speed, SpeedButton } from "@/components/solid/organisms/Reader/SpeedButton.tsx";

export const Reader: Component<{ dojoInfo: DojoInfo }> = (props) => {
const techniqueStore = createTechniqueStore(props.dojoInfo.id);
const [techniques] = createResource(techniqueStore.load, { initialValue: [] });
const [playing, setPlaying] = createSignal(false);
const [player] = createResource(
async () => {
const speechPackPlayer = await loadSpeechPackPlayer(speechPack, playArrayBuffer);
return (technique: Technique) => {
if (technique.direction === SINGLE_DIRECTION) {
return speechPackPlayer.play([technique.execution, technique.attack, technique.defence]);
} else {
return speechPackPlayer.play([technique.execution, technique.attack, technique.defence, technique.direction]);
}
return {
play: async (technique: Technique) => {
setPlaying(true);
if (technique.direction === SINGLE_DIRECTION) {
await speechPackPlayer.play([technique.execution, technique.attack, technique.defence]);
} else {
await speechPackPlayer.play([
technique.execution,
technique.attack,
technique.defence,
technique.direction,
]);
}
setPlaying(false);
},
stop: async () => speechPackPlayer.stop(),
};
},
{
initialValue: async () => {},
initialValue: { play: async () => {}, stop: async () => {} },
},
);

return (
<div class={"flex flex-col gap-4"}>
<Suspense fallback={"Loading"}>
<Player player={player()} techniques={techniques()} />
<Player player={player()} techniques={techniques()} playing={playing()} />
<ExamScroll class={"h-[40vh]"} techniques={techniques()} currentTechnique={techniques()[0]} />
</Suspense>
</div>
);
};

const Player: Component<{ player: (technique: Technique) => Promise<void>; techniques: Technique[] }> = (props) => {
const Player: Component<{
player: { play: (technique: Technique) => Promise<void>; stop: () => Promise<void> };
techniques: Technique[];
playing: boolean;
}> = (props) => {
const [autoPlay, setAutoPlay] = createSignal(false);
const [speed, setSpeed] = createSignal<Speed>("normal");
return (
<>
<div class={"grid grid-cols-3 gap-4"}>
<SimpleButton size="large" icon={IconSkipPrevious} />
<SimpleButton size="large" onClick={() => props.player(props.techniques[0])} icon={IconPlay} />
<SimpleButton
size="large"
onClick={() => (props.playing ? props.player.stop() : props.player.play(props.techniques[0]))}
icon={props.playing ? IconPause : IconPlay}
/>
<SimpleButton size="large" icon={IconSkipNext} />
</div>
<div class={"grid grid-cols-2 gap-4"}>
Expand Down
16 changes: 13 additions & 3 deletions src/core/SpeechPackPlayer/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@ export async function loadSpeechPackPlayer(speechPack: SpeechPack, playArrayBuff
class SpeechPackPlayer {
private readonly speechPack: Promise<ResolvedSpeechPack>;
private readonly playArrayBuffer: PlayArrayBuffer;
private abortController: AbortController;
constructor(speechPack: Promise<ResolvedSpeechPack>, playArrayBuffer: PlayArrayBuffer) {
this.abortController = new AbortController();
this.speechPack = speechPack;
this.playArrayBuffer = playArrayBuffer;
}

async play(audioFiles: SpeechFile[]): Promise<void> {
this.abortController.abort();
const abortController = new AbortController();
this.abortController = abortController;
for (const file of audioFiles) {
await this.playSingle(file);
if (abortController.signal.aborted) return;
await this.playSingle(file, abortController);
}
}

private async playSingle(audioFile: SpeechFile) {
async stop() {
this.abortController.abort();
}

private async playSingle(audioFile: SpeechFile, abortController: AbortController) {
const loadedSpeechPack = await this.speechPack;
await this.playArrayBuffer(loadedSpeechPack[audioFile]);
await this.playArrayBuffer(loadedSpeechPack[audioFile], { abortSignal: abortController.signal });
}
}

0 comments on commit fd750c4

Please sign in to comment.