<!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>