在保留 IEEE 754 表示的同时将 Float32Array 转换为 Uint8Array

Converting Float32Array to Uint8Array while Preserving IEEE 754 Representation

我有一个来自 decodeAudioData 方法的 float32Array,我想将其转换为 Uint8Array,同时保留 float32 IEEE 754 音频数据

到目前为止我试过了,

var length = float32Array.length;

var emptyBuffer = new ArrayBuffer(length * 4);
var view = new DataView(emptyBuffer);

for (var i = 0; i < length; i++) {
  view.setFloat32(i * 4, float32Array[i], true);
}

var outputArray = new Uint8Array(length);

for (var j = 0; j < length; j++) {
  outputArray[j] = view.getUint8(j * 4);
}

return outputArray;

编辑:

我只需要像这个 answer.

一样坚持二进制表示

你问的不是很清楚;或者,更确切地说,出现 你问的是一件毫无意义的事情。

A Float32Array 实例是 "raw" 字节值缓冲区的视图,就像所有类型化数组一样。数组的每个元素代表这些原始字节中的 4 个。通过简单的数组查找提取值:

var n = float32array[1];

隐含地将这 4 个字节解释为 IEEE 32 位浮点值,然后将该值转换为标准 JavaScript 数字。 JavaScript 数字始终是 64 位 IEEE 浮点值。

类似地,Uint8Array 是缓冲区的视图,每个元素给出一个字节的无符号整数值。也就是说,

var n = uint8array[1];

访问该元素,将其解释为无符号 one-byte 整数,并将其转换为 JavaScript 数字。

因此:如果您想检查 32 位浮点值列表作为每个字节的原始整数值,您可以创建一个 Uint8Array 与 "shares" 相同的缓冲区Float32Array:

var uintShared = new Uint8Array(float32array.buffer);

您从 Uint8Array 值中看到的数值与您从 Float32Array 元素中获得的数值似乎没有任何关系,即意料之中。

另一方面,如果您想创建一个新的 Uint8Array 来保存 Float32Array 中明显的 ,您只需创建一个相同长度的新数组并复制每个值:

var uintCopy = new Uint8Array(float32array.length);
for (let i = 0; i < float32array.length; ++i)
  uintCopy[i] = float32array[i]; // deeply problematic; see below

一般来说,这不会太有效,因为 Float32Array 中数值的数值范围远远大于 Uint8Array 中数值的数值范围。一方面,32 位浮点值可以是负数。更重要的是,即使你知道浮点值都是 0 到 255 范围内的整数,你也肯定不会在 Uint8Array 中得到相同的位模式,原因很简单,32 位浮点number 与 8 位无符号整数不同。 "preserve the IEEE-754 representation" 毫无意义。

这就是现实情况。如果您要解释 为什么 您认为您想以某种方式将 32 位 IEEE 浮点数的所有 32 位塞入一个 8 位无符号整数,则可以提供更直接的有帮助的答案。

var output = new Uint8Array(float32Array.length);

for (var i = 0; i < float32Array.length; i++) {
  var tmp = Math.max(-1, Math.min(1, float32Array[i]));
  tmp = tmp < 0 ? (tmp * 0x8000) : (tmp * 0x7FFF);
  tmp = tmp / 256;
  output[i] = tmp + 128;
}

return output;

任何有疑问的人都可以使用 Audacity 导入原始数据 功能轻松测试。

  1. 下载我使用 Web Audio Api 的 decodeAudioData 方法从视频文件解码的 sample raw data
  2. sample raw data填充的Float32Array用上面的方法转换成Uint8Array(或者用自己的方法比如new Uint8Array(float32Array.buffer)听到损坏的嘶嘶声)并下载 uint8 pcm 文件。

    forceDownload(new Blob([output], { type: 'application/octet-binary' }));

  3. 在 Audacity 中使用 File-> Import -> Raw Data 对下载的数据进行编码... 编码应设置为 Unsigned 8 -bit PCM 和采样率应为 16000 Hz,因为原始解码音频文件为 16000 Hz。