sing-song-player-3vx0f39v / test-speed.html
soiz1's picture
Create test-speed.html
f18867c verified
raw
history blame
3.22 kB
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Audio Combine Speed Test</title>
<style>
body { font-family: sans-serif; padding: 20px; }
button { margin: 10px 0; padding: 5px 10px; }
.result { margin-top: 15px; }
</style>
</head>
<body>
<h1>音声合成速度比較テスト</h1>
<p>対象ファイル: p.mp3, a.mp3, t.mp3, s.mp3, k.mp3</p>
<button id="test-button">速度比較を実行</button>
<div class="result">
<p id="loop-result">従来ループ方式: 未測定</p>
<p id="offline-result">OfflineAudioContext方式: 未測定</p>
</div>
<script>
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const audioFiles = ['p', 'a', 't', 's', 'k'];
const basePath = './t/'; // mp3ファイルのパス(必要に応じて変更)
// fetch & decode helper
async function loadAudioBuffer(file) {
const res = await fetch(`${basePath}${file}.mp3`);
const buf = await res.arrayBuffer();
return await audioContext.decodeAudioData(buf);
}
// --- 従来ループ方式 ---
async function combineByLoop(buffers) {
const maxDuration = Math.max(...buffers.map(b => b.duration));
const combined = audioContext.createBuffer(
2, Math.ceil(audioContext.sampleRate * maxDuration), audioContext.sampleRate
);
buffers.forEach(buffer => {
for (let ch = 0; ch < 2; ch++) {
const input = buffer.getChannelData(ch % buffer.numberOfChannels);
const output = combined.getChannelData(ch);
for (let i = 0; i < input.length; i++) {
output[i] += input[i]; // 音量=1固定
}
}
});
return combined;
}
// --- OfflineAudioContext方式 ---
async function combineByOffline(buffers) {
const maxDuration = Math.max(...buffers.map(b => b.duration));
const offline = new OfflineAudioContext(
2, Math.ceil(audioContext.sampleRate * maxDuration), audioContext.sampleRate
);
buffers.forEach(buffer => {
const src = offline.createBufferSource();
src.buffer = buffer;
const gain = offline.createGain();
gain.gain.value = 1.0; // 音量=1固定
src.connect(gain).connect(offline.destination);
src.start(0);
});
return await offline.startRendering();
}
// --- 実行処理 ---
document.getElementById('test-button').addEventListener('click', async () => {
document.getElementById('loop-result').textContent = "従来ループ方式: 実行中...";
document.getElementById('offline-result').textContent = "Offline方式: 実行中...";
// すべてのバッファを読み込み
const buffers = await Promise.all(audioFiles.map(f => loadAudioBuffer(f)));
// 従来方式
let start = performance.now();
await combineByLoop(buffers);
let end = performance.now();
document.getElementById('loop-result').textContent =
`従来ループ方式: ${(end - start).toFixed(2)} ms`;
// Offline方式
start = performance.now();
await combineByOffline(buffers);
end = performance.now();
document.getElementById('offline-result').textContent =
`Offline方式: ${(end - start).toFixed(2)} ms`;
});
</script>
</body>
</html>