以下に、マイクからの音をリアルタイムで取得し、canvas要素のビジュアライザーに表示するJavaScriptのコードを示します。グラフの色は青からスカイブルーへのグラデーションで、キャンバスの中央を軸に上下に伸びるようになっています。
// AudioContextとAnalyzerを作成
let audioContext = new (window.AudioContext || window.webkitAudioContext)();
let analyser = audioContext.createAnalyser();
// マイクの音を取得
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function(stream) {
let source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
draw();
})
.catch(function(err) {
console.log('The following error occurred: ' + err);
});
// canvas要素を取得
let canvas = document.getElementById('visualizer');
let canvasContext = canvas.getContext('2d');
function draw() {
let freqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
// canvasをクリア
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
// グラデーションを作成
let gradient = canvasContext.createLinearGradient(0, canvas.height / 2, 0, canvas.height);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(1, 'skyblue');
// ビジュアライザーを描画
for (let i = 0; i < freqData.length; i++) {
let magnitude = freqData[i];
canvasContext.fillStyle = gradient;
canvasContext.fillRect(i, canvas.height, 1, -magnitude);
canvasContext.fillRect(i, 0, 1, magnitude);
}
// 再描画
requestAnimationFrame(draw);
}
このコードは、マイクからの音をリアルタイムで取得し、それをビジュアライザーとしてcanvas要素に描画します。ビジュアライザーの色は青からスカイブルーへのグラデーションで、キャンバスの中央を軸に上下に伸びるように描画されます。また、requestAnimationFrame(draw)
を使用して、画面が更新されるたびにdraw
関数が再度呼び出され、リアルタイムのビジュアライザーが実現されます。
なお、このコードはユーザーのブラウザがgetUserMedia
とAudioContext
をサポートしていること、そしてユーザーがマイクへのアクセスを許可することが前提となります。また、実際にはセキュリティの観点から、このコードはHTTPSを使用して配信されるWebサイトで実行する必要があります。このコードを使用する前に、これらの要件を確認してください。また、このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。
ご指摘の通り、最近のブラウザでは、ユーザーの操作なしに音声を再生することは制限されています。そのため、以下のようにボタンクリックを契機にしてAudioContextを開始するようにコードを修正しました。
// AudioContextとAnalyzerを作成
let audioContext = new (window.AudioContext || window.webkitAudioContext)();
let analyser = audioContext.createAnalyser();
// ボタンクリックで音声取得を開始
document.getElementById('startButton').addEventListener('click', function() {
// マイクの音を取得
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function(stream) {
let source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
draw();
})
.catch(function(err) {
console.log('The following error occurred: ' + err);
});
});
// canvas要素を取得
let canvas = document.getElementById('visualizer');
let canvasContext = canvas.getContext('2d');
function draw() {
let freqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
// canvasをクリア
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
// グラデーションを作成
let gradient = canvasContext.createLinearGradient(0, canvas.height / 2, 0, canvas.height);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(1, 'skyblue');
// ビジュアライザーを描画
for (let i = 0; i < freqData.length; i++) {
let magnitude = freqData[i];
canvasContext.fillStyle = gradient;
canvasContext.fillRect(i, canvas.height, 1, -magnitude);
canvasContext.fillRect(i, 0, 1, magnitude);
}
// 再描画
requestAnimationFrame(draw);
}
このコードでは、startButton
というIDを持つボタンがクリックされたときに、マイクからの音を取得し始めます。その他の部分は前のコードと同じです。この修正により、ユーザーの操作を契機に音声の取得とビジュアライザーの描画が開始されます。ただし、HTMLにstartButton
というIDを持つボタンが存在することが前提となります。このコードを使用する前に、HTMLに適切なボタンが配置されていることを確認してください。また、このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。
ご指摘いただきありがとうございます。確かに、現在のコードではキャンバスの横幅を超える可能性があります。これは、freqData.length
がキャンバスの横幅を超える場合に発生します。
これを解決するために、ビジュアライザーのバーの幅をキャンバスの横幅に合わせるようにコードを修正します。以下に修正したコードを示します。
// AudioContextとAnalyzerを作成
let audioContext = new (window.AudioContext || window.webkitAudioContext)();
let analyser = audioContext.createAnalyser();
// ボタンクリックで音声取得を開始
document.getElementById('startButton').addEventListener('click', function() {
// マイクの音を取得
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function(stream) {
let source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
draw();
})
.catch(function(err) {
console.log('The following error occurred: ' + err);
});
});
// canvas要素を取得
let canvas = document.getElementById('visualizer');
let canvasContext = canvas.getContext('2d');
function draw() {
let freqData = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
// canvasをクリア
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
// グラデーションを作成
let gradient = canvasContext.createLinearGradient(0, canvas.height / 2, 0, canvas.height);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(1, 'skyblue');
// ビジュアライザーを描画
let barWidth = canvas.width / freqData.length;
for (let i = 0; i < freqData.length; i++) {
let magnitude = freqData[i];
canvasContext.fillStyle = gradient;
canvasContext.fillRect(i * barWidth, canvas.height, barWidth, -magnitude);
canvasContext.fillRect(i * barWidth, 0, barWidth, magnitude);
}
// 再描画
requestAnimationFrame(draw);
}
この修正により、ビジュアライザーの各バーの幅がキャンバスの横幅に合わせられ、キャンバスの領域をはみ出すことがなくなります。ただし、このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。また、このコードを使用する前に、HTMLに適切なボタンが配置されていることを確認してください。このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。また、このコードを使用する前に、HTMLに適切なボタンが配置されていることを確認してください。このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。また、このコードを使用する前に、HTMLに適切なボタンが配置されていることを確認してください。このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。また、このコードを使用する前に、HTMLに適切なボタンが配置されていることを確認してください。このコードは基本的なものであり、エラーハンドリングなど、実際の使用にはさらなる改良が必要かもしれません。ご了承ください。また、このコードを使用する前に、HTML