// マルチバイト文字セット
#include <stdio.h>
#include <Windows.h>
// 関数プロトタイプ宣言
void WriteBE(int len, DWORD val);
void WriteData(DWORD t, BYTE cmd, BYTE d1, BYTE d2);
// 外部変数
FILE* pFile;
int datalen; // データ長
//==============================================================================
int main()
{
if (fopen_s(&pFile, "sample.mid", "wb") != 0) {
fprintf(stderr, "fopen error\n");
return 1;
}
// ヘッダチャンク
fwrite("MThd", 1, 4, pFile);
WriteBE(4, 6); // データ長
WriteBE(2, 0); // フォーマットタイプ
WriteBE(2, 1); // トラック数
WriteBE(2, 480); // タイムベース
// トラックチャンク
fwrite("MTrk", 1, 4, pFile);
datalen = 0;
WriteBE(4, datalen); // データ長(仮)
// データセクション
WriteData(0, 0x90, 60, 0x70);
WriteData(480, 0x80, 60, 0);
WriteData(0, 0x90, 64, 0x70);
WriteData(480, 0x80, 64, 0);
WriteData(0, 0x90, 67, 0x70);
WriteData(480, 0x80, 67, 0);
// トラック終了
WriteData(0, 0xff, 0x2f, 0x00);
fseek(pFile, -4 - datalen, SEEK_CUR);
WriteBE(4, datalen); // データ長
fclose(pFile);
return 0;
}
void WriteBE(int len, DWORD val)
{
BYTE* p = (BYTE*)&val + len;
for (int n = 0; n < len; n++) {
fwrite(--p, 1, 1, pFile);
}
}
void WriteData(DWORD t, BYTE cmd, BYTE d1, BYTE d2)
{
// 可変長tick
DWORD v = ((t&0xfe00000)<<3)|((t&0x1fc000)<<2)|((t&0x3f80)<<1)|(t&0x7f)|0x80808000;
BYTE* p = (BYTE*)&v + 4;
for (int n = 0; n < 4; n++) {
if (*--p != 0x80) {
fwrite(p, 1, 1, pFile);
datalen++;
}
}
fwrite(&cmd, 1, 1, pFile);
fwrite(&d1, 1, 1, pFile);
fwrite(&d2, 1, 1, pFile);
datalen += 3;
}