diff options
Diffstat (limited to 'libs/fluidsynth/src/fluid_chan.h')
-rw-r--r-- | libs/fluidsynth/src/fluid_chan.h | 279 |
1 files changed, 209 insertions, 70 deletions
diff --git a/libs/fluidsynth/src/fluid_chan.h b/libs/fluidsynth/src/fluid_chan.h index 85aa1ef00c..42d73df7b5 100644 --- a/libs/fluidsynth/src/fluid_chan.h +++ b/libs/fluidsynth/src/fluid_chan.h @@ -3,16 +3,16 @@ * 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 + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser 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 @@ -25,6 +25,50 @@ #include "fluid_midi.h" #include "fluid_tuning.h" +/* The mononophonic list is part of the legato detector for monophonic mode */ +/* see fluid_synth_monopoly.c about a description of the legato detector device */ +/* Size of the monophonic list + - 1 is the minimum. it allows playing legato passage of any number + of notes on noteon only. + - Size above 1 allows playing legato on noteon but also on noteOff. + This allows the musician to play fast trills. + This feature is particularly usful when the MIDI input device is a keyboard. + Choosing a size of 10 is sufficient (because most musicians have only 10 + fingers when playing a monophonic instrument). +*/ +#define FLUID_CHANNEL_SIZE_MONOLIST 10 + +/* + + The monophonic list + +------------------------------------------------+ + | +----+ +----+ +----+ +----+ | + | |note| |note| |note| |note| | + +--->|vel |-->|vel |-->....-->|vel |-->|vel |----+ + +----+ +----+ +----+ +----+ + /|\ /|\ + | | + i_first i_last + + The monophonic list is a circular buffer of FLUID_CHANNEL_SIZE_MONOLIST elements. + Each element is linked forward at initialisation time. + - when a note is added at noteOn (see fluid_channel_add_monolist()) each + element is use in the forward direction and indexed by i_last variable. + - when a note is removed at noteOff (see fluid_channel_remove_monolist()), + the element concerned is fast unlinked and relinked after the i_last element. + + The most recent note added is indexed by i_last. + The most ancient note added is the first note indexed by i_first. i_first is + moving in the forward direction in a circular manner. + +*/ +struct mononote +{ + unsigned char next; /* next note */ + unsigned char note; /* note */ + unsigned char vel; /* velocity */ +}; + /* * fluid_channel_t * @@ -33,83 +77,93 @@ */ struct _fluid_channel_t { - fluid_mutex_t mutex; /* Lock for thread sensitive parameters */ - - fluid_synth_t* synth; /**< Parent synthesizer instance */ - int channum; /**< MIDI channel number */ - - int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */ - fluid_preset_t* preset; /**< Selected preset */ - - int key_pressure; /**< MIDI key pressure */ - int channel_pressure; /**< MIDI channel pressure */ - int pitch_bend; /**< Current pitch bend value */ - int pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */ - - int cc[128]; /**< MIDI controller values */ - - /* Sostenuto order id gives the order of SostenutoOn event. - This value is useful to known when the sostenuto pedal is depressed - (before or after a key note). We need to compare SostenutoOrderId with voice id. - */ - unsigned int sostenuto_orderid; - int interp_method; /**< Interpolation method (enum fluid_interp) */ - fluid_tuning_t* tuning; /**< Micro tuning */ - int tuning_bank; /**< Current tuning bank number */ - int tuning_prog; /**< Current tuning program number */ - - /* NRPN system */ - int nrpn_select; /* Generator ID of SoundFont NRPN message */ - int nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */ - - /* The values of the generators, set by NRPN messages, or by - * fluid_synth_set_gen(), are cached in the channel so they can be - * applied to future notes. They are copied to a voice's generators - * in fluid_voice_init(), which calls fluid_gen_init(). */ - fluid_real_t gen[GEN_LAST]; - - /* By default, the NRPN values are relative to the values of the - * generators set in the SoundFont. For example, if the NRPN - * specifies an attack of 100 msec then 100 msec will be added to the - * combined attack time of the sound font and the modulators. - * - * However, it is useful to be able to specify the generator value - * absolutely, completely ignoring the generators of the SoundFont - * and the values of modulators. The gen_abs field, is a boolean - * flag indicating whether the NRPN value is absolute or not. - */ - char gen_abs[GEN_LAST]; - - /* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */ - int channel_type; + fluid_synth_t *synth; /**< Parent synthesizer instance */ + int channum; /**< MIDI channel number */ + + /* Poly Mono variables see macro access description */ + int mode; /**< Poly Mono mode */ + int mode_val; /**< number of channel in basic channel group */ + + /* monophonic list - legato detector */ + unsigned char i_first; /**< First note index */ + unsigned char i_last; /**< most recent note index since the most recent add */ + unsigned char prev_note; /**< previous note of the most recent add/remove */ + unsigned char n_notes; /**< actual number of notes in the list */ + struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */ + + unsigned char key_mono_sustained; /**< previous sustained monophonic note */ + unsigned char previous_cc_breath; /**< Previous Breath */ + enum fluid_channel_legato_mode legatomode; /**< legato mode */ + enum fluid_channel_portamento_mode portamentomode; /**< portamento mode */ + /*- End of Poly/mono variables description */ + + unsigned char cc[128]; /**< MIDI controller values from [0;127] */ + unsigned char key_pressure[128]; /**< MIDI polyphonic key pressure from [0;127] */ + + /* Drum channel flag, CHANNEL_TYPE_MELODIC, or CHANNEL_TYPE_DRUM. */ + enum fluid_midi_channel_type channel_type; + enum fluid_interp interp_method; /**< Interpolation method (enum fluid_interp) */ + + unsigned char channel_pressure; /**< MIDI channel pressure from [0;127] */ + unsigned char pitch_wheel_sensitivity; /**< Current pitch wheel sensitivity */ + short pitch_bend; /**< Current pitch bend value */ + /* Sostenuto order id gives the order of SostenutoOn event. + * This value is useful to known when the sostenuto pedal is depressed + * (before or after a key note). We need to compare SostenutoOrderId with voice id. + */ + unsigned int sostenuto_orderid; + + int tuning_bank; /**< Current tuning bank number */ + int tuning_prog; /**< Current tuning program number */ + fluid_tuning_t *tuning; /**< Micro tuning */ + + fluid_preset_t *preset; /**< Selected preset */ + int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */ + + /* NRPN system */ + enum fluid_gen_type nrpn_select; /* Generator ID of SoundFont NRPN message */ + char nrpn_active; /* 1 if data entry CCs are for NRPN, 0 if RPN */ + /* The values of the generators, set by NRPN messages, or by + * fluid_synth_set_gen(), are cached in the channel so they can be + * applied to future notes. They are copied to a voice's generators + * in fluid_voice_init(), which calls fluid_gen_init(). */ + fluid_real_t gen[GEN_LAST]; + + /* By default, the NRPN values are relative to the values of the + * generators set in the SoundFont. For example, if the NRPN + * specifies an attack of 100 msec then 100 msec will be added to the + * combined attack time of the sound font and the modulators. + * + * However, it is useful to be able to specify the generator value + * absolutely, completely ignoring the generators of the SoundFont + * and the values of modulators. The gen_abs field, is a boolean + * flag indicating whether the NRPN value is absolute or not. + */ + char gen_abs[GEN_LAST]; }; -fluid_channel_t* new_fluid_channel(fluid_synth_t* synth, int num); -void fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off); -int delete_fluid_channel(fluid_channel_t* chan); -void fluid_channel_reset(fluid_channel_t* chan); -int fluid_channel_set_preset(fluid_channel_t* chan, fluid_preset_t* preset); -fluid_preset_t* fluid_channel_get_preset(fluid_channel_t* chan); -void fluid_channel_set_sfont_bank_prog(fluid_channel_t* chan, int sfont, +fluid_channel_t *new_fluid_channel(fluid_synth_t *synth, int num); +void fluid_channel_init_ctrl(fluid_channel_t *chan, int is_all_ctrl_off); +void delete_fluid_channel(fluid_channel_t *chan); +void fluid_channel_reset(fluid_channel_t *chan); +int fluid_channel_set_preset(fluid_channel_t *chan, fluid_preset_t *preset); +void fluid_channel_set_sfont_bank_prog(fluid_channel_t *chan, int sfont, int bank, int prog); -void fluid_channel_set_bank_lsb(fluid_channel_t* chan, int banklsb); -void fluid_channel_set_bank_msb(fluid_channel_t* chan, int bankmsb); -void fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont, +void fluid_channel_set_bank_lsb(fluid_channel_t *chan, int banklsb); +void fluid_channel_set_bank_msb(fluid_channel_t *chan, int bankmsb); +void fluid_channel_get_sfont_bank_prog(fluid_channel_t *chan, int *sfont, int *bank, int *prog); -int fluid_channel_get_num(fluid_channel_t* chan); -void fluid_channel_set_interp_method(fluid_channel_t* chan, int new_method); -int fluid_channel_get_interp_method(fluid_channel_t* chan); #define fluid_channel_get_preset(chan) ((chan)->preset) #define fluid_channel_set_cc(chan, num, val) \ ((chan)->cc[num] = (val)) #define fluid_channel_get_cc(chan, num) \ ((chan)->cc[num]) -#define fluid_channel_get_key_pressure(chan) \ - ((chan)->key_pressure) -#define fluid_channel_set_key_pressure(chan, val) \ - ((chan)->key_pressure = (val)) +#define fluid_channel_get_key_pressure(chan, key) \ + ((chan)->key_pressure[key]) +#define fluid_channel_set_key_pressure(chan, key, val) \ + ((chan)->key_pressure[key] = (val)) #define fluid_channel_get_channel_pressure(chan) \ ((chan)->channel_pressure) #define fluid_channel_set_channel_pressure(chan, val) \ @@ -138,6 +192,12 @@ int fluid_channel_get_interp_method(fluid_channel_t* chan); ((chan)->tuning_prog) #define fluid_channel_set_tuning_prog(chan, prog) \ ((chan)->tuning_prog = (prog)) +#define fluid_channel_portamentotime(_c) \ + ((_c)->cc[PORTAMENTO_TIME_MSB] * 128 + (_c)->cc[PORTAMENTO_TIME_LSB]) +#define fluid_channel_portamento(_c) ((_c)->cc[PORTAMENTO_SWITCH] >= 64) +#define fluid_channel_breath_msb(_c) ((_c)->cc[BREATH_MSB] > 0) +#define fluid_channel_clear_portamento(_c) ((_c)->cc[PORTAMENTO_CTRL] = INVALID_NOTE) +#define fluid_channel_legato(_c) ((_c)->cc[LEGATO_SWITCH] >= 64) #define fluid_channel_sustained(_c) ((_c)->cc[SUSTAIN_SWITCH] >= 64) #define fluid_channel_sostenuto(_c) ((_c)->cc[SOSTENUTO_SWITCH] >= 64) #define fluid_channel_set_gen(_c, _n, _v, _a) { (_c)->gen[_n] = _v; (_c)->gen_abs[_n] = _a; } @@ -146,4 +206,83 @@ int fluid_channel_get_interp_method(fluid_channel_t* chan); #define fluid_channel_get_min_note_length_ticks(chan) \ ((chan)->synth->min_note_length_ticks) +/* Macros interface to poly/mono mode variables */ +#define MASK_BASICCHANINFOS (FLUID_CHANNEL_MODE_MASK|FLUID_CHANNEL_BASIC|FLUID_CHANNEL_ENABLED) +/* Set the basic channel infos for a MIDI basic channel */ +#define fluid_channel_set_basic_channel_info(chan,Infos) \ + (chan->mode = (chan->mode & ~MASK_BASICCHANINFOS) | (Infos & MASK_BASICCHANINFOS)) +/* Reset the basic channel infos for a MIDI basic channel */ +#define fluid_channel_reset_basic_channel_info(chan) (chan->mode &= ~MASK_BASICCHANINFOS) + +/* Macros interface to breath variables */ +#define FLUID_CHANNEL_BREATH_MASK (FLUID_CHANNEL_BREATH_POLY|FLUID_CHANNEL_BREATH_MONO|FLUID_CHANNEL_BREATH_SYNC) +/* Set the breath infos for a MIDI channel */ +#define fluid_channel_set_breath_info(chan,BreathInfos) \ +(chan->mode = (chan->mode & ~FLUID_CHANNEL_BREATH_MASK) | (BreathInfos & FLUID_CHANNEL_BREATH_MASK)) +/* Get the breath infos for a MIDI channel */ +#define fluid_channel_get_breath_info(chan) (chan->mode & FLUID_CHANNEL_BREATH_MASK) + +/* Returns true when channel is mono or legato is on */ +#define fluid_channel_is_playing_mono(chan) ((chan->mode & FLUID_CHANNEL_POLY_OFF) ||\ + fluid_channel_legato(chan)) + +/* Macros interface to monophonic list variables */ +#define INVALID_NOTE (255) +/* Returns true when a note is a valid note */ +#define fluid_channel_is_valid_note(n) (n != INVALID_NOTE) +/* Marks prev_note as invalid. */ +#define fluid_channel_clear_prev_note(chan) (chan->prev_note = INVALID_NOTE) + +/* Returns the most recent note from i_last entry of the monophonic list */ +#define fluid_channel_last_note(chan) (chan->monolist[chan->i_last].note) + +/* Returns the most recent velocity from i_last entry of the monophonic list */ +#define fluid_channel_last_vel(chan) (chan->monolist[chan->i_last].vel) + +/* + prev_note is used to determine fromkey_portamento as well as + fromkey_legato (see fluid_synth_get_fromkey_portamento_legato()). + + prev_note is updated on noteOn/noteOff mono by the legato detector as this: + - On noteOn mono, before adding a new note into the monolist,the most + recent note in the list (i.e at i_last position) is kept in prev_note. + - Similarly, on noteOff mono , before removing a note out of the monolist, + the most recent note (i.e those at i_last position) is kept in prev_note. +*/ +#define fluid_channel_prev_note(chan) (chan->prev_note) + +/* Interface to poly/mono mode variables */ +enum fluid_channel_mode_flags_internal +{ + FLUID_CHANNEL_BASIC = 0x04, /**< if flag set the corresponding midi channel is a basic channel */ + FLUID_CHANNEL_ENABLED = 0x08, /**< if flag set the corresponding midi channel is enabled, else disabled, i.e. channel ignores any MIDI messages */ + + /* + FLUID_CHANNEL_LEGATO_PLAYING bit of channel mode keeps trace of the legato /staccato + state playing. + FLUID_CHANNEL_LEGATO_PLAYING bit is updated on noteOn/noteOff mono by the legato detector: + - On noteOn, before inserting a new note into the monolist. + - On noteOff, after removing a note out of the monolist. + + - On noteOn, this state is used by fluid_synth_noteon_mono_LOCAL() + to play the current note legato or staccato. + - On noteOff, this state is used by fluid_synth_noteoff_mono_LOCAL() + to play the current noteOff legato with the most recent note. + */ + /* bit7, 1: means legato playing , 0: means staccato playing */ + FLUID_CHANNEL_LEGATO_PLAYING = 0x80 +}; + +/* End of interface to monophonic list variables */ + +void fluid_channel_add_monolist(fluid_channel_t *chan, unsigned char key, unsigned char vel, unsigned char onenote); +int fluid_channel_search_monolist(fluid_channel_t *chan, unsigned char key, int *i_prev); +void fluid_channel_remove_monolist(fluid_channel_t *chan, int i, int *i_prev); +void fluid_channel_clear_monolist(fluid_channel_t *chan); +void fluid_channel_set_onenote_monolist(fluid_channel_t *chan, unsigned char key, unsigned char vel); +void fluid_channel_invalid_prev_note_staccato(fluid_channel_t *chan); +void fluid_channel_cc_legato(fluid_channel_t *chan, int value); +void fluid_channel_cc_breath_note_on_off(fluid_channel_t *chan, int value); + + #endif /* _FLUID_CHAN_H */ |