首页 > 解决方案 > 在 javascript 中将 Float32Array 转换为 base64

问题描述

Uint8Array有很多关于将 blob 转换为 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 UsingJSON.stringify直接将每个 float 元素转换为其 ascii 等效项 - 这会使 datasize 膨胀。对于以上内容:

“0.10000000149011612”,“1”:0.20000000298023224,“2”:0.30000001192092896

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

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

标签: javascriptbase64

解决方案


您当前代码的问题在于它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

如果你不喜欢函数,这里有一些单行代码!

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

推荐阅读