I want to send the data captured from my microphone (converted to unsigned 16bit integers) in the browser to my server as a binary string, but I'm having a hard time doing that.
I tried using String.fromCodePoint on my array, but it seems that the resulting String is not a valid one. I also tried using DataView, but not sure how to get a binary String out of that either.
Does anyone know how that can be achieved?
EDIT: I am referring to binary data, as is "binary file", and not to "binary representation of an integer".
This did not answer the question.
If only in the browser you can use the btoa function to encode to a base64 string.
Edit:
I am assuming you have an array of integers.
Final Edit:
Maybe try something like:
arr.map(function(item) {
var value = item.toString(2);
var padLength = 16 - value.length;
var binaryVal = "0".repeat(padLength) + value;
return binaryVal;
}).join("");
Related
I really want to work with hex values in TTN but I haven't found a way to get the 'frm_payload'. So now I use a default script to convert it to decimals but I can't find a solution for turning it back into a hex value. I think the solution is probably quite simple but I keep overlooking it, so maybe someone can help me and give a push in the right direction.
This is my code, it reads the payload and turns the first hex value (7C) to a decimal number (124):
var decoded = {};
function Decoder(bytes, port) {
if (port == 1) {
decoded.test = bytes[0];
}
return decoded;
}
And this is the output I get:
{
"test": 124
}
Convert a number to a hexadecimal string with:
hexString = yourNumber.toString(16);
And reverse the process with:
yourNumber = parseInt(hexString, 16);
Overview:
I'm building a Javascript tool inside a web page. Except for loading that page, the tool will run without server communication. A user will select a local file containing multiple binary records, each with a x'F0 start byte and x'F0 end byte. The data in between is constrained to x'00 - x'7F and consists of:
bit maps
1-byte numbers
2-byte numbers, low order byte first
a smattering of ASCII characters
The records vary in lengths and use different formats.
[It's a set of MIDI Sysex messages, probably not relevant].
The local file is read via reader.readAsArrayBuffer and then processed thus:
var contents = event.target.result;
var bytes = new Uint8Array(contents);
var rawAccum = '';
for (x = 0; x < bytes.length; x++) {
rawAccum += bytes[x];
}
var records = rawAccum.split(/\xF0/g);
I expect this to split the string into an array of its constituent records, deleting the x'F0 start byte in the process.
It actually does very little. records.length is 1 and records[0] contains the entire input stream.
[The actual split code is: var records = rawAccum.split(/\xF0\x00\x00\x26\x02/g); which should remove several identical bytes from the start of each record. When this failed I tried the abbreviated version above, with identical (non)results.]
I've looked at the doc on split( and at several explanations of \xXX among regex references. Clearly something does not work as I have deduced. My experience with JavaScript is minimal and sporadic.
How can I split a string of binary data at the occurrence of a specific binary byte?
The splitting appears to work correctly:
var rawAccum = "\xf0a\xf0b\xf0c\xf0"
console.log( rawAccum.length); // 7
var records = rawAccum.split(/\xF0/g);
console.log(records); // "", "a", "b", "c", ""
but the conversion of the array buffer to a string looks suspicious. Try converting the unsigned byte value to a string before appending it to rawAccum:
for (x = 0; x < bytes.length; x++) {
rawAccum += String.fromCharCode( bytes[x]);
}
Data conversions (update after comment)
The filereader reads the file into an array buffer in memory, but JavaScript does not provide access to array buffers directly. You can either create and initialize a typed array from the buffer (e.g. using the Uint8Array constructor as in the post), or access bytes in the buffer using a DataView object. Methods of DataView objects can convert sequences of bytes at specified positions to integers of varying types, such as the 16 bit integers in the Midi sysex records.
JavaScript strings use sequences of 16 bit values to hold characters, where each character uses one or two 16 bit values encoded using UTF-16 character encoding. 8 bit characters use only the lower 8 bits of a single 16 bit value to store their Unicode code point.
It is possible to convert an array buffer of octet values into a "binary string", by storing each byte value from the buffer in the low order bits of a 16 bit character and appending it to an existing string. This is what the post attempts to do. But in JavaScript strings (and individual characters which have a string length of 1) are not a subset of integer numbers and have their own data type, "string".
So to convert an unsigned 8 bit number to a JavaScript 16 bit character of type "string", use the fromCharCode static method of the global String object, as in
rawAccum += String.fromCharCode( bytes[x]);
Calling String.fromCharCode is also how to convert an ASCII character code located within MIDI data to a character in JavaScript.
To convert a binary string character derived from an 8 bit value back into a number, use the String instance method charCodeAt on a string value and provide the character position:
var byteValue = "\xf0".charCodeAt(0);
returns the number 0xf0 or 250 decimal.
If you append a number to a string, as in the question, the number is implicitly converted to a decimal string representation of its value first:
"" + 0xf0 + 66 // becomes the string "24066"
Note that an array buffer can be inspected using a Uint8Array created from it, sliced into pieces using the buffer's slice method and have integers of various types extracted from the buffer using data views. Please review if creating a binary string remains the best way to extract and interpret Midi record contents.
Is there any way to send text and binary in one request via websocket? For example: file name (text) and file content (binary)
I can send them as string like:
JSON.stringify({filename: "test.dat", filecontent: data});
But it is a lot slower than sending only file content as binary (arraybuffer).
Remember that binary is just encoded data. This is less a JavaScript question and more an encoding question. Here's how I would do it.
Set aside 32 bits (representing one integer) at the beginning of your request to specify the bit length of test.dat. Then combine this with your two data sources. Your payload will look like this:
TEXT_LENGTH + TEST.DAT AS BINARY + FILECONTENT AS BINARY
Then get back the data as an array buffer. Use
textLengthBits = parseInt(arrBuffer.slice(0,32), 2);
To get the length of the text. Then slice again,
textBits = arrBuffer.slice(32, 32 + textLengthBits)
To get the text. The remaining bits are your file.
fileBits = arrBuffer.slice(32 + textLengthBits);
I have a project using Node.JS. I need to send a string to the terminal (UART COM-port) in Latin1. I just realised that I cannot create String object with 1-byte encoding (like Latin-1).
I need to create string from array of bytes. Bytes that a less than 128 are ASCII bytes and string with these bytes always looks good. But if I pass bytes that are greater than 127 then I always retrieve string with 2 bytes (in UTF-16).
I really want only 1-byte representation of every byte. How can I achieve that?
IconV could perhaps work
Something like (untested code!):
var Buffer = require('buffer').Buffer;
var Iconv = require('iconv').Iconv;
var iconv = new Iconv('UTF-16','latin1');
bytes.forEach(function(byte){
var bufferbyte = iconv.convert(byte);
});
I have a VBArray in Javascript containing a long set of 8-bit unsigned integers, more than 1'000'000 entries usually.
I can easily transform it to a conventional array or Uint8Array, and my goal is to obtain its base64 representation.
I have tried the methods here, but running
var b64encoded = btoa(String.fromCharCode.apply(null, _uint8Array));
throws an out of stack space exception.
The conversion in itself is not a problem, because I could write my own conversion method which does the following
create empty bit string
foreach value in the array
get binary with toString(2)
pad the binary to make it 8-bit
add it to the bit string
Base64 conversion is then trivial.
Performance, as you can imagine, is rather poor. Any suggestions on how to improve this?
You could try something like this to limit the number of arguments, thus reducing the required stack space:
var A = new Uint8Array(10000000), s = '';
// Encode at most 49152 bytes at a time
for (var i = 0; i < A.length; i += 49152) {
s += btoa(String.fromCharCode.apply(null, A.subarray(i, i + 49152)));
}
You can change the number 49152 to anything that is both under the browser's limit and divisible by 3.