I want to convert a float value like 26,4 into a byte array. Something like: [51,51,-45,65]. Another example: 32,2 > [-51, -52, 0, 66].
I can do it in Arduino C++ and Python, but I don't see how to do it in JavaScript.
I have an input field in my HTML page where I want to write my float value and decode it before sending it to a Python script.
Is it possible?
Typed Arrays
First create a Float32Array which is a view on top of an actual byte-buffer (ArrayBuffer). We can allocate the buffer and view in a single operation:
var farr = new Float32Array(2); // two indexes each 4 bytes
Store the floating point numbers. These will be stored in IEEE-754 format:
farr[0] = 26.4;
farr[1] = 32.2;
Now we can add another view for the underlying buffer, this time signed 8-bit view:
var barr = new Int8Array(farr.buffer); // use the buffer of Float32Array view
console.log(barr);
// -> 51,51,-45,65,-51,-52,0,66
Live demo below
var farr = new Float32Array(2); // two indexes each 4 bytes
farr[0] = 26.4;
farr[1] = 32.2;
var barr = new Int8Array(farr.buffer); // use the buffer of Float32Array view
console.log(barr);
document.querySelector("div").innerHTML = barr[0]+","+barr[1]+","+barr[2]+","+barr[3]+","+barr[4]+","+barr[5]+","+barr[6]+","+barr[7];
<div></div>
Related
I can not found a way to change a value in an ArrayBuffer.
I am able to print the content of an ArrayBuffer by using a TextDecoder. When printing the buffer there is a string. I want to change one char on the string by editing one byte on the buffer. I was able to access one byte on the buffer by converting it to an Int8Array but I am not sure on how to converting it again to an ArrayBuffer after editing the byte
var enc = new TextDecoder("utf-8");
console.log('ArrayBuffer string content : ', enc.decode(data));
let view = new Int8Array(data);
view[56] = 48;
view[57] = 48;
// Convert view again to an ArrayBuffer
//console.log('ArrayBuffer string new content : ', enc.decode(data));
You can use the set method on your Int8Array directly :
var enc = new TextDecoder("utf-8");
console.log('ArrayBuffer string content : ', enc.decode(data));
let view = new Int8Array(data);
view.set([48], 56);
view.set([48], 57);
As stated in the top answer:
var enc = new TextDecoder("utf-8");
console.log('ArrayBuffer string content : ', enc.decode(data));
let view = new Int8Array(data);
view.set([48], 56);
view.set([48], 57);
It actually does change the byte value in the data variable.
I spend the last couple of hours trying to figure out how to do this, myself.
Then I finally understood that when you create the new Int8Array(), you're not creating a copy of the data - you're just creating a different type of pointer to it.
It's messy, it's confusing, but it works.
Cheers!
I use emscripten compile the c code into asm.js
my c code like this:
int _call_main(char* p, int number)//p is the start arrary, number is the lengh
I want to send a bytearray data to the c code, My Js code like this:
var decode_encode_audio = Module.cwrap('_call_main', 'number', ['array','number']);
........
var byteArray = new Uint8Array(message.data);//audio data
var offset = Module._malloc(70000);
Module.HEAP8.set(byteArray, offset);
decode_encode_audio(offset , byteArray.length);
In the C code, I print the point p array, I got a messed data, the start part and the end part of p is correct(I save the file), However, In the middle part is messed.I replace the function(Module.HEAP8.set) with [Module.HEAPU8.set],also got error. I don't know why?
I change the Js code :
var decode_encode_audio = Module.cwrap('_call_main', 'number', ['number','number']);//not array
........
var byteArray = new Uint8Array(message.data);//audio data
//var offset = Module._malloc(70000);
//Module.HEAP8.set(byteArray, offset);
decode_encode_audio(byteArray, byteArray.length);
I can get correct data.
Can anyone tell me what's wrong with "Module.HEAP8.set" method.
You are writing unsigned data from your Uint8Array into the signed view HEAP8. You should use the HEAPU8, which is used for unsigned data.
I want convert an integer (signed) to 32 bit (big endian) into a octet stream and give the octet stream as a array value to the constructor of a
Buffer Object.
I can create it in the console for example for the value -2000:
<code>
buf = Buffer(4)
buf.writeInt32BE(-2000)
buf // is <Buffer ff ff f8 30>
buf1 = new Buffer([0xff, 0xff, 0xf8, 0x30])
</code>
The value -3000 is for example -3000 : 0xff ,0xff, 0xf4, 0x48
But the framework i use accepts not the writeInt32BE function and throws exception.
How can i convert a 32 bit integer value signed to a octet Array stream without the writeInt32BE ?
A function that takes a value and returns an array of octet stream.
Using a 4 byte array buffer, converted to a data view and calling setInt32 on the view seems to work. This approach supports specification of both little endian and big endian (the default) formats independent of machine architecture.
function bigEnd32( value) {
var buf = new ArrayBuffer(4);
var view = new DataView(buf);
view.setInt32( 0, value);
return view;
}
// quick test (in a browser)
var n = prompt("Signed 32: ");
var view = bigEnd32( +n);
for(var i = 0 ; i < 4; ++i)
console.log(view.getUint8( i));
Documentation was located searching for "MDN ArrayBuffer" "MDN Dataview" etc. Check out DataView in detail for properties that access the underlying array buffer - you may be able to tweak the code to suite your application.
Let's say I have a hex data stream, which I want to divide into 3-bytes blocks which I need to read as an integer.
For example: given a hex string 01be638119704d4b9a I need to read the first three bytes 01be63 and read it as integer 114275. This is what I got:
var sample = '01be638119704d4b9a';
var buffer = new Buffer(sample, 'hex');
var bufferChunk = buffer.slice(0, 3);
var decimal = bufferChunk.readUInt32BE(0);
The readUInt32BE works perfectly for 4-bytes data, but here I obviously get:
RangeError: index out of range
at checkOffset (buffer.js:494:11)
at Buffer.readUInt32BE (buffer.js:568:5)
How do I read 3-bytes as integer correctly?
If you are using node.js v0.12+ or io.js, there is buffer.readUIntBE() which allows a variable number of bytes:
var decimal = buffer.readUIntBE(0, 3);
(Note that it's readUIntBE for Big Endian and readUIntLE for Little Endian).
Otherwise if you're on an older version of node, you will have to do it manually (check bounds first of course):
var decimal = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
I'm using this, if someone knows something wrong with it, please advise;
const integer = parseInt(buffer.toString("hex"), 16)
you should convert three byte to four byte.
function three(var sample){
var buffer = new Buffer(sample, 'hex');
var buf = new Buffer(1);
buf[0] = 0x0;
return Buffer.concat([buf, buffer.slice(0, 3)]).readUInt32BE();
}
You can try this function.
I have to read a binary file which is said to be encoded 4 byte single format and never having to work with binary data, I don't know what this means.
I can do this reading a file with binary data in JavaScript:
d = new FileReader();
d.onload = function (e) {
var i, len;
// grab a "chunk"
response_buffer = e.target.result.slice(0, 1024);
view = new DataView(response_buffer);
for (i = 0, len = response_buffer.byteLength; i < len; i += 1) {
// hmhm
console.log(view.getUint8(i));
}
}
d.readAsArrayBuffer(some_file);
Which runs a loop from 0 to 1023 and I am getting numbers on the console, but I don't know if this is my decoded data :-)
Question:
What is 4 byte single format and how do I access the data correctly? What is the difference between say getUint8() and getint8() or getInt32() in "human understandable language"?
Thanks!
4 byte single format is not a commonly understood term in computer science.
If you could expect your file to be a series of single precision floating point numbers, then I might guess that "4 byte single format" means single precision floating point because each of those is four bytes long.
You will want to use getFloat32() to parse single precision floating point numbers from the binary stream.
If you want 1024 numbers parsed with getFloat32(), then you need 1024*4 bytes and you need to advance your for loop by four bytes each time since getFloat32() processes four bytes at a time:
d = new FileReader();
d.onload = function (e) {
var i, len;
// grab a "chunk"
response_buffer = e.target.result.slice(0, 1024 * 4);
view = new DataView(response_buffer);
for (i = 0, len = response_buffer.byteLength; i < len; i += 4) {
// hmhm
console.log(view.getFloat32(i));
}
}
d.readAsArrayBuffer(some_file);
Also, please note that IE10 and IOS 5 do not have the .slice() method for an ArrayBuffer if you're planning on using this in a general web page.