在 C 中生成 MIDI 文件

Posted

技术标签:

【中文标题】在 C 中生成 MIDI 文件【英文标题】:Generating MIDI-files in C 【发布时间】:2017-12-22 00:18:02 【问题描述】:

我正在尝试,但文件的标题块有点问题。

所以 MIDI 头的形式是:

块类型-长度-格式-ntrks-划分

块类型是四个ASCII字符'MThd';长度是数字 6 的 32 位表示(高字节在前)。其余为 16 位。

所以我为 Header 创建了一个结构体,如下所示:

struct headerStruct 
    char chunktype[4]; //MThd
    long length; //32bit length
    int format;//16bit format
    int ntraks;//16bit number of tracks
    int division;//16bit division
;

然后我在代码中创建结构:

struct headerStruct *mthd = malloc(sizeof(struct headerStruct));
strncpy(mthd->chunktype, "MThd",4);
mthd->length = 6;
mthd->format = 0;
mthd->ntraks = 1;
mthd->division = 96;

然后我用 fwrite 编写文件(还有这里没有介绍的其他内容),我将保留这部分代码。但是,如果我用 xxd 查看二进制/十六进制并将其与使用 ableton 创建的正确 midi 文件进行比较,我会发现它们是不同的,而我的不正确。

正确的十六进制 midi 标头:

4d54 6864 0000 0006 0000 0001 0060

我不正确的十六进制 midi 标头:

4d54 6864 0000 0000 0600 0000 0000 0000 0000 0100 6000 0000

这是什么原因造成的?是字节顺序问题还是我使用了错误的数据类型。我在 64 位操作系统 X 10.10.5 上。因为如果我理解正确,标题中的 16 位部分应该是整数和长度(32 位)长等等。如果这是一个字节顺序的事情,我该如何纠正这个问题。我在这里阅读了一些字节顺序主题,但并没有真正理解它们。

以下是 pdf 的链接,以获取有关 MIDI 的更多信息: https://www.cs.cmu.edu/~music/cmsip/readings/Standard-MIDI-file-format-updated.pdf

【问题讨论】:

我猜你的ints 是 32 位的。尝试 short 获取 16 位值。 我认为你是对的,但它们的顺序仍然错误,长度为 int 并且剩余短裤的十六进制看起来像这样:4d54 6864 0600 0000 0000 0100 6000 0000 应该是这样的:4d54 6864 0000 0006 0000 0001 0060 所以还有16位太多了。我想知道是不是因为 strncpy 和额外的 \0? 我建议您包含stdint.h 并使用uint32_tuint16_t 等。这将更便携(因为int 也可以是 32 位)。 检查其他生成 MIDI 文件的程序,例如,git.alsa-project.org/?p=alsa-utils.git;a=blob;f=seq/aplaymidi/…。 谢谢 CL 我会经历的! Myst 我在 *** 中查看了其他一些主题中的内容,但我在 C 方面没有那么丰富的经验,那么这些 uint32_t uint16_t 是如何工作的?就像文件开头的某种定义一样吗? 【参考方案1】:

MIDI 文件要求值以大端字节顺序写入,也称为“网络顺序”;您可能会发现 htnol(3) 和 htons(3) 很有用:

#include <arpa/inet.h>
...
mthd->length = htonl(6);
mthd->ntraks = htons(1);
...

【讨论】:

是的,就是这样!非常感谢!现在,ableton 接受了文件并且很好......崩溃了:D 猜猜我现在需要处理 MTrk 部分。 嗯。即使我将结构的 int 更改为 shorts 并将 long 更改为 int,仍然有 16 位太多。现在十六进制是这样的: 4d54 6864 0000 0006 0000 0001 0060 0000 所以最后两个字节太多了。他们来自哪里? 如何将结构写入文件?不要使用sizeof(* mthd),因为那是4字节的倍数(long的对齐方式)。一个一个地写字段。 是的,成功了!太好了,非常感谢!为什么是4字节的倍数? 它是 4 的倍数,因为它包含一个 long 成员,并且编译器需要使结构的大小成为 long 所需对齐的倍数,以防你创建一个数组其中。

以上是关于在 C 中生成 MIDI 文件的主要内容,如果未能解决你的问题,请参考以下文章

在.net项目中生成的pdb是啥文件?

[转]如何禁止 IIS 在 C:WindowsSystem32LogFilesHTTPERR 中生成日志文件

如何在SSIS中的每一行中生成具有不同数据类型的固定宽度文件

在gcc、g++中生成ASM代码需要啥

使用 C 解析 MIDI 文件 - (分配内存的可能问题)

未在 laravel 中生成 PDF