Типизированные массивы в Gecko 2: конкатенация и расширение Float32Array - PullRequest
13 голосов
/ 29 декабря 2010

Я немного запутался с Типизированными массивами Javascript .

У меня есть несколько Float32Array s, у которых нет concat метод.Я не знаю, сколько их заранее, кстати.Я хотел бы объединить их все в другом массиве Float32Array, но:

  • , как я уже говорил, нет метода сцепления
  • , если я пытаюсь записать после длины массива,массив не расширяется (иначе это не сработает - обратите внимание, что event.frameBuffer и buffer оба являются Float32Array, и я не знаю, какой будет конечная длина моего буфера):

var length_now = buffer.length;
for (var i = 0; i < event.frameBuffer.length; i += 1) {
      buffer [length_now + i] = event.frameBuffer[i];
}

Единственное решение, которое я нашел, это скопировать массив Float32Array в обычный массив, это определенно не то, что я хочу.Как бы вы поступили, stackoverflowers?

Ответы [ 3 ]

19 голосов
/ 29 декабря 2010

Типизированные массивы основаны на буферах массива , размер которых не может быть изменен динамически, поэтому запись за конец массива или использование push() невозможны.

Одним из способов достижения желаемого результата является выделение нового Float32Array, достаточно большого для размещения обоих массивов, и выполнения оптимизированной копии:

function Float32Concat(first, second)
{
    var firstLength = first.length,
        result = new Float32Array(firstLength + second.length);

    result.set(first);
    result.set(second, firstLength);

    return result;
}

Это позволит вам написать:

buffer = Float32Concat(buffer, event.frameBuffer);
2 голосов
/ 30 декабря 2012

Или, если вы пытаетесь объединить N массивов:

// one-liner to sum the values in an array
function sum(a){
  return a.reduce(function(a,b){return a+b;},0);
}

// call this with an array of Uint8Array objects
function bufjoin(bufs){
  var lens=bufs.map(function(a){return a.length;});
  var aout=new Uint8Array(sum(lens));
  for (var i=0;i<bufs.length;++i){
    var start=sum(lens.slice(0,i));
    aout.set(bufs[i],start); // copy bufs[i] to aout at start position
  }
  return aout;
}
1 голос
/ 14 июля 2016

У меня была такая же проблема, вы можете добавить следующее к прототипу

Float32Array.prototype.concat = function() {
    var bytesPerIndex = 4,
        buffers = Array.prototype.slice.call(arguments);

    // add self
    buffers.unshift(this);

    buffers = buffers.map(function (item) {
        if (item instanceof Float32Array) {
            return item.buffer;
        } else if (item instanceof ArrayBuffer) {
            if (item.byteLength / bytesPerIndex % 1 !== 0) {
                throw new Error('One of the ArrayBuffers is not from a Float32Array');  
            }
            return item;
        } else {
            throw new Error('You can only concat Float32Array, or ArrayBuffers');
        }
    });

    var concatenatedByteLength = buffers
        .map(function (a) {return a.byteLength;})
        .reduce(function (a,b) {return a + b;}, 0);

    var concatenatedArray = new Float32Array(concatenatedByteLength / bytesPerIndex);

    var offset = 0;
    buffers.forEach(function (buffer, index) {
        concatenatedArray.set(new Float32Array(buffer), offset);
        offset += buffer.byteLength / bytesPerIndex;
    });

    return concatenatedArray;
};

теперь вы можете просто сделать

var array1 = new Float32Array(10000000),
    array2 = new Float32Array(10000000);

var array3 = array1.concat(array2);
...