Encoding MIDI和位顺序
我一直在尝试格式化一条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参数值-0b31b30b29b28Encoding 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
所以,当尝试输入偏移量值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