static short _fluid_seq_queue_init(fluid_sequencer_t* seq, int maxEvents) { seq->heap = _fluid_evt_heap_init(maxEvents); if (seq->heap == NULL) { fluid_log(FLUID_PANIC, "sequencer: Out of memory\n"); return -1; } seq->preQueue = NULL; seq->preQueueLast = NULL; FLUID_MEMSET(seq->queue0, 0, 2*256*sizeof(fluid_evt_entry *)); FLUID_MEMSET(seq->queue1, 0, 2*255*sizeof(fluid_evt_entry *)); seq->queueLater = NULL; seq->queue0StartTime = fluid_sequencer_get_tick(seq); seq->prevCellNb = -1; fluid_mutex_init(seq->mutex); /* start timer */ if (seq->useSystemTimer) { seq->timer = new_fluid_timer((int)(1000/seq->scale), _fluid_seq_queue_process, (void *)seq, TRUE, FALSE, TRUE); } return (0); }
int main (int argc, char *argv[]) { int n; fluid_settings_t *settings; settings = new_fluid_settings (); if (argc < 2) { usage (argv[0]); } else { /* create the synth, driver and sequencer instances */ synth = new_fluid_synth (settings); audiodriver = new_fluid_audio_driver (settings, synth); sequencer = new_fluid_sequencer (); /* register the synth with the sequencer */ synth_destination = fluid_sequencer_register_fluidsynth (sequencer, synth); /* register the client name and callback */ client_destination = fluid_sequencer_register_client (sequencer, "fluidsynth_metronome", sequencer_callback, NULL); /* load a SoundFont */ n = fluid_synth_sfload (synth, argv[1], 1); if (n != -1) { if (argc > 2) { n = atoi (argv[2]); if (n > 0) pattern_size = n; } if (argc > 3) { n = atoi (argv[3]); if (n > 0) note_duration = 60000 / n; } /* get the current time in ticks */ time_marker = fluid_sequencer_get_tick (sequencer); /* schedule patterns */ schedule_pattern (); schedule_timer_event (); schedule_pattern (); /* wait for user input */ printf ("press <Enter> to stop\n"); n = getchar (); } /* clean and exit */ delete_fluid_sequencer (sequencer); delete_fluid_audio_driver (audiodriver); delete_fluid_synth (synth); } delete_fluid_settings (settings); return 0; }
/** * Schedule an event for sending at a later time. * @param seq Sequencer object * @param evt Event to send * @param time Time value in ticks (in milliseconds with the default time scale of 1000). * @param absolute TRUE if \a time is absolute sequencer time (time since sequencer * creation), FALSE if relative to current time. * @return #FLUID_OK on success, #FLUID_FAILED otherwise */ int fluid_sequencer_send_at (fluid_sequencer_t* seq, fluid_event_t* evt, unsigned int time, int absolute) { unsigned int now = fluid_sequencer_get_tick(seq); /* set absolute */ if (!absolute) time = now + time; /* time stamp event */ fluid_event_set_time(evt, time); /* queue for processing later */ return _fluid_seq_queue_pre_insert(seq, evt); }
/* Event not actually copied, but since its used immediately it virtually is. */ void fluid_sequencer_send_now(fluid_sequencer_t* seq, fluid_event_t* evt) { short destID = fluid_event_get_dest(evt); /* find callback */ fluid_list_t *tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *dest = (fluid_sequencer_client_t*)tmp->data; if (dest->id == destID) { if (dest->callback) (dest->callback)(fluid_sequencer_get_tick(seq), evt, seq, dest->data); return; } tmp = tmp->next; } }
/** * Transforms an incoming midi event (from a midi driver or midi router) to a * sequencer event and adds it to the sequencer queue for sending as soon as possible. * @param data The sequencer, must be a valid #fluid_sequencer_t * @param event MIDI event * @return #FLUID_OK or #FLUID_FAILED * @since 1.1.0 */ int fluid_sequencer_add_midi_event_to_buffer(void* data, fluid_midi_event_t* event) { fluid_event_t evt; fluid_sequencer_t* seq = (fluid_sequencer_t*) data; int chan = fluid_midi_event_get_channel(event); fluid_event_clear(&evt); fluid_event_set_time(&evt, fluid_sequencer_get_tick(seq)); fluid_event_set_dest(&evt, get_fluidsynth_dest(seq)); switch (fluid_midi_event_get_type(event)) { case NOTE_OFF: fluid_event_noteoff(&evt, chan, fluid_midi_event_get_key(event)); break; case NOTE_ON: fluid_event_noteon(&evt, fluid_midi_event_get_channel(event), fluid_midi_event_get_key(event), fluid_midi_event_get_velocity(event)); break; case CONTROL_CHANGE: fluid_event_control_change(&evt, chan, fluid_midi_event_get_control(event), fluid_midi_event_get_value(event)); break; case PROGRAM_CHANGE: fluid_event_program_change(&evt, chan, fluid_midi_event_get_program(event)); break; case PITCH_BEND: fluid_event_pitch_bend(&evt, chan, fluid_midi_event_get_pitch(event)); break; case CHANNEL_PRESSURE: fluid_event_channel_pressure(&evt, chan, fluid_midi_event_get_program(event)); break; case MIDI_SYSTEM_RESET: fluid_event_system_reset(&evt); break; default: /* Not yet implemented */ return FLUID_FAILED; } /* Schedule for sending at next call to fluid_sequencer_process */ return fluid_sequencer_send_at(seq, &evt, 0, 0); }
static void _fluid_seq_queue_send_queued_events(fluid_sequencer_t* seq) { unsigned int nowTicks = fluid_sequencer_get_tick(seq); short cellNb; cellNb = seq->prevCellNb + 1; while (cellNb <= (int)(nowTicks - seq->queue0StartTime)) { if (cellNb == 256) { cellNb = 0; _fluid_seq_queue_slide(seq); } /* slide */ /* process queue0[cellNb] */ _fluid_seq_queue_send_cell_events(seq, cellNb); /* next cell */ cellNb++; } seq->prevCellNb = cellNb - 1; }
/** * Unregister a previously registered client. * @param seq Sequencer object * @param id Client ID as returned by fluid_sequencer_register_client(). */ void fluid_sequencer_unregister_client (fluid_sequencer_t* seq, short id) { fluid_list_t *tmp; fluid_event_t* evt; if (seq->clients == NULL) return; evt = new_fluid_event(); if (evt != NULL) { fluid_event_unregistering(evt); fluid_event_set_dest(evt, id); } tmp = seq->clients; while (tmp) { fluid_sequencer_client_t *client = (fluid_sequencer_client_t*)tmp->data; if (client->id == id) { /* What should we really do if evt is null due to out-of-memory? */ if (client->callback != NULL && evt != NULL) (client->callback)(fluid_sequencer_get_tick(seq), evt, seq, client->data); if (client->name) FLUID_FREE(client->name); seq->clients = fluid_list_remove_link(seq->clients, tmp); delete1_fluid_list(tmp); FLUID_FREE(client); delete_fluid_event(evt); return; } tmp = tmp->next; } delete_fluid_event(evt); return; }
unsigned midi_ticks() const { return fluid_sequencer_get_tick(source_.seq.get()); }