Как я могу определить время активации аудиофайла в зависимости от окончания дополнительного аудиофайла?

#reactjs #audio #react-hooks #use-state

Вопрос:

Я пишу циклическую машину ,предназначенную для циклирования нескольких звуковых дорожек. Функциональность, с которой я борюсь, заключается в активации аудиофайла, когда уже воспроизводится другая дорожка. Файл, который активируется позже, должен запуститься только после завершения цикла текущего воспроизводимого файла. Другими словами, ему нужно подождать, прежде чем он начнет играть, пока не завершится цикл другой песни. Только тогда они начнут играть одновременно.

Прямо сейчас я сохраняю логическое состояние с родителем («loopHasEnded»), которое изменяет свое значение по завершении цикла внутри дочернего элемента. Я пытаюсь запустить воспроизведение дополнительного файла в зависимости от того, верно ли значение «loopHasEnded» и другое логическое значение, указывающее, находится ли звуковая дорожка «в списке ожидания», т. Е. Я пытался активировать ее, но уже играла другая песня.

Что-то не работает, и у меня такое чувство, что это как-то связано с передачей информации между родителем и ребенком.

Родитель:

 import Header from './components/Header';
import React, { useState } from 'react';
import MusicBox from './components/MusicBox';
import { Play } from './components/Play';

import Bass from './music_files/Bass Warwick heavy funk groove on E 120 BPM.mp3';
import futureFunk from './music_files/120_future_funk_beats_25.mp3';
import stutterBeats from './music_files/120_stutter_breakbeats_16.mp3';
import electricGuitar from './music_files/electric guitar coutry slide 120bpm - B.mp3';
import StompySlosh from './music_files/FUD_120_StompySlosh.mp3';
import groove from './music_files/GrooveB_120bpm_Tanggu.mp3';
import MazePolitics from './music_files/MazePolitics_120_Perc.mp3';
import pas3 from './music_files/PAS3GROOVE1.03B.mp3';
import organSynth from './music_files/SilentStar_120_Em_OrganSynth.mp3';
import reactDom from 'react-dom';

function App() {
  const [counter, setCounter] = useState(0);
  const [loopHasEnded, setLoopHasEnded] = useState(true);
  const [audioClips, setAudioClips] = useState([
    { sound: Bass, label: 'Funky Bass', shouldBePlaying: false },
    { sound: stutterBeats, label: 'Stuttering Beats', shouldBePlaying: false },
    { sound: futureFunk, label: 'Future Funk', shouldBePlaying: false },
    { sound: StompySlosh, label: 'Stompin rythm', shouldBePlaying: false },
    { sound: electricGuitar, label: 'Electric country guitar', shouldBePlaying: false },
    { sound: groove, label: 'Groovyyy', shouldBePlaying: false },
    { sound: MazePolitics, label: 'The Maze', shouldBePlaying: false },
    { sound: pas3, label: 'Sachi drums', shouldBePlaying: false },
    { sound: organSynth, label: 'Psychedelic Organ', shouldBePlaying: false },
  ])

  const handleStart = value => setCounter(counter   1)
  const handleStop = value => setCounter(counter > 0 ? counter - 1 : 0)
  const startPlay = value => setLoopHasEnded(false)
  const endLoop = value => setLoopHasEnded(true)
  const updateArray = (i, needToPlay) => {
    let newArr = [...audioClips];
    console.log(`new array is`, { newArr })
    let clip = { ...newArr[i] }
    console.log(`chosen clip is`, { clip })
    clip.shouldBePlaying = needToPlay;
    newArr[i] = clip;
    setAudioClips(newArr);
  }
  const joinPlay = (start, shouldPlay) => {
    if (shouldPlay amp;amp; loopHasEnded) {
      console.log('WE ARE IN joinPlay')
      start()
    }
  }

  // const setLoopHasEndedSong = (index, playingNow) => {
  //   const audioClipsModified = [...audioClips];
  //   const clip = { ...audioClips[index] };
  //   clip.playing = playingNow;
  //   audioClipsModified[index] = clip;
  //   setAudioClips({ audioClipsModified });
  // }

  return (
    <div className="container">
      {audioClips.map((audio, i) => {
        return <Play key={i} index={i}  onStart={handleStart} onStop={handleStop} join={joinPlay} count={counter} changeShouldPlay={updateArray} anyPlaying={startPlay} loopEnd={endLoop} canJoin ={loopHasEnded}  audioClip={audio} />
      })}
    </div>
  );
}

export default App;

 

Ребенок:

 import React, { useState, useEffect } from 'react';
// import style from "srcstyle.js"
import { Spinnie } from './Spinner'
import Button from 'react-bootstrap/Button';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Card, Container } from 'react-bootstrap';
import { render } from '@testing-library/react';

export function Play(props) {
  const [currentlyPlaying, setCurrentlyPlaying] = useState(false);
  const  = useState(new Audio(props.audioClip.sound))
  const [shouldPlay, setShouldPlay] = useState(props.audioClip.shouldBePlaying)

  const start = () => {
    if (props.count === 0) {
      props.anyPlaying();//change 'loopHasEnded' value to false
      console.log(`has the loop ended? the answer:`,props.canJoin);
      setCurrentlyPlaying((currentlyPlaying) => (currentlyPlaying = true));
      props.onStart();//necessary, adds  1 to counter of active songs
      audio.play();
      audio.onended = function () {
        props.loopEnd();//change 'loopHasEnded' value to true
        console.log(`has the loop ended? the answer:`,props.canJoin);
        console.log('song ended');
        start();
      }
    }
    else {
      props.changeShouldPlay(props.index, true);
      // if someone else is playing then add this one to waiting list 
      // i.e. shouldBePlaying = true
    }
  }

  const joinPlay = () => {
    props.anyPlaying();
    setCurrentlyPlaying((currentlyPlaying) => (currentlyPlaying = true));
    props.onStart();///necessary, adds  1 to counter of active songs
    audio.play();
    audio.onended = function () {
      props.loopEnd();
      console.log('loop has ended');
      joinPlay();
    }
  }

  props.join(joinPlay, shouldPlay);

  const stop = () => {
    if (currentlyPlaying) {
      props.onStop();//necessary, subtracts -1 from counter of active songs
      setCurrentlyPlaying((currentlyPlaying) => (currentlyPlaying = false));;
      console.log('PRESSED STOP')
      console.log(audio)
      audio.pause()
      audio.currentTime = 0;
      props.changeShouldPlay(props.index, false);
    }
  }

  return (
    <div>
      <Container>
        <Card className='m-3'>
          <Card.Body>
            <Card.Title>Hear the sound of {props.audioClip.label}!: </Card.Title>
            <Button id="startMusic" onClick={start}  >Playyyy day</Button>
            <button id="stopMusic" onClick={stop}>Stop me!</button>
          </Card.Body>
          <Spinnie on={currentlyPlaying} />
        </Card>
      </Container >
    </div>
  );
}

export default Play