Проблема с пакетом React js и Howler js при воспроизведении звуков через несколько секунд

#javascript #reactjs #setinterval #howler.js

Вопрос:

Проблема с пакетом React js и Howler js при воспроизведении звуков через несколько секунд

Здравствуйте и спасибо, что ответили на мою проблему, надеюсь, вы это понимаете, мой английский не самый лучший.

Здесь я загрузил видео, которое точно показывает, в чем моя проблема: https://youtu.be/BvuK0zDGvgY

Таким образом, через несколько секунд программа просто начинает обрезать и отставать от моего компьютера. Проблемы, которые, я думаю, могут возникнуть, заключаются в следующем:

  1. Аудиофайл html5 исчерпан. Кто-нибудь знает решение для этого?
  2. setInterval() Функция, которую я использовал для итерации в миллисекундах, имитирует темп. Я думаю, что это может быть проблемой, потому что даже если я нажму кнопку воспроизведения драм-машины без какого-либо звука внутри стойки, через несколько секунд приложение столкнется с той же проблемой.
  3. Много рендеров. Так как я использую React js и крючок react useState() для запуска нового рендеринга. Я использовал setInterval() для изменения крючка состояния, который увеличивает число с каждым интервалом. Может быть, если темп высокий (это означает более быстрые интервалы), браузер или компьютер перегружаются? и если да, то знает ли кто-нибудь альтернативу setInterval() увеличению числа с течением времени?.

это мой код, я думаю, что в нем нет необходимости, но на всякий случай

 import React, {useState} from 'react'
import {IoMdMusicalNote} from "react-icons/io"
import {AiFillCaretDown} from "react-icons/ai"
import {BsFillPlayFill, BsPauseFill} from "react-icons/bs"
//sounds
import Kick from "./sounds/kick.mp3"
import Button_sound from "./sounds/sound_fx/play_button.mp3"
import Snare from "./sounds/snare.mp3"
import Hat from "./sounds/hat.mp3"
import crash from "./sounds/cymbal.mp3"
import tom from "./sounds/tom.mp3"
import jump from "./sounds/jump.mp3"
//
import {Howl} from 'howler';
import "./App.css"
const App = () => {
    //A value that increases by the tempo.
    const [currentStep, setStep] = useState(undefined)
    //a bool to know when the drum machine is running
    const [isPlaying, setIsPlaying] = useState(null)
    //to clear the interval later
    const [intervalState, setIntervalState] = useState(null)
    //tempo value, it is set with an input below
    const [tempo, setTempo] = useState(undefined)
    //set sounds to later use
    const sounds = {
        kick: new Howl({src: [Kick]}),
        snare: new Howl({src: [Snare]}),
        hat: new Howl({src: [Hat]}),
        crash: new Howl({src: [crash]}),
        tom: new Howl({src: [tom]}),
        jump: new Howl({src: [jump]}),
        pebbel: new Howl({src: [Button_sound]}),
    }
    //creates the rack of slots
    const createSteps = () => {
        let arr = new Array(32)
        for (let i = 0 ; i < 32; i  ){
            arr[i] = 0
        }
        return arr
    }
    //the instruments
    const [instrumental, setInstrumental] = useState([
        {name:"kick", steps: createSteps(), audio: sounds.kick},
        {name: "hat", steps: createSteps(), audio: sounds.hat},
        {name: "snare", steps: createSteps(), audio: sounds.snare},
        {name: "crash", steps: createSteps(), audio: sounds.crash},
        {name: "tom", steps: createSteps(), audio: sounds.tom},
        {name: "jump", steps: createSteps(), audio: sounds.jump},
    ]);

    //turn on a slot to make it sound when play, it receives stepIndex to modify the specified indexed element and instrument name refers to the specific instrument of the instrumental array
    const toggleSound = (stepIndex, instrumentName) => {
        const stepsState = instrumental.find(instrument => instrument.name === instrumentName).steps
        stepsState[stepIndex] = stepsState[stepIndex] === 1 ? 0 : 1;
        const newInstrumentState = {...instrumental.find(instrument => instrument.name === instrumentName), steps: stepsState}
        let newInstrumentalState = [...instrumental]
        newInstrumentalState[newInstrumentalState.find(
            instrument => instrument.name === instrumentName
            )] = newInstrumentState
        setInstrumental(newInstrumentalState)
    }
    
    //id del set interval
    let intervalo;
    //plays the interval and increases the currentStep state
    const play = () =>{
        sounds.pebbel.play();
        let step = -1
        console.log("started")
        const stepper = () => {
            if (step === 31){
                step = 0
            } else {
                step  = 1
            }
            setStep(step)
        }
        intervalo = setInterval(stepper,tempo)
        setIntervalState(intervalo)
        setIsPlaying(true)
    }
    //clear interval to stop
    const stop = () => {
        sounds.pebbel.play();
        clearInterval(intervalState)
        setIsPlaying(false)
        console.log("stoped") 
    }  
    return (
        <>
        <h1 className="title">D R U M S</h1>
        <div className="drum-machine">
            <div className="buttons-container">
                {isPlaying ? <BsPauseFill className="btn danger" onClick={() =>{stop()}}/> :<BsFillPlayFill className="btn success" onClick={() =>{ play();}}/>}
                <input type="number"  onKeyPress={(e) => e.key === "Enter" ? setTempo(15000 / parseInt(e.target.value)) : undefined}/>
            </div>
            <div className="instruments-container">
                {instrumental.map((instrument, instrumentIndex)=>{
                    return <div key={instrumentIndex} className="instrument-container">
                        <p className="instrument-name">{instrument.name}</p>
                        <div className="bulb" style={{background: `${instrument.steps[currentStep] === 1 ? "#a95013" : "none"}`}}></div>
                        <div className="instrument-rack">
                            {instrument.steps.map((step, stepIndex)=>{
                                let lit = "";
                                let jump = "0";
                                if (stepIndex === currentStep){
                                    lit = "#a33e2a"
                                    if (step === 1 amp;amp; isPlaying){
                                        instrument.audio.play()
                                        jump = "-6px"
                                    }
                                }
                                return (
                                    <div 
                                        className="slot"
                                        style={{background: lit, marginLeft: `${stepIndex % 4 === 0 ? "8px" : "0px"}`, transform: `translateY(${jump})` }} 
                                        onClick={() => {toggleSound(stepIndex, instrument.name); instrument.audio.play()}} 
                                        key={stepIndex}
                                        >
                                            {step === 1 ? <IoMdMusicalNote className="beat-btn"/> : <AiFillCaretDown className="slot-btn"/> }
                                    </div>
                                )
                            })}   
                        </div>
                    </div>
                })}
            </div>
        </div>
        </>
    )
}


export default App