Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Java中看似8位的数据流中检索无符号16位数字_Java_Byte_Bit - Fatal编程技术网

从Java中看似8位的数据流中检索无符号16位数字

从Java中看似8位的数据流中检索无符号16位数字,java,byte,bit,Java,Byte,Bit,我正在使用SysEx和AH Qu-16开发一个MIDI应用程序 仪表值是有符号的dB值(从-xxx到大约0或稍高),编码为定点7Q8偏移8000格式,存储为无符号16位数字(在Sysex中以“7位化”格式传输) 举例如下: 7-bit-ized binary 00100000 01111100 00000000 Unpacks to 8-bit-ized binary 01111100 10000000 Equivalent to hexadecimal: 7C80

我正在使用SysEx和AH Qu-16开发一个MIDI应用程序

仪表值是有符号的dB值(从-xxx到大约0或稍高),编码为定点7Q8偏移8000格式,存储为无符号16位数字(在Sysex中以“7位化”格式传输)

举例如下:

7-bit-ized binary            00100000 01111100 00000000
Unpacks to 8-bit-ized binary 01111100 10000000
Equivalent to hexadecimal:   7C80 
Remove the offset:           (int16_t) 7C80 – (int16_t) 8000 = FC80
Float and scale:             (float) FC80 / 256.0f = -3.5dB
然而,我无法获得有意义的价值观。将8字节转换为7字节似乎不是问题,但获取合理的值确实是问题,我想知道这是否与8位和16位值有关

例如,我得到的值非常低,没有意义(例如,将信号放在约0dB中,它会给出-210和-126,没有声音),但在输入示例值时,它会起作用。我在转换过程中做错了什么吗?我只是觉得这是件愚蠢的事情,我对这些操作不太熟悉

我在混合器底部添加了一个十六进制的样品

这是我的代码:

   private void processMeterReadings(String hex) throws Exception {
        byte[] fullInput;
        fullInput = Hex.decodeHex(hex.toCharArray());

        int groups = (fullInput.length / 8);
        int rest = fullInput.length % 8;
        byte[] meterData;
        if (rest == 0) meterData = new byte[groups * 7];
        else {
            meterData = new byte[groups * 7 + (rest - 1)];
            groups++;
        }
        //Work in groups of 8 (7 bytes) for x groups.
        int nrBits = 8;
        for (int g = 0; g < groups; g++) {
            if (rest > 0 && g == groups - 1) {
                //Logger.debug("Last group? g: " + g + " of total " + groups);
                nrBits = rest;
            }

            for (int i = 0; i < nrBits - 1; i++) { 
                meterData[g * 7 + i] = fullInput[g * 8 + i + 1];
                if((fullInput[g * 8] >> (Math.abs((i+1) - 7)) & 1) == 1) meterData[g * 7 + i] = (byte)(meterData[g * 7 + i] | (1 << 7));
            }
        }

        // Now we need to get each value (of 2 bytes to 16 bits int)??
        int totalValues = meterData.length / 2;
        float[] values = new float[totalValues];
        for (int i = 0; i < totalValues; i++) {
            ByteBuffer wrapped = ByteBuffer.wrap(meterData, i * 2, 2); // big-endian by default
            int num = wrapped.getShort(); // 1
            int num2 = Integer.parseInt("8000", 16);
            values[i] = ((num - num2) / 256f);
        }

    }


    String hex = "407f26011201120100120112011201124a356d0d000d00010012011201120112000112011201123616700d000d003a430101120112011274003a011201127a692c0d000d00513d0100120112011201120001120112136c0d58000d00513d0112000112011201120101120112136c0d00200d00011201120100120112011201121201127a6d0d000d400001120112011200011201120112010512136c0d000d00003355011201120100123e4d011201120a096c0d000d00742a5b513d513d513d51614f513d011236146e0d000d0001120001120112011201001201120112176c280d000d00011201001201120112011204011201126d750d50000d0001120112000112011201120109120112766b0d00200d0001120112010012011201120112020112166c0d000d400001120112011200011201120112010512166c0d000d00000112011201120100120112011201120a166c0d000d000100120112011201120001120112011216146c0d000d00011200011201120112010012011201120100200d0001000112010012011201120112000112011201000d400001000112011200011201120112010112011201000d000001000112011201001201120112011202011201000d000100000112011201120001120112011201041201000d000100000112011201120100120112011201120801000d000100010012011201120112000112011201120110000d000100011200011201120112010012011201120100240d000100513d01021201120112513d0001120112176c0d58000d00513d01120401120112513d0101120112176c0d00300d003a4301120108120112513d0112020112176c0d000d6000513d01120112100112513d0112010512176c0d000d00000112011201120100120112011201120a076c0d000d000100120112011201120001120112011207146c0d000d00011200011201120112005012001201120100200d0001000112010112011201120012200012011201000d400001000112011200011201120112010112011201120d000001000112011201001201120112011202011201120d000100000112011201120001120112011201041201120d000100000112011201120100120112011201120801120d000100010012011201120112000112011201120110120d000100011200011201120112010012011201120112200d0001000112010012011201120112000112011201120d400001000112011200011201120112010112011201120d000501000112743a74283a513d513d5b4754743a513d7b7f010a000112743a743a51513d513d5b4774283a513d7b7f0100000112011201120100120112011201121001127b7f0100010012011201120112000112011201120120127b7f010001120001120112011201001201120112011200011201120112010012011201120112000112011201120100120112011201120001120112011201001201120112011200011201120112010012011201120112000112011201120100120112011201120001120112011201001201120112011200011201120112010012011201120112000112011201120100120112011201120001120112011201001201120112011200011201120112010012011201120112000112011201120108120112454a1b4d0001120112011201001201120112011200011201120112010012011201120112000112011201000100000112011201120001120112011201001201120112011200011201120112010012011201120100000100011201120100120112011201120001120112011201001201120112011200011201120112010000010001120112000112011201120100120112011201120001120112";
private void processMeterReadings(字符串十六进制)引发异常{
字节[]完整输入;
fullInput=Hex.decodeHex(Hex.toCharArray());
int groups=(fullInput.length/8);
int rest=fullInput.length%8;
字节[]米数据;
如果(rest==0)meterData=新字节[groups*7];
否则{
meterData=新字节[组*7+(其余-1)];
组++;
}
//对于x组,以8(7字节)为一组进行工作。
int nrBits=8;
对于(int g=0;g0&&g==组-1){
//Logger.debug(“最后一组?g:+g+”,共“+组);
nrBits=静止;
}
对于(int i=0;i如果((fullInput[g*8]>>(Math.abs((i+1)-7))&1)==1)meterData[g*7+i]=(byte)(meterData[g*7+i]|(1我不知道你的代码出了什么问题,但我想建议用一种更系统的方法来编写这样相当复杂的东西

自下而上构建您的操作,并在运行时为它们编写单元测试

然后,您将更好地了解实现的哪一部分是正确的,以及可能存在的问题

e、 g.(7比特化解码的实现)


公共类SysEx{
静态字节[]unpack7BitIzedData(字节[]in){
整数组=in.length/8;
整数余数=英寸长度%8;
字节[]输出=新字节[组*7+(余数-1)];
对于(int g=0;g0){
转换组(输入,组*8,剩余,输出,组*7);
}
返回;
}
/**
*@param在包含7位化数据的缓冲区中
*@param inStart我们正在解码的组的缓冲区中的起始位置,即hi位字节的索引
*@param length GROUP中的字节数,包括hi位字节
*@param输出缓冲区以存储解码数据
*@param超出了解码数据输出缓冲区中的起始位置
*/
静态无效转换组(字节[]in,int inStart,int length,字节[]out,int outStart){
int-hiBits=in[inStart];
对于(int i=0;i>targetByteIndex))!=0?0x80:0x00);
}
}
导入org.hamcrest.Matchers;
导入org.junit.jupiter.api.Test;
导入静态org.hamcrest.matcherasert.assertThat;
导入静态org.hamcrest.Matchers.is;
公共类TestSysEx{
@试验
公共void testTopBit(){
校验位(0x00,0,0,0,0,0,0,0,0);
校验位(0x40,0x80,0,0,0,0,0,0);
校验位(0x60,0x80,0x80,0,0,0,0,0);
}
私有void校验位(整型数据、整型…值){
int i=0;
对于(整数v:值){
断言(SysEx.topBit((字节)数据,i++)为(v));
}
}
@试验
public void testConvertGroup(){
字节[]in={0b00100000,0b01111100,0b00000000};
字节[]输出=新字节[2];
字节[]应为{0b01111100,(字节)0b10000000};
SysEx.convertGroup(in,0,3,out,0);
资产(不存在,是(预期的));
}
@试验
公共无效testUnpack7BitIzedData(){
字节[]in={0b00100000,0b01111100,0b00000000};
字节[]应为{0b01111100,(字节)0b10000000};
资产(SysEx.unpac7bitizeddata(in),是(预期的));
}
@试验
公共无效测试unpack7bitizeddata_longer(){
字节[]in={0b01010101、0x01、0x02、0x03、0x04、0x05、0x06、0x07、0b00101010、0x08、0x09、0x0A、0x0B、0x0C、0x0D、0x0E,(字节)0b01000000、0x0F};
字节[]预期={(字节)0x81,0x02,(字节)0x83,0x04,(字节)0x85,0x06,(字节)0x87,
0x08,(字节)0x89,0x0A,(字节)0x8B,0x0C,(字节)0x8D,0x0E,(字节)0x8F};
资产(SysEx.unpac7bitizeddata(in),是(预期的));
}
}

谢谢,这非常有用。我必须承认,我对位/字节运算不太熟悉。我觉得以8位格式存储的无符号16位值有问题(如果我正确获取的话)在Java中转换为int,但我对它了解得还不够,还无法追踪到它。如果Java有像C这样的无符号数据类型,那就太好了。这就是问题的一部分。支持人员建议更改这两个byt

public class SysEx {
    static byte[] unpack7BitIzedData(byte[] in) {
        int groups = in.length / 8;
        int remainder = in.length % 8;

        byte[] out = new byte[groups * 7 + (remainder - 1)];
        for (int g = 0; g < groups; ++g) {
            convertGroup(in, g * 8, 8, out, g * 7);
        }
        if (remainder > 0) {
            convertGroup(in, groups * 8, remainder, out, groups * 7);
        }
        return out;
    }

    /**
     * @param in the buffer containing the 7bitized data
     * @param inStart the start location in the buffer of the group we are decoding, i.e. the index of the hi bits byte
     * @param length the number of bytes in the gruop, including the hi bits byte
     * @param out the buffer to store the decoded data in
     * @param outStart the start location in the out buffer for the decoded data
     */
    static void convertGroup(byte[] in, int inStart, int length, byte[] out, int outStart) {
        int hiBits = in[inStart];
        for (int i = 0; i < length-1; ++i) {
            out[outStart+i] = (byte)(in[inStart+1+i] | topBit(hiBits, i));
        }
    }

    /**
     * @param hiBits The byte containing high bits for a group
     * @param targetByteIndex The index into the group (starting at 0)
     * @return 0x80 if the hi bit is set for that byte of the group, otherwise 0
     */
    static int topBit(int hiBits, int targetByteIndex) {
        if ((hiBits & 0x80) != 0) {
            throw new RuntimeException();
        }
        return ((hiBits & (0x40 >> targetByteIndex)) != 0 ? 0x80 : 0x00);
    }
}

import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

public class TestSysEx {
    @Test
    public void testTopBit() {
        checkTopBit(0x00, 0,0,0,0,0,0,0);
        checkTopBit(0x40, 0x80,0,0,0,0,0,0);
        checkTopBit(0x60, 0x80,0x80,0,0,0,0,0);
    }

    private void checkTopBit(int data, Integer... values) {
        int i = 0;
        for (Integer v : values) {
            assertThat(SysEx.topBit((byte)data, i++), is(v));
        }
    }

    @Test
    public void testConvertGroup() {
        byte[] in = {0b00100000, 0b01111100, 0b00000000};
        byte[] out = new byte[2];
        byte[] expected = {0b01111100, (byte)0b10000000};
        SysEx.convertGroup(in, 0, 3, out, 0);
        assertThat(out, is(expected));
    }

    @Test
    public void testUnpack7BitIzedData() {
        byte[] in = {0b00100000, 0b01111100, 0b00000000};
        byte[] expected = {0b01111100, (byte)0b10000000};
        assertThat(SysEx.unpack7BitIzedData(in), is(expected));
    }

    @Test
    public void testUnpack7BitIzedData_longer() {
        byte[] in = {0b01010101, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0b00101010, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, (byte)0b01000000, 0x0F};
        byte[] expected = {(byte)0x81, 0x02, (byte)0x83, 0x04, (byte)0x85, 0x06, (byte)0x87,
                0x08, (byte)0x89, 0x0A, (byte)0x8B, 0x0C, (byte)0x8D, 0x0E, (byte)0x8F};
        assertThat(SysEx.unpack7BitIzedData(in), is(expected));
    }
}