0

I have this code that will add some arrayBuffer to an array.

  let buffer = [];
  fetch(dataURI)
  .then( (res) => res.arrayBuffer() )
  .then( (data) => {
    buffer.push(data);
  });

I need to convert the resulting array into a single Int16Array to process it, I'm trying with this code but with no success. I'm unable to get the single Int16Array I need

  buffer.forEach( (item) => {
    samples = [...Int16Array.from(item)];
  });

Any suggestion on how I can proceed?

3 Answers 3

1

maybe try this with Array.flat()

let I16 = buffer.map(a => new Int16Array(a)).flat()
Sign up to request clarification or add additional context in comments.

2 Comments

I need to test, I'm reading the related documentation. Will this create a single array that will contain all the arrayBuffer I have?
Yes it should do exactly that.
1

There is something slightly off with this question, as a fetch request won't ever push more than once that data to the buffer, but I guess it's just an example of your use case, and your buffer gets populated multiple times by different fetches.

In any case, what I would use instead of .flat() after all things are pushed, is the following:

buffer.push(...data);
// or ...
buffer.push(...new Int16Array(data));

This will flatten out data right away so that once all fetches are completed, all you have to do is:

const i16a = Int16Array.from(buffer);
// or ...
const i16a = new Int16Array(buffer);

The previous mentioned solution would instead flatten the array without concatenating all received data so I think it won't work, accordingly with your request.

15 Comments

I've already tried with spread operator but data is an arrayBuffer and will cause this error Uncaught (in promise) TypeError: Found non-callable @@iterator
have you tried buffer.push(...Int16Array.from(data)); instead? if that works, the rest wouldn't change (but I need to edit the answer if that's the case).
no, but I've tried with buffer.push(...new Int8Array(data)) and I get this error Uncaught (in promise) RangeError: Maximum call stack size exceeded
P.S. it makes literally no sense you had a call stack error but splitting the operation in two parts doesn't give you the exact same error ... buffer.push(...i16a) or buffer.push(...Int16Array.from(data)) are exactly the same thing.
I've already answered that with a module that does exactly that (as string, but you have all details to convert)
|
1

You would have to map you buffers to int16 chunks and then concatenate those chunks into one array:

const int16Chunks = [];
let byteLength = 0;

fetch(dataURI)
  .then(res => res.arrayBuffer())
  .then(buffer => {
    const chunk = createChunk(buffer, Int16Array.BYTES_PER_ELEMENT);

    int16Chunks.push(chunk);
    byteLength += chunk.byteLength;
  });

later, when everything has been fetched:

const bytes = new Uint8Array(byteLength);
let offset = 0;

for (const chunk of int16Chunks) {
  bytes.set(offset, chunk);
  offset += chunk.length;
}

const result = new Int16Array(bytes.buffer);

finally, createChunk function:

function createChunk(buffer, step) {
  const bytes = new Uint8Array(buffer);
  const length = Math.ceil(bytes.length / step) * step;
  const padded = new Uint8Array(length);
  const offset = padded.length - bytes.length;
  const chunk = padded.set(offset, bytes);

  return chunk;
}

2 Comments

Tried this but not work as expected Uncaught (in promise) RangeError: byte length of Int16Array should be a multiple of 2
That means you got an odd number of bytes as array buffer, e.g. 1 or 3. I guess you would want to pad those with zeros.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.