2
3

ボイスチェンジャーゲーム。

Posted at

ボイスチェンジャーゲーム。

スクリーンショット 2024-09-30 044738.png

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ボイスチェンジャー</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin-top: 50px;
        }
    </style>
</head>
<body>
    <h1>ボイスチェンジャー</h1>
    <!-- マイクをオンにするボタン -->
    <button id="startButton">マイクをオンにする</button>
    <br><br>
    <!-- 声の高さを変更するスライダー -->
    <label for="pitchSlider">声の高さ:</label>
    <input type="range" id="pitchSlider" min="0.5" max="2" step="0.1" value="1">
    <span id="pitchValue">1</span>

    <script>
        // グローバル変数の宣言
        let audioContext;       // オーディオコンテキスト
        let microphone;         // マイク入力を表すオブジェクト
        let scriptProcessor;    // 音声データを処理するためのスクリプトプロセッサ
        let pitchFactor = 1;    // 声の高さを調整するための係数(初期値は1)

        // 「マイクをオンにする」ボタンがクリックされたときの処理
        document.getElementById('startButton').addEventListener('click', startMicrophone);
        // スライダーの値が変わったときの処理
        document.getElementById('pitchSlider').addEventListener('input', updatePitch);

        // マイク入力を開始し、音声データの処理を開始する関数
        function startMicrophone() {
            // Web Audio API のオーディオコンテキストを作成
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
            
            // ユーザーのマイク入力を取得するためのメディアデバイスAPI
            navigator.mediaDevices.getUserMedia({ audio: true })
                .then(stream => {
                    // マイク入力をオーディオコンテキストに接続
                    microphone = audioContext.createMediaStreamSource(stream);
                    // ScriptProcessorNodeを作成し、音声処理を行うバッファを設定
                    scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1);
                    // マイク入力をスクリプトプロセッサに接続
                    microphone.connect(scriptProcessor);
                    // スクリプトプロセッサをオーディオ出力(スピーカー)に接続
                    scriptProcessor.connect(audioContext.destination);
                    // オーディオデータが処理されるたびに呼ばれる関数を設定
                    scriptProcessor.onaudioprocess = processAudio;
                })
                .catch(err => {
                    // マイクの取得に失敗した場合のエラーハンドリング
                    console.error('マイクの取得に失敗しました:', err);
                });
        }

        // オーディオデータをリアルタイムで処理する関数
        function processAudio(event) {
            // 入力バッファからチャンネルデータを取得(マイクからの音声データ)
            const inputBuffer = event.inputBuffer.getChannelData(0);
            // 出力バッファを取得(処理後の音声データを格納)
            const outputBuffer = event.outputBuffer.getChannelData(0);

            // 入力バッファの各サンプルを処理してピッチを変更
            for (let i = 0; i < inputBuffer.length; i++) {
                // ピッチを変更するためにインデックスを調整
                const index = Math.floor(i * pitchFactor);
                // 入力データのインデックスがバッファの範囲内であることを確認
                outputBuffer[i] = inputBuffer[index < inputBuffer.length ? index : inputBuffer.length - 1];
            }
        }

        // スライダーの値が変わったときに呼び出される関数
        function updatePitch() {
            // スライダーの値を取得し、pitchFactorに設定
            pitchFactor = document.getElementById('pitchSlider').value;
            // 現在のピッチ係数を表示
            document.getElementById('pitchValue').textContent = pitchFactor;
        }
    </script>
</body>
</html>

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3