2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "pattern-maker.h"
32 static gint
event_entry_compare(gconstpointer a
, gconstpointer b
, gpointer unused
)
34 const struct event_entry
*ea
= a
, *eb
= b
;
35 // Event ordering - it's to ensure bank changes are emitted before program
36 // changes and program changes are emitted before notes.
37 static const char event_class
[8] = {
48 if (ea
->time
< eb
->time
)
50 if (ea
->time
== eb
->time
&& event_class
[ea
->data
[0] >> 4] < event_class
[eb
->data
[0] >> 4])
52 if (ea
->time
== eb
->time
&& (ea
->data
[0] & 15) < (eb
->data
[0] & 15))
54 if (ea
->time
== eb
->time
&& ea
->data
[0] == eb
->data
[0] && ea
->data
[1] < eb
->data
[1])
56 if (ea
->time
== eb
->time
&& ea
->data
[0] == eb
->data
[0] && ea
->data
[1] == eb
->data
[1])
61 static void event_entry_destroy(gpointer p
)
63 struct event_entry
*e
= p
;
67 struct cbox_midi_pattern_maker
73 struct cbox_midi_pattern_maker
*cbox_midi_pattern_maker_new(void)
75 struct cbox_midi_pattern_maker
*maker
= malloc(sizeof(struct cbox_midi_pattern_maker
));
76 maker
->events
= g_tree_new_full(event_entry_compare
, NULL
, event_entry_destroy
, NULL
);
81 void cbox_midi_pattern_maker_add(struct cbox_midi_pattern_maker
*maker
, uint32_t time
, uint8_t cmd
, uint8_t val1
, uint8_t val2
)
83 struct event_entry
*e
= malloc(sizeof(struct event_entry
));
89 g_tree_insert(maker
->events
, e
, NULL
);
92 void cbox_midi_pattern_maker_add_mem(struct cbox_midi_pattern_maker
*maker
, uint32_t time
, const uint8_t *src
, uint32_t len
)
96 g_warning("Event size %d not supported yet, ignoring", (int)len
);
99 struct event_entry
*e
= malloc(sizeof(struct event_entry
));
101 memcpy(e
->data
, src
, len
);
103 g_tree_insert(maker
->events
, e
, NULL
);
106 struct traverse_state
108 struct cbox_midi_event
*events
;
112 static gboolean
traverse_func(gpointer key
, gpointer value
, gpointer pstate
)
114 struct traverse_state
*state
= pstate
;
115 struct event_entry
*e
= key
;
116 struct cbox_midi_event
*event
= &state
->events
[state
->pos
++];
117 event
->time
= e
->time
;
118 event
->size
= midi_cmd_size(e
->data
[0]);
119 memcpy(event
->data_inline
, &e
->data
[0], 3);
123 extern void cbox_song_add_pattern(struct cbox_song
*song
, struct cbox_midi_pattern
*pattern
);
125 struct cbox_midi_pattern
*cbox_midi_pattern_maker_create_pattern(struct cbox_midi_pattern_maker
*maker
, struct cbox_song
*song
, gchar
*name
)
127 struct cbox_midi_pattern
*p
= malloc(sizeof(struct cbox_midi_pattern
));
128 CBOX_OBJECT_HEADER_INIT(p
, cbox_midi_pattern
, CBOX_GET_DOCUMENT(song
));
129 cbox_command_target_init(&p
->cmd_target
, cbox_midi_pattern_process_cmd
, p
);
132 p
->event_count
= g_tree_nnodes(maker
->events
);
133 p
->events
= malloc(sizeof(struct cbox_midi_event
[1]) * p
->event_count
);
135 struct traverse_state st
= { p
->events
, 0 };
137 g_tree_foreach(maker
->events
, traverse_func
, &st
);
139 CBOX_OBJECT_REGISTER(p
);
141 cbox_song_add_pattern(song
, p
);
146 gboolean
cbox_midi_pattern_maker_load_smf(struct cbox_midi_pattern_maker
*maker
, const char *filename
, int *length
, GError
**error
)
148 smf_t
*smf
= smf_load(filename
);
151 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Cannot load SMF file '%s'", filename
);
155 int ppqn
= smf
->ppqn
;
156 smf_event_t
*event
= NULL
;
157 while ((event
= smf_get_next_event(smf
)) != NULL
) {
158 if (smf_event_is_metadata(event
))
161 cbox_midi_pattern_maker_add_mem(maker
, event
->time_pulses
* 1.0 * PPQN
/ ppqn
, event
->midi_buffer
, event
->midi_buffer_length
);
164 *length
= smf_get_length_pulses(smf
) * 1.0 * PPQN
/ ppqn
;
170 void cbox_midi_pattern_maker_destroy(struct cbox_midi_pattern_maker
*maker
)
172 g_tree_destroy(maker
->events
);