javascript 从Array tone.js创建振荡器

wdebmtf2  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(115)

我在使用Tone.js从buffer对象创建声音时遇到了一些困难
这应该很简单,但我在不熟悉的领域。越来越无用的建议,从chatGPT困惑我非常。
下面是代码(我知道代码有点乱,很抱歉,我甚至不能简化它)

import React, { useEffect, useState } from 'react';
import * as Tone from 'tone';

function AudioPlayer() {
  const [isPlaying, setIsPlaying] = useState(false);
  const chunkSize = 1024;
  const bufferArray = new Float32Array(chunkSize);
  const sampleRate = 16384;
  let t = 0;
  let x = 0;
  const context = Tone.context;
  const buffer = context.createBuffer(1, chunkSize, sampleRate);
// const source = context.createBufferSource(); <= do I really need this!
  const player = new Tone.Player(buffer).toDestination();

  useEffect(() => {

    while (isPlaying){
      for (let i = 0; i < chunkSize; i++) {
        bufferArray[i] = Math.sin(2 * Math.PI * 440 * x);
        t++;
        x = t / sampleRate;
      }
      // buffer.fromArray(bufferArray); <= is there a simple method that just override on buffer? 
    }

    
  }, [isPlaying]);

  const handlePlayClick = async () => {
    setIsPlaying(true);
    player.start()
    
  };

  const handleStopClick = () => {
    setIsPlaying(false);
    player.stop()
  };

  return (
    <div>
      {!isPlaying && (
        <button onClick={handlePlayClick}>Play</button>
      )}
      {isPlaying && (
        <button onClick={handleStopClick}>Stop</button>
      )}
    </div>
  );
}

export default AudioPlayer;

我只想填充buffer(bufferArray[chunkSize])并覆盖bufferArray并连续播放它。

vngu2lb8

vngu2lb81#

我几乎不知道我在做什么,我不确定我是否理解这个问题,但我玩了一点;以下内容有帮助吗?:

const sampleRate = 16384;

const get_audio_buffer = () => {
  return Tone.context.createBuffer(
    1,
    sampleRate,
    sampleRate
  );
};

const populate_audio_buffer = (buffer) => {
  const nowBuffering = buffer.getChannelData(0);
  
  for(let i = 0; i < buffer.length; i++) {
    nowBuffering[i] = Math.sin(2 * Math.PI * i * 440 / sampleRate);
  }
};

function AudioPlayer() {
  const [isPlaying, setIsPlaying] = React.useState(false);
  const player = React.useRef(null);
  
  if(!player.current) {
    const buffer = get_audio_buffer();
    populate_audio_buffer(buffer);
    
    player.current = new Tone.Player(buffer).toDestination();
    player.current.loop = true;
  }

  const handlePlayClick = () => {
    setIsPlaying(true);
    player.current.start();
  };

  const handleStopClick = () => {
    setIsPlaying(false);
    player.current.stop();
  };

  return (
    <div>
      {!isPlaying && (
        <button onClick={handlePlayClick}>Play</button>
      )}
      {isPlaying && (
        <button onClick={handleStopClick}>Stop</button>
      )}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<AudioPlayer />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.min.js"></script>

<div id="app"></div>

我看的东西:

juud5qan

juud5qan2#

这里有一个答案-不完全是,但工作-为我问的问题。

import React, { useEffect, useState } from 'react';

function AudioPlayer() {
  const [isPlaying, setIsPlaying] = useState(false);
  const [audioCtx, setAudioCtx] = useState(false);
  const [oscillator, setOscillator] = useState(null);
  // const audioDataArray = [-1, 1]//[...Array(4)].map(e => Math.random(-1, 1));
  const [audioDataArray, setAudioDataArray] = useState([-1, 1]);

  useEffect(() => {
    // Create an oscillator and set the waveform to the custom audio data array
    if (!isPlaying){
      const ac = new AudioContext();
      setAudioCtx(ac)
      const oscillator = ac.createOscillator();
      const real = new Float32Array(audioDataArray);
      const imag = new Float32Array(audioDataArray.length).fill(0);
      const wave = ac.createPeriodicWave(real, imag);
      oscillator.setPeriodicWave(wave);
      console.log(oscillator)
      oscillator.connect(ac.destination);
      setOscillator(oscillator);
    }

  }, [isPlaying]);

  useEffect(() => {
    // Update the audio data array with new random values every 100 milliseconds
    const intervalId = setInterval(() => {
      const newAudioDataArray = [...Array(4)].map(e => Math.random(-1, 1));
      setAudioDataArray(newAudioDataArray);
    }, 100);

    return () => {
      clearInterval(intervalId);
    };
  }, []);

  const handlePlayClick = () => {
    if (!isPlaying && oscillator) {
      setIsPlaying(true);
      oscillator.start();
    }
  };

  const handleStopClick = () => {
    if (isPlaying && oscillator) {
      setIsPlaying(false);
      oscillator.stop();
      oscillator.disconnect();
      setOscillator(null);
    }
  };

  const handleUpdateClick = () => {
    if (oscillator) {
      const real = new Float32Array(audioDataArray);
      const imag = new Float32Array(audioDataArray.length).fill(0);
      const wave = audioCtx.createPeriodicWave(real, imag);
      oscillator.setPeriodicWave(wave);
    }
  };

  return (
    <div>
      <button onClick={handlePlayClick}>Play</button>
      <button onClick={handleStopClick}>Stop</button>
      <button onClick={handleUpdateClick}>Update Waveform</button>
    </div>
  );
}

export default AudioPlayer;

相关问题