如何在 C++ 中使用十六进制信息创建 MIDI 文件
How to create MIDI file using hexadecimal information in C++
我正在尝试用 C++ 从头开始创建 MIDI 文件。
我将此网站用作资源:https://intuitive-theory.com/midi-from-scratch/ .
由于 MIDI 要求它以十六进制编码,我编写了一个程序来创建一个 MIDI 文件并将十六进制代码粘贴到其中,如下所示:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
using namespace std;
int main(){
ofstream myfile;
myfile.open ("output.mid",ios::binary);
char buffer[44] = {static_cast<char>(0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00)};
myfile.write(buffer,44);
myfile.close();
}
然而,这甚至无法在任何 MIDI 播放器上打开,因为“文件已损坏”。我不明白为什么会这样。
谢谢
char buffer[] = {static_cast<char>(0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00)};
不会将所有逗号分隔值转换为 char
。相反,因为 staic_cast
一次只能处理一个值,它会调用 comma operator ,这将使您保留最后一个值并丢弃其余值。
相反,让 buffer
成为正确的“形状”然后在将其传递给 write
时将其转换为 char
会更好。
int main(){
ofstream myfile;
myfile.open ("output.mid",ios::binary);
unsigned char buffer[] = {0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00};
// unsigned char can fit any of the given values
// Removed the 44. The compiler can figure the number of elements out from the
// number of initializers. Usually this is safer. Now you can add or remove
// a few bytes without also having to change the element count
myfile.write(reinterpret_cast<char *>(buffer), //casting here
sizeof(buffer)); // Letting compiler figure out how many bytes to write
myfile.close();
}
注意:reinterpret_cast
真的非常小心。它告诉编译器关闭它的大脑并相信你。如果你错了,程序将 break 并且你不会从编译器那里得到警告,并且运行时结果可能完全无法解释,直到你弄清楚发生了什么。
我正在尝试用 C++ 从头开始创建 MIDI 文件。 我将此网站用作资源:https://intuitive-theory.com/midi-from-scratch/ .
由于 MIDI 要求它以十六进制编码,我编写了一个程序来创建一个 MIDI 文件并将十六进制代码粘贴到其中,如下所示:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
using namespace std;
int main(){
ofstream myfile;
myfile.open ("output.mid",ios::binary);
char buffer[44] = {static_cast<char>(0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00)};
myfile.write(buffer,44);
myfile.close();
}
然而,这甚至无法在任何 MIDI 播放器上打开,因为“文件已损坏”。我不明白为什么会这样。
谢谢
char buffer[] = {static_cast<char>(0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00)};
不会将所有逗号分隔值转换为 char
。相反,因为 staic_cast
一次只能处理一个值,它会调用 comma operator ,这将使您保留最后一个值并丢弃其余值。
相反,让 buffer
成为正确的“形状”然后在将其传递给 write
时将其转换为 char
会更好。
int main(){
ofstream myfile;
myfile.open ("output.mid",ios::binary);
unsigned char buffer[] = {0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x01,0x00,0x01,0x00,0x80,0x4D,0x54,0x72,0x6B,0x00,0x00,0x00,0x16,0x80,0x00,0x90,0x3C,0x60,0x81,0x00,0x3E,0x60,0x81,0x00,0x40,0x60,0x81,0x00,0xB0,0x7B,0x00,0x00,0xFF,0x2F,0x00};
// unsigned char can fit any of the given values
// Removed the 44. The compiler can figure the number of elements out from the
// number of initializers. Usually this is safer. Now you can add or remove
// a few bytes without also having to change the element count
myfile.write(reinterpret_cast<char *>(buffer), //casting here
sizeof(buffer)); // Letting compiler figure out how many bytes to write
myfile.close();
}
注意:reinterpret_cast
真的非常小心。它告诉编译器关闭它的大脑并相信你。如果你错了,程序将 break 并且你不会从编译器那里得到警告,并且运行时结果可能完全无法解释,直到你弄清楚发生了什么。