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/>.
26 static inline void accumulate_event(struct cbox_midi_playback_active_notes
*notes
, const struct cbox_midi_event
*event
)
30 // this ignores poly aftertouch - which, I supposed, is OK for now
31 if (event
->data_inline
[0] < 0x80 || event
->data_inline
[0] > 0x9F)
33 int ch
= event
->data_inline
[0] & 0x0F;
34 if (event
->data_inline
[0] >= 0x90 && event
->data_inline
[2] > 0)
36 int note
= event
->data_inline
[1] & 0x7F;
37 if (!(notes
->channels_active
& (1 << ch
)))
39 for (int i
= 0; i
< 4; i
++)
40 notes
->notes
[ch
][i
] = 0;
41 notes
->channels_active
|= 1 << ch
;
43 notes
->notes
[ch
][note
>> 5] |= 1 << (note
& 0x1F);
47 struct cbox_track_playback
*cbox_track_playback_new_from_track(struct cbox_track
*track
, struct cbox_master
*master
, struct cbox_song_playback
*spb
)
49 struct cbox_track_playback
*pb
= malloc(sizeof(struct cbox_track_playback
));
51 int len
= g_list_length(track
->items
);
52 pb
->items
= calloc(len
, sizeof(struct cbox_track_playback_item
));
53 pb
->external_merger
= NULL
;
56 GList
*it
= track
->items
;
57 struct cbox_track_playback_item
*p
= pb
->items
;
61 struct cbox_track_item
*item
= it
->data
;
62 struct cbox_midi_pattern_playback
*mppb
= cbox_song_playback_get_pattern(spb
, item
->pattern
);
64 // if items overlap, the first one takes precedence
65 if (item
->time
< safe
)
67 // fully contained in previous item? skip all of it
68 // not fully contained - insert the fragment
69 if (item
->time
+ item
->length
>= safe
)
71 int cut
= safe
- item
->time
;
74 p
->offset
= item
->offset
+ cut
;
75 p
->length
= item
->length
- cut
;
83 p
->offset
= item
->offset
;
84 p
->length
= item
->length
;
85 safe
= item
->time
+ item
->length
;
91 // in case of full overlap, some items might have been skipped
92 pb
->items_count
= p
- pb
->items
;
94 cbox_midi_clip_playback_init(&pb
->playback
, &pb
->active_notes
, master
);
95 cbox_midi_playback_active_notes_init(&pb
->active_notes
);
96 cbox_midi_buffer_init(&pb
->output_buffer
);
97 cbox_track_playback_start_item(pb
, 0, FALSE
, 0);
99 if (track
->external_output_set
)
101 struct cbox_midi_merger
*merger
= cbox_rt_get_midi_output(spb
->rt
, &track
->external_output
);
104 cbox_midi_merger_connect(merger
, &pb
->output_buffer
, spb
->rt
);
105 pb
->external_merger
= merger
;
112 void cbox_track_playback_seek_ppqn(struct cbox_track_playback
*pb
, int time_ppqn
, int min_time_ppqn
)
115 while(pb
->pos
< pb
->items_count
&& pb
->items
[pb
->pos
].time
+ pb
->items
[pb
->pos
].length
< time_ppqn
)
117 cbox_track_playback_start_item(pb
, time_ppqn
, TRUE
, min_time_ppqn
);
120 void cbox_track_playback_seek_samples(struct cbox_track_playback
*pb
, int time_samples
)
123 while(pb
->pos
< pb
->items_count
&& cbox_master_ppqn_to_samples(pb
->master
, pb
->items
[pb
->pos
].time
+ pb
->items
[pb
->pos
].length
) < time_samples
)
125 cbox_track_playback_start_item(pb
, time_samples
, FALSE
, 0);
128 void cbox_track_playback_start_item(struct cbox_track_playback
*pb
, int time
, int is_ppqn
, int min_time_ppqn
)
130 if (pb
->pos
>= pb
->items_count
)
134 struct cbox_track_playback_item
*cur
= &pb
->items
[pb
->pos
];
135 int time_samples
, time_ppqn
;
140 time_samples
= cbox_master_ppqn_to_samples(pb
->master
, time_ppqn
);
145 time_ppqn
= cbox_master_samples_to_ppqn(pb
->master
, time_samples
);
147 int start_time_ppqn
= cur
->time
, end_time_ppqn
= cur
->time
+ cur
->length
;
148 int start_time_samples
= cbox_master_ppqn_to_samples(pb
->master
, start_time_ppqn
);
149 int end_time_samples
= cbox_master_ppqn_to_samples(pb
->master
, end_time_ppqn
);
150 cbox_midi_clip_playback_set_pattern(&pb
->playback
, cur
->pattern
, start_time_samples
, end_time_samples
, cur
->time
, cur
->offset
);
154 if (time_ppqn
< start_time_ppqn
)
155 cbox_midi_clip_playback_seek_ppqn(&pb
->playback
, 0, min_time_ppqn
);
157 cbox_midi_clip_playback_seek_ppqn(&pb
->playback
, time_ppqn
- start_time_ppqn
, min_time_ppqn
);
161 if (time_ppqn
< start_time_ppqn
)
162 cbox_midi_clip_playback_seek_samples(&pb
->playback
, 0);
164 cbox_midi_clip_playback_seek_samples(&pb
->playback
, time_samples
- start_time_samples
);
168 void cbox_track_playback_render(struct cbox_track_playback
*pb
, int offset
, int nsamples
)
170 struct cbox_song_playback
*spb
= pb
->master
->spb
;
172 while(rpos
< nsamples
&& pb
->pos
< pb
->items_count
)
175 struct cbox_track_playback_item
*cur
= &pb
->items
[pb
->pos
];
176 // a gap before the current item
177 if (spb
->song_pos_samples
+ rpos
< pb
->playback
.start_time_samples
)
179 int space_samples
= pb
->playback
.start_time_samples
- (spb
->song_pos_samples
+ rpos
);
180 if (space_samples
>= rend
- rpos
)
182 rpos
+= space_samples
;
183 offset
+= space_samples
;
185 // check if item finished
186 int cur_segment_end_samples
= cbox_master_ppqn_to_samples(pb
->master
, cur
->time
+ cur
->length
);
187 int render_end_samples
= spb
->song_pos_samples
+ rend
;
188 if (render_end_samples
> cur_segment_end_samples
)
190 rend
= cur_segment_end_samples
- spb
->song_pos_samples
;
191 cbox_midi_clip_playback_render(&pb
->playback
, &pb
->output_buffer
, offset
, rend
- rpos
);
193 cbox_track_playback_start_item(pb
, cur_segment_end_samples
, FALSE
, FALSE
);
196 cbox_midi_clip_playback_render(&pb
->playback
, &pb
->output_buffer
, offset
, rend
- rpos
);
197 offset
+= rend
- rpos
;
202 void cbox_track_playback_destroy(struct cbox_track_playback
*pb
)
204 if (pb
->external_merger
)
205 cbox_midi_merger_disconnect(pb
->external_merger
, &pb
->output_buffer
, pb
->spb
->rt
);
211 /////////////////////////////////////////////////////////////////////////////////////////////////////
213 void cbox_midi_pattern_playback_destroy(struct cbox_midi_pattern_playback
*mppb
)
219 /////////////////////////////////////////////////////////////////////////////////////////////////////
221 void cbox_midi_clip_playback_init(struct cbox_midi_clip_playback
*pb
, struct cbox_midi_playback_active_notes
*active_notes
, struct cbox_master
*master
)
226 pb
->rel_time_samples
= 0;
227 pb
->start_time_samples
= 0;
228 pb
->end_time_samples
= 0;
229 pb
->active_notes
= active_notes
;
230 pb
->min_time_ppqn
= 0;
231 // cbox_midi_playback_active_notes_init(active_notes);
234 void cbox_midi_clip_playback_set_pattern(struct cbox_midi_clip_playback
*pb
, struct cbox_midi_pattern_playback
*pattern
, int start_time_samples
, int end_time_samples
, int item_start_ppqn
, int offset_ppqn
)
236 pb
->pattern
= pattern
;
238 pb
->rel_time_samples
= 0;
239 pb
->start_time_samples
= start_time_samples
;
240 pb
->end_time_samples
= end_time_samples
;
241 pb
->item_start_ppqn
= item_start_ppqn
;
242 pb
->offset_ppqn
= offset_ppqn
;
243 pb
->min_time_ppqn
= 0;
246 void cbox_midi_clip_playback_render(struct cbox_midi_clip_playback
*pb
, struct cbox_midi_buffer
*buf
, int offset
, int nsamples
)
248 uint32_t end_time_samples
= pb
->end_time_samples
;
249 uint32_t cur_time_samples
= pb
->start_time_samples
+ pb
->rel_time_samples
;
251 if (end_time_samples
> cur_time_samples
+ nsamples
)
252 end_time_samples
= cur_time_samples
+ nsamples
;
254 while(pb
->pos
< pb
->pattern
->event_count
)
256 const struct cbox_midi_event
*src
= &pb
->pattern
->events
[pb
->pos
];
258 if (src
->time
- pb
->offset_ppqn
>= pb
->min_time_ppqn
)
260 int event_time_samples
= cbox_master_ppqn_to_samples(pb
->master
, src
->time
- pb
->offset_ppqn
) + pb
->start_time_samples
;
262 if (event_time_samples
>= end_time_samples
)
265 if (event_time_samples
>= cur_time_samples
) // convert negative relative time to 0 time
266 time
= event_time_samples
- cur_time_samples
;
268 cbox_midi_buffer_copy_event(buf
, src
, offset
+ time
);
269 if (pb
->active_notes
)
270 accumulate_event(pb
->active_notes
, src
);
274 pb
->rel_time_samples
+= nsamples
;
277 void cbox_midi_clip_playback_seek_ppqn(struct cbox_midi_clip_playback
*pb
, int time_ppqn
, int min_time_ppqn
)
280 int patrel_time_ppqn
= time_ppqn
+ pb
->offset_ppqn
;
281 while (pos
< pb
->pattern
->event_count
&& patrel_time_ppqn
> pb
->pattern
->events
[pos
].time
)
283 pb
->rel_time_samples
= cbox_master_ppqn_to_samples(pb
->master
, pb
->item_start_ppqn
+ time_ppqn
) - pb
->start_time_samples
;
284 pb
->min_time_ppqn
= min_time_ppqn
;
288 void cbox_midi_clip_playback_seek_samples(struct cbox_midi_clip_playback
*pb
, int time_samples
)
291 while (pos
< pb
->pattern
->event_count
&& time_samples
> cbox_master_ppqn_to_samples(pb
->master
, pb
->item_start_ppqn
+ pb
->pattern
->events
[pos
].time
- pb
->offset_ppqn
))
293 pb
->rel_time_samples
= time_samples
;
294 pb
->min_time_ppqn
= 0;
298 /////////////////////////////////////////////////////////////////////////////////////////////////////
300 void cbox_midi_playback_active_notes_init(struct cbox_midi_playback_active_notes
*notes
)
302 notes
->channels_active
= 0;
305 int cbox_midi_playback_active_notes_release(struct cbox_midi_playback_active_notes
*notes
, struct cbox_midi_buffer
*buf
)
307 if (!notes
->channels_active
)
310 for (int c
= 0; c
< 16; c
++)
312 if (!(notes
->channels_active
& (1 << c
)))
315 for (int g
= 0; g
< 4; g
++)
317 uint32_t group
= notes
->notes
[c
][g
];
320 for (int i
= 0; i
< 32; i
++)
323 if (!(group
& (1 << i
)))
325 if (!cbox_midi_buffer_can_store_msg(buf
, 3))
327 cbox_midi_buffer_write_inline(buf
, cbox_midi_buffer_get_last_event_time(buf
), 0x80 + c
, n
, 0);
329 notes
->notes
[c
][g
] = group
;
333 // all Note Offs emitted without buffer overflow - channel is no longer active
334 notes
->channels_active
&= ~(1 << c
);
339 /////////////////////////////////////////////////////////////////////////////////////////////////////
341 struct cbox_song_playback
*cbox_song_playback_new(struct cbox_song
*song
, struct cbox_master
*master
, struct cbox_rt
*rt
)
343 struct cbox_song_playback
*spb
= calloc(1, sizeof(struct cbox_song_playback
));
345 spb
->pattern_map
= g_hash_table_new_full(NULL
, NULL
, NULL
, (GDestroyNotify
)cbox_midi_pattern_playback_destroy
);
346 spb
->master
= master
;
347 spb
->track_count
= g_list_length(song
->tracks
);
348 spb
->tracks
= malloc(spb
->track_count
* sizeof(struct cbox_track_playback
*));
349 spb
->song_pos_samples
= 0;
350 spb
->song_pos_ppqn
= 0;
351 spb
->min_time_ppqn
= 0;
352 spb
->loop_start_ppqn
= song
->loop_start_ppqn
;
353 spb
->loop_end_ppqn
= song
->loop_end_ppqn
;
354 cbox_midi_merger_init(&spb
->track_merger
, NULL
);
356 for (GList
*p
= song
->tracks
; p
!= NULL
; p
= g_list_next(p
))
358 struct cbox_track
*trk
= p
->data
;
359 spb
->tracks
[pos
++] = cbox_track_playback_new_from_track(trk
, spb
->master
, spb
);
360 if (!trk
->external_output_set
)
361 cbox_midi_merger_connect(&spb
->track_merger
, &spb
->tracks
[pos
- 1]->output_buffer
, NULL
);
364 spb
->tempo_map_item_count
= g_list_length(song
->master_track_items
);
365 spb
->tempo_map_items
= malloc(spb
->tempo_map_item_count
* sizeof(struct cbox_tempo_map_item
));
369 double tempo
= master
->tempo
;
370 int timesig_nom
= master
->timesig_nom
;
371 int timesig_denom
= master
->timesig_denom
;
372 for (GList
*p
= song
->master_track_items
; p
!= NULL
; p
= g_list_next(p
))
374 struct cbox_master_track_item
*mti
= p
->data
;
377 if (mti
->timesig_nom
> 0)
378 timesig_nom
= mti
->timesig_nom
;
379 if (mti
->timesig_denom
> 0)
380 timesig_denom
= mti
->timesig_denom
;
381 struct cbox_tempo_map_item
*tmi
= &spb
->tempo_map_items
[pos
];
382 tmi
->time_ppqn
= pos_ppqn
;
383 tmi
->time_samples
= pos_samples
;
385 tmi
->timesig_nom
= timesig_nom
;
386 tmi
->timesig_denom
= timesig_denom
;
388 pos_ppqn
+= mti
->duration_ppqn
;
389 pos_samples
+= spb
->master
->srate
* 60.0 * mti
->duration_ppqn
/ (tempo
* PPQN
);
395 static void cbox_song_playback_set_tempo(struct cbox_song_playback
*spb
, double tempo
)
397 int ppos
= spb
->song_pos_ppqn
;
398 int pos1
= cbox_master_ppqn_to_samples(spb
->master
, ppos
);
399 int pos2
= cbox_master_ppqn_to_samples(spb
->master
, ppos
+ 1);
402 relpos
= (spb
->song_pos_samples
- pos1
) * 1.0 / (pos2
- pos1
);
403 spb
->master
->tempo
= tempo
;
405 // This seek loses the fractional value of the PPQN song position.
406 // This needs to be compensated for by shifting the playback
407 // position by the fractional part.
408 cbox_song_playback_seek_ppqn(spb
, ppos
, spb
->min_time_ppqn
);
411 pos2
= cbox_master_ppqn_to_samples(spb
->master
, ppos
+ 1);
412 cbox_song_playback_seek_samples(spb
, spb
->song_pos_samples
+ (pos2
- spb
->song_pos_samples
) * relpos
+ 0.5);
416 int cbox_song_playback_get_next_tempo_change(struct cbox_song_playback
*spb
)
418 double new_tempo
= 0;
419 // Skip items at or already past the playback pointer
420 while (spb
->tempo_map_pos
+ 1 < spb
->tempo_map_item_count
&&
421 spb
->song_pos_samples
>= spb
->tempo_map_items
[spb
->tempo_map_pos
+ 1].time_samples
)
423 new_tempo
= spb
->tempo_map_items
[spb
->tempo_map_pos
+ 1].tempo
;
424 spb
->tempo_map_pos
++;
426 if (new_tempo
!= 0.0 && new_tempo
!= spb
->master
->tempo
)
427 cbox_song_playback_set_tempo(spb
, new_tempo
);
430 if (spb
->tempo_map_pos
+ 1 >= spb
->tempo_map_item_count
)
433 return spb
->tempo_map_items
[spb
->tempo_map_pos
+ 1].time_samples
;
436 void cbox_song_playback_render(struct cbox_song_playback
*spb
, struct cbox_midi_buffer
*output
, int nsamples
)
438 cbox_midi_buffer_clear(output
);
440 if (spb
->master
->new_tempo
!= 0 && spb
->master
->new_tempo
!= spb
->master
->tempo
)
442 cbox_song_playback_set_tempo(spb
, spb
->master
->new_tempo
);
443 spb
->master
->new_tempo
= 0;
445 for(int i
= 0; i
< spb
->track_count
; i
++)
447 cbox_midi_buffer_clear(&spb
->tracks
[i
]->output_buffer
);
449 if (spb
->master
->state
== CMTS_STOPPING
)
451 if (cbox_song_playback_active_notes_release(spb
, output
) > 0)
452 spb
->master
->state
= CMTS_STOP
;
455 if (spb
->master
->state
== CMTS_ROLLING
)
457 int end_samples
= cbox_master_ppqn_to_samples(spb
->master
, spb
->loop_end_ppqn
);
460 while (rpos
< nsamples
)
464 // 1. Shorten the period so that it doesn't go past a tempo change
465 int tmpos
= cbox_song_playback_get_next_tempo_change(spb
);
468 // Number of samples until the next tempo change
469 int stntc
= tmpos
- spb
->song_pos_samples
;
470 if (rend
- rpos
> stntc
)
474 // 2. Shorten the period so that it doesn't go past the song length
475 int end_pos
= spb
->song_pos_samples
+ (rend
- rpos
);
476 if (end_pos
>= end_samples
)
478 rend
= end_samples
- spb
->song_pos_samples
;
479 end_pos
= end_samples
;
484 for (int i
= 0; i
< spb
->track_count
; i
++)
485 cbox_track_playback_render(spb
->tracks
[i
], rpos
, rend
- rpos
);
488 if (end_pos
< end_samples
)
490 spb
->song_pos_samples
+= rend
- rpos
;
492 spb
->min_time_ppqn
= cbox_master_samples_to_ppqn(spb
->master
, spb
->song_pos_samples
- 1) + 1;
493 spb
->song_pos_ppqn
= cbox_master_samples_to_ppqn(spb
->master
, spb
->song_pos_samples
);
497 if (spb
->loop_start_ppqn
>= spb
->loop_end_ppqn
)
499 spb
->song_pos_samples
= end_samples
;
500 spb
->song_pos_ppqn
= spb
->loop_end_ppqn
;
501 spb
->master
->state
= CMTS_STOPPING
;
505 cbox_song_playback_seek_ppqn(spb
, spb
->loop_start_ppqn
, spb
->loop_start_ppqn
);
509 cbox_midi_merger_render_to(&spb
->track_merger
, output
);
513 int cbox_song_playback_active_notes_release(struct cbox_song_playback
*spb
, struct cbox_midi_buffer
*buf
)
515 for(int i
= 0; i
< spb
->track_count
; i
++)
517 struct cbox_track_playback
*trk
= spb
->tracks
[i
];
518 struct cbox_midi_buffer
*output
= trk
->external_merger
? &trk
->output_buffer
: buf
;
519 if (cbox_midi_playback_active_notes_release(&trk
->active_notes
, output
) < 0)
525 void cbox_song_playback_seek_ppqn(struct cbox_song_playback
*spb
, int time_ppqn
, int min_time_ppqn
)
527 for(int i
= 0; i
< spb
->track_count
; i
++)
529 struct cbox_track_playback
*trk
= spb
->tracks
[i
];
530 cbox_track_playback_seek_ppqn(trk
, time_ppqn
, min_time_ppqn
);
532 spb
->song_pos_samples
= cbox_master_ppqn_to_samples(spb
->master
, time_ppqn
);
533 spb
->song_pos_ppqn
= time_ppqn
;
534 spb
->min_time_ppqn
= min_time_ppqn
;
535 spb
->tempo_map_pos
= cbox_song_playback_tmi_from_ppqn(spb
, time_ppqn
);
538 void cbox_song_playback_seek_samples(struct cbox_song_playback
*spb
, int time_samples
)
540 for(int i
= 0; i
< spb
->track_count
; i
++)
542 struct cbox_track_playback
*trk
= spb
->tracks
[i
];
543 cbox_track_playback_seek_samples(trk
, time_samples
);
545 spb
->song_pos_samples
= time_samples
;
546 spb
->song_pos_ppqn
= cbox_master_samples_to_ppqn(spb
->master
, time_samples
);
547 spb
->min_time_ppqn
= spb
->song_pos_ppqn
;
548 spb
->tempo_map_pos
= cbox_song_playback_tmi_from_samples(spb
, time_samples
);
551 int cbox_song_playback_tmi_from_ppqn(struct cbox_song_playback
*spb
, int time_ppqn
)
553 if (!spb
->tempo_map_item_count
)
555 assert(spb
->tempo_map_items
[0].time_samples
== 0);
556 assert(spb
->tempo_map_items
[0].time_ppqn
== 0);
557 // XXXKF should use binary search here really
558 for (int i
= 1; i
< spb
->tempo_map_item_count
; i
++)
560 if (time_ppqn
< spb
->tempo_map_items
[i
].time_ppqn
)
563 return spb
->tempo_map_item_count
- 1;
566 int cbox_song_playback_tmi_from_samples(struct cbox_song_playback
*spb
, int time_samples
)
568 if (!spb
->tempo_map_item_count
)
570 assert(spb
->tempo_map_items
[0].time_samples
== 0);
571 assert(spb
->tempo_map_items
[0].time_ppqn
== 0);
572 // XXXKF should use binary search here really
573 for (int i
= 1; i
< spb
->tempo_map_item_count
; i
++)
575 if (time_samples
< spb
->tempo_map_items
[i
].time_samples
)
578 return spb
->tempo_map_item_count
- 1;
581 struct cbox_midi_pattern_playback
*cbox_song_playback_get_pattern(struct cbox_song_playback
*spb
, struct cbox_midi_pattern
*pattern
)
583 struct cbox_midi_pattern_playback
*mppb
= g_hash_table_lookup(spb
->pattern_map
, pattern
);
587 mppb
= malloc(sizeof(struct cbox_midi_pattern_playback
));
589 mppb
->events
= malloc(sizeof(struct cbox_midi_event
) * pattern
->event_count
);
590 memcpy(mppb
->events
, pattern
->events
, sizeof(struct cbox_midi_event
) * pattern
->event_count
);
591 mppb
->event_count
= pattern
->event_count
;
592 g_hash_table_insert(spb
->pattern_map
, pattern
, mppb
);
597 void cbox_song_playback_destroy(struct cbox_song_playback
*spb
)
599 for (int i
= 0; i
< spb
->track_count
; i
++)
601 cbox_track_playback_destroy(spb
->tracks
[i
]);
603 free(spb
->tempo_map_items
);
605 g_hash_table_destroy(spb
->pattern_map
);
606 cbox_midi_merger_close(&spb
->track_merger
);