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 "config-api.h"
23 #include "pattern-maker.h"
28 extern void cbox_song_remove_pattern(struct cbox_song
*song
, struct cbox_midi_pattern
*pattern
);
30 CBOX_CLASS_DEFINITION_ROOT(cbox_midi_pattern
)
32 struct cbox_midi_pattern
*cbox_midi_pattern_new_metronome(struct cbox_song
*song
, int ts
, uint64_t ppqn_factor
)
34 struct cbox_midi_pattern_maker
*m
= cbox_midi_pattern_maker_new(ppqn_factor
);
36 int length
= (int)ppqn_factor
;
37 int channel
= cbox_config_get_int("metronome", "channel", 10);
38 int accnote
= cbox_config_get_note("metronome", "note_accent", 37);
39 int note
= cbox_config_get_note("metronome", "note", 37);
41 for (int i
= 0; i
< ts
; i
++)
43 int accent
= !i
&& ts
!= 1;
44 cbox_midi_pattern_maker_add(m
, length
* i
, 0x90 + channel
- 1, accent
? accnote
: note
, accent
? 127 : 100);
45 cbox_midi_pattern_maker_add(m
, length
* i
+ 1, 0x80 + channel
- 1, accent
? accnote
: note
, 0);
48 struct cbox_midi_pattern
*p
= cbox_midi_pattern_maker_create_pattern(m
, song
, g_strdup_printf("click-%d", ts
));
49 p
->loop_end
= length
* ts
;
51 cbox_midi_pattern_maker_destroy(m
);
56 void cbox_midi_pattern_destroyfunc(struct cbox_objhdr
*objhdr
)
58 struct cbox_midi_pattern
*pattern
= CBOX_H2O(objhdr
);
60 cbox_song_remove_pattern(pattern
->owner
, pattern
);
61 g_free(pattern
->name
);
62 if (pattern
->events
!= NULL
)
63 free(pattern
->events
);
68 static int cbox_midi_pattern_load_smf_into(struct cbox_midi_pattern_maker
*m
, const char *smf
)
71 if (!cbox_midi_pattern_maker_load_smf(m
, smf
, &length
, NULL
))
73 g_error("Cannot load SMF file %s", smf
);
80 static int cbox_midi_pattern_load_melodic_into(struct cbox_midi_pattern_maker
*m
, const char *name
, int start_pos
, int transpose
, int transpose_to_note
, uint64_t ppqn_factor
)
82 gchar
*cfg_section
= g_strdup_printf("pattern:%s", name
);
84 if (!cbox_config_has_section(cfg_section
))
86 g_error("Melodic pattern '%s' not found", name
);
91 gchar
*smf
= cbox_config_get_string(cfg_section
, "smf");
94 return cbox_midi_pattern_load_smf_into(m
, smf
);
97 g_warning("libsmf disabled at build time, MIDI import functionality not available.");
100 int length
= ppqn_factor
* cbox_config_get_int(cfg_section
, "beats", 4);
101 int gchannel
= cbox_config_get_int(cfg_section
, "channel", 1);
102 int gswing
= cbox_config_get_int(cfg_section
, "swing", 0);
103 int gres
= cbox_config_get_int(cfg_section
, "resolution", 4);
104 int orignote
= cbox_config_get_note(cfg_section
, "base_note", 24);
105 if (transpose_to_note
!= -1)
106 transpose
+= transpose_to_note
- orignote
;
108 for (int t
= 1; ; t
++)
110 gchar
*tname
= g_strdup_printf("track%d", t
);
111 char *trkname
= cbox_config_get_string(cfg_section
, tname
);
115 tname
= g_strdup_printf("%s_vel", trkname
);
116 int vel
= cbox_config_get_note(cfg_section
, tname
, 100);
118 tname
= g_strdup_printf("%s_res", trkname
);
119 int res
= cbox_config_get_note(cfg_section
, tname
, gres
);
121 tname
= g_strdup_printf("%s_channel", trkname
);
122 int channel
= cbox_config_get_note(cfg_section
, tname
, gchannel
);
124 tname
= g_strdup_printf("%s_swing", trkname
);
125 int swing
= cbox_config_get_int(cfg_section
, tname
, gswing
);
127 tname
= g_strdup_printf("%s_notes", trkname
);
128 const char *notes
= cbox_config_get_string(cfg_section
, tname
);
132 g_error("Invalid track %s", trkname
);
134 const char *s
= notes
;
142 const char *comma
= strchr(s
, ',');
145 note
= g_strndup(s
, comma
- s
);
156 int pitch
= note_from_string(note
);
158 int pos
= t
* ppqn_factor
/ res
+ start_pos
;
160 pos
+= ppqn_factor
* swing
/ (res
* 24);
162 int pos2
= (t
+ 1) * ppqn_factor
/ res
+ start_pos
;
164 pos2
+= ppqn_factor
* swing
/ (res
* 24);
168 cbox_midi_pattern_maker_add(m
, pos
, 0x90 + channel
- 1, pitch
, vel
);
169 cbox_midi_pattern_maker_add(m
, pos2
- 1, 0x80 + channel
- 1, pitch
, 0);
183 static int cbox_midi_pattern_load_drum_into(struct cbox_midi_pattern_maker
*m
, const char *name
, int start_pos
, uint64_t ppqn_factor
)
185 gchar
*cfg_section
= g_strdup_printf("drumpattern:%s", name
);
187 if (!cbox_config_has_section(cfg_section
))
189 g_error("Drum pattern '%s' not found", name
);
194 gchar
*smf
= cbox_config_get_string(cfg_section
, "smf");
197 return cbox_midi_pattern_load_smf_into(m
, smf
);
200 g_warning("libsmf disabled at build time, MIDI import functionality not available.");
203 int length
= ppqn_factor
* cbox_config_get_int(cfg_section
, "beats", 4);
204 int channel
= cbox_config_get_int(cfg_section
, "channel", 10);
205 int gswing
= cbox_config_get_int(cfg_section
, "swing", 0);
206 int gres
= cbox_config_get_int(cfg_section
, "resolution", 4);
208 for (int t
= 1; ; t
++)
210 gchar
*tname
= g_strdup_printf("track%d", t
);
211 char *trkname
= cbox_config_get_string(cfg_section
, tname
);
215 tname
= g_strdup_printf("%s_note", trkname
);
216 int note
= cbox_config_get_note(cfg_section
, tname
, -1);
218 tname
= g_strdup_printf("%s_res", trkname
);
219 int res
= cbox_config_get_note(cfg_section
, tname
, gres
);
221 tname
= g_strdup_printf("%s_swing", trkname
);
222 int swing
= cbox_config_get_int(cfg_section
, tname
, gswing
);
224 tname
= g_strdup_printf("%s_trigger", trkname
);
225 const char *trigger
= cbox_config_get_string(cfg_section
, tname
);
227 if (!trigger
|| note
== -1)
229 g_error("Invalid track %s", trkname
);
232 for (int i
= 0; trigger
[i
]; i
++)
234 int pos
= t
* ppqn_factor
/ res
+ start_pos
;
236 pos
+= ppqn_factor
* swing
/ (res
* 24);
237 if (trigger
[i
] >= '1' && trigger
[i
] <= '9')
239 int amt
= (trigger
[i
] - '0') * 127 / 9;
240 cbox_midi_pattern_maker_add(m
, pos
, 0x90 + channel
- 1, note
, amt
);
241 cbox_midi_pattern_maker_add(m
, pos
+ 1, 0x80 + channel
- 1, note
, 0);
244 if (trigger
[i
] == 'F') // flam
246 int dflam
= ppqn_factor
/ 4;
247 int rnd
= rand() & 7;
249 cbox_midi_pattern_maker_add(m
, pos
- dflam
, 0x90 + channel
- 1, note
, 90+rnd
);
250 cbox_midi_pattern_maker_add(m
, pos
- dflam
+ 1, 0x80 + channel
- 1, note
, 0);
251 cbox_midi_pattern_maker_add(m
, pos
, 0x90 + channel
- 1, note
, 120 + rnd
);
252 cbox_midi_pattern_maker_add(m
, pos
+ 1, 0x80 + channel
- 1, note
, 0);
255 if (trigger
[i
] == 'D') // drag
257 pos
= (t
+ 1) * ppqn_factor
/ res
+ start_pos
;
259 // pos += ppqn_factor * swing / (res * 24);
260 float dflam
= ppqn_factor
/8.0;
261 int rnd
= rand() & 7;
262 cbox_midi_pattern_maker_add(m
, pos
- dflam
*2, 0x90 + channel
- 1, note
, 70+rnd
);
263 cbox_midi_pattern_maker_add(m
, pos
- dflam
*2 + 1, 0x80 + channel
- 1, note
, 0);
264 cbox_midi_pattern_maker_add(m
, pos
- dflam
, 0x90 + channel
- 1, note
, 60+rnd
);
265 cbox_midi_pattern_maker_add(m
, pos
- dflam
+ 1, 0x80 + channel
- 1, note
, 0);
268 else if (trigger
[i
] == '.')
281 struct cbox_midi_pattern
*cbox_midi_pattern_load(struct cbox_song
*song
, const char *name
, int is_drum
, uint64_t ppqn_factor
)
283 struct cbox_midi_pattern_maker
*m
= cbox_midi_pattern_maker_new(ppqn_factor
);
287 length
= cbox_midi_pattern_load_drum_into(m
, name
, 0, ppqn_factor
);
289 length
= cbox_midi_pattern_load_melodic_into(m
, name
, 0, 0, -1, ppqn_factor
);
290 struct cbox_midi_pattern
*p
= cbox_midi_pattern_maker_create_pattern(m
, song
, g_strdup(name
));
291 p
->loop_end
= length
;
293 cbox_midi_pattern_maker_destroy(m
);
298 struct cbox_midi_pattern
*cbox_midi_pattern_load_track(struct cbox_song
*song
, const char *name
, int is_drum
, uint64_t ppqn_factor
)
301 struct cbox_midi_pattern_maker
*m
= cbox_midi_pattern_maker_new(ppqn_factor
);
303 gchar
*cfg_section
= g_strdup_printf(is_drum
? "drumtrack:%s" : "track:%s", name
);
305 if (!cbox_config_has_section(cfg_section
))
307 g_error("Drum track '%s' not found", name
);
312 for (int p
= 1; ; p
++)
314 gchar
*pname
= g_strdup_printf("pos%d", p
);
315 char *patname
= cbox_config_get_string(cfg_section
, pname
);
320 char *comma
= strchr(patname
, ',');
323 char *v
= comma
? g_strndup(patname
, comma
- patname
) : g_strdup(patname
);
324 patname
= comma
? comma
+ 1 : patname
+ strlen(patname
);
326 int xpval
= 0, xpnote
= -1;
329 char *xp
= strchr(v
, '+');
333 xpval
= atoi(xp
+ 1);
341 xpnote
= note_from_string(xp
+ 1);
346 int is_drum_pat
= is_drum
;
351 is_drum_pat
= !is_drum_pat
;
354 plen
= cbox_midi_pattern_load_drum_into(m
, v
+ nofs
, length
, ppqn_factor
);
356 plen
= cbox_midi_pattern_load_melodic_into(m
, v
+ nofs
, length
, xpval
, xpnote
, ppqn_factor
);
360 cbox_midi_pattern_maker_destroy(m
);
366 comma
= strchr(patname
, ',');
376 struct cbox_midi_pattern
*p
= cbox_midi_pattern_maker_create_pattern(m
, song
, g_strdup(name
));
377 p
->loop_end
= length
;
379 cbox_midi_pattern_maker_destroy(m
);
384 struct cbox_midi_pattern
*cbox_midi_pattern_new_from_blob(struct cbox_song
*song
, const struct cbox_blob
*blob
, int length
, uint64_t ppqn_factor
)
386 struct cbox_midi_pattern_maker
*m
= cbox_midi_pattern_maker_new(ppqn_factor
);
388 struct cbox_blob_serialized_event event
;
389 for (size_t i
= 0; i
< blob
->size
; i
+= sizeof(event
))
391 // not sure about alignment guarantees of Python buffers
392 memcpy(&event
, ((uint8_t *)blob
->data
) + i
, sizeof(event
));
393 cbox_midi_pattern_maker_add(m
, event
.time
, event
.cmd
, event
.byte1
, event
.byte2
);
396 struct cbox_midi_pattern
*p
= cbox_midi_pattern_maker_create_pattern(m
, song
, g_strdup("unnamed-blob"));
397 p
->loop_end
= length
;
399 cbox_midi_pattern_maker_destroy(m
);
404 struct cbox_blob
*cbox_midi_pattern_to_blob(struct cbox_midi_pattern
*pat
, int *length
)
407 *length
= pat
->loop_end
;
409 struct cbox_blob_serialized_event event
;
411 for (int i
= 0; i
< pat
->event_count
; i
++)
413 // currently sysex events and the like are not supported
414 if (pat
->events
[i
].size
< 4)
415 size
+= sizeof(event
);
418 struct cbox_blob
*blob
= cbox_blob_new(size
);
421 uint8_t *data
= blob
->data
;
422 for (int i
= 0; i
< pat
->event_count
; i
++)
424 // currently sysex events and the like are not supported
425 const struct cbox_midi_event
*src
= &pat
->events
[i
];
428 event
.time
= src
->time
;
429 event
.len
= src
->size
;
430 memcpy(&event
.cmd
, &src
->data_inline
[0], event
.len
);
431 memcpy(data
+ size
, &event
, sizeof(event
));
432 size
+= sizeof(event
);
438 gboolean
cbox_midi_pattern_process_cmd(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
440 struct cbox_midi_pattern
*p
= ct
->user_data
;
442 if (!strcmp(cmd
->command
, "/status") && !strcmp(cmd
->arg_types
, ""))
444 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
447 return cbox_execute_on(fb
, NULL
, "/event_count", "i", error
, (int)p
->event_count
) &&
448 cbox_execute_on(fb
, NULL
, "/loop_end", "i", error
, (int)p
->loop_end
) &&
449 cbox_execute_on(fb
, NULL
, "/name", "s", error
, p
->name
) &&
450 CBOX_OBJECT_DEFAULT_STATUS(p
, fb
, error
)
453 else if (!strcmp(cmd
->command
, "/name") && !strcmp(cmd
->arg_types
, "s"))
455 char *old_name
= p
->name
;
456 p
->name
= g_strdup(CBOX_ARG_S(cmd
, 0));
460 return cbox_object_default_process_cmd(ct
, fb
, cmd
, error
);