JS音频倍速后音调发生变化实例页面

回到相关文章 »

效果:

原始音频

选择播放速率:

转换音频预览

代码:

HTML代码:
<h4>原始音频</h4>
<p>
    <audio src="/study/201812/audio/zxx-comic-01.mp3" controls></audio>
</p>

<p>选择播放速率:</p>
<p>
    <label><input type="radio" name="rate" value="0.5">0.5倍速</label>
    <label><input type="radio" name="rate" value="1" checked>1倍速</label>
    <label><input type="radio" name="rate" value="1.5">1.5倍速</label>
    <label><input type="radio" name="rate" value="2">2倍速</label>
</p>

<p>
    <button class="button">开始转换</button>
</p>

<h4>转换音频预览</h4>
<p>
    <audio id="audio" controls></audio>
</p>
JS代码:
<script type="module">
    import bufferToWav from './buffer2wav.js';

    // 原始音频的AudioBuffer
    let originAudioBuffer;
    
    const eleAudio = document.querySelector('audio');

    // 获取原始音频的audiobuffer数据
    fetch(eleAudio.src)
        .then(response => response.arrayBuffer())
        .then(arrayBuffer => new AudioContext().decodeAudioData(arrayBuffer))
        .then(audioBuffer => {
            // 获取原始音频的采样率
            originAudioBuffer = audioBuffer;
        });

    // 点击按钮
    document.querySelector('button').onclick = () => {
        // 获取选中的倍速
        const rate = document.querySelector('input[name="rate"]:checked').value * 1;
    
        // 创建新的AudioBuffer
        const audioBuffer = new AudioContext().createBuffer(
            originAudioBuffer.numberOfChannels,
            originAudioBuffer.length / rate,
            originAudioBuffer.sampleRate
        );
        
        // 复制原始音频的数据到新的AudioBuffer
        for (let channel = 0; channel < originAudioBuffer.numberOfChannels; channel++) {
            const originChannelData = originAudioBuffer.getChannelData(channel);
            const newChannelData = audioBuffer.getChannelData(channel);
            for (let i = 0; i < audioBuffer.length; i += 1) {
                 newChannelData[i] = originChannelData[Math.floor(i * rate)] || 0;
            }
        }
        
        // 创建新的音频
        const audio = document.querySelector('#audio');
        const blob = bufferToWav(audioBuffer, audioBuffer.length);
        const audioURL = URL.createObjectURL(blob, { type: 'audio/wav' });
        audio.src = audioURL;
    };
</script>