代码之家  ›  专栏  ›  技术社区  ›  Some Guy Trying To Do Math

如何将arrayBuffer转换为11位值,然后用javascript重新转换

  •  0
  • Some Guy Trying To Do Math  · 技术社区  · 6 年前

    我需要将一个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 回复  |  直到 6 年前
        1
  •  0
  •   traktor    6 年前

    使用位操作可以简化转换过程-使用 parseInt 十进制算法不是一个简单的方法。

    下面的概念代码使用八位字节和11位值的普通数组。当 Uint8Array Uint16Array 类型可能是更好的选择,创建类型化数组和/或转换 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);

    这里有一个假设,输入数组是小endian,因为输入数组中的每个条目都是 更多 比上一个条目重要。

    8位和11位值之间的转换和再次转换遵循类似的模式,但将位从累加器推送到输出数组需要一个循环,才能从较高的位数转换到较低的位数。

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

        2
  •  0
  •   Some Guy Trying To Do Math    6 年前

    有一个名为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];
        }
    }