Fade auio
Thu Mar 17 2022 09:02:08 GMT+0000 (Coordinated Universal Time)
Saved by @minhhung1106 #html
import React, { useCallback, useEffect, useRef, useState } from 'react'; import useEventListener from './useEventListener'; interface UseFadeAudioProps { audioRef: React.RefObject<HTMLAudioElement>; cloneAudioRef: React.RefObject<HTMLAudioElement>; startFade: boolean; paused: boolean; } const TIMING = 10; const useFadeAudio = ({ audioRef, cloneAudioRef, startFade, paused }: UseFadeAudioProps) => { const [isStartFadeClone, setIsStartFadeClone] = useState<boolean>(false); const currentTimeRef = useRef<number>(0); const cloneCurrentTimeRef = useRef<number>(0); const timerIdRef = useRef<number>(0); const cloneTimerIdRef = useRef<number>(0); const canStartAudio1Ref = useRef<boolean>(true); const canStartAudio2Ref = useRef<boolean>(true); const fadeAudio = useCallback( ( audio: HTMLAudioElement, nextAudio: HTMLAudioElement, isCloneAudio: boolean, canStartCurrentAudioRef: React.MutableRefObject<boolean>, canStartNextAudioRef: React.MutableRefObject<boolean>, ) => { const { duration } = audio; const startPoint = 50; const startRange = (duration * startPoint) / 100; // ex: duration = 10s, startPoint = 50% => startRange = 5s const fadeStart = (startRange * 1000) / TIMING; const timerId = window.setInterval(() => { const currentTime = !isCloneAudio ? currentTimeRef.current : cloneCurrentTimeRef.current; // Start fade in for next audio if (duration - currentTime <= startRange && canStartCurrentAudioRef.current) { nextAudio.volume = 0; nextAudio.play(); cloneCurrentTimeRef.current = 0; canStartCurrentAudioRef.current = !canStartCurrentAudioRef.current; // Prevent canStartNextAudioRef.current = true; if (!isCloneAudio) setIsStartFadeClone(true); } // Fade in if (audio.volume < 1 && duration - currentTime > startRange) { const newVolume = audio.volume + 1 / fadeStart; console.log('FADE In'); if (newVolume >= 1) audio.volume = 1; else audio.volume = newVolume; return; } // Fade out if (audio.volume > 0 && duration - currentTime <= startRange) { const newVolume = audio.volume - 1 / fadeStart; if (newVolume <= 0) audio.volume = 0; else audio.volume = newVolume; } console.log('PAUSED', timerId); }, TIMING); return timerId; }, [], ); useEffect(() => { if (paused) { clearInterval(timerIdRef.current); clearInterval(cloneTimerIdRef.current); } }, [paused]); useEffect(() => { const audio = audioRef.current; const nextAudio = cloneAudioRef.current; if (!audio || !nextAudio || !startFade) return; timerIdRef.current = fadeAudio(audio, nextAudio, false, canStartAudio2Ref, canStartAudio1Ref); return () => clearInterval(timerIdRef.current); }, [audioRef, cloneAudioRef, startFade, paused, fadeAudio]); useEffect(() => { const audio = cloneAudioRef.current; const nextAudio = audioRef.current; if (!audio || !nextAudio || !isStartFadeClone) return; cloneTimerIdRef.current = fadeAudio( audio, nextAudio, true, canStartAudio1Ref, canStartAudio2Ref, ); return () => clearInterval(cloneTimerIdRef.current); }, [audioRef, cloneAudioRef, paused, isStartFadeClone, fadeAudio]); useEventListener( 'timeupdate', () => { currentTimeRef.current = audioRef.current?.currentTime ?? 0; }, audioRef, ); useEventListener( 'timeupdate', () => { cloneCurrentTimeRef.current = cloneAudioRef.current?.currentTime ?? 0; }, cloneAudioRef, ); }; export default useFadeAudio;
Comments