如何将ArrayBuffer转换为11位值并在Javascript中再次返回

时间:2018-07-19 21:23:45

标签: javascript

我需要将256位ArrayBuffer转换为24个11位值,然后再次返回。

是否有一个简单的代码段可以处理这种类型的操作。

我有这个版本,可以将其转换为24个11位值。

var newBuffer = new Uint8Array(data);

var result = [];
for (var i =0, l = 24;i<l;i++){
  var index = parseInt((i*11.0)/8.0);
  var subBuffer;

  if (i==23){
    var proxyBuffer = new Uint8Array(2);
    proxyBuffer.set(newBuffer.slice(index,index+1));
    subBuffer = proxyBuffer;
  }else{
    subBuffer = newBuffer.slice(index,index+2);
  }

  var value = new Uint16Array(subBuffer.buffer);
  value = value >> (i*3)%8;
  value = value % 2048;
  result.push(value);
}
console.log(result);

2 个答案:

答案 0 :(得分:0)

使用位运算可以简化转换过程-使用parseInt和十进制算术并非易事。

下面的概念代码使用八位字节和11位值的纯数组。虽然Uint8ArrayUint16Array类型可能是一个更好的选择,但不包括创建类型化数组和/或将arrayBuffer与合适的数组类型之间进行转换。

function ui8To11( buffer8) {
    var buffer11 = [];
    var acc = 0;
    var accBits = 0;
    function add( octet) {
       acc = (octet << accBits) | acc; 
       accBits += 8;
       if( accBits >=11) {
           buffer11.push( acc & 0x7ff);
           acc >>= 11;
           accBits -= 11;
       }
    }
    function flush() {
       if( accBits) {
           buffer11.push( acc);
       }
    }

    buffer8.forEach( add);
    flush();
    return buffer11;
}

function ui11To8( buffer11) {
    var buffer8 = [];
    var acc = 0;
    var accBits = 0;
    function add( ui11) {
       acc = (ui11 << accBits) | acc; 
       accBits += 11;
       while( accBits >= 8) {
           buffer8.push( acc & 0xff);
           acc >>= 8;
           accBits -= 8;
       }
    }
    function flush() {
       if( accBits) {
           buffer8.push( acc);
       }
    }

    buffer11.forEach( add);
    flush();
    return buffer8;
}


var buffer8 = [1,2,3];  // 8 bit values, least significant octet at index 0
console.log("octets: ", buffer8);
var buffer11 = ui8To11( buffer8);
console.log("undectets: ", buffer11);
var reconstructed = ui11To8( buffer11)
console.log("convertedBack", reconstructed);

这里有一个假设,输入数组是低位字节序,因为在输入数组中的每个条目比上一个条目更重要

在8到11位值之间进行转换并再次返回类似的模式,但是当从较高位数转换为较低位数时,将位从累加器推入输出数组需要一个循环。

该示例采用3 x 8位值(总计24位)并产生3 x 11位值(总计33位)。将33位转换回uint8整数将产生5 x 8位值(40位)。您可能需要添加代码以限制转换例程中推入输出数组的整数的数量,或截断根据需要返回的输出数组。

答案 1 :(得分:0)

有一个名为Uint1Array的库,它使一切变得简单得多。

var arr = new Uint1Array(buffer);

for (let i=0, l=arr.length; i<l; i+=11){
    var zero = new Uint1Array(16);
    for (let index =0, length = 11; index<length;index++){
        zero[index]=arr[i+index];
    }

    let bit16 = new Uint16Array(zero.buffer)[0];
    outPut.push(bit16);
}

console.log(outPut);

var bit256 = new Uint1Array(256);
for (let i=0, l=outPut.length;i<l;i++){
    var hold = new Uint16Array(1);
    hold[0]=outPut[i];
    let bit16 = new Uint1Array(hold.buffer);
    let bit11 = bit16.slice(0,11);

    for (let i2=0, l2=11;i2<l2;i2++){
        bit256[(i*11)+i2]=bit11[i2];
    }
}