Skip to content

Commit

Permalink
Move preload component to playback.js
Browse files Browse the repository at this point in the history
  • Loading branch information
Evert-R committed Oct 8, 2023
1 parent 63247f9 commit 2160df0
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 135 deletions.
134 changes: 48 additions & 86 deletions frontend/src/components/Playback/Autoplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,115 +2,77 @@ import React, { useRef, useState, useEffect } from "react";

import * as audio from "../../util/audio";
import * as webAudio from "../../util/webAudio";
import { MEDIA_ROOT } from "../../config";

import Circle from "../Circle/Circle";
import ListenCircle from "../ListenCircle/ListenCircle";
import Preload from "../Preload/Preload";

const PRELOAD = "PRELOAD";
const RECOGNIZE = "RECOGNIZE";


const AutoPlay = ({instruction, preloadMessage, onPreloadReady, playConfig, sections, time, startedPlaying, finishedPlaying, responseTime, className=''}) => {
// player state
const [state, setState] = useState({ view: RECOGNIZE });

const running = useRef(playConfig.auto_play);
const setView = (view, data = {}) => {
setState({ view, ...data });
}


const section = sections[0];

const onCircleTimerTick = (t) => {
time.current = t;
};

// Handle view logic
useEffect(() => {
switch (state.view) {
case RECOGNIZE:
let latency = 0;
// Play audio at start time
if (!playConfig.mute) {
if (playConfig.play_method === 'BUFFER' && !playConfig.external_audio) {
console.log('Autoplay buffer');
latency = webAudio.getTotalLatency();
webAudio.playBufferFrom(section.id, 0, Math.max(0, playConfig.playhead));
} else {
console.log('Autoplay HTML audio')
audio.playFrom(Math.max(0, playConfig.playhead));
}
}
setTimeout(startedPlaying(), latency);
break;
default:
// nothing
useEffect(() => {
let latency = 0;
// Play audio at start time
if (!playConfig.mute) {
if (playConfig.play_method === 'BUFFER' && !playConfig.external_audio) {
console.log('Autoplay buffer');
latency = webAudio.getTotalLatency();
webAudio.playBufferFrom(section.id, 0, Math.max(0, playConfig.playhead));
} else {
console.log('Autoplay HTML audio')
audio.playFrom(Math.max(0, playConfig.playhead));
}
setTimeout(startedPlaying(), latency);
}
}, [playConfig, startedPlaying]);

// Clean up
return () => {
audio.pause();
};
}, [state, playConfig, startedPlaying]);


// Render component based on view
switch (state.view) {
case PRELOAD:
return (
<Preload
instruction={preloadMessage}
duration={playConfig.ready_time}
url={MEDIA_ROOT + section.url}
onNext={() => {
setView(RECOGNIZE);
onPreloadReady();
// Render component
return (
<div>
<div className="circle">
<Circle
running={running}
duration={responseTime}
color="white"
animateCircle={playConfig.show_animation}
onTick={onCircleTimerTick}
onFinish={() => {
// Stop audio
finishedPlaying();
}}
/>
);
case RECOGNIZE:
return (
<div>
<div className="circle">
<Circle
running={running}
<div className="circle-content">
{playConfig.show_animation
? <ListenCircle
duration={responseTime}
color="white"
animateCircle={playConfig.show_animation}
onTick={onCircleTimerTick}
onFinish={() => {
// Stop audio
finishedPlaying();
}}
histogramRunning={running}
countDownRunning={running}
/>
<div className="circle-content">
{playConfig.show_animation
? <ListenCircle
duration={responseTime}
histogramRunning={running}
countDownRunning={running}
/>
: <div className="stationary">
<span className="fa-solid fa-headphones fa-6x"></span>
</div>
}
: <div className="stationary">
<span className="fa-solid fa-headphones fa-6x"></span>
</div>
</div>
<div className={
"aha__listen d-flex flex-column justify-content-center align-items-center " +
className
}
>
{/* Instruction */}
{instruction && (<div className="instruction d-flex justify-content-center align-items-center">
<h3 className="text-center">{instruction}</h3>
</div>)}
</div>
</div>
)
default:
return <div>Unknown view: {state.view}</div>;
}
<div className={
"aha__listen d-flex flex-column justify-content-center align-items-center " +
className
}
>
{/* Instruction */}
{instruction && (<div className="instruction d-flex justify-content-center align-items-center">
<h3 className="text-center">{instruction}</h3>
</div>)}
</div>
</div>
)
}
export default AutoPlay;
70 changes: 32 additions & 38 deletions frontend/src/components/Playback/Playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import PlayButton from "../PlayButton/PlayButton";
import MultiPlayer from "./MultiPlayer";
import SpectrogramPlayer from "./SpectrogramPlayer";
import MatchingPairs from "./MatchingPairs";
import Loading from "../Loading/Loading";
import Preload from "../Preload/Preload";

export const AUTOPLAY = "AUTOPLAY";
export const BUTTON = "BUTTON";
export const MULTIPLAYER = "MULTIPLAYER";
export const SPECTROGRAM = "SPECTROGRAM";
export const MATCHINGPAIRS = "MATCHINGPAIRS";
export const PRELOAD = "PRELOAD";

const Playback = ({
playerType,
Expand All @@ -31,10 +32,13 @@ const Playback = ({
startedPlaying,
finishedPlaying,
}) => {
const [sectionsLoaded, setSectionsLoaded] = useState(null);
const [playerIndex, setPlayerIndex] = useState(-1);
const lastPlayerIndex = useRef(-1);
const activeAudioEndedListener = useRef(null);
const [state, setState] = useState({ view: PRELOAD });
const setView = (view, data = {}) => {
setState({ view, ...data });
}

// Keep track of which player has played, in a an array of player indices
const [hasPlayed, setHasPlayed] = useState([]);
Expand All @@ -50,31 +54,6 @@ const Playback = ({
prevPlayerIndex.current = parseInt(playerIndex);
}, [playerIndex]);


useEffect(() => {
if (playConfig.play_method === 'BUFFER' && !playConfig.external_audio) {
// Use Web-audio and preload sections in buffers
sections.map((section, index) => {
// Clear buffers if this is the first section
if (index === 0) {
webAudio.clearBuffers();
}
return webAudio.loadBuffer(section.id, MEDIA_ROOT + section.url, () => {
if (index === (sections.length-1)) {
setSectionsLoaded(1);
}
});
})
} else {
if (playConfig.external_audio) {
webAudio.closeWebAudio();
}
setSectionsLoaded(1);
// Preload first section
return audio.loadUntilAvailable(MEDIA_ROOT + sections[0].url, () => {});
}
}, [sections]);

// Cancel events
const cancelAudioListeners = useCallback(() => {
activeAudioEndedListener.current && activeAudioEndedListener.current();
Expand All @@ -97,7 +76,6 @@ const Playback = ({
} else {
finishedPlaying();
}

}, []);

// Play audio
Expand All @@ -106,42 +84,46 @@ const Playback = ({
let latency = 0;
if (playConfig.play_method === 'BUFFER' && !playConfig.external_audio) {
console.log('Play buffer (local)');

// Determine latency for current audio device
latency = webAudio.getTotalLatency();

// Store player index
setPlayerIndex(index);

// Determine if audio should be played
if (playConfig.mute) {
setPlayerIndex(-1);
webAudio.stopBuffer();
return;
}
// Volume 1
// audio.setVolume(1);

// Cancel active events
cancelAudioListeners();

// Play audio
// audio.playFrom(Math.max(0, playConfig.playhead || 0));

// Play audio
webAudio.playBuffer(sections[index].id);

// listen for active audio events
activeAudioEndedListener.current = webAudio.listenOnce("ended", onAudioEnded);
} else {
console.log('Play HTML audo')

// Only initialize webaudio if section is local
if (!playConfig.external_audio) {
latency = webAudio.initWebAudio();
}

// Store player index
setPlayerIndex(index);

// Determine if audio should be played
if (playConfig.mute) {
setPlayerIndex(-1);
audio.pause();
return;
}

// Volume 1
audio.setVolume(1);

Expand Down Expand Up @@ -178,6 +160,7 @@ const Playback = ({
playAudio(index);
return;
}

// Stop playback
if (lastPlayerIndex.current === index) {
webAudio.suspend();
Expand All @@ -191,6 +174,7 @@ const Playback = ({
if (playConfig.external_audio) {
// webAudio.closeWebAudio();
}

// Play section from <AUDIO> tag
if (index !== lastPlayerIndex.current) {
// Load different audio
Expand Down Expand Up @@ -249,6 +233,7 @@ const Playback = ({
const render = (view) => {
const attrs = {
sections,
setView,
instruction,
preloadMessage,
autoAdvance,
Expand All @@ -264,7 +249,20 @@ const Playback = ({
submitResult
};

switch (view) {
switch (state.view) {
case PRELOAD:
return (
<Preload
instruction={preloadMessage}
duration={playConfig.ready_time}
sections={sections}
playConfig={playConfig}
onNext={() => {
setView(playerType);
onPreloadReady();
}}
/>
);
case AUTOPLAY:
return <AutoPlay {...attrs} onPreloadReady={onPreloadReady} />;
case BUTTON:
Expand Down Expand Up @@ -300,10 +298,6 @@ const Playback = ({
return <div> Unknown player view {view} </div>;
}
};

if (!sectionsLoaded) {
return <Loading loadingText={'loading'} />;
}

return (
<div className="aha__playback">
Expand Down
Loading

0 comments on commit 2160df0

Please sign in to comment.