[Unity][WebGL]ブラウザゲームでマイク入力使いたーい(Microphone対策)

Unityを使ってWebGL向けのゲームを作っている真っ最中のふーすけです。
今作っているゲームは「マイク入力」を使って操作しようとしているのですが、WebGLでビルドしようとしたら問題に遭遇しまして…

なんと「Microphone」クラスはWebGL未対応でした!!!!!←

まぁちゃんと調べとけって話なんですが、調べたところ有料アセットだったり、Githubプロジェクトでプラグインを提供されてたりと、皆さん何かしらの回避方法で対応してらっしゃるらしいです。
どうしようかなーと思ったんですが、今回やりたいことは「マイク入力で周波数を取りたい」だけだし、ネイティブプラグイン作れるんじゃね?(JS未経験だけど!)と思ったのでチャレンジしてみました。

ということでChatGPTくんを駆使して、以下のネイティブプラグインを作ってみました。

// Unity WebGLビルドにマイク入力処理を追加
mergeInto(LibraryManager.library, {
  StartMicrophoneCapture: function () {
    console.log("* start StartMicrophoneCapture");
    // getUserMedia がサポートされているかチェック
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      console.error("***** getUserMedia is not supported");
      return;
    }

  // マイクの音声入力を取得
  navigator.mediaDevices.getUserMedia({ audio: true })
    .then(function (stream) {
      // AudioContext の作成(ブラウザ互換対応)
      const audioContext = new (window.AudioContext || window.webkitAudioContext)();
      // マイクストリームからオーディオノードを作成
      const micSource = audioContext.createMediaStreamSource(stream);
      // 音声処理ノードの作成(バッファサイズ: 1024サンプル, mono)
      const processor = audioContext.createScriptProcessor(1024, 1, 1);
      // 音声データが入力されるたびに呼ばれる処理
      processor.onaudioprocess = function (event) {
        // 左チャンネル(0)のデータを取得(Float32Array)
        const input = event.inputBuffer.getChannelData(0);

        // Unity側に渡せるように通常の配列へ変換
        const floatArray = Array.from(input);

        // Unity側の PitchDetector.OnMicPCMJson に送信
        if (typeof unityInstanceGlobal !== 'undefined') {
          console.log("***** sendMessage: OnMicPCMJson");
          unityInstanceGlobal.SendMessage("PitchDetector", "OnMicPCMJson", JSON.stringify(floatArray));
        } else {
          console.warn("***** unityInstanceGlobal is undefined!");
        }
      };

      // マイク入力 → 処理ノード → 出力先(スピーカー等)へ接続
      micSource.connect(processor);
      processor.connect(audioContext.destination);
    })
    .catch(function (err) {
      console.error("***** マイク取得失敗:", err);
    });
  }
});

とりあえず上記プラグインをUnity側で実行して呼び出したところ、ちゃんとブラウザで音声取得できました。
とはいえJavaScriptわからないマンなのでまだ自分でもお試し中です。
あまり内容は信用しないでくださいw(アドバイスはお待ちしております!)

おそらく上記コードをベースにこれから修正していきますが、
大きな変更点や考慮漏れ、不具合などがあれば、また記事にしたいと思います。

コメント

タイトルとURLをコピーしました