在 javascript 中将 Float32Array 转换为 base64

Convert Float32Array to base64 in javascript

有很多关于将 blob 或 Uint8Array 转换为 base64 的问答。但我一直无法找到如何将 32 位数组转换为 base64。这是一个尝试。

function p(msg) { console.log(msg) }

let wav1 = [0.1,0.2,0.3]
let wav = new Float32Array(wav1)
p(`Len array to encrypt=${wav.length}`)
let omsg = JSON.stringify({onset: { id: 'abc', cntr: 1234}, wav: atob(wav) })
p(omsg)

atob 给出:

 Uncaught InvalidCharacterError: Failed to execute 'atob' on 'Window': 
 The string to be decoded is not correctly encoded."

需要什么中间步骤才能将浮点数正确编码为 base64?请注意,我也尝试过 TweetNacl-util 而不是 atob 这种方式:

 nacl.util.encodeBase64(wav)

这会导致同样的错误。

Update 使用 JSON.stringify 直接将每个 float 元素转换为它的 ascii 等价物 - 这会膨胀 datasize 。对于上面的是:

"0.10000000149011612,"1":0.20000000298023224,"2":0.30000001192092896

我们正在传输大型数组,因此这是一个次优解决方案。

Update 已接受答案中解决方案的关键要素是使用 Float32Array(floats).buffer 。我不知道 buffer 属性。

您当前代码的问题是 nacl.util.encodeBase64() 接收字符串、数组或 Uint8Array。由于您的输入不是 Array 或 Uint8Array,它假定您希望将其作为字符串传递。

解决办法当然是先编码成Uint8Array,再将Uint8Array编码成base64。解码时,首先将 base64 解码为 Uint8Array,然后将 Uint8Array 转换回 Float32Array。这可以使用 JavaScript ArrayBuffers.

来完成
const floatSize = 4;

function floatArrayToBytes(floats) {
    var output = floats.buffer; // Get the ArrayBuffer from the float array
    return new Uint8Array(output); // Convert the ArrayBuffer to Uint8s.
}

function bytesToFloatArray(bytes) {
    var output = bytes.buffer; // Get the ArrayBuffer from the Uint8Array.
    return new Float32Array(output); // Convert the ArrayBuffer to floats.
}

var encoded = nacl.util.encodeBase64(floatArrayToBytes(wav)) // Encode
var decoded = bytesToFloatArray(nacl.util.decodeBase64(encoded)) // Decode

如果您不喜欢函数,这里有一些 one-liners!

var encoded = nacl.util.encodeBase64(new Uint8Array(wav.buffer)) // Encode
var decoded = new Float32Array(nacl.util.decodeBase64(encoded).buffer) // Decode