Javascript: UInt8Array to Float32Array - javascript

I have some audio buffer in usigned 8bit PCM format need to play via web audio which only accept signed 32bit PCM. And now I have ArrayBuffer for pieces of pcm_u8 data(come from Uint8array). How can I convert it to Float32Array?

ECMAScript 2015 and onwards has TypedArray.from which converts any typed array (and indeed, any iterable) to the specified typed array format.
So converting a Uint8Array to a Float32Array is now as easy as:
const intArray = new Uint8Array()
const floatArray = Float32Array.from(intArray)

This function converts an ArrayBuffer to Float32Array
var convertBlock(buffer) { // incoming data is an ArrayBuffer
var incomingData = new Uint8Array(buffer); // create a uint8 view on the ArrayBuffer
var i, l = incomingData.length; // length, we need this for the loop
var outputData = new Float32Array(incomingData.length); // create the Float32Array for output
for (i = 0; i < l; i++) {
outputData[i] = (incomingData[i] - 128) / 128.0; // convert audio to float
}
return outputData; // return the Float32Array
}
This one converts a Uint8Array to Float32Array
var convertBlock(incomingData) { // incoming data is a UInt8Array
var i, l = incomingData.length;
var outputData = new Float32Array(incomingData.length);
for (i = 0; i < l; i++) {
outputData[i] = (incomingData[i] - 128) / 128.0;
}
return outputData;
}

Related

Convert Base64 String to Javascript Uint16Array?

I'm working in an Javascript application that receives a base64 array. This array encodes a 16 bits per pixel raw image.
Thus, I would like to do some calculations in it. For this, I need to unpack this Base64 string in a Uint16Array, so I can iterate over pixels and perform the required calculations.
What are my options for doing that?
After some hours looking for a solution, I found a way for doing this:
function getData()
{
fetch("test_data/img_base64.txt")
.then(res => res.text())
.then((out) => {
rawString = window.atob(out);
uint8Array = new Uint8Array(rawString.length);
for(var i = 0; i < rawString.length; i++)
{
uint8Array[i] = rawString.charCodeAt(i);
}
uint16Array = new Uint16Array(uint8Array.buffer);
console.log(uint16Array);
})
.catch(err => { throw err });
}
First I fetch my base64 string from a file. Then using window.atob it is converted to a JavaScript string. After this, I need to fill a Uint8Array with every byte loaded from the string. Finally, I had to convert this Uint8Array, into the final Uint16Array.
That was tough to achieve exactly what I was looking. But I have found it.
You can use this function that converts a base64 string into a binary Uint16 Array
var BASE64_MARKER = ';base64,';
function convertDataURIToBinary(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint16Array(new ArrayBuffer(rawLength));
for(i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
}
If you're targeting Firefox and feeling adventurous you can shorten the function down to this:
var BASE64_MARKER = ';base64,';
function convertDataURIToBinaryFF(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var raw = window.atob(dataURI.substring(base64Index));
return Uint8Array.from(Array.prototype.map.call(raw, function(x) {
return x.charCodeAt(0);
}));
};

Javascript/node.js Object that can store arbitrary binary data and do appending very fast

I need to process lots of binary data in a Node.js app. As data arrive in many small chunks (in the format of Buffer object) that comes to my part of code via a callback, I have to do MANY operations per second like appending, slicing etc.
I was tempted to store the binary data in Javascript string, which support appending, slicing etc. But unfortunately I can't really convert the (arbitrary) binary data to string, which has to have an valid encoding, like UTF8.
To use Buffer object, the appending operation become very expensive. For example, the following code snippet took 1.5 seconds on my P7 processor.
var a = new Buffer([1])
var b = new Buffer([2])
var start = new Date()
for (i=0; i<100000; i++) {
a = Buffer.concat([a, b], a.length + 1)
}
console.log(new Date() - start)
If I were doing simple string appending a += b assuming a and b are strings, it will take only 0.01 second.
I wonder if there is an object in Javascript that can store arbitrary binary data and support appending very efficiently.
Thanks in advance
Update1
Tried TypeArray, the speed is a little better, but it's still far slower than string appending.
var a = new Uint8Array(),
b = new Uint8Array(1);
var c
b[0] = 11
var start = new Date()
for (i=0; i<100000; i++) {
c = new Uint8Array (a.length + b.length)
c.set(a,0)
c.set(b, a.length)
a = c
}
console.log(new Date() - start)
console.log(a.length)
I think smart-buffer might be what you're after? It allows you to write other buffers into it and will dynamically resize as needed.
Testing script:
const SmartBuffer = require('smart-buffer').SmartBuffer;
// set up buffers
var a = new Buffer([1])
var smart_a = new SmartBuffer();
smart_a.writeInt8(1);
var b = new Buffer([2])
// time buffer concatenation method
console.time("Buffer concatenation");
for (let i = 0; i < 100000; i++) {
a = Buffer.concat([a, b], a.length + 1)
}
console.timeEnd("Buffer concatenation");
// time smart buffer writeBuffer method
console.time("Smart Buffer writing");
for (let i = 0; i < 100000; i++) {
smart_a.writeBuffer(b);
}
let final_smart_a = smart_a.toBuffer();
console.timeEnd("Smart Buffer writing");
// check that resulting buffers match
for (let i = 0; i < 100000; i++) {
console.assert(a[i] == final_smart_a[i]);
}
Results (1 trial):
Buffer concatenation: 2110.282ms
Smart Buffer writing: 14.971ms

Convert a byteArray into an IntegerArray using javascript

I receive a bytearray and I want to convert it into a intarray.
Is this possible in NodeJS?
Reason to do that:
A proxy receives values from a serialconnection which is a bytearray and I try to decode that and put it into a more specific JSON object.
var uint8Message = new Uint8Array(8),
output = [];
uint8Message[0] = 40;
uint8Message[1] = 40;
uint8Message[2] = 40;
uint8Message[3] = 40;
uint8Message[4] = 40;
uint8Message[5] = 40;
uint8Message[6] = 40;
uint8Message[7] = 40;
var counter = 0;
var intermediate = [];
for (var i = 0; i< uint8Message.byteLength; i++) {
if (counter < 4) {
intermediate.push(uint8Message[i]);
}
counter++;
if (counter === 3 ){
output.push(new Uint16Array(intermediate));
counter = 0;
intermediate = [];
}
}
console.log(output);
I am sending a intArray which is converted to byteArray from arduino to a NodeJS serialport handler. I want to get 8 integer values in array:
Status and value for four engines.
So in the end I want to have this:
[1,89,2,49,1,28,3,89]
Which is not complete correct with the example. But the example above is for testing.
Still not sure I understand your question correctly but if you want to convert Uint8Array to say Uint32Array you could do
const uint8Array = new Uint8Array(8).fill(40)
console.log(new Uint32Array(uint8Array.buffer))
If you need plain old js array you could do
const uint8Array = new Uint8Array(8).fill(40)
const intArray = Array.from(new Uint32Array(uint8Array.buffer))
console.log(Array.isArray(intArray))
Also you might want to take a look at what is called DataView that allows low level access to buffers' contents.

Blob from javascript binary string

I have a binary string created with FileReader.readAsBinaryString(blob).
I want to create a Blob with the binary data represented in this binary string.
Is the blob that you used not available for use anymore?
Do you have to use readAsBinaryString? Can you use readAsArrayBuffer instead. With an array buffer it would be much easier to recreate the blob.
If not you could build back the blob by cycling through the string and building a byte array then creating a blob from it.
$('input').change(function(){
var frb = new FileReader();
frb.onload = function(){
var i, l, d, array;
d = this.result;
l = d.length;
array = new Uint8Array(l);
for (var i = 0; i < l; i++){
array[i] = d.charCodeAt(i);
}
var b = new Blob([array], {type: 'application/octet-stream'});
window.location.href = URL.createObjectURL(b);
};
frb.readAsBinaryString(this.files[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="file">

how to convert object to binary string

Here is how I compress binary string (char codes above 255) with pako:
var charData = xhr.responseText.split('').map(function(x){return x.charCodeAt(0);});
var binData = new Uint8Array(charData);
var data = pako.deflate(binData, {level:"9"});
Here is how I decompress data back:
var data2 = pako.inflate(xhr.responseText);
Now, how can I get original string in JavaScript from this object?
I tried methods like this:
A.
pako.inflate(xhr.responseText, {to:"string"});
B.
String.fromCharCode.apply(null, data2);
C.
for (var i = 0, l = data2.length; i < l; i++)
{
result += String.fromCharCode(parseInt(array[i], 2));
}
All of these methods bring different data as JavaScript string than original.
When I save decompressed pako.inflate(xhr.responseText) to a file (using functions with a.download) then dempressed file has exactly the same bytes as original file (so compression and decompression works correctly, without any byte modification).
I am just trying to do the same and found a way to convert Object to binary string and vice versa. I just create a two function that converts JSON Object to Binary String and Binary String to JSON Object viz. covertObjectToBinary and convertBinaryToObject.
let obj = {a:1}
function covertObjectToBinary(obj) {
let output = '',
input = JSON.stringify(obj) // convert the json to string.
// loop over the string and convert each charater to binary string.
for (i = 0; i < input.length; i++) {
output += input[i].charCodeAt(0).toString(2) + " ";
}
return output.trimEnd();
}
function convertBinaryToObject(str) {
var newBin = str.split(" ");
var binCode = [];
for (i = 0; i < newBin.length; i++) {
binCode.push(String.fromCharCode(parseInt(newBin[i], 2)));
}
let jsonString = binCode.join("");
return JSON.parse(jsonString)
}
console.log('covertObjectToBinary =>', covertObjectToBinary(obj))
console.log('convertBinaryToObject =>', convertBinaryToObject(covertObjectToBinary(obj)))

Categories