Hi Ben,

Thanks a lot for your contribution you have done a good job.

After looking the result of the compiler you have posted on your site, I have found
some differences that strike me.
You will find below an new attached file: fluid_synth_mono.c.

Please may you:
1) substitute the one you have: in /src/synth/fluid_synth_mono.c by the attached new one.
2) rebuild.
3) And tell if the issue is always there ?.

Thanks you very much

jjc

Le 06/07/2016 14:37, Ben Gonzales a écrit :
Hi all.

When I said "are there any tests...?" I didn't expect so many!
Nevertheless, I have completed the tests, and I have put all the resulting files in:

http://gonzos.net/fluid-dev

Also in that directory are the soundfont, and other files I have referenced in this discussion.

cmakelog.txt is the results of the command <cmake ..> from the empty build directory
makelog.txt is the results of the command <make> from the build directory

I think I covered all the variations that you requested. They are summarised in polymonotests.pdf

ewi.conf is the configuration file I use to start fluidsynth, and the command line in the batch file is

        nice -20 fluidsynth --server --no-shell --audio-driver=alsa \
               -o audio.alsa.device=hw:$CARDNO \
--load-config=$CONFIG --portname="$SYNTHPORT" &> /home/pi/ewi/scripts/fluidsynth.out &

Notes:
- The %CPU is taken from the <top> command, and represents what is used by FluidSynth only. I arriving at the readings, I had to do a bit of "averaging" in my head, as the % utilisation fluctuated. I was not running the Xwindows graphical interface - it was all done via ssh.
- each test was done with a fresh instance of fluidsynth
- the ewi.conf file is a "snapshot" of one of its possible states - it gets changed depending on what options are selected. - I tested all the presets in the soundfont. The tenor sax displays the worst effects on the CPU, the clarinet displays the least. - The test with 24 notes was the test I did to see how far I could go before getting audio distortion as a result of high CPU load


Ben

On 06/07/16 19:17, jean-jacques.ceresa wrote:
Hi Ben,

>Is there any test I could run on the Pi....

While i'm preparing my RPi2, could you please:

Describe and localize when you see excess CPU usage. followings the tests below:
0)Building steps:
0.1) Which options did you choose at cmake time (please send the summary log or put it to your WebSite) ?.
0.1) Please send the log of compiler or put it on your WebSite ?.
0.2) What are the fluidsynth arguments when you start it ?.

1)Playing steps
1.1) What is the meter you use to see CPU usage (probably the one to top right of X windows graphic interface) ?
1.1.1) Please note the meter value when issue occurs.

1.2) Using your soundfont (gonzos-20160702.sf2), which preset causes the issue ?, and which preset doesn't cause the issue ?. 1.3) I remember the issue is when you play (in mono mode) (at the the noteOn time), but i 'm not sure ?. Please confirm.

1.4) Assuming the issue occurs in mono mode, does this issue occur in poly mode ? (using the same preset). 1.4.1) Is it when you play staccato (n1On,n1Off,n1On,n1Off,...) on the same note ? 1.4.2) Is it when you play staccato (n1On,n1Off,n2On,n2Off,...) on different note ? 1.4.2) Is it when you play legato (n1On,,n2On,n1Off,n3On,n2Off...) ?, please note the legato mode number (0 to 3).

The following test are related to Element remarks
2) Please do the test 1.x.x with Reverb and Chorus On and when the issue occurs, do the same tests without Reverb/Chorus.

Thanks a lot.

jjc

Le 06/07/2016 00:28, Ben Gonzales a écrit :
Hi all.

Is there any test I could run on the Pi that would help you analyse the problem?

Ben

On 06/07/16 04:55, Element Green wrote:
Hello,

I'm not sure if it could be the issue or not. But I remember a long while back (many years) FluidSynth used to have issues with denormal numbers causing excessive CPU usage. That would be floating point numbers which are very small, but not 0. I don't know if ARM processors deal with denormal numbers in software, which would result in poor performance and possibly floating point exception handlers being triggered. It seems like this would more often occur when the audio went towards silence.

Some general information on this:
https://en.wikipedia.org/wiki/Denormal_number#Performance_issues

Might be worth looking in to. Code was added in certain areas to detect if a number was below a very small value and if it was, then it would be forced to 0. Maybe there are still some areas where this is occurring which are only affecting this particular platform?

Best regards,

Element

On Tue, Jul 5, 2016 at 11:21 AM, jean-jacques.ceresa <jean-jacques.cer...@enac.fr> wrote:

    Hi Ben,

    On Windows, using your soundfont (gonzos-20160702.sf2), in mono
    mode i haven't expererienced absolutely no cpu excess usage, on
    alls 6 presets.
    I have look inside the preset. Each preset make use of 2
    simulateneous voices maximum. So this is a very low CPU usage
    soundfont.
    Normally on a RPi2 you can run 180 voices (using the 4 cores of
    course). Even if fluidsynth use only one core, the maximum
    number of voices
    falls to 45 which is sufficient to play any preset on this
    soundfont. So really, i don't understand what happens on your
    setting.

    Anyway, i have got a RPi2. So I will try this and also an other
    machine with Debian. I will return the results, using the same
    soundfont.

    >The legato is working, and I have noticed that if I do a long
    descending glissando to the lower register on the clarinet, the
    voice that I end up with
    > on the low note is the voice I started with - I don't get the
    low reedy sound until I stop and play the note again.
    Jean-Jacques said this was a limitation.

    Yes , i confirm this is currently a know limitation and it
    occurs only on legato mode  1,2,3 but not on legato mode 0.
    Playing a legato passage, n1,n2,n3,... using legato mode 1,2,3:
    The notes (n2,n3,..) following the first (n1) make use of
    running voices of n1, (regardless of the keyRange and Velocity
    Range), so the notes n2,n3,... make use
    of the IZ (Instruments Zone) of note n1 ignoring possible
    others IZ with their samples. In others words, the actual patch
    doesn't not follows fully the instructions
    given by the soundfont designer. This is a serious limitation.
    But anyway, i 'm working to cancel this limitation.

    jjc



    Le 02/07/2016 14:02, Ben Gonzales a écrit :
    Hi

    I downloaded the git snapshot, used the patch from Mr(?) Horn
    (thankyou), and re-complied.

    I'm still experiencing the CPU runaway. It happens a) if I put
the channel I'm using into MONO or b) if I use cc ch 68 127 (legato on). It doesn't matter which setlegatomode I am using
    for the channel. Note that it happens on 5 out of 6 of the
    voices I am using. I can't see any significant config
    differences between the voices when using Swami. One voice
    works fine.

    The legato is working, and I have noticed that if I do a long
    descending glissando to the lower register on the clarinet,
    the voice that I end up with on the low note is the voice I
    started with - I don't get the low reedy sound until I stop
    and play the note again. Jean-Jacques said this was a limitation.

    For info, I'm running a RPi2 with Raspbian Jessie, all latest
    updates installed. I'm trying to get legato working on
    channels 10-15 inclusive, and I'm not using the other channels.

    Ben




_______________________________________________
fluid-dev mailing list
fluid-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fluid-dev



_______________________________________________
fluid-dev mailing list
fluid-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fluid-dev



_______________________________________________
fluid-dev mailing list
fluid-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fluid-dev

/* 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
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "fluid_synth.h"
#include "fluid_chan.h"


/**  monophonic playing *******************************************************/
extern void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth,
                                                            int chan, int key);

/*-----------------------------------------------------------------------------
  Monophonic list methods
------------------------------------------------------------------------------*/

/**
 * Add a note to the monophonic list.
 * @param chan  fluid_channel_t
 * @param key MIDI note number (0-127)
 * @param vel MIDI velocity (0-127, 0=noteoff)
 * return prev index.
 */
static short 
fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key,
                                                                            
unsigned char vel)
{
        short iPrev = chan->iLast;
        short iNext = chan->iNext;
        chan->monolist[iNext].note = key;
        chan->monolist[iNext].vel = vel;
        chan->iLast = iNext; /* most recent adding */
        /* iNext will be used for the next adding */
        chan->iNext = chan->monolist[iNext].next;
        if(chan->nNotes < maxNotes) chan->nNotes++; /* update nNotes */
        else { /* overflow situation. So circular motion for iFirst */
                chan->iFirst = chan->iNext;
                /* warning */
        FLUID_LOG(FLUID_INFO, "Overflow on monophonic list channel %d ",
                                                                chan->channum);
        }
        return iPrev;
}

/**
 * Search a note in the monophonic list.
 * @param chan  fluid_channel_t
 * @param key MIDI note number (0-127) to search
 * @return index of the note if find, -1 otherwise.
 */
static short
fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key)
{
        short n = chan->nNotes; /* number of notes in monophonic list */
        short i= chan->iFirst; /* search starts at iFirst included */
        while(n) {
                if(chan->monolist[i].note == key) break; /* found */
                i = chan->monolist[i].next; /* next element */
                n--;
        }
        if (n) return i;/* found i */
        else return -1; /* not found */
}

/**
 * remove a note from the monophonic list.
 * @param chan  fluid_channel_t
 * @param i, index of the note to remove
 * If i is invalid or the list is empty, the function do nothing.
 * return prev index (>= 0) if the note is the last note in the list
          -1 otherwise.
 */
static short
fluid_channel_rem_monolist(fluid_channel_t* chan, short i)
{
        short iPrev = -1;
        if(i < 0 || i >= maxNotes || !chan->nNotes) return 0;
        /* index is valid */
        /* The element is about to be removed and inserted between iLast and 
iNext */
        /* Note: when i is egal to iLast or egal to iFirst, Removing/Inserting
           isn't necessary */
        if (i == chan->iLast) { /* Removing/Inserting isn't necessary */
                /* update iLast to the previous if it exists */
                iPrev = chan->monolist[i].prev;
                if(chan->iLast != chan->iFirst) chan->iLast = iPrev;
                chan->iNext = i; /* i becames iNext for the next adding */
        }
        else { /* i is before iLast */
                if(i == chan->iFirst)  chan->iFirst = chan->monolist[i].next;
                else { /* i is between iFist ans iLast */
                        /* Removing element i and inserting between iLast and 
iNext */
                        unsigned char next,prev;
                        /* removing by chainning prev and next */
                        next = chan->monolist[i].next;          prev = 
chan->monolist[i].prev;
                        chan->monolist[next].prev = prev;       
chan->monolist[prev].next = next;
                        /* inserting between iLast and iNext */
                        chan->monolist[i].next = chan->iNext; 
                        chan->monolist[chan->iNext].prev = i;
                        chan->monolist[i].prev = chan->iLast;
                        chan->monolist[chan->iLast].next = i;
                        chan->iNext = i; /* i becames iNext for the next adding 
*/
                }
        }
        chan->nNotes--;
        return iPrev;
}


/**
 * remove all notees from the monophonic list.
 * @param chan  fluid_channel_t
 */
void fluid_channel_clear_monolist(fluid_channel_t* chan)
{
        chan->iFirst = chan->iLast = chan->iNext = chan->nNotes = 0;
}

/**
 * The monophonic list is flushed keeping last note only.
 * @param chan  fluid_channel_t
 */
void fluid_channel_keep_lastnote_monolist(fluid_channel_t* chan)
{
        chan->iFirst = chan->iLast;
        chan->nNotes = 1;
}

/**
 * The function store the note in the first position of monophonic list 
 * @param chan  fluid_channel_t
 */
void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char 
key,
                                                                            
unsigned char vel)
{
        fluid_channel_clear_monolist(chan);
        fluid_channel_add_monolist(chan, key, vel);
}

/*-----------------------------------------------------------------------------
  noteon - noteoff on a channel in "monophonic playing".
  
  A channel needs to be played monophonic if this channel has been set
  monophonic by basic channel API.(see fluid_synth_polymono.c).
  A channel needs also to be played monophonic if it has been set
  polyphonic and legato pedal is On.
  When in "monophonic playing" only one note at a time can be played in
  a staccato or legato manner.

------------------------------------------------------------------------------*/
int fluid_synth_noteon_mono(fluid_synth_t* synth, int chan, int key, int vel);
int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key,
                                                         char Mono);

int
fluid_synth_noteon_mono_legato(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel);

/**
 * Send a note-on event to a FluidSynth object in "monophonic playing".
 * Please see the description above about "monophonic playing".
 * @param synth FluidSynth instance
 * @param chan MIDI channel number (0 to MIDI channel count - 1)
 * @param key MIDI note number (0-127)
 * @param vel MIDI velocity (0-127)
 * @return FLUID_OK on success, FLUID_FAILED otherwise
 */
int
fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan, int key, int vel)
{
        int status;
        char iPrev;
        fluid_channel_t* channel = synth->channel[chan];;
        /* Add note to the monophonic list */
        iPrev = fluid_channel_add_monolist(channel,(unsigned char)key, 
(unsigned char)vel);
        /* legato/staccato playing detection */
        if(channel->nNotes >= 2) { /* legato playing */
                /* legato from iPrev to key */
                /* the voices from iPrev key number are to be used to play key 
number */
                status = fluid_synth_noteon_mono_legato(synth, chan,
                                                           
channel->monolist[iPrev].note, key, vel);
        }
        /* staccato playing */
        else  status = fluid_synth_noteon_mono(synth, chan, key, vel);
        return status;
}

/**
 * Send a note-off event to a FluidSynth object in "monophonic playing".
 * Please see the description above about "monophonic playing".
 * @param synth FluidSynth instance
 * @param chan MIDI channel number (0 to MIDI channel count - 1)
 * @param key MIDI note number (0-127)
 * @return FLUID_OK on success, FLUID_FAILED otherwise
 */
int
fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key)
{
        int status;
        short i,iPrev;
        fluid_channel_t* channel = synth->channel[chan];;
        /* search the note in monophonic list */
        i=fluid_channel_search_monolist(channel, (unsigned char)key);
        
        if (i >= 0)     { /* the note is in monophonic list */
                /* Remove note from the monophonic list */
                iPrev = fluid_channel_rem_monolist(channel,i);
                /* legato playing detection */
                if(channel->nNotes) { /* the list contains others notes */
                        if(iPrev >=0) { /* legato playing detection */
                                /* legato from key to iPrev key */
                                /* the voices from key number are to be used to
                                play iPrev key number. */
                                status = fluid_synth_noteon_mono_legato(synth, 
chan,
                                                           key, 
channel->monolist[iPrev].note,
                                                           
channel->monolist[iPrev].vel);
                        }
                        /* else the note doesn't need to be played off */
                        else status = FLUID_OK;
                }
                else { /* the monophonic list is empty */
                        /* play the monophonic note noteoff and eventually held
                        by sustain only (R2) */
                        status = fluid_synth_noteoff_monopoly(synth, chan, key, 
1);

                }
        }
        else { /* the note is not found in the list so the note will 
                   be played On when we was in polyphonic playing */
                        /* play the noteoff as for polyphonic  */
                        status = fluid_synth_noteoff_monopoly(synth, chan, key, 
0);
        }
        return status;
}

/*----------------------------------------------------------------------------
 staccato playing
-----------------------------------------------------------------------------*/

/**
 * noteon for monophonic note.
 * Please see the description above about "monophonic playing".
 * @param synth FluidSynth instance
 * @param chan MIDI channel number (0 to MIDI channel count - 1)
 * @param key MIDI note number (0-127)
 * @param vel MIDI velocity (0-127)
 * @return FLUID_OK on success, FLUID_FAILED otherwise
 */
int
fluid_synth_noteon_mono(fluid_synth_t* synth, int chan, int key, int vel)
{
        fluid_channel_t* channel = synth->channel[chan];
        
        /* Before playing a new note, il a previous monophonic note is currently
           sustained it needs to be released */
        fluid_synth_release_voice_on_same_note_LOCAL(synth,chan,
                                                                                
                channel->key_sustained);

        /* The note needs to be played by voices allocation  */
        return fluid_preset_noteon(channel->preset, synth, chan, key, vel);
}

/**
 * noteoff for a polyphonic or monophonic note
 * Please see the description above about "monophonic playing".
 * @param synth FluidSynth instance
 * @param chan MIDI channel number (0 to MIDI channel count - 1)
 * @param key MIDI note number (0-127)
 * @param Mono, 1 noteoff on monophonic note.
 *              0 noteoff on polyphonic note
 * @return FLUID_OK on success, FLUID_FAILED otherwise

 * Note: On return, on monophonic, sustained note  needs to be remembered
 * in key_sustained.
 * On noteon for a monophonic note if a previous monophonic note is sustained
 * it will be released. Remembering is done here on noteOff.
 */
int
fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key,
                                                         char Mono)
{
        int status = FLUID_FAILED;
        fluid_voice_t* voice;
        int i, IsSustained;
        fluid_channel_t* channel = synth->channel[chan];
        /* Key_sustained is prepared to return no note sustained (-1) */
        if (Mono) channel->key_sustained = -1; /* no mono note sustained */
        /* noteoff for all voices with same chan and same key */
        for (i = 0; i < synth->polyphony; i++) {
                voice = synth->voice[i];
                if (_ON(voice) && (voice->chan == chan) && (voice->key == key)) 
{
                        if (synth->verbose) {
                                int used_voices = 0;
                                int k;
                                for (k = 0; k < synth->polyphony; k++) {
                                        if (!_AVAILABLE(synth->voice[k])) {
                                        used_voices++;
                                        }
                                }
                                FLUID_LOG(FLUID_INFO, 
"noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d",
                                                voice->chan, voice->key, 0, 
voice->id,
                                                (fluid_curtime() - 
synth->start) / 1000.0f,
                                                used_voices);
                        } /* if verbose */
                        IsSustained = fluid_voice_noteoff(voice);
                        /* noteoff on monophonic note */
                        /* Key remembering if the note is sustained  */
                        if(Mono && IsSustained) channel->key_sustained = key;
                        status = FLUID_OK;
                } /* if voice on */
        } /* for all voices */
        return status;
}

/*----------------------------------------------------------------------------
 legato playing
-----------------------------------------------------------------------------*/
int fluid_synth_noteon_mono_legato_retrigger(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel);

int fluid_synth_noteon_mono_legato_multi_retrigger(fluid_synth_t* synth, int 
chan,
                                                           int fromkey, int 
tokey, int vel);
int fluid_synth_noteon_mono_legato_single_trigger0(fluid_synth_t* synth, int 
chan,
                                                           int fromkey, int 
tokey, int vel);
fluid_synth_noteon_mono_legato_single_trigger1(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel);

/**
 * noteon for monophonic note played legato.
 * Please see the description above about "monophonic playing".
 * @param synth FluidSynth instance
 * @param chan MIDI channel number (0 to MIDI channel count - 1)
 * @param fromkey MIDI note number (0-127)
 * @param tokey MIDI note number (0-127)
 * @param vel MIDI velocity (0-127)
 * @return FLUID_OK on success, FLUID_FAILED otherwise
 * Note: The voices with key 'fromkey' are to be used to play key 'tokey'.
 */
int
fluid_synth_noteon_mono_legato(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel)
{
        int status;
        unsigned char legatomode = GetChanLegatoMode(synth->channel[chan]);
        switch (legatomode) 
        {
                case RETRIGGER: /* mode 0 */
                        status= 
fluid_synth_noteon_mono_legato_retrigger(synth,chan,fromkey,
                                                                                
                                        tokey,vel);
                break;
                case MULTI_RETRIGGER: /* mode 1 */
                        status = 
fluid_synth_noteon_mono_legato_multi_retrigger(synth,chan,fromkey,
                                                                                
                                tokey,vel);
                break;
                case SINGLE_TRIGGER_0: /* mode 2 */
                        status= 
fluid_synth_noteon_mono_legato_single_trigger0(synth,chan,fromkey,
                                                                tokey,vel);
                break;
                case SINGLE_TRIGGER_1: /* mode 3 */
                        status= 
fluid_synth_noteon_mono_legato_single_trigger1(synth,chan,fromkey,
                                                                tokey,vel);
                break;
                default:
                FLUID_LOG(FLUID_WARN, "Failed to execute legato mode: 
%d",legatomode);
                status = FLUID_FAILED;
        }
        return status;
}


/*-----------------------------------------------------------------------------
/* Mode 0: retrigger */
int fluid_synth_noteon_mono_legato_retrigger(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel)
{
        fluid_channel_t* channel = synth->channel[chan];
        fluid_voice_t* voice;
        int i, status ;
        /* Mode 0: retrigger (with crossfading between release and attack) */
        /* Release the fromkey note */
        for (i = 0; i < synth->polyphony; i++) {
                /* search fromkey voice: only those who don't have 'note off' */
                voice = synth->voice[i];
                if (_ON(voice) && (voice->chan == chan) && 
                        (voice->key == fromkey)){

                        fluid_update_release(voice);
                }
        }
        /* tokey note needs to be played by voices allocation  */
        synth->fromkey = fromkey; /* portamento fromkey */
        status = fluid_preset_noteon(channel->preset, synth, chan, tokey, vel);
        /* When fromkey is set to -1 , portamento is disabled even if portamento
        pedal is pressed. Once portamento is triggered by
        fluid_preset_noteon(), fromkey is set to -1 to disable
        portamento for the next fluid_preset_noteon. This is very useful has the
        first note (n1) of a legato passage (n1,n2,n3,..) will be always without
        portamento but not the following notes (n2,n3,..) */
        synth->fromkey = -1; /* disable portamento */
        return status;
}

/*-----------------------------------------------------------------------------
/* Mode 1: multi_retrigger */
int 
fluid_synth_noteon_mono_legato_multi_retrigger(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel)
{
        fluid_channel_t* channel = synth->channel[chan];
        unsigned char found = 0;
        fluid_voice_t* voice;
        int i, status = FLUID_OK;
        /* Mode 0: retrigger (with crossfading between release and attack) */
        for (i = 0; i < synth->polyphony; i++) {
                /* search fromkey voice: only those who don't have 'note off' */
                voice = synth->voice[i];
                if (_ON(voice) && (voice->chan == chan) && 
                        (voice->key == fromkey)){
                        found = 1;
                        /* Skip in attack section */
                        fluid_update_multi_retrigger_attack(voice,tokey,vel);
                        /* Start portamento if enabled */
                        if(     fluid_channel_portamento(channel))
                                /* Send portamento parameters to the voice dsp 
*/
                                
fluid_voice_update_portamento(voice,fromkey,tokey);
                }
        }
        if(!found) /* fromkey note have finished */
        { /* The note needs to be played by voices allocation  */
                int i, status ;

                synth->fromkey = fromkey; /* portamento fromkey */
                status = 
fluid_preset_noteon(channel->preset,synth,chan,tokey,vel);
                synth->fromkey = -1; /* disable portamento */
        }
        return status;
}

/*-----------------------------------------------------------------------------
/* Mode 2: single_trigger_0 */
int 
fluid_synth_noteon_mono_legato_single_trigger0(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel)
{
        fluid_channel_t* channel = synth->channel[chan];
        unsigned char found = 0;
        fluid_voice_t* voice;
        int i, status = FLUID_OK;
        /* Mode 0: retrigger (with crossfading between release and attack) */
        for (i = 0; i < synth->polyphony; i++) {
                /* search fromkey voice: only those who don't have 'note off' */
                voice = synth->voice[i];
                if (_ON(voice) && (voice->chan == chan) && 
                        (voice->key == fromkey)){
                        found = 1;
                        fluid_update_single_trigger0(voice,fromkey,tokey,vel);
                        /* Start portamento if enabled */
                        if(     fluid_channel_portamento(channel))
                                /* Send portamento parameters to the voice dsp 
*/
                                
fluid_voice_update_portamento(voice,fromkey,tokey);
                }
        }
        if(!found) /* fromkey note have finished */
        { /* The note needs to be played by voices allocation  */
                synth->fromkey = fromkey; /* portamento fromkey */
                status = 
fluid_preset_noteon(channel->preset,synth,chan,tokey,vel);
                synth->fromkey = -1; /* disable portamento */
        }
        return status;
}

/*-----------------------------------------------------------------------------
/* Mode 3: single_trigger_1 */
int 
fluid_synth_noteon_mono_legato_single_trigger1(fluid_synth_t* synth, int chan,
                                                           int fromkey, int 
tokey, int vel)
{
        fluid_channel_t* channel = synth->channel[chan];
        unsigned char found = 0;
        fluid_voice_t* voice;
        int i, status = FLUID_OK;
        /* Mode 0: retrigger (with crossfading between release and attack) */
        for (i = 0; i < synth->polyphony; i++) {
                /* search fromkey voice: only those who don't have 'note off' */
                voice = synth->voice[i];
                if (_ON(voice) && (voice->chan == chan) && 
                        (voice->key == fromkey)){
                        found = 1;
                        fluid_update_single_trigger1(voice,fromkey,tokey,vel);
                        /* Start portamento if enabled */
                        if(     fluid_channel_portamento(channel))
                                /* Send portamento parameters to the voice dsp 
*/
                                
fluid_voice_update_portamento(voice,fromkey,tokey);
                }
        }
        if(!found) /* fromkey note have finished */
        { /* The note needs to be played by voices allocation  */
                synth->fromkey = fromkey; /* portamento fromkey */
                status = 
fluid_preset_noteon(channel->preset,synth,chan,tokey,vel);
                synth->fromkey = -1; /* disable portamento */
        }
        return status;
}
_______________________________________________
fluid-dev mailing list
fluid-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/fluid-dev

Reply via email to