fluid-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [fluid-dev] Some questions about Midi playback


From: Sebastien Frippiat
Subject: Re: [fluid-dev] Some questions about Midi playback
Date: Thu, 29 Jun 2006 14:05:29 +0200
User-agent: Mozilla Thunderbird 1.0.7-1.4.1 (X11/20050929)

Hi.

It's me... again :-)

Support for a Midi event callback function has been improved (now uses specified user data) and a new function (fluid_player_is_playing) has been added to return wheter the player is currently playing a Midi file or not.

You'll find the patch file attached to this message. Intructions are the same as in my previous message.

Regards,
Sebastien
diff -r -u fluidsynth-1.0.7/include/fluidsynth/midi.h 
fluidsynth-1.0.7-new/include/fluidsynth/midi.h
--- fluidsynth-1.0.7/include/fluidsynth/midi.h  Tue Mar 11 17:57:01 2003
+++ fluidsynth-1.0.7-new/include/fluidsynth/midi.h      Thu Jun 29 10:35:04 2006
@@ -47,7 +47,6 @@
 FLUIDSYNTH_API int fluid_midi_event_get_pitch(fluid_midi_event_t* evt);
 FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t* evt, int 
val);
 
-
   /* Generic callback function for MIDI events.
    * Will be used between
    * - MIDI driver and MIDI router
@@ -126,6 +125,63 @@
 FLUIDSYNTH_API int fluid_player_set_loop(fluid_player_t* player, int loop);
 FLUIDSYNTH_API int fluid_player_set_midi_tempo(fluid_player_t* player, int 
tempo);
 FLUIDSYNTH_API int fluid_player_set_bpm(fluid_player_t* player, int bpm);
+
+
+/** \brief Set a multiplier value to be applied to all tempo events
+  *
+  * \param player Pointer to player to be modified
+  * \param multiplier Multiplier to be applied :
+  *                   - multiplier in ]0,1] : increase tempo
+  *                   - multiplier o, ]1,oo] : decrease tempo
+  * \return One of these :
+  *         - 0 on success
+  *         - -1 if multiplier is <= 0
+  */
+FLUIDSYNTH_API int fluid_player_set_tempo_multiplier(fluid_player_t* player, 
float multiplier);
+
+/** \brief Set a multiplier value to be applied to all velocities specified in 
NOTE_ON events
+  *
+  * \param player Pointer to player to be modified
+  * \param multiplier Multiplier to be applied, must be in ]0,1] (can only 
decrease velocity)
+  * \return One of these :
+  *         - 0 on success
+  *         - -1 if multiplier is not in ]0,1]
+  */
+FLUIDSYNTH_API int fluid_player_set_velocity_multiplier(fluid_player_t* 
player, float multiplier);
+
+/** \brief Set a callback to be called each time a Midi event is generated
+  *
+  * \param player Pointer to player to be modified
+  * \param callback Pointer to callback function
+  * \param data Data to be passed to the callback function
+  * \return Always 0
+  *
+  * The callback function should return 0 if it wants the FluidSynth 
synthetizer to play the sound and
+  * it should return -1 if it wants to inhibit the FluidSynth synthetizer. For 
example, in the first case,
+  * it can be used as a logger and in the other one it can be used to process 
the Midi events by yourself
+  * and send them to a Midi device).
+  *
+  * Here is a sample callback function which inhibits the FluidSynth software 
synthetizer and output
+  * Midi events to a Midi device (pMidiOStream is a PortMidi output stream) :
+  *    <PRE>
+       int myCallback (void* data, fluid_midi_event_t* event)
+       {
+         Pm_WriteShort(pMidiOStream, 0, Pm_Message(event->type | 
event->channel, event->param1, event->param2));
+         return -1;
+       }
+       </PRE>
+  */
+  FLUIDSYNTH_API int fluid_player_set_midi_event_callback(fluid_player_t* 
player, handle_midi_event_func_t callback, void* data);
+
+/** \brief Tell if the player is currently playing
+  *
+  * \param player Pointer to player to be checked
+  * \return One of these :
+  *         - 1 if the player is currently playing a Midi file
+  *         - 0 otherwise
+  */
+FLUIDSYNTH_API int fluid_player_is_playing(fluid_player_t* player);
+
 
 #ifdef __cplusplus
 }
Only in fluidsynth-1.0.7-new/include/fluidsynth: mididefs.h
diff -r -u fluidsynth-1.0.7/src/fluid_midi.c 
fluidsynth-1.0.7-new/src/fluid_midi.c
--- fluidsynth-1.0.7/src/fluid_midi.c   Mon Mar 29 12:05:17 2004
+++ fluidsynth-1.0.7-new/src/fluid_midi.c       Thu Jun 29 10:31:58 2006
@@ -1072,6 +1072,14 @@
        player->send_program_change = 1;
        player->miditempo = 480000;
        player->deltatime = 4.0;
+
+       player->tempo_multiplier = 1.0f;
+       player->tempo_last_multiplier = 1.0f;
+       player->tempo_last_value = player->miditempo;
+       player->velocity_multiplier = 1.0f;
+       player->midi_event_callback = NULL;
+       player->midi_event_callback_data = NULL;
+
        return player;
 }
 
@@ -1107,9 +1115,46 @@
        player->send_program_change = 1;
        player->miditempo = 480000;
        player->deltatime = 4.0;
+
        return 0;
 }
 
+int fluid_player_set_tempo_multiplier(fluid_player_t* player, float multiplier)
+{
+  if (multiplier < 0) {
+    return -1;
+  }
+
+  player->tempo_multiplier = multiplier;
+
+  return 0;
+}
+
+int fluid_player_set_velocity_multiplier(fluid_player_t* player, float 
multiplier)
+{
+  if ((multiplier < 0) || (multiplier > 1)) {
+    return -1;
+  }
+
+  player->velocity_multiplier = multiplier;
+
+  return 0;
+}
+
+int fluid_player_set_midi_event_callback(fluid_player_t* player, 
handle_midi_event_func_t callback, void* data)
+{
+  player->midi_event_callback = callback;
+  player->midi_event_callback_data = data;
+
+  return 0;
+}
+
+int fluid_player_is_playing(fluid_player_t* player)
+{
+  return (player->status == FLUID_PLAYER_PLAYING);
+}
+
+
 /*
  * fluid_player_add_track
  */
@@ -1487,37 +1532,77 @@
  */
 int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, 
fluid_midi_event_t* event)
 {
+  fluid_midi_event_t callbackEvent;
+
+  /* handle tempo multiplier modification */
+  if (player != NULL) {
+    if (player->tempo_last_multiplier != player->tempo_multiplier) {
+      if (player->midi_event_callback != NULL) {
+       memcpy(&callbackEvent, event, sizeof(fluid_midi_event_t));
+       callbackEvent.type = MIDI_SET_TEMPO;
+       callbackEvent.channel = 0;
+       callbackEvent.param1 == player->tempo_last_value * 
player->tempo_multiplier;
+       callbackEvent.param2 = 0;
+       player->midi_event_callback(player->midi_event_callback_data, 
&callbackEvent);
+      }
+      if (fluid_player_set_midi_tempo(player, player->tempo_last_value * 
player->tempo_multiplier) != FLUID_OK) {
+       return FLUID_FAILED;
+      }
+      player->tempo_last_multiplier = player->tempo_multiplier;
+    }
+
+    memcpy(&callbackEvent, event, sizeof(fluid_midi_event_t));
+  }
+
+  /* handle event */
        switch (event->type) {
        case NOTE_ON:
-               if (fluid_synth_noteon(synth, event->channel, event->param1, 
event->param2) != FLUID_OK) {
-                       return FLUID_FAILED;
+               callbackEvent.param2 *= player->velocity_multiplier;
+               if ((player->midi_event_callback != NULL) && 
(player->midi_event_callback(player->midi_event_callback_data, &callbackEvent) 
== 0)) {
+                 if (fluid_synth_noteon(synth, event->channel, event->param1, 
event->param2 * player->velocity_multiplier) != FLUID_OK) {
+                   return FLUID_FAILED;
+                 }
                }
                break;
        case NOTE_OFF:
-               if (fluid_synth_noteoff(synth, event->channel, event->param1) 
!= FLUID_OK) {
-                       return FLUID_FAILED;
+               if ((player->midi_event_callback != NULL) && 
(player->midi_event_callback(player->midi_event_callback_data, &callbackEvent) 
== 0)) {
+                 if (fluid_synth_noteoff(synth, event->channel, event->param1) 
!= FLUID_OK) {
+                   return FLUID_FAILED;
+                 }
                }
                break;
        case CONTROL_CHANGE:
-               if (fluid_synth_cc(synth, event->channel, event->param1, 
event->param2) != FLUID_OK) {
-                       return FLUID_FAILED;
+               if ((player->midi_event_callback != NULL) && 
(player->midi_event_callback(player->midi_event_callback_data, &callbackEvent) 
== 0)) {
+                 if (fluid_synth_cc(synth, event->channel, event->param1, 
event->param2) != FLUID_OK) {
+                   return FLUID_FAILED;
+                 }
                }
                break;
        case MIDI_SET_TEMPO:
                if (player != NULL) {
-                       if (fluid_player_set_midi_tempo(player, event->param1) 
!= FLUID_OK) {
-                               return FLUID_FAILED;
+                       callbackEvent.param1 *= player->tempo_multiplier;
+                       if (player->midi_event_callback != NULL) {
+                         
player->midi_event_callback(player->midi_event_callback_data, &callbackEvent);
+                       }
+                       if (fluid_player_set_midi_tempo(player, event->param1 * 
player->tempo_multiplier) != FLUID_OK) {
+                         return FLUID_FAILED;
                        }
+                       player->tempo_last_value = event->param1;
+                       player->tempo_last_multiplier = 
player->tempo_multiplier;
                }
                break;
        case PROGRAM_CHANGE:
-               if (fluid_synth_program_change(synth, event->channel, 
event->param1) != FLUID_OK) {
-                       return FLUID_FAILED;
+               if ((player->midi_event_callback != NULL) && 
(player->midi_event_callback(player->midi_event_callback_data, &callbackEvent) 
== 0)) {
+                 if (fluid_synth_program_change(synth, event->channel, 
event->param1) != FLUID_OK) {
+                   return FLUID_FAILED;
+                 }
                }
                break;
        case PITCH_BEND:
-               if (fluid_synth_pitch_bend(synth, event->channel, 
event->param1) != FLUID_OK) {
-                       return FLUID_FAILED;
+               if ((player->midi_event_callback != NULL) && 
(player->midi_event_callback(player->midi_event_callback_data, &callbackEvent) 
== 0)) {
+                 if (fluid_synth_pitch_bend(synth, event->channel, 
event->param1) != FLUID_OK) {
+                   return FLUID_FAILED;
+                 }
                }
                break;
        default:
diff -r -u fluidsynth-1.0.7/src/fluid_midi.h 
fluidsynth-1.0.7-new/src/fluid_midi.h
--- fluidsynth-1.0.7/src/fluid_midi.h   Mon Mar 29 12:05:18 2004
+++ fluidsynth-1.0.7-new/src/fluid_midi.h       Mon Jun 26 16:26:32 2006
@@ -251,6 +251,14 @@
   int miditempo;            /* as indicated by MIDI SetTempo: n 24th of a usec 
per midi-clock. bravo! */
   double deltatime;         /* milliseconds per midi tick. depends on 
set-tempo */
   unsigned int division;
+
+  float tempo_multiplier;   /* all tempo events will be multiplied by this one 
(if > 1, will slow down the play) */
+  float tempo_last_multiplier;
+  float tempo_last_value;
+  float velocity_multiplier;/* all velocities will be multiplied by this one 
(must be in ]0,1]) */
+
+  handle_midi_event_func_t midi_event_callback; /* customized function for 
handling Midi events */
+  void* midi_event_callback_data;               /* data to be passed to 
customized function */
 };
 
 int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]