easy-three

create.audio

create.audio(audioFileURL, props : Object) : { Audio, AudioAnalyser }

audioFileURL - サウンドファイルのURL。
props - 設定オブジェクト。
  • loop (Boolean) : ループ再生設定 (デフォルト : true)。
  • volume (Number) : 音量 (デフォルト : 0.5)。
  • target (Object) : サウンドを再生する対象のオブジェクト (デフォルト : camera)。
  • fftSize (Number) : AudioAnalyser の fftSize (デフォルト : 128)。
  • onLoad (Function) : サウンドのロード完了時に呼ばれるコールバック関数。
  • onError (Function) : サウンドのロードエラー時に呼ばれるコールバック関数。
  • onProgress (Function) : サウンドのロード進捗時に呼ばれるコールバック関数。

サウンドを再生するためのオーディオオブジェクトを作成します。

サウンドを再生するには、ユーザーの操作が必要です。
そのため、サウンドのロード完了時に自動で再生することはできません。
サウンドを再生するには、ユーザーの操作 (クリックやタップなど) をトリガーとして、Audio.play() メソッドを呼び出す必要があります。

React で利用する際は、useEffect の戻り値で Audio オブジェクトを破棄するようにしてください。
そのために audio.destroy() が用意されています。

コードの例

サウンドを再生する

以下のコードは、サウンドを再生するための基本的な例です。
サウンドのロード完了時に、ユーザーの操作 (クリックやタップなど) をトリガーとして、Audio.play() メソッドを呼び出すことで、サウンドを再生することができます。

const { camera, create, animate } = init()
camera.position.set(0, 0, 3);

create.ambientLight();
create.directionalLight();
create.sky()
const box = create.box();

// free sound (Neon Eternity) by mxNeko
const { audio } = create.audio("/easy-three/sound/neon_eternity.mp3")

animate(({ delta }) => {
  if (audio.isPlaying) {
    box.rotation.x += delta;
    box.rotation.y += delta;
  }
});

document.querySelector(".playButton").addEventListener("click", () => {
  if (audio.isPlaying) {
    audio.stop()
  } else {
    audio.play()
  }
})

周波数データを使う

analyser.getFrequencyData() メソッドを使うことで、サウンドの周波数データを取得することができます。
取得した周波数データを使って、オブジェクトのスケールや色を変化させることができます。

以下のコードは、サウンドの周波数データを使って、複数の立方体のスケールと色を変化させる例です。

const { camera, create, controls, animate } = init()
camera.position.set(0, 0, 3);
controls.connect();

create.ambientLight();
create.directionalLight();
create.sky()

const fftSize = 128;
// free sound (Neon Eternity) by mxNeko
const { audio, analyser } = create.audio("/easy-three/sound/neon_eternity.mp3", {
  fftSize: fftSize,
});

const cubeSize = 0.05;
const soundCubes = create.instances(
  create.cube({ size: cubeSize }),
  fftSize / 2,
  {
    position: [-(cubeSize*1.4) * fftSize / 4, 0, 0],
    offset: [(cubeSize*1.4), 0, 0]
  }
)

animate(({ delta }) => {
  if (audio.isPlaying) {
    for (let i = 0; i < soundCubes.count; i++) {
      const cube = soundCubes.at(i);
      const scale = analyser.getFrequencyData()[i] / 10;
      cube.scale.set(1, Math.max(scale, 0.01), 1);
      const position = cube.position.get();
      cube.position.set(
        position.x,
        cubeSize * scale / 2 - cubeSize / 2,
        position.z
      );
    }
  }
});

document.querySelector(".playButton").addEventListener("click", () => {
  if (audio.isPlaying) {
    audio.stop()
  } else {
    audio.play()
  }
})