Skip to content

Commit bb4f903

Browse files
committed
patch duration issue when audio not yet loaded
1 parent 11979a7 commit bb4f903

File tree

7 files changed

+80
-55
lines changed

7 files changed

+80
-55
lines changed

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ function App() {
4949
annotations={annotations}
5050
navigator={true}
5151
settings={true}
52-
startTimeInitial={2}
53-
endTimeInitial={4}
52+
//startTimeInitial={2}
53+
//endTimeInitial={4}
5454
playbackSpeedInitial={1.0}
5555
playheadModeInitial="loop"
5656
specHeight={300}

src/lib/PlaybackProvider.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@ import {
1010
import { useTheme } from "./ThemeProvider";
1111

1212
export type PlaybackContextType = {
13-
duration: number;
13+
duration: number | null;
1414
currentTime: number;
1515
playbackRate: number;
1616
mode: string;
1717
sampleRate: number;
18-
setDuration: Dispatch<SetStateAction<number>>;
18+
setDuration: Dispatch<SetStateAction<number | null>>;
1919
setCurrentTime: (newTime: number) => void;
2020
setPlaybackRate: (newTime: number) => void;
2121
pause: () => void;
2222
audioSamples: Float32Array;
2323
};
2424

2525
export const PlaybackContext = createContext<PlaybackContextType>({
26-
duration: 999,
26+
duration: null,
2727
currentTime: 0,
2828
playbackRate: 1.0,
2929
mode: "page",
@@ -61,7 +61,7 @@ function PlaybackProvider(props: PlaybackProviderProps) {
6161
playheadModeInitial = "page",
6262
} = props;
6363
const settings = props.settings ? true : false;
64-
const [duration, setDuration] = useState(999);
64+
const [duration, setDuration] = useState<number | null>(null);
6565
const [currentTime, _setCurrentTime] = useState(currentTimeInitial);
6666
const [playbackRate, _setPlaybackRate] = useState(playbackSpeedInitial);
6767
const [mode, setMode] = useState<string>(playheadModeInitial);
@@ -81,6 +81,11 @@ function PlaybackProvider(props: PlaybackProviderProps) {
8181
if (audioRef.current.duration) {
8282
setDuration(audioRef.current.duration);
8383
}
84+
85+
if (audioRef.current.readyState >= 1) {
86+
setDuration(audioRef.current.duration);
87+
}
88+
8489
audioRef.current.playbackRate = playbackSpeedInitial;
8590

8691
if (intervalRef.current) {

src/lib/SpectrogramContent.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ function SpectrogramContent(props: SpectrogramContentProps) {
1313
const { duration, currentTime } = usePlayback();
1414
const { zoomedDuration } = useZoom();
1515

16+
if (!duration) {
17+
return null;
18+
}
19+
1620
return (
1721
<>
1822
<image

src/lib/SpectrogramGraphics.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ function SpectrogramGraphics(props: SpectrogramGraphicsProps) {
103103
// for backwards compatibility, where user could specify sxx as a number[][] array
104104
setSpec(
105105
sxx[0].map(
106-
(_, colIndex) => new Float32Array(sxx.map((row) => row[colIndex]))
107-
)
106+
(_, colIndex) => new Float32Array(sxx.map((row) => row[colIndex])),
107+
),
108108
);
109109
return;
110110
}
@@ -119,7 +119,7 @@ function SpectrogramGraphics(props: SpectrogramGraphicsProps) {
119119
f_min,
120120
f_max,
121121
n_mels,
122-
top_db
122+
top_db,
123123
);
124124

125125
setSpec(melSpec);
@@ -197,7 +197,7 @@ function SpectrogramGraphics(props: SpectrogramGraphicsProps) {
197197
data={data}
198198
strokeWidth={strokeWidth}
199199
/>
200-
))
200+
)),
201201
)}
202202
{navigator && (
203203
<SpectrogramNavigator height={navHeight}>

src/lib/SpectrogramNavigator.tsx

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ function SpectrogramNavigator(props: SpectrogramNavigatorProps) {
3434
const draggingToPan = isZoomed && dragStart;
3535

3636
const getPointerCoordinate = (
37-
e: React.MouseEvent<SVGSVGElement, MouseEvent>
37+
e: React.MouseEvent<SVGSVGElement, MouseEvent>,
3838
) => {
3939
const boundingClientRect = svgRef.current?.getBoundingClientRect();
40-
if (boundingClientRect) {
40+
if (boundingClientRect && duration) {
4141
const { left, right } = boundingClientRect;
4242
let newTime = (duration * (e.clientX - left)) / (right - left);
4343
return newTime;
@@ -53,10 +53,10 @@ function SpectrogramNavigator(props: SpectrogramNavigatorProps) {
5353
const newDragEnd = getPointerCoordinate(e);
5454
setDragEnd(newDragEnd);
5555
if (newDragEnd) {
56-
if (draggingToPan) {
56+
if (draggingToPan && duration) {
5757
const newCenterTime = Math.min(
5858
Math.max(zoomedDuration / 2, newDragEnd),
59-
duration - zoomedDuration / 2
59+
duration - zoomedDuration / 2,
6060
);
6161
setCenterTime(newCenterTime);
6262
setCurrentTime(newCenterTime - zoomedDuration / 2);
@@ -65,7 +65,7 @@ function SpectrogramNavigator(props: SpectrogramNavigatorProps) {
6565
};
6666

6767
const onPointerUp = (e: React.MouseEvent<SVGSVGElement, MouseEvent>) => {
68-
if (draggingToZoom) {
68+
if (draggingToZoom && duration) {
6969
if (dragEnd - dragStart >= MINIMUM_ZOOM_WINDOW_DURATION) {
7070
setStartTime(dragStart);
7171
setEndTime(dragEnd);
@@ -80,47 +80,53 @@ function SpectrogramNavigator(props: SpectrogramNavigatorProps) {
8080
setDragEnd(null);
8181
};
8282

83+
const placeholder_svg = <svg width="100%" height={height} />;
84+
8385
return (
8486
<div style={{ display: "flex", flexDirection: "row", gap: 5 }}>
8587
<button className={theme} onClick={zoomOut}>
8688
Zoom Out
8789
</button>
88-
<svg
89-
ref={svgRef}
90-
width="100%"
91-
height={height}
92-
viewBox={`0,0,${duration},100`}
93-
cursor={isZoomed ? "grabbing" : "zoom-in"}
94-
preserveAspectRatio="none"
95-
onPointerDown={onPointerDown}
96-
onPointerUp={onPointerUp}
97-
onPointerMove={onPointerMove}
98-
>
99-
{children}
100-
<rect
101-
x={0}
102-
width={startTime}
103-
y="0"
104-
height="100"
105-
style={{ fill: "white", opacity: 0.5 }}
106-
/>
107-
<rect
108-
x={endTime}
109-
width={duration - endTime}
110-
y="0"
111-
height="100"
112-
style={{ fill: "white", opacity: 0.5 }}
113-
/>
114-
{draggingToZoom && dragEnd > dragStart && (
90+
{duration ? (
91+
<svg
92+
ref={svgRef}
93+
width="100%"
94+
height={height}
95+
viewBox={`0,0,${duration},100`}
96+
cursor={isZoomed ? "grabbing" : "zoom-in"}
97+
preserveAspectRatio="none"
98+
onPointerDown={onPointerDown}
99+
onPointerUp={onPointerUp}
100+
onPointerMove={onPointerMove}
101+
>
102+
{children}
103+
<rect
104+
x={0}
105+
width={startTime}
106+
y="0"
107+
height="100"
108+
style={{ fill: "white", opacity: 0.5 }}
109+
/>
115110
<rect
116-
x={dragStart}
117-
width={dragEnd - dragStart}
111+
x={endTime}
112+
width={duration - endTime}
118113
y="0"
119114
height="100"
120-
style={{ fill: "red", opacity: 0.5 }}
115+
style={{ fill: "white", opacity: 0.5 }}
121116
/>
122-
)}
123-
</svg>
117+
{draggingToZoom && dragEnd > dragStart && (
118+
<rect
119+
x={dragStart}
120+
width={dragEnd - dragStart}
121+
y="0"
122+
height="100"
123+
style={{ fill: "red", opacity: 0.5 }}
124+
/>
125+
)}
126+
</svg>
127+
) : (
128+
placeholder_svg
129+
)}
124130
<button
125131
className={theme}
126132
style={{ fontFamily: "monospace" }}

src/lib/SpectrogramViewer.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function SpectrogramViewer(props: SpectrogramViewerProps) {
1515

1616
const onClick = (e: React.MouseEvent<SVGSVGElement, MouseEvent>) => {
1717
const boundingClientRect = svgRef.current?.getBoundingClientRect();
18-
if (boundingClientRect) {
18+
if (boundingClientRect && duration) {
1919
const { left, right } = boundingClientRect;
2020
let newTime =
2121
startTime +
@@ -30,7 +30,9 @@ function SpectrogramViewer(props: SpectrogramViewerProps) {
3030
}
3131
};
3232

33-
return (
33+
const placeholder_svg = <svg width="100%" height={height} />;
34+
35+
return duration ? (
3436
<svg
3537
ref={svgRef}
3638
width="100%"
@@ -42,6 +44,8 @@ function SpectrogramViewer(props: SpectrogramViewerProps) {
4244
>
4345
{children}
4446
</svg>
47+
) : (
48+
placeholder_svg
4549
);
4650
}
4751

src/lib/ZoomProvider.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@ function ZoomProvider(props: ZoomProviderProps) {
4646
const { children, startTimeInitial, endTimeInitial } = props;
4747
const { duration, currentTime, mode, pause, setCurrentTime } = usePlayback();
4848
const [startTime, setStartTime] = useState(startTimeInitial ?? 0);
49-
const [endTime, setEndTime] = useState(endTimeInitial ?? duration);
49+
const [endTime, setEndTime] = useState(endTimeInitial ?? duration ?? 1);
5050

5151
useEffect(() => {
52-
setStartTime(startTimeInitial ?? 0);
53-
setEndTime(endTimeInitial ?? duration);
54-
setCurrentTime(startTimeInitial ?? 0);
55-
}, [startTimeInitial, endTimeInitial]);
52+
if (duration !== null) {
53+
setStartTime(startTimeInitial ?? 0);
54+
setEndTime(endTimeInitial ?? duration);
55+
setCurrentTime(startTimeInitial ?? 0);
56+
}
57+
}, [duration, startTimeInitial, endTimeInitial]);
5658

5759
const zoomedDuration = endTime - startTime;
5860

@@ -111,6 +113,7 @@ function ZoomProvider(props: ZoomProviderProps) {
111113
}, [currentTime, mode]);
112114

113115
const zoomIn = () => {
116+
if (duration === null) return;
114117
const newStartTime = Math.max(0, startTime + 0.2 * zoomedDuration);
115118
const newEndTime = Math.min(duration, endTime - 0.2 * zoomedDuration);
116119
setStartTime(newStartTime);
@@ -119,6 +122,7 @@ function ZoomProvider(props: ZoomProviderProps) {
119122
};
120123

121124
const zoomOut = () => {
125+
if (duration === null) return;
122126
const newStartTime = Math.max(0, startTime - (1 / 3) * zoomedDuration);
123127
const newEndTime = Math.min(duration, endTime + (1 / 3) * zoomedDuration);
124128
setStartTime(newStartTime);
@@ -127,20 +131,22 @@ function ZoomProvider(props: ZoomProviderProps) {
127131
};
128132

129133
const nextPage = () => {
134+
if (duration === null) return;
130135
const newEndTime = Math.min(duration, endTime + zoomedDuration);
131136
const newStartTime = Math.max(0, newEndTime - zoomedDuration);
132137
setStartTime(newStartTime);
133138
setEndTime(newEndTime);
134139
};
135140

136141
const previousPage = () => {
142+
if (duration === null) return;
137143
const newStartTime = Math.max(0, startTime - zoomedDuration);
138144
const newEndTime = Math.min(duration, newStartTime + zoomedDuration);
139145
setStartTime(newStartTime);
140146
setEndTime(newEndTime);
141147
};
142148

143-
const isZoomed = startTime > 0 || endTime < duration;
149+
const isZoomed = duration !== null && (startTime > 0 || endTime < duration);
144150

145151
return (
146152
<ZoomContext.Provider

0 commit comments

Comments
 (0)