繁体   English   中英

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

[英]Retrieving unsigned 16-bit numbers from what seems an 8-bit data stream in Java

我正在使用带有 AH Qu-16 的 SysEx 开发 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";

我不知道你的代码有什么问题,但我想建议一种更系统的方式来编写像这样相当复杂的东西。

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

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

例如(7bitized 解码的实现)


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));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM