2 * Copyright (C) 2003 Peter Hanappe and others.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public License
6 * as published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* this file originally taken from FluidSynth - A Software Synthesizer
21 * modified by Paul Brossier for aubio
26 * \bug timer still broken
27 * (should use alsa seq anyway) (fixed?) realtime playing is slower than
28 * it should. moved msec_passed and deltatime to microseconds (usec)
29 * (rounding were causing the drift) the new offline version is not quite
32 * \bug the player does not seem to understand a ``reprise'' in a file
35 #include "aubio_priv.h"
39 #include "midi_event.h"
40 #include "midi_track.h"
41 #include "midi_player.h"
42 #include "midi_file.h"
45 /** aubio_midi_player */
46 struct _aubio_midi_player_t {
47 aubio_track_t *track[AUBIO_MIDI_PLAYER_MAX_TRACKS];
52 aubio_list_t* playlist;
54 char send_program_change;/**< should we ignore the program changes? */
55 sint_t ticks_passed; /**< number of midi ticks that have passed */
56 sint_t usec_passed; /**< number of microseconds that have passed */
57 sint_t miditempo; /**< as indicated by midi settempo: n 24th of a
58 * usec per midi-clock. bravo! */
59 lsmp_t deltatime; /**< microseconds per midi tick. depends on
61 uint_t division; /**< the number of ticks per beat (quarter-note)
63 //aubio_synth_t* synth;
66 /******************************************************
70 /** new_aubio_midi_player */
71 aubio_midi_player_t* new_aubio_midi_player()
72 //aubio_midi_player_t* new_aubio_midi_player(aubio_synth_t* synth)
75 aubio_midi_player_t* player;
76 player = AUBIO_NEW(aubio_midi_player_t);
78 AUBIO_ERR( "Out of memory");
81 player->status = AUBIO_MIDI_PLAYER_READY;
84 for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) {
85 player->track[i] = NULL;
87 //player->synth = synth;
89 player->playlist = NULL;
90 player->current_file = NULL;
92 player->send_program_change = 1;
93 player->ticks_passed = 0;
94 player->usec_passed = 0;
95 player->miditempo = 480000;
96 player->deltatime = 4000.0;
100 /** delete_aubio_midi_player */
101 sint_t del_aubio_midi_player(aubio_midi_player_t* player)
103 if (player == NULL) {
106 aubio_midi_player_stop(player);
107 aubio_midi_player_reset(player);
112 /** aubio_midi_player_reset */
113 sint_t aubio_midi_player_reset(aubio_midi_player_t* player)
117 for (i = 0; i < AUBIO_MIDI_PLAYER_MAX_TRACKS; i++) {
118 if (player->track[i] != NULL) {
119 del_aubio_track(player->track[i]);
120 player->track[i] = NULL;
123 player->current_file = NULL;
124 player->status = AUBIO_MIDI_PLAYER_READY;
127 player->division = 0;
128 player->send_program_change = 1;
129 player->ticks_passed = 0;
130 player->usec_passed = 0;
131 player->miditempo = 480000;
132 player->deltatime = 4000.0;
136 /** aubio_midi_player_add_track */
137 sint_t aubio_midi_player_add_track(aubio_midi_player_t* player, aubio_track_t* track)
139 if (player->ntracks < AUBIO_MIDI_PLAYER_MAX_TRACKS) {
140 player->track[player->ntracks++] = track;
147 /** aubio_midi_player_count_tracks */
148 sint_t aubio_midi_player_count_tracks(aubio_midi_player_t* player)
150 return player->ntracks;
153 /** aubio_midi_player_get_track */
154 aubio_track_t* aubio_midi_player_get_track(aubio_midi_player_t* player, sint_t i)
156 if ((i >= 0) && (i < AUBIO_MIDI_PLAYER_MAX_TRACKS)) {
157 return player->track[i];
163 /** aubio_midi_player_get_track */
164 sint_t aubio_midi_player_add(aubio_midi_player_t* player, char* midifile)
166 char *s = AUBIO_STRDUP(midifile);
167 player->playlist = aubio_list_append(player->playlist, s);
171 /** aubio_midi_player_load */
172 sint_t aubio_midi_player_load(aubio_midi_player_t* player, char *filename)
174 aubio_midi_file_t* midifile;
176 midifile = new_aubio_midi_file(filename);
177 if (midifile == NULL) {
180 player->division = aubio_midi_file_get_division(midifile);
182 AUBIO_DBG("quarter note division=%d\n", player->division);
184 if (aubio_midi_file_load_tracks(midifile, player) != AUBIO_OK){
188 AUBIO_DBG("Tracks loaded\n");
190 del_aubio_midi_file(midifile);
194 /** aubio_midi_player_callback */
195 sint_t aubio_midi_player_callback(void* data, uint_t usec)
200 sint_t status = AUBIO_MIDI_PLAYER_DONE;
201 aubio_midi_player_t* player;
202 //aubio_synth_t* synth;
203 player = (aubio_midi_player_t*) data;
204 //synth = player->synth;
206 /* Load the next file if necessary */
207 while (player->current_file == NULL) {
209 if (player->playlist == NULL) {
213 aubio_midi_player_reset(player);
215 player->current_file = aubio_list_get(player->playlist);
216 player->playlist = aubio_list_next(player->playlist);
218 //AUBIO_DBG( "%s: %d: Loading midifile %s", __FILE__, __LINE__, player->current_file);
219 AUBIO_DBG("Loading midifile %s\n", player->current_file);
221 if (aubio_midi_player_load(player, player->current_file) == AUBIO_OK) {
223 player->ticks_passed = 0;
224 player->usec_passed = 0;
226 for (i = 0; i < player->ntracks; i++) {
227 if (player->track[i] != NULL) {
228 aubio_track_reset(player->track[i]);
233 player->current_file = NULL;
237 delta_ticks = (uint_t) ((lsmp_t)(usec - player->usec_passed) / player->deltatime);
238 ticks = player->ticks_passed + delta_ticks;
240 for (i = 0; i < player->ntracks; i++) {
241 if (!aubio_track_eot(player->track[i])) {
242 status = AUBIO_MIDI_PLAYER_PLAYING;
243 if (aubio_track_send_events(player->track[i], /*synth,*/ player, ticks) != AUBIO_OK) {
249 player->status = status;
250 player->ticks_passed = ticks;
251 player->usec_passed = usec;
253 if (player->status == AUBIO_MIDI_PLAYER_DONE) {
254 player->current_file = NULL;
260 /** aubio_midi_player_play */
261 sint_t aubio_midi_player_play(aubio_midi_player_t* player)
263 AUBIO_DBG("Starting midi player\n");
264 if (player->status == AUBIO_MIDI_PLAYER_PLAYING) {
265 AUBIO_DBG("Midi player already playing\n");
269 if (player->playlist == NULL) {
270 AUBIO_DBG("No playlist\n");
274 player->status = AUBIO_MIDI_PLAYER_PLAYING;
276 /** \bug timer is still in millisec, should be moved to microseconds,
277 * and replaced in favor of the alsa sequencer api */
278 player->timer = new_aubio_timer((sint_t) player->deltatime * 1.e-3, aubio_midi_player_callback,
279 (void*) player, 1, 0);
280 if (player->timer == NULL) {
281 AUBIO_DBG("Failed creating timer for midi player.\n");
284 if (player->current_file == NULL) {
285 AUBIO_DBG("No more file.\n");
286 delete_aubio_timer(player->timer);
293 /** aubio_midi_player_play_offline */
294 sint_t aubio_midi_player_play_offline(aubio_midi_player_t* player)
296 uint_t usec = 0; /* start looking n ms in advance */
297 AUBIO_DBG("Starting midi player\n");
298 if (player->status == AUBIO_MIDI_PLAYER_PLAYING) {
299 AUBIO_DBG("Midi player already playing\n");
303 if (player->playlist == NULL) {
304 AUBIO_DBG("No playlist\n");
308 //AUBIO_DBG("Starting callback.\n");
309 player->status = AUBIO_MIDI_PLAYER_PLAYING;
311 /* no timer, no thread ! */
312 while(aubio_midi_player_callback((void *)player,usec))
314 /* step at least one microsecond forward */
315 usec += 1 + player->deltatime;
316 if (player->status == AUBIO_MIDI_PLAYER_DONE)
319 //AUBIO_DBG("End of callback.\n");
321 if (player->current_file == NULL) {
322 AUBIO_DBG("No more file.\n");
327 /** aubio_midi_player_stop */
328 sint_t aubio_midi_player_stop(aubio_midi_player_t* player)
330 if (player->timer != NULL) {
331 delete_aubio_timer(player->timer);
333 player->status = AUBIO_MIDI_PLAYER_DONE;
334 player->timer = NULL;
338 /** aubio_midi_player_set_loop */
339 sint_t aubio_midi_player_set_loop(aubio_midi_player_t* player, sint_t loop)
345 /** aubio_midi_player_set_midi_tempo */
346 sint_t aubio_midi_player_set_midi_tempo(aubio_midi_player_t* player, sint_t tempo)
348 player->miditempo = tempo;
349 //player->deltatime = (lsmp_t) tempo / player->division * 1.e-3; /* in milliseconds */
350 player->deltatime = (lsmp_t) tempo / player->division; /* in microseconds */
352 AUBIO_DBG("Tempo Change: %d tempo=%f tick time=%f msec\n",
353 // player->usec_passed, 60.*1.e6/tempo, player->deltatime);
354 player->usec_passed, 60.*1.e6/tempo, 1e-3*player->deltatime);
359 /** aubio_midi_player_set_bpm */
360 sint_t aubio_midi_player_set_bpm(aubio_midi_player_t* player, sint_t bpm)
362 return aubio_midi_player_set_midi_tempo(player, (sint_t)((lsmp_t) 60 * 1e6 / bpm));
365 /** aubio_midi_player_join */
366 sint_t aubio_midi_player_join(aubio_midi_player_t* player)
368 return player->timer? aubio_timer_join(player->timer) : AUBIO_OK;
371 /** aubio_track_send_events */
372 sint_t aubio_track_send_events(aubio_track_t* track,
373 // aubio_synth_t* synth,
374 aubio_midi_player_t* player,
377 sint_t status = AUBIO_OK;
378 aubio_midi_event_t* event;
386 /* prsint_t each midi tick */
388 AUBIO_DBG("track=%d\tticks=%u\ttrack=%u\tdtime=%u\tnext=%u\n",
393 track->ticks + event->dtime);
396 if (track->ticks + event->dtime > ticks) {
400 track->ticks += event->dtime;
401 status = aubio_midi_send_event(/*synth, */player, event);
402 aubio_track_next_event(track);
410 * aubio_midi_send_event
412 * This is a utility function that doesn't really belong to any class or
413 * structure. It is called by aubio_midi_track and aubio_midi_device.
415 * \note This could be moved to a callback function defined in the main programs
417 //sint_t aubio_midi_send_event(aubio_synth_t* synth, aubio_player_t* player, aubio_midi_event_t* event)
418 sint_t aubio_midi_send_event(aubio_midi_player_t* player, aubio_midi_event_t* event)
420 /* current time in seconds */
421 //smpl_t print_time = player->msec_passed * 1e-3;
422 smpl_t print_time = player->usec_passed * 1e-6;
423 switch (event->type) {
425 AUBIO_MSG("Time=%f, chan=%d, pitch=%d vol=%d \n",
426 print_time, event->channel, event->param1, event->param2);
427 /*if (aubio_synth_noteon(synth, event->channel, event->param1, event->param2) != AUBIO_OK) {
432 AUBIO_MSG("Time=%f, chan=%d, pitch=%d, vol=0\n",
433 print_time, event->channel, event->param1);
434 /*if (aubio_synth_noteoff(synth, event->channel, event->param1) != AUBIO_OK) {
439 AUBIO_MSG("Time=%f Parameter, chan=%d c1=%d c2=%d\n",
440 print_time, event->channel, event->param1, event->param2);
441 /*if (aubio_synth_cc(synth, event->channel, event->param1, event->param2) != AUBIO_OK) {
446 if (player != NULL) {
447 if (aubio_midi_player_set_midi_tempo(player, event->param1) != AUBIO_OK) {
453 AUBIO_MSG("Time=%f Program, chan=%d program=%d\n",
454 print_time, event->channel, event->param1);
455 /*if (aubio_synth_program_change(synth, event->channel, event->param1) != AUBIO_OK) {
460 AUBIO_MSG("Time=%f Pitchbend, chan=%d msb=%d lsb=%d \n",
461 print_time, event->channel, event->param1, event->param2);
462 /*if (aubio_synth_pitch_bend(synth, event->channel, event->param1) != AUBIO_OK) {
474 * aubio_midi_receive_event
476 * \note This could be moved to a callback function defined in the main programs
478 sint_t aubio_midi_receive_event(aubio_midi_player_t* player, aubio_midi_event_t* event)
480 /* current time in seconds */
481 //smpl_t print_time = player->msec_passed * 1e-3;
482 //smpl_t print_time = player->usec_passed * 1e-6;
483 switch (event->type) {