Encoding MIDI和位顺序

Encoding MIDI和位顺序,encoding,hex,bytearray,bit-manipulation,midi,Encoding,Hex,Bytearray,Bit Manipulation,Midi,我一直在尝试格式化一条MIDI Sys Ex消息,但设备一直拒绝该消息,认为该消息无效。问题是消息的一部分涉及下面描述的数据编码类型 根据手册, 设备“将编码/解释一组连续的4字节” 字节#0-B31B30B29B28B227B26B25B24 字节#1-B23B22B221B20B19B18B17B16 字节2-b15b14b13b12b11b10b09b08 字节3-B07B06B05B004B03B02B01B00 与以下5个连续的SysEx字节相同: 字节0-0 B06B005B04B0

我一直在尝试格式化一条MIDI Sys Ex消息,但设备一直拒绝该消息,认为该消息无效。问题是消息的一部分涉及下面描述的数据编码类型

根据手册,

设备“将编码/解释一组连续的4字节”

字节#0-B31B30B29B28B227B26B25B24

字节#1-B23B22B221B20B19B18B17B16

字节2-b15b14b13b12b11b10b09b08

字节3-B07B06B05B004B03B02B01B00

与以下5个连续的SysEx字节相同:

字节0-0 B06B005B04B03B02B001B00

字节#1-0 b13b12b11b10b09b08b07

字节2-0 b20b19b18b17b16b15b14

字节#3-0 B27B226B25B224B23B22B221

字节4-0 b31b30b29b28

其中“b”是位号。请注意位号已翻转。您应该以哪种方式读取位?根据惯例,MIDI数据是反向位序(MSB=7),如果这有帮助的话。此外,手册还指出“所有数据类型都是按摩托罗拉大端字节顺序。”

下面是我试图正确格式化的消息的描述-

“命令将允许编辑一到四个字节的连续组。当指定3个或更少字节时,设备希望参数值字段按位排序,就像它正在执行完整的32位(4字节)参数更改一样。例如,编辑双字节参数时,字节#0将占用b24-b31的位范围,而字节#1将占用位b16-b23。参数值字段中的剩余位(b00-b15)应设置为零。”

bb参数偏移量-0b06b05b04b03b02b01b00

bb参数偏移量-0b13b12b11b10b09b08b07

bb参数偏移量-0b20b19b18b17b16b15b14

bb参数偏移量-0B27B26B25B224B23B22B21

bb参数偏移量-0b31b30b29b28

0b参数字节大小(1到4)

00

00

00

00

bb参数值-0b06b05b04b03b02b01b00

bb参数值-0b13b12b11b10b09b08b07

bb参数值-0b20b19b18b17b16b15b14

bb参数值-0B27B26B25B224B23B22B21

bb参数值-0b31b30b29b28


所以,当尝试输入偏移量值15H、16H、17H和18H时,它们的值分别是00、01、02、03,我应该如何编码这些十六进制值,或者我甚至需要编码它们?如果需要,我应该向哪个方向写入位,这样二进制值才是正确的?

你的问题有点让人困惑。1字节是8位因此,以下行:

字节-#0 B31B30B29B28B227B26B225B24

字节-#1 B23B22B221B20B19B18B17B16

字节-#2 b15b14b13b12b11b10b09b08

字节-#3 B07B006B05B004B03B02B001B00

对我来说没有意义。第一行#0有8个字节。我做了一些搜索,这是一个更好的解释()。从第2页中获取内容并编辑它们以保持清晰

 Offset           | Byte 0 | Byte 1 | Byte 2 |  Byte 3
 --------   bits  |  24-31 | 16-23  |  8-15  |   0-7
 00000000         |    00  |        |        |
 00000040         |    40  |        |        |
 0000007F         |    7F  |        |        |
 00000080         |    81  |   00   |        |
 00002000         |    C0  |   00   |        |
 00003FFF         |    FF  |   7F   |        |             <--- example
 00004000         |    81  |   80   |   00   |
 00100000         |    C0  |   80   |   00   |
 001FFFFF         |    FF  |   FF   |   7F   |
 00200000         |    81  |   80   |   80   |   00
 08000000         |    C0  |   80   |   80   |   00
 0FFFFFFF         |    FF  |   FF   |   FF   |   7F


Example at offset 3FFF
Hex format 0xFF7F_0000 (32-bit number, unused bits are 0) 

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
 1  1  1  1  1  1  1  1  0  1  1  1  1  1  1  1

15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
Offset |字节0 |字节1 |字节2 |字节3
--------位| 24-31 | 16-23 | 8-15 | 0-7
00000000         |    00  |        |        |
00000040         |    40  |        |        |
000000 7F | 7F | ||
00000080         |    81  |   00   |        |
000020000 | C0 | 00 ||

00003FFF | FF | 7F | |写入时,字节中的位顺序始终为大端,即MSB优先。 数据字节的MSB必须为零这一事实可以证实这一点



这种转换的基本方法是将四个8位值组合成一个32位值,然后依次将最低有效位的七位移到五个字节中

#include <stdio.h>
#include <stdint.h>

void convert(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t *outBytes) {
    uint32_t inBytes = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3; //combine the input bytes into a single 32-bit value
    for (int i = 0; i < 5; i++) {
        outBytes[i] = inBytes & 0x7F; //Copy the least significant seven bits into the next byte in the output array
        inBytes >>= 7; //Shift right to discard the seven bits that were copied
    }
}

void printByteArray(uint8_t *byteArray) {
    for (int i = 0; i < 5; i++) {
        printf("Byte %d: %02xh\n", i, byteArray[i]);
    }
    printf("\n");
}

int main(int argc, char *argv[]) {
    uint8_t sysExBytes[5]; //Five bytes to contain the converted SysExData

    convert(0x15, 0x16, 0x17, 0x18, sysExBytes);
    printByteArray(sysExBytes);

    convert(0x00, 0x01, 0x02, 0x03, sysExBytes);
    printByteArray(sysExBytes);

    return 0;
}

谢谢!在本例中,b31是MSB,b00是LSB?位通常用这样的数字表示吗?除了知道如何重新排列它们之外,这些位并不重要。如果这些位被称为A、B、C…或Tom、Dick和Harry,则不会有任何区别。您可以使用来生成下标。我将这些位数字更改为下标to使问题更易于阅读。这并不能解决问题。问题是MIDI数据字节在MSB中必须有一个零。问题是如何做到这一点。谢谢@SSteve。你认为你可以用简单的英语解释算法吗?我不是程序员,我也不太理解你使用的语法。我不会抱歉,本周是时候写些深入的东西了。关键是你把四个八位字节放在一起,然后把这些字节分成七个一组,而不是八个。
Four bytes:
  01 -> 00000001
  02 -> 00000010
  03 -> 00000011
  04 -> 00000100
SysEx bytes:
        0 0000100 -> 04h
        0 0000110 -> 06h
        0 0001000 -> 08h
        0 0001000 -> 08h
        0000 0000 -> 00h
#include <stdio.h>
#include <stdint.h>

void convert(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t *outBytes) {
    uint32_t inBytes = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3; //combine the input bytes into a single 32-bit value
    for (int i = 0; i < 5; i++) {
        outBytes[i] = inBytes & 0x7F; //Copy the least significant seven bits into the next byte in the output array
        inBytes >>= 7; //Shift right to discard the seven bits that were copied
    }
}

void printByteArray(uint8_t *byteArray) {
    for (int i = 0; i < 5; i++) {
        printf("Byte %d: %02xh\n", i, byteArray[i]);
    }
    printf("\n");
}

int main(int argc, char *argv[]) {
    uint8_t sysExBytes[5]; //Five bytes to contain the converted SysExData

    convert(0x15, 0x16, 0x17, 0x18, sysExBytes);
    printByteArray(sysExBytes);

    convert(0x00, 0x01, 0x02, 0x03, sysExBytes);
    printByteArray(sysExBytes);

    return 0;
}
Byte 0: 18h
Byte 1: 2eh
Byte 2: 58h
Byte 3: 28h
Byte 4: 01h

Byte 0: 03h
Byte 1: 04h
Byte 2: 04h
Byte 3: 00h
Byte 4: 00h