改变audio采样数据改变音频音量实例页面
回到相关文章 »效果:
原始音频
//zxx: 原始音频音量较大,播放前请注意周围环境
生成新的音频
代码:
HTML代码:
<h4>原始音频</h4> <audio src="./bgmusic.mp3" controls></audio> <h4>生成新的音频</h4> <button id="button">生成20%音量音频</button> <div id="output" class="output"></div>
JS代码:
// 音量
const volume = 0.2;
// 定义一个AudioContext对象
// 因为 Web Audio API都是源自此对象
const audioContext = new AudioContext();
// 降低音量后的audioBuffer数据
let newAudioBuffer = null;
// 获取音频资源
fetch('./bgmusic.mp3')
.then(res => res.arrayBuffer())
.then(buffer => audioContext.decodeAudioData(buffer))
.then(audioBuffer => {
newAudioBuffer = new AudioBuffer({
length: audioBuffer.length,
numberOfChannels: audioBuffer.numberOfChannels,
sampleRate: audioBuffer.sampleRate
});
for (let channel = 0; channel < audioBuffer.numberOfChannels; channel += 1) {
const channelData = audioBuffer.getChannelData(channel);
const copiedChannelData = newAudioBuffer.getChannelData(channel);
for (let sample = 0; sample < channelData.length; sample += 1) {
copiedChannelData[sample] = channelData[sample] * volume;
}
}
});
// Convert AudioBuffer to a Blob using WAVE representation
function bufferToWave(abuffer, len) {
var numOfChan = abuffer.numberOfChannels,
length = len * numOfChan * 2 + 44,
buffer = new ArrayBuffer(length),
view = new DataView(buffer),
channels = [], i, sample,
offset = 0,
pos = 0;
// write WAVE header
// "RIFF"
setUint32(0x46464952);
// file length - 8
setUint32(length - 8);
// "WAVE"
setUint32(0x45564157);
// "fmt " chunk
setUint32(0x20746d66);
// length = 16
setUint32(16);
// PCM (uncompressed)
setUint16(1);
setUint16(numOfChan);
setUint32(abuffer.sampleRate);
// avg. bytes/sec
setUint32(abuffer.sampleRate * 2 * numOfChan);
// block-align
setUint16(numOfChan * 2);
// 16-bit (hardcoded in this demo)
setUint16(16);
// "data" - chunk
setUint32(0x61746164);
// chunk length
setUint32(length - pos - 4);
// write interleaved data
for(i = 0; i < abuffer.numberOfChannels; i++)
channels.push(abuffer.getChannelData(i));
while(pos < length) {
// interleave channels
for(i = 0; i < numOfChan; i++) {
// clamp
sample = Math.max(-1, Math.min(1, channels[i][offset]));
// scale to 16-bit signed int
sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767)|0;
// write 16-bit sample
view.setInt16(pos, sample, true);
pos += 2;
}
// next source sample
offset++
}
// create Blob
return new Blob([buffer], {type: "audio/wav"});
function setUint16(data) {
view.setUint16(pos, data, true);
pos += 2;
}
function setUint32(data) {
view.setUint32(pos, data, true);
pos += 4;
}
}
// 点击按钮播放
button.onclick = function () {
const blob = bufferToWave(newAudioBuffer, newAudioBuffer.length);
const blobUrl = URL.createObjectURL(blob);
output.innerHTML = `<audio src="${blobUrl}" controls></audio>
<p><a href="${blobUrl}" download="bgmusic-volume-down.wav">下载该音频</a></p>
`;
};