newbiedev
newbiedev

Reputation: 3586

merge multiple arrayBuffer arrays to single Int16Array

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?

Upvotes: 0

Views: 889

Answers (3)

Pavlo
Pavlo

Reputation: 44889

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;
}

Upvotes: 1

Andrea Giammarchi
Andrea Giammarchi

Reputation: 3198

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.

Upvotes: 1

ptothep
ptothep

Reputation: 395

maybe try this with Array.flat()

let I16 = buffer.map(a => new Int16Array(a)).flat()

Upvotes: 1

Related Questions