fluid-dev
[Top][All Lists]
Advanced

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

Re: [fluid-dev] Would it be possible to add these three functions from a


From: Graham Goode
Subject: Re: [fluid-dev] Would it be possible to add these three functions from a 2006 patch to the latest fluidsynth trunk?
Date: Mon, 21 Jan 2013 08:05:26 +0200

Hi Matt,

Many thanks for taking the time to look at this and get a 'working
patch' for the 104 SVN revision.

I'm hoping that someone can either work out how to add these functions
to the re-factored code, or can add something similar to the
re-factored code provide and example of how to use those re-factored
functions to get a similar result.

Kind regards,
GrahamG

On 1/19/13, Matt Giuca <address@hidden> wrote:
> I took a look at this patch (Sebastien's original one, not Jan's). The news
> isn't good for merging it into the current HEAD. The main part of the patch
> is about updating a function called fluid_midi_send_event in
> src/fluid_midi.c (now src/midi/fluid_midi.c). The problem is that that
> function no longer exists. That has all been refactored and now the MIDI
> events are processed at file load time in fluid_midi_file_read_event. I
> haven't done a lot of understanding about how the old and new code relates
> to one another, and I don't have any more time this weekend to look at it.
>
> If anyone is interested, at least I've made it possible to apply the patch
> cleanly to the old version of the code. For some reason, Sebastien pasted
> the patch into an email instead of attaching it, and it was word-wrapped to
> hell. It also messed up the tabs and spaces so that it cannot be applied by
> patch. Finally, note that Graham pasted an older version of the patch.
> Sebastien followed up his email a few days later with a revised patch with
> more features (
> http://lists.gnu.org/archive/html/fluid-dev/2006-06/msg00016.html).
>
> So what I am attaching is Sebastien's second patch, with:
> - Word wrapping fixed.
> - Indentation fixed so it matches the code as it was at the time.
> - Other minor formatting blemishes removed.
> - The new file he added (mididefs.h) included in the patch itself.
>
> This patch applies cleanly against SVN revision 104 (the latest version at
> the time he wrote his patch). Of course, it *does not* apply cleanly
> against a modern version of FluidSynth, and that's the challenge...
>
>
> On Sat, Jan 19, 2013 at 12:24 PM, Jan Newmarch <address@hidden> wrote:
>
>> I posted a ticket to ask for similar functionality last month, but it
>> hasn't been picked up so far. It uses the new 1.1.6 filtering mechanism
>> but adds in Text/Lyric events which are what the posting below seems to
>> want too.
>>
>> The ticket runs:
>>
>> Karaoke files contain Lyric or Text meta-events in addition to the other
>> MIDI events. Playing such files in a Karaoke system requires that all of
>> the lyrics are available to the karaoke application at the start of the
>> song and the Lyric/Text events need to be captured at the time they are
>> "played". I suggest two changes to make this possible:
>>
>> a) Add an event handler that is called on completion of file loading:
>>
>> typedef int (*handle_onload_func_t)(void* data, fluid_player_t* player);
>>
>> int fluid_player_set_onload_callback(fluid_player_t* player,
>>                      handle_onload_func_t handler, void* handler_data);
>>
>> This will expose the player _after_ it has loaded a file so that its
>> parsed MIDI file data can be examined.
>>
>> b) Add code to fluid_midi.c to handle Text/Lyric events and send them
>> from the sequencer to the MIDI synthesizer. NOTE: the default
>> synthesizer fluid_synth_handle_midi_event() is NOT changed so will
>> continue to ignore such events. Only if a custom event handler is
>> installed will these events be seen (see example below).
>> I have working code for this (including appropriate garbage collection)
>> and have attached a patch file, against 1.1.6.
>>
>> An example showing how this could work is attached. It is based on
>> file_player.c from the API documentation
>>
>> On Fri, 2013-01-18 at 21:11 +0200, Graham Goode wrote:
>> > Hi Guys,
>> >
>> > I'm looking at doing some PortAudio / Native Jack builds of fluidsynth
>> > for Miditzer (main code from 2006/2007) but their fluidsynth.dll
>> > contains the following patch, which was added in order to use an
>> > in-app MIDI file player.
>> >
>> > I have just found this in an archive, so have not even attempted
>> > anything with it yet.
>> >
>> > Would anyone else be able to look at it, and what are the chances of
>> > being able to add this to 1.1.7?
>> >
>> > Kind regards,
>> > GrahamG
>> >
>> >
>> > Re: [fluid-dev] Some questions about Midi playback
>> > From:         Sebastien Frippiat
>> > Subject:      Re: [fluid-dev] Some questions about Midi playback
>> > Date:         Mon, 26 Jun 2006 14:27:16 +0200
>> > User-agent:   Mozilla Thunderbird 1.0.7-1.4.1 (X11/20050929)
>> >
>> > Hi again !
>> >
>> > I finally managed to do what I wanted to do without too much trouble.
>> > I know it is not the main purpose of fluidsynth but as I don't think
>> > of my modifications are a ugly hack, I post my code here. In fact, it
>> > add three functions : - fluid_player_set_tempo_multiplier : multiply
>> > all received tempo by a specified multiplier (useful for accelerating
>> > / slowing down music playback) - fluid_player_set_velocity_multiplier
>> > : multiply all notes velocities by a specified multiplier (useful for
>> > decreasing volume) - fluid_player_set_midi_event_callback : call a
>> > specified callback function on any Midi event and that function can
>> > specify whether FluidSynth must forward the event to the synthesizer
>> >
>> >
>> > I wrote the first two functions last week and I posted the code on the
>> > mailing list. For a quick explanation, I needed these functions to be
>> > able to play some sort of adaptive music (like with DirectMusic for
>> > those who know it).
>> >
>> >
>> > The last one is in fact to redirect the Midi events to a real Midi
>> > device. There seems to be something planned/ (?) in FluidSynth about
>> > routers which would allow to apply filters to Midi events. However,
>> > like said in the docs, it is only used for Midi inputs (and not Midi
>> > file playback). With my modification, if you specify a callback and
>> > tell FluidSynth to forward the event to the synthesizer, you'll be
>> > able to provide feedback to the user of your application (add events
>> > to log, show visual feedback like notes being played...). I personnaly
>> > used it to prevent FluidSynth playing the Midi file and processed the
>> > event myself. It allows me to load a .mid file and to play it without
>> > having to take care of timing as fluidsynth already do it.
>> >
>> >
>> > Even if it is not the main purpose of this lib, I do think that my
>> > code is quite clean (I also wrote the Doxygen documentation to the
>> > functions) and that it could be useful to some other people. Anyway,
>> > whether you want it or not... here it is, attached to my post.
>> >
>> >
>> > You need to copy the patch file into the fluidsynth directory and run
>> > "patch -u -i fluidsynth_modifs.patch -p 1". Then copy the mididefs.h
>> > file in the include/fluidsynth.h directory. I had to add it because
>> > the _fluid_midi_event_t was defined in src/fluid_midi.h but not in
>> > include/fluidsynth/midi.h and it was not accessible to users of the
>> > library.
>> >
>> >
>> > Thanks for your advices,
>> > Sebastien Frippiat
>> >
>> > 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      Mon Jun 26
>> 12:49:59 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,52 @@
>> >  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
>> > +  * \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);
>> >
>> >  #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       Mon Jun 26 12:49:59
>> > 2006
>> > @@ -1072,6 +1072,13 @@
>> >         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;
>> > +
>> >         return player;
>> >  }
>> >
>> > @@ -1107,9 +1114,39 @@
>> >         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)
>> > +{
>> > +  player->midi_event_callback = callback;
>> > +
>> > +  return 0;
>> > +}
>> > +
>> >  /*
>> >   * fluid_player_add_track
>> >   */
>> > @@ -1487,37 +1524,69 @@
>> >   */
>> >  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 (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(NULL, &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(NULL, &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(NULL, &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(NULL,
>> &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(NULL, &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(NULL, &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 12:49:59
>> > 2006
>> > @@ -251,6 +251,13 @@
>> >    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 */
>> >  };
>> >
>> >  int fluid_player_add_track(fluid_player_t* player, fluid_track_t*
>> track);
>> >
>> > /* FluidSynth - A Software Synthesizer
>> >  *
>> >  * Copyright (C) 2003  Peter Hanappe and others.
>> >  *
>> >  * This library is free software; you can redistribute it and/or
>> >  * modify it under the terms of the GNU Library General Public License
>> >  * as published by the Free Software Foundation; either version 2 of
>> >  * the License, or (at your option) any later version.
>> >  *
>> >  * This library is distributed in the hope that it will be useful, but
>> >  * WITHOUT ANY WARRANTY; without even the implied warranty of
>> >  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> >  * Library General Public License for more details.
>> >  *
>> >  * You should have received a copy of the GNU Library General Public
>> >  * License along with this library; if not, write to the Free
>> >  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> >  * 02111-1307, USA
>> >  */
>> >
>> > /*
>> >    This file should be included by anyone willing to use a callback
>> function
>> >    to handle Midi events.
>> > */
>> >
>> > #ifndef _FLUIDSYNTH_MIDIDEFS_H
>> > #define _FLUIDSYNTH_MIDIDEFS_H
>> >
>> > #ifdef __cplusplus
>> > extern "C" {
>> > #endif
>> >
>> > /*
>> >  * fluid_midi_event_t
>> >  */
>> > struct _fluid_midi_event_t {
>> >   fluid_midi_event_t* next;  /* Don't use it, it will dissappear. Used
>> in midi
>> > tracks.  */
>> >   unsigned int dtime;       /* Delay (ticks) between this and previous
>> event.
>> > midi tracks. */
>> >   unsigned char type;       /* MIDI event type */
>> >   unsigned char channel;    /* MIDI channel */
>> >   unsigned int param1;      /* First parameter */
>> >   unsigned int param2;      /* Second parameter */
>> > };
>> >
>> > #ifdef __cplusplus
>> > }
>> > #endif
>> >
>> > #endif /* _FLUIDSYNTH_MIDIDEFS_H */
>> >
>> > _______________________________________________
>> > fluid-dev mailing list
>> > address@hidden
>> > https://lists.nongnu.org/mailman/listinfo/fluid-dev
>>
>> --
>> Dr Jan Newmarch
>> Head of Higher Education (ICT)
>>
>> P 61 3 9286 9971
>> M +61 4 0117 0509
>> F 61 3 9286 9100
>> W www.boxhill.edu.au
>> W jan.newmarch.name
>> E address@hidden
>> E address@hidden
>>
>> _______________________________________________
>> fluid-dev mailing list
>> address@hidden
>> https://lists.nongnu.org/mailman/listinfo/fluid-dev
>>
>>
>



reply via email to

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