gpt4 book ai didi

javascript - 使用 JavaScript 播放 PCM16 时声音饱和

转载 作者:行者123 更新时间:2023-11-28 07:50:51 26 4
gpt4 key购买 nike

我正在尝试使用 AudioContext 对象播放原始 PCM16 缓冲区。声音确实播放了,但是非常饱和。

问题可能来自于将无符号 16 位整数转换为 [-1.0 ; 1.0] float ,但我没有发现我所做的有任何问题。

我在下面制作了一个最小的 html 示例以方便复制。可以使用以下命令从 MP3 文件获取 output.raw 文件:

MP3FILE=myfile.mp3
ffmpeg -i $MP3FILE -f s16le -ac 1 -acodec pcm_s16le output.raw

我使用 Linux Chromium 版本 38.0.2125.111 (290379)(64 位)

感谢您的帮助!

编辑:直接加载 PCM32 (s32le) 样本也会出现同样的问题。

<html>

<head>
</head>

<body>
<script>
var oReq = new XMLHttpRequest();
oReq.open("GET", "output.raw", true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
var context = new window.AudioContext();

var pcm16Buffer = new Uint16Array(oReq.response);
var frameCount = pcm16Buffer.length;
var channels = 1;
var buffer = context.createBuffer(channels, frameCount, context.sampleRate);

for (var channel = 0; channel < channels; ++channel) {
var channelBuffer = buffer.getChannelData(channel);
for (var i = 0; i < frameCount; ++i) {
channelBuffer[i] = pcm16Buffer[i] * 2 / 65535 - 1;
}
}

var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start();
};

function run() {
oReq.send();
}
</script>
<a href="javascript:run()">run</a>
</body>

</html>

答案:上面将 PCM16 转换为 PCM32 的 for 循环是不正确的,因为它没有正确转换二进制补码。

最佳答案

您让 ffmpeg 输出带符号的 16 位数据,但随后您通过 Uint16Array 类型数组(无符号 16 位)在 JavaScript 中读取它。这不会将文件中的 -32k 到 +32k 值转换为 0 到 64k;值存储在two's complement中因此负值将显示为大的正值。您首先需要做的是将 pcm16Buffer 更改为 Int16Array

到 float 的转换就可以很简单

channelBuffer[i] = pcm16Buffer[i] / 32768;

关于javascript - 使用 JavaScript 播放 PCM16 时声音饱和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26819525/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com