【问题标题】:How to create MIDI file using hexadecimal information in C++如何在 C++ 中使用十六进制信息创建 MIDI 文件
【发布时间】:2021-08-09 06:04:00
【问题描述】:

我正在尝试在 C++ 中从头开始创建一个 MIDI 文件。 我正在使用这个网站作为资源:https://intuitive-theory.com/midi-from-scratch/

由于 MIDI 要求它以十六进制编码,我编写了一个程序来创建一个 MIDI 文件并将 HEX 代码粘贴到其中,如下所示:

#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 播放器上打开。我不明白为什么会这样。

谢谢

【问题讨论】:

  • static_cast&lt;char&gt;(0x4D,0x54,...) 不会将该列表中的所有项目都转换为 chars it is casting the last one and discarding the rest
  • 你为什么在这里使用static_cast
  • @tadman 有些数字太大,很可能无法放入signed char
  • @user4581301 那么是时候确定unsigned charuint8_t了。
  • 建议:创建一个unsigned char 的数组,并在对write 的调用中将其转换为char*。例如:unsigned char buffer[44] = {0x4D,0x54,0x68,0x64,0x00,...};,然后是myfile.write(reinterpret_cast&lt;char*&gt;(buffer),sizeof(buffer));。注意:一般来说,要非常非常小心reinterpret_cast。它告诉编译器关掉它的大脑并相信你。如果你错了,程序会 be goofy 并且你不会收到任何警告。

标签: c++ hex midi


【解决方案1】:
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 并且你不会收到来自编译器的警告,并且在你弄清楚发生了什么之前,运行时结果可能完全无法解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-17
    • 2013-07-28
    • 2010-12-18
    • 2014-04-08
    • 1970-01-01
    • 2017-09-16
    • 2015-07-10
    • 2013-05-24
    相关资源
    最近更新 更多