Skip to content

Commit

Permalink
Merge pull request #362 from Renumics/feature/loop-audio-playback
Browse files Browse the repository at this point in the history
Feature/loop audio playback
  • Loading branch information
neindochoh authored Nov 14, 2023
2 parents fff931b + 53320e9 commit c70e901
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 18 deletions.
57 changes: 39 additions & 18 deletions src/components/shared/AudioViewer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import useResizeObserver from '@react-hook/resize-observer';
import Maximize from '../../../icons/Maximize';
import MaximizeIcon from '../../../icons/Maximize';
import ResetIcon from '../../../icons/Reset';
import RepeatIcon from '../../../icons/Repeat';
import Button from '../../ui/Button';
import * as d3 from 'd3';
import { useEffect, useLayoutEffect, useRef, useState, WheelEvent } from 'react';
Expand All @@ -20,7 +21,10 @@ import CursorPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.cursor.min.js';
const MAX_ZOOM = 2500;

const Container = tw.div`flex flex-col w-full h-full items-stretch justify-center`;
const Toolbar = tw.div`flex flex-row items-baseline justify-center p-px`;

const Toolbar = tw.div`flex flex-row items-center justify-center p-px`;
const ToolbarButton = tw(Button)`rounded-none py-0`;

const EmptyNote = styled.p`
color: ${theme`colors.gray.500`};
${tw`flex h-full items-center justify-center`}
Expand Down Expand Up @@ -139,6 +143,8 @@ interface Props {
editable: boolean;
optional: boolean;
showControls?: boolean;
repeat?: boolean;
onChangeRepeat?: (enabled: boolean) => void;
onEditWindow?: (window: [number, number]) => void;
onDeleteWindow?: () => void;
onRegionEnter?: (windowIndex: number) => void;
Expand All @@ -153,6 +159,8 @@ const AudioViewer = ({
editable,
optional,
showControls,
repeat,
onChangeRepeat,
onEditWindow,
onDeleteWindow,
onRegionEnter,
Expand All @@ -169,6 +177,11 @@ const AudioViewer = ({
const [isPlaying, setIsPlaying] = useState(false);
const [isReady, setIsReady] = useState(false);

const [_repeat, _setRepeat] = useState(false);
repeat = repeat ?? _repeat;
onChangeRepeat = onChangeRepeat ?? _setRepeat;
const toggleRepeat = () => onChangeRepeat?.(!repeat);

const redrawWaveform = (height: number) => {
waveform.current?.setHeight(height);
};
Expand Down Expand Up @@ -316,6 +329,11 @@ const AudioViewer = ({
onRegionLeave,
]);

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(waveform.current?.backend as any).media.loop = repeat;
}, [repeat]);

useEffect(() => {
if (!waveform.current?.isReady) return;

Expand Down Expand Up @@ -510,49 +528,52 @@ const AudioViewer = ({
{showControls && (
<Toolbar>
{windows !== undefined && (
<Button
<ToolbarButton
tooltip="Play Region"
tw="max-h-full rounded-none py-0"
onClick={playRegion}
disabled={
!windows[0] || windows.length > 1 || url === undefined
}
>
<BsPlayCircleFill />
</Button>
</ToolbarButton>
)}
<Button
<ToolbarButton
tooltip="Play/Pause"
tw="max-h-full rounded-none py-0"
onClick={playPause}
disabled={url === undefined}
>
{isPlaying ? <BsPauseCircle /> : <BsPlayCircle />}
</Button>
<Button
</ToolbarButton>
<ToolbarButton
tooltip="Stop"
tw="max-h-full rounded-none py-0"
onClick={stopPlaying}
disabled={url === undefined}
>
<BsStopCircle />
</Button>
<Button
</ToolbarButton>
<div tw="flex-grow" />
<ToolbarButton
tooltip="Zoom to window"
tw="max-h-full rounded-none py-0"
onClick={zoomToWindow}
disabled={url === undefined}
>
<ResetIcon />
</Button>
<Button
</ToolbarButton>
<ToolbarButton
tooltip="Fit screen"
tw="max-h-full rounded-none py-0"
onClick={fitToScreen}
disabled={url === undefined}
>
<Maximize />
</Button>
<MaximizeIcon />
</ToolbarButton>
<ToolbarButton
tooltip="Repeat"
checked={repeat}
onClick={toggleRepeat}
>
<RepeatIcon />
</ToolbarButton>
</Toolbar>
)}
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
Expand Down
8 changes: 8 additions & 0 deletions src/icons/Repeat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { IconType } from 'react-icons';
import { MdRepeat } from 'react-icons/md';
import tw from 'twin.macro';

const Repeat: IconType = tw(
MdRepeat
)`w-4 h-4 font-semibold inline-block align-middle stroke-current`;
export default Repeat;
5 changes: 5 additions & 0 deletions src/lenses/AudioLens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Lens } from '../types';
import AudioViewer from '../components/shared/AudioViewer';
import { useDataset } from '../stores/dataset';
import api from '../api';
import useSetting from './useSetting';

async function fetchWaveform(row: number, column: string): Promise<number[]> {
const generationId = useDataset.getState().generationID;
Expand All @@ -20,6 +21,8 @@ const AudioLens: Lens = ({ rowIndex, columns, urls, values }) => {

const [waveform, setWaveform] = useState<number[]>();

const [repeat, setRepeat] = useSetting('repeat', false);

useEffect(() => {
fetchWaveform(rowIndex, columns[audioIndex].key).then((waveform) => {
setWaveform(waveform);
Expand All @@ -34,6 +37,8 @@ const AudioLens: Lens = ({ rowIndex, columns, urls, values }) => {
editable={false}
optional={optional}
showControls={true}
repeat={repeat}
onChangeRepeat={setRepeat}
/>
);
};
Expand Down

0 comments on commit c70e901

Please sign in to comment.