Je travaille avec des objets ArrayBuffer
et je voudrais les dupliquer. Bien que ce soit assez facile avec les pointeurs réels et memcpy
, je n'ai trouvé aucun moyen simple de le faire en Javascript.
En ce moment, voici comment je copie mon ArrayBuffers
:
function copy(buffer)
{
var bytes = new Uint8Array(buffer);
var output = new ArrayBuffer(buffer.byteLength);
var outputBytes = new Uint8Array(output);
for (var i = 0; i < bytes.length; i++)
outputBytes[i] = bytes[i];
return output;
}
Existe-t-il une manière plus jolie?
ArrayBuffer
est censé prendre en charge slice
(http://www.khronos.org/registry/typedarray/specs/latest/) afin que vous puissiez essayer,
buffer.slice(0);
qui fonctionne dans Chrome 18 mais pas Firefox 10 ou 11. Quant à Firefox, vous devez le copier manuellement. Vous pouvez patcher singe la slice()
dans Firefox car la Chrome slice()
surpassera une copie manuelle. Cela ressemblerait à quelque chose,
if (!ArrayBuffer.prototype.slice)
ArrayBuffer.prototype.slice = function (start, end) {
var that = new Uint8Array(this);
if (end == undefined) end = that.length;
var result = new ArrayBuffer(end - start);
var resultArray = new Uint8Array(result);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i + start];
return result;
}
Ensuite, vous pouvez appeler,
buffer.slice(0);
pour copier le tableau à la fois dans Chrome et Firefox.
Je préfère la méthode suivante
function copy(src) {
var dst = new ArrayBuffer(src.byteLength);
new Uint8Array(dst).set(new Uint8Array(src));
return dst;
}
Il semble que le simple passage de la vue de données source effectue une copie:
var a = new Uint8Array([2,3,4,5]);
var b = new Uint8Array(a);
a[0] = 6;
console.log(a); // [6, 3, 4, 5]
console.log(b); // [2, 3, 4, 5]
Testé en FF 33 et Chrome 36.
Hmmm ... si c'est le Uint8Array que vous souhaitez découper (ce qui devrait logiquement être le cas), cela peut fonctionner.
if (!Uint8Array.prototype.slice && 'subarray' in Uint8Array.prototype)
Uint8Array.prototype.slice = Uint8Array.prototype.subarray;
Version plus rapide et légèrement plus compliquée de la réponse de chuckj. Doit utiliser environ 8 fois moins d'opérations de copie sur de grands tableaux typés. Fondamentalement, nous copions autant de morceaux de 8 octets que possible, puis copions les 0 à 7 octets restants. Ceci est particulièrement utile dans la version actuelle d'IE, car il n'a pas de méthode de tranche implémentée pour ArrayBuffer.
if (!ArrayBuffer.prototype.slice)
ArrayBuffer.prototype.slice = function (start, end) {
if (end == undefined) end = that.length;
var length = end - start;
var lengthDouble = Math.floor(length / Float64Array.BYTES_PER_ELEMENT);
// ArrayBuffer that will be returned
var result = new ArrayBuffer(length);
var that = new Float64Array(this, start, lengthDouble)
var resultArray = new Float64Array(result, 0, lengthDouble);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i];
// copying over the remaining bytes
that = new Uint8Array(this, start + lengthDouble * Float64Array.BYTES_PER_ELEMENT)
resultArray = new Uint8Array(result, lengthDouble * Float64Array.BYTES_PER_ELEMENT);
for (var i = 0; i < resultArray.length; i++)
resultArray[i] = that[i];
return result;
}
Dans certains cas (comme les audiobuffers webaudio), vous ne disposez que d'une référence aux 2 baies.
Donc, si vous avez array1 comme float32Array et array2 comme float32Array,
vous devez faire une copie élément par élément.
Pour ce faire, vous pouvez utiliser différentes méthodes.
var ib=z.inputBuffer.getChannelData(0);
var ob=z.outputBuffer.getChannelData(0);
ce
ib.forEach((chd,i)=>ob[i]=chd);
ou c'est plus agréable et probablement plus rapide
ob.set(ib);
En effet, Array.set remplit un tableau existant avec plusieurs données (même à partir d'un autre tableau)