-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmidi_data.c
More file actions
120 lines (105 loc) · 3.17 KB
/
midi_data.c
File metadata and controls
120 lines (105 loc) · 3.17 KB
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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "midi_data.h"
struct MIDI_DATA *midi_new(uint8_t format, uint16_t n_tracks, uint16_t ticks_per_beat)
{
struct MIDI_DATA *midi = malloc(sizeof(struct MIDI_DATA) + n_tracks*sizeof(struct MIDI_TRACK));
if (midi == NULL) {
return NULL;
}
midi->format = format;
midi->ticks_per_beat = ticks_per_beat;
midi->n_tracks = n_tracks;
for (int i = 0; i < n_tracks; i++) {
midi->tracks[i].n_events = 0;
midi->tracks[i].alloc_events = 0;
midi->tracks[i].events = NULL;
}
return midi;
}
static void free_midi_event(struct MIDI_EVENT *ev)
{
switch (ev->type) {
case MIDI_EVENT_TYPE_MIDI:
break;
case MIDI_EVENT_TYPE_SYSEX:
free(ev->sysex.data);
break;
case MIDI_EVENT_TYPE_META:
if (ev->meta.type == MIDI_EVENT_TYPE_META_LONG) {
free(ev->meta.long_data.data);
}
break;
default:
fprintf(stderr, "WARNING: internal error: invalid MIDI event type: %d\n", ev->type);
break;
}
}
void midi_free(struct MIDI_DATA *midi)
{
if (midi == NULL) return;
for (int t = 0; t < midi->n_tracks; t++) {
for (int e = 0; e < midi->tracks[t].n_events; e++) {
free_midi_event(&midi->tracks[t].events[e]);
}
free(midi->tracks[t].events);
}
free(midi);
}
static struct MIDI_EVENT *add_event(struct MIDI_DATA *midi, uint16_t track_num)
{
struct MIDI_TRACK *tr = &midi->tracks[track_num];
if (tr->n_events+1 >= tr->alloc_events) {
int new_alloc_events = tr->alloc_events + 64;
struct MIDI_EVENT *evs = realloc(tr->events, sizeof(struct MIDI_EVENT)*new_alloc_events);
if (evs == NULL) {
return NULL;
}
tr->events = evs;
tr->alloc_events = new_alloc_events;
}
struct MIDI_EVENT *ev = &tr->events[tr->n_events++];
ev->delta_time = 0;
return ev;
}
struct MIDI_EVENT_MIDI *midi_add_midi_event(struct MIDI_DATA *midi, uint16_t track_num, uint32_t delta_time)
{
struct MIDI_EVENT *ev = add_event(midi, track_num);
if (ev == NULL) {
return NULL;
}
ev->type = MIDI_EVENT_TYPE_MIDI;
ev->delta_time = delta_time;
ev->midi.status = 0x80;
ev->midi.data1 = 0;
ev->midi.data2 = 0;
return &ev->midi;
}
struct MIDI_EVENT_SYSEX *midi_add_sysex_event(struct MIDI_DATA *midi, uint16_t track_num, uint32_t delta_time)
{
struct MIDI_EVENT *ev = add_event(midi, track_num);
if (ev == NULL) {
return NULL;
}
ev->type = MIDI_EVENT_TYPE_SYSEX;
ev->delta_time = delta_time;
ev->sysex.sysex_type = 0xf0;
ev->sysex.data_len = 0;
ev->sysex.data = NULL;
return &ev->sysex;
}
struct MIDI_EVENT_META *midi_add_meta_event(struct MIDI_DATA *midi, uint16_t track_num, uint32_t delta_time)
{
struct MIDI_EVENT *ev = add_event(midi, track_num);
if (ev == NULL) {
return NULL;
}
ev->type = MIDI_EVENT_TYPE_META;
ev->delta_time = delta_time;
ev->meta.meta_type = 0x00;
ev->meta.type = MIDI_EVENT_TYPE_META_LONG;
ev->meta.data_len = 0;
ev->meta.long_data.data = NULL;
return &ev->meta;
}