[toc]

使用C语言在Windows中创建一个MIDI格式的文件

1.使用C语言在Windows中创建一个MIDI格式的文件(未能成功)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdint.h>

typedef struct {
char chunk_type[5]; // Chunk type
uint32_t header_size; // Header size
uint16_t format_type; // Format type
uint16_t track_count; // Number of tracks
uint16_t division; // Ticks per quarter note
} MidiHeader;

typedef struct {
char chunk_type[5]; // Chunk type
uint32_t track_size; // Track size
uint8_t* events; // Pointer to MIDI events
size_t event_count; // Number of events
} MidiTrack;

void write_midi_header(FILE* file) {
MidiHeader header = {
.chunk_type = "MThd",
.header_size = 6,
.format_type = 0, // Format type 0
.track_count = 1, // One track
.division = 480 // Ticks per quarter note
};

// Write MIDI file header
fwrite(header.chunk_type, 1, 4, file); // Chunk type
fwrite(&header.header_size, 4, 1, file); // Header size
fwrite(&header.format_type, 2, 1, file); // Format type
fwrite(&header.track_count, 2, 1, file); // Track count
fwrite(&header.division, 2, 1, file); // Division
}

void write_midi_track(FILE* file, MidiTrack* track) {
// Write MIDI track header
fwrite(track->chunk_type, 1, 4, file); // Chunk type
fwrite(&track->track_size, 4, 1, file); // Placeholder for track size

// Write note events
for (size_t i = 0; i < track->event_count; i++) {
fputc(track->events[i], file); // Write each event
}

// Update track size
long current_pos = ftell(file);
track->track_size = current_pos - 8; // 8 bytes for "MTrk" and size
fseek(file, -4, SEEK_CUR); // Move to track size position
fwrite(&track->track_size, 4, 1, file); // Write track size
fseek(file, current_pos, SEEK_SET); // Move back to the end
}

int main() {
FILE* file = fopen("output.mid", "wb");
if (!file) {
perror("Unable to create MIDI file");
return 1;
}

write_midi_header(file);

// Create a MIDI track
MidiTrack track = {
.chunk_type = "MTrk",
.track_size = 0,
.event_count = 0
};

// Allocate memory for events (for "do re mi fa so la ti do")
uint8_t events[256]; // Buffer for events
size_t event_index = 0;

// Note values for "do re mi fa so la ti do"
uint8_t notes[] = { 60, 62, 64, 65, 67, 69, 71, 72 }; // MIDI note numbers
uint8_t note_count = sizeof(notes) / sizeof(notes[0]);

// Write note events
for (int i = 0; i < note_count; i++) {
// Note On event
events[event_index++] = 0x00; // Delta time
events[event_index++] = 0x90; // Note On, channel 1
events[event_index++] = notes[i]; // Note number
events[event_index++] = 0x7F; // Velocity

// Note Off event after a delay
events[event_index++] = 0x80; // Delta time (128 ticks)
events[event_index++] = 0x80; // Note Off, channel 1
events[event_index++] = notes[i]; // Note number
events[event_index++] = 0x00; // Velocity
}

// Set tempo (120 BPM)
events[event_index++] = 0x00; // Delta time
events[event_index++] = 0xFF; // Meta event
events[event_index++] = 0x51; // Set tempo
events[event_index++] = 0x03; // Length of the event
events[event_index++] = 0x07; // Tempo in microseconds per quarter note (120 BPM)
events[event_index++] = 0xA1;
events[event_index++] = 0x20;

// End of track event
events[event_index++] = 0x00; // Delta time
events[event_index++] = 0xFF; // Meta event
events[event_index++] = 0x2F; // End of track
events[event_index++] = 0x00; // Length of the event

// Set the event count and allocate the events
track.event_count = event_index;
track.events = events;

// Write the MIDI track
write_midi_track(file, &track);

fclose(file);
printf("MIDI file created: output.mid\n");
return 0;
}