Add volume/enable state and follow the music's bpm for the metronome

This commit is contained in:
2023-09-18 17:18:01 +02:00
committed by Clément Le Bihan
parent 94658d4379
commit 31b965e8f6
4 changed files with 38 additions and 6 deletions

View File

@@ -1,13 +1,38 @@
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Slider, Switch, Text, View } from 'native-base';
export const Metronome = ({ paused = false, bpm }: { paused?: boolean; bpm: number }) => {
const ref = useRef<HTMLAudioElement | null>(null);
const enabled = useRef<boolean>(false);
const volume = useRef<number>(50);
useEffect(() => {
if (paused) return;
const int = setInterval(() => {
if (!ref.current) ref.current = new Audio("/assets/metronome.mp3");
console.log(enabled.current, volume.current);
if (!enabled.current) return;
if (!ref.current) ref.current = new Audio('/assets/metronome.mp3');
ref.current.volume = volume.current / 100;
ref.current.play();
}, 60000 / bpm);
return () => clearInterval(int);
}, []);
return null;
}, [bpm, paused]);
return (
<View>
<Text>Metronome Settings</Text>
<Text>Enabled:</Text>
<Switch value={enabled.current} onToggle={() => (enabled.current = !enabled.current)} />
<Text>Volume:</Text>
<Slider
maxWidth={'500px'}
value={volume.current}
onChange={(x) => (volume.current = x)}
>
<Slider.Track>
<Slider.FilledTrack />
</Slider.Track>
<Slider.Thumb />
</Slider>
</View>
);
};

View File

@@ -6,6 +6,7 @@ import { PianoCursorPosition } from '../models/PianoGame';
type PartitionCoordProps = {
// The Buffer of the MusicXML file retreived from the API
file: string;
bpmRef: React.MutableRefObject<number>;
onPartitionReady: () => void;
onEndReached: () => void;
onResume: () => void;
@@ -18,6 +19,7 @@ const PartitionCoord = ({
onEndReached,
onPause,
onResume,
bpmRef,
}: PartitionCoordProps) => {
const [partitionData, setPartitionData] = React.useState<
[[number, number], string, PianoCursorPosition[]] | null
@@ -28,6 +30,7 @@ const PartitionCoord = ({
{!partitionData && (
<PartitionView
file={file}
bpmRef={bpmRef}
onPartitionReady={(dims, base64data, a) => {
setPartitionData([dims, base64data, a]);
onPartitionReady();

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-mixed-spaces-and-tabs */
// Inspired from OSMD example project
// https://github.com/opensheetmusicdisplay/react-opensheetmusicdisplay/blob/master/src/lib/OpenSheetMusicDisplay.jsx
import React, { useEffect } from 'react';
import React, { MutableRefObject, useEffect } from 'react';
import {
CursorType,
Fraction,
@@ -19,6 +19,7 @@ type PartitionViewProps = {
base64data: string,
cursorInfos: PianoCursorPosition[]
) => void;
bpmRef: MutableRefObject<number>;
onEndReached: () => void;
// Timestamp of the play session, in milisecond
timestamp: number;
@@ -62,6 +63,7 @@ const PartitionView = (props: PartitionViewProps) => {
_osmd.render();
_osmd.cursor.show();
const bpm = _osmd.Sheet.HasBPMInfo ? _osmd.Sheet.getExpressionsStartTempoInBPM() : 60;
props.bpmRef.current = bpm;
const wholeNoteLength = Math.round((60 / bpm) * 4000);
const curPos = [];
while (!_osmd.cursor.iterator.EndReached) {

View File

@@ -84,6 +84,7 @@ const PlayView = ({ songId, type, route }: RouteProps<PlayViewProps>) => {
const toast = useToast();
const [lastScoreMessage, setLastScoreMessage] = useState<ScoreMessage>();
const webSocket = useRef<WebSocket>();
const bpm = useRef<number>(60);
const [paused, setPause] = useState<boolean>(true);
const stopwatch = useStopwatch();
const [time, setTime] = useState(0);
@@ -349,6 +350,7 @@ const PlayView = ({ songId, type, route }: RouteProps<PlayViewProps>) => {
>
<PartitionCoord
file={musixml.data}
bpmRef={bpm}
onEndReached={onEnd}
onPause={onPause}
onResume={onResume}
@@ -358,7 +360,7 @@ const PlayView = ({ songId, type, route }: RouteProps<PlayViewProps>) => {
{!partitionRendered && <LoadingComponent />}
</View>
<Metronome paused={paused} bpm={60} />
<Metronome paused={paused} bpm={bpm.current} />
<Box
shadow={4}