import React, { useEffect } from 'react'; import StartAudioContext from 'startaudiocontext'; import Tone from '../lib/tone'; type SongContextProps = { isPlaying: boolean; }; export const SongContext = React.createContext({ isPlaying: false, }); export type SongProps = { isPlaying?: boolean; bpm?: number; swing?: number; subdivision?: string; swingSubdivision?: string; volume?: number; isMuted?: boolean; children?: React.ReactNode; }; const Song: React.FC = ({ isPlaying = false, bpm = 90, // subdivision = '4n', swing = 0, swingSubdivision = '8n', volume = 0, isMuted = false, children, }) => { useEffect(() => { document.body.addEventListener( 'click', () => { // iOS Web Audio API requires this library. StartAudioContext(Tone.context); }, { once: true, }, ); }, []); useEffect(() => { Tone.Transport.bpm.value = bpm; Tone.Transport.swing = swing; Tone.Transport.swingSubdivision = swingSubdivision; }, [bpm, swing, swingSubdivision]); useEffect(() => { if (isPlaying) { // Hack to get Tone to NOT use same settings from another instance Tone.Transport.bpm.value = bpm; Tone.Transport.swing = swing; Tone.Transport.swingSubdivision = swingSubdivision; Tone.Transport.start(); } else { Tone.Transport.stop(); } /* eslint-disable-next-line */ }, [isPlaying]); useEffect(() => { Tone.Master.volume.value = volume; }, [volume]); useEffect(() => { Tone.Master.mute = isMuted; }, [isMuted]); if (typeof window === 'undefined') { return null; } return ( {children} ); }; export default Song;