要创建 24 位 WAV 文件,我需要做什么特别的事情吗?

Is there anything special I have to do to create a 24-bit WAV file?

我可以成功创建一个 16 位的 wav 文件,但是在创建一个 24 位的文件时,我听到的只是白噪声。我正在设置 24 位有符号整数数据块。我是否必须在 wav 文件头的字节 20 处设置一些特殊的音频格式?我目前使用格式 1。

编辑#1

wBitsPerSample字段设置为24。wAvgBytesPerSec(字节率)字段设置为

// 44100 * (2 * 3)
sampleRate * blockAlign

并且 wBlockAlign 设置为

// 2 * 3
numChannels * bytesPerSampe

Assuming you already did, the data itself needs to be 24-bit butt-to-butt (requires bit-shifting and masking unless the data already is from a 24-bit byte source). Or put differently: each sample will take 3 bytes. And as with 16-bit the byte-order matters.

不过我不知道这部分是否正确。

我的数据以 Float32 的形式出现,从 -1 到 1 (AudioBuffer.getChannelData())。然后我将它转换为 Int24:

function floatTo24BitPCM(output, offset, input) {
  for (var i = 0; i < input.length; i++, offset += 3) {
    var s = Math.floor(input[i] * 8388608 + 0.5)
    output.setInt24(offset, s, true)
  }
}

DataView.prototype.setInt24 = function(pos, val, littleEndian) {
    this.setInt16(pos, val >> 8, littleEndian);
    this.setInt8(pos+2, val & ~4294967040, littleEndian); // this "magic number" masks off the first 16 bits
}

这个过程是否符合规范(我似乎在 setInt24 中进行位移和屏蔽)?

编辑 #2

正在修改

DataView.prototype.setInt24 = function(pos, val, littleEndian) {
    this.setInt16(pos, val >> 8, littleEndian);
    this.setInt8(pos+2, val & ~4294967040, littleEndian); // this "magic number" masks off the first 16 bits
}

DataView.prototype.setUint24 = function(pos, val, littleEndian) {
    this.setUint8(pos, val & ~4294967040, littleEndian); // this "magic number" masks off the first 16 bits
    this.setUint16(pos + 1, val >> 8, littleEndian);
}

成功了。我假设字节顺序不正确?我很困惑为什么把最后一个字节放在前两个字节之前是正确的顺序。

我还建议重新打开这个问题,因为它足够窄,不再被视为 "broad"。

来自post中有限的语境-

字段 wBitsPerSample(在 fmt->fmt-ck 格式特定块内,对 wFormatTag 使用 1 (PCM) 很好)必须反映每个样本的位数,即。在这种情况下为 24。

假设您已经这样做了,数据本身需要是 24 位 butt-to-butt(需要 bit-shifting 和屏蔽,除非数据已经来自 24 位字节源)。或者换句话说:每个样本将占用 3 个字节。与 16 位一样,byte-order 很重要。

wAvgBytesPerSecwBlockAlign 与之前一样计算,只是使用新的位大小。