在 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
有很多关于将 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