Path: blob/master/libs/fluidsynth/src/synth/fluid_event.c
4396 views
/* FluidSynth - A Software Synthesizer1*2* Copyright (C) 2003 Peter Hanappe and others.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public License6* as published by the Free Software Foundation; either version 2.1 of7* the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful, but10* WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* You should have received a copy of the GNU Lesser General Public15* License along with this library; if not, write to the Free16* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA17* 02110-1301, USA18*/192021/*222002 : API design by Peter Hanappe and Antoine Schmitt23August 2002 : Implementation by Antoine Schmitt [email protected]24as part of the infiniteCD author project25http://www.infiniteCD.org/26Oct4.2002 : AS : corrected bug in heap allocation, that caused a crash during sequencer free.27*/282930#include "fluid_event.h"31#include "fluidsynth_priv.h"32#include "fluid_midi.h"3334/***************************************************************35*36* SEQUENCER EVENTS37*/3839/* Event alloc/free */4041void42fluid_event_clear(fluid_event_t *evt)43{44FLUID_MEMSET(evt, 0, sizeof(fluid_event_t));4546// by default, no type47evt->dest = -1;48evt->src = -1;49evt->type = -1;50evt->id = -1;51}5253/**54* Create a new sequencer event structure.55* @return New sequencer event structure or NULL if out of memory56*/57fluid_event_t *58new_fluid_event(void)59{60fluid_event_t *evt;6162evt = FLUID_NEW(fluid_event_t);6364if(evt == NULL)65{66FLUID_LOG(FLUID_PANIC, "event: Out of memory\n");67return NULL;68}6970fluid_event_clear(evt);7172return(evt);73}7475/**76* Delete a sequencer event structure.77* @param evt Sequencer event structure created by new_fluid_event().78*/79void80delete_fluid_event(fluid_event_t *evt)81{82fluid_return_if_fail(evt != NULL);8384FLUID_FREE(evt);85}8687/**88* Set the time field of a sequencer event.89* @internal90* @param evt Sequencer event structure91* @param time Time value to assign92*/93void94fluid_event_set_time(fluid_event_t *evt, unsigned int time)95{96evt->time = time;97}9899void100fluid_event_set_id(fluid_event_t *evt, fluid_note_id_t id)101{102evt->id = id;103}104105/**106* Set source of a sequencer event. \c src must be a unique sequencer ID or -1 if not set.107* @param evt Sequencer event structure108* @param src Unique sequencer ID109*/110void111fluid_event_set_source(fluid_event_t *evt, fluid_seq_id_t src)112{113evt->src = src;114}115116/**117* Set destination of this sequencer event, i.e. the sequencer client this event will be sent to. \c dest must be a unique sequencer ID.118* @param evt Sequencer event structure119* @param dest The destination unique sequencer ID120*/121void122fluid_event_set_dest(fluid_event_t *evt, fluid_seq_id_t dest)123{124evt->dest = dest;125}126127/**128* Set a sequencer event to be a timer event.129* @param evt Sequencer event structure130* @param data User supplied data pointer131*/132void133fluid_event_timer(fluid_event_t *evt, void *data)134{135evt->type = FLUID_SEQ_TIMER;136evt->data = data;137}138139/**140* Set a sequencer event to be a note on event.141* @param evt Sequencer event structure142* @param channel MIDI channel number143* @param key MIDI note number (0-127)144* @param vel MIDI velocity value (0-127)145* @note Since fluidsynth 2.2.2, this function will give you a #FLUID_SEQ_NOTEOFF when146* called with @p vel being zero.147*/148void149fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel)150{151if(vel == 0)152{153fluid_event_noteoff(evt, channel, key);154return;155}156157evt->type = FLUID_SEQ_NOTEON;158evt->channel = channel;159evt->key = key;160evt->vel = vel;161}162163/**164* Set a sequencer event to be a note off event.165* @param evt Sequencer event structure166* @param channel MIDI channel number167* @param key MIDI note number (0-127)168*/169void170fluid_event_noteoff(fluid_event_t *evt, int channel, short key)171{172evt->type = FLUID_SEQ_NOTEOFF;173evt->channel = channel;174evt->key = key;175}176177/**178* Set a sequencer event to be a note duration event.179*180* Before fluidsynth 2.2.0, this event type was naively implemented when used in conjunction with fluid_sequencer_register_fluidsynth(),181* because it simply enqueued a fluid_event_noteon() and fluid_event_noteoff().182* A handling for overlapping notes was not implemented. Starting with 2.2.0, this changes: If a fluid_event_note() is already playing,183* while another fluid_event_note() arrives on the same @c channel and @c key, the earlier event will be canceled.184* @param evt Sequencer event structure185* @param channel MIDI channel number186* @param key MIDI note number (0-127)187* @param vel MIDI velocity value (1-127)188* @param duration Duration of note in the time scale used by the sequencer189*190* @note The application should decide whether to use only Notes with duration, or separate NoteOn and NoteOff events.191* @warning Calling this function with @p vel or @p duration being zero results in undefined behavior!192*/193void194fluid_event_note(fluid_event_t *evt, int channel, short key, short vel, unsigned int duration)195{196evt->type = FLUID_SEQ_NOTE;197evt->channel = channel;198evt->key = key;199evt->vel = vel;200evt->duration = duration;201}202203/**204* Set a sequencer event to be an all sounds off event.205* @param evt Sequencer event structure206* @param channel MIDI channel number207*/208void209fluid_event_all_sounds_off(fluid_event_t *evt, int channel)210{211evt->type = FLUID_SEQ_ALLSOUNDSOFF;212evt->channel = channel;213}214215/**216* Set a sequencer event to be a all notes off event.217* @param evt Sequencer event structure218* @param channel MIDI channel number219*/220void221fluid_event_all_notes_off(fluid_event_t *evt, int channel)222{223evt->type = FLUID_SEQ_ALLNOTESOFF;224evt->channel = channel;225}226227/**228* Set a sequencer event to be a bank select event.229* @param evt Sequencer event structure230* @param channel MIDI channel number231* @param bank_num MIDI bank number (0-16383)232*/233void234fluid_event_bank_select(fluid_event_t *evt, int channel, short bank_num)235{236evt->type = FLUID_SEQ_BANKSELECT;237evt->channel = channel;238evt->control = bank_num;239}240241/**242* Set a sequencer event to be a program change event.243* @param evt Sequencer event structure244* @param channel MIDI channel number245* @param val MIDI program number (0-127)246*/247void248fluid_event_program_change(fluid_event_t *evt, int channel, int val)249{250evt->type = FLUID_SEQ_PROGRAMCHANGE;251evt->channel = channel;252evt->value = val;253}254255/**256* Set a sequencer event to be a program select event.257* @param evt Sequencer event structure258* @param channel MIDI channel number259* @param sfont_id SoundFont ID number260* @param bank_num MIDI bank number (0-16383)261* @param preset_num MIDI preset number (0-127)262*/263void264fluid_event_program_select(fluid_event_t *evt, int channel,265unsigned int sfont_id, short bank_num, short preset_num)266{267evt->type = FLUID_SEQ_PROGRAMSELECT;268evt->channel = channel;269evt->duration = sfont_id;270evt->value = preset_num;271evt->control = bank_num;272}273274/**275* Set a sequencer event to be a pitch bend event.276* @param evt Sequencer event structure277* @param channel MIDI channel number278* @param pitch MIDI pitch bend value (0-16383, 8192 = no bend)279*/280void281fluid_event_pitch_bend(fluid_event_t *evt, int channel, int pitch)282{283evt->type = FLUID_SEQ_PITCHBEND;284evt->channel = channel;285286if(pitch < 0)287{288pitch = 0;289}290291if(pitch > 16383)292{293pitch = 16383;294}295296evt->pitch = pitch;297}298299/**300* Set a sequencer event to be a pitch wheel sensitivity event.301* @param evt Sequencer event structure302* @param channel MIDI channel number303* @param value MIDI pitch wheel sensitivity value in semitones304*/305void306fluid_event_pitch_wheelsens(fluid_event_t *evt, int channel, int value)307{308evt->type = FLUID_SEQ_PITCHWHEELSENS;309evt->channel = channel;310evt->value = value;311}312313/**314* Set a sequencer event to be a modulation event.315* @param evt Sequencer event structure316* @param channel MIDI channel number317* @param val MIDI modulation value (0-127)318*/319void320fluid_event_modulation(fluid_event_t *evt, int channel, int val)321{322evt->type = FLUID_SEQ_MODULATION;323evt->channel = channel;324325if(val < 0)326{327val = 0;328}329330if(val > 127)331{332val = 127;333}334335evt->value = val;336}337338/**339* Set a sequencer event to be a MIDI sustain event.340* @param evt Sequencer event structure341* @param channel MIDI channel number342* @param val MIDI sustain value (0-127)343*/344void345fluid_event_sustain(fluid_event_t *evt, int channel, int val)346{347evt->type = FLUID_SEQ_SUSTAIN;348evt->channel = channel;349350if(val < 0)351{352val = 0;353}354355if(val > 127)356{357val = 127;358}359360evt->value = val;361}362363/**364* Set a sequencer event to be a MIDI control change event.365* @param evt Sequencer event structure366* @param channel MIDI channel number367* @param control MIDI control number (0-127)368* @param val MIDI control value (0-127)369*/370void371fluid_event_control_change(fluid_event_t *evt, int channel, short control, int val)372{373evt->type = FLUID_SEQ_CONTROLCHANGE;374evt->channel = channel;375evt->control = control;376evt->value = val;377}378379/**380* Set a sequencer event to be a stereo pan event.381* @param evt Sequencer event structure382* @param channel MIDI channel number383* @param val MIDI panning value (0-127, 0=left, 64 = middle, 127 = right)384*/385void386fluid_event_pan(fluid_event_t *evt, int channel, int val)387{388evt->type = FLUID_SEQ_PAN;389evt->channel = channel;390391if(val < 0)392{393val = 0;394}395396if(val > 127)397{398val = 127;399}400401evt->value = val;402}403404/**405* Set a sequencer event to be a volume event.406* @param evt Sequencer event structure407* @param channel MIDI channel number408* @param val Volume value (0-127)409*/410void411fluid_event_volume(fluid_event_t *evt, int channel, int val)412{413evt->type = FLUID_SEQ_VOLUME;414evt->channel = channel;415416if(val < 0)417{418val = 0;419}420421if(val > 127)422{423val = 127;424}425426evt->value = val;427}428429/**430* Set a sequencer event to be a reverb send event.431* @param evt Sequencer event structure432* @param channel MIDI channel number433* @param val Reverb amount (0-127)434*/435void436fluid_event_reverb_send(fluid_event_t *evt, int channel, int val)437{438evt->type = FLUID_SEQ_REVERBSEND;439evt->channel = channel;440441if(val < 0)442{443val = 0;444}445446if(val > 127)447{448val = 127;449}450451evt->value = val;452}453454/**455* Set a sequencer event to be a chorus send event.456* @param evt Sequencer event structure457* @param channel MIDI channel number458* @param val Chorus amount (0-127)459*/460void461fluid_event_chorus_send(fluid_event_t *evt, int channel, int val)462{463evt->type = FLUID_SEQ_CHORUSSEND;464evt->channel = channel;465466if(val < 0)467{468val = 0;469}470471if(val > 127)472{473val = 127;474}475476evt->value = val;477}478479480/**481* Set a sequencer event to be an unregistering event.482* @param evt Sequencer event structure483* @since 1.1.0484*/485void486fluid_event_unregistering(fluid_event_t *evt)487{488evt->type = FLUID_SEQ_UNREGISTERING;489}490491/**492* Set a sequencer event to be a scale change event.493* Useful for scheduling tempo changes.494* @param evt Sequencer event structure495* @param new_scale The new time scale to apply to the sequencer, see fluid_sequencer_set_time_scale()496* @since 2.2.0497*/498void499fluid_event_scale(fluid_event_t *evt, double new_scale)500{501evt->type = FLUID_SEQ_SCALE;502evt->scale = new_scale;503}504505/**506* Set a sequencer event to be a channel-wide aftertouch event.507* @param evt Sequencer event structure508* @param channel MIDI channel number509* @param val Aftertouch amount (0-127)510* @since 1.1.0511*/512void513fluid_event_channel_pressure(fluid_event_t *evt, int channel, int val)514{515evt->type = FLUID_SEQ_CHANNELPRESSURE;516evt->channel = channel;517518if(val < 0)519{520val = 0;521}522523if(val > 127)524{525val = 127;526}527528evt->value = val;529}530531/**532* Set a sequencer event to be a polyphonic aftertouch event.533* @param evt Sequencer event structure534* @param channel MIDI channel number535* @param key MIDI note number (0-127)536* @param val Aftertouch amount (0-127)537* @since 2.0.0538*/539void540fluid_event_key_pressure(fluid_event_t *evt, int channel, short key, int val)541{542evt->type = FLUID_SEQ_KEYPRESSURE;543evt->channel = channel;544545if(key < 0)546{547key = 0;548}549550if(key > 127)551{552key = 127;553}554555if(val < 0)556{557val = 0;558}559560if(val > 127)561{562val = 127;563}564565evt->key = key;566evt->value = val;567}568569/**570* Set a sequencer event to be a midi system reset event.571* @param evt Sequencer event structure572* @since 1.1.0573*/574void575fluid_event_system_reset(fluid_event_t *evt)576{577evt->type = FLUID_SEQ_SYSTEMRESET;578}579580/**581* Transforms an incoming MIDI event (from a MIDI driver or MIDI router) to a582* sequencer event.583*584* @param evt Sequencer event structure585* @param event MIDI event586* @return #FLUID_OK or #FLUID_FAILED587*588* @note This function copies the fields of the MIDI event into the provided589* sequencer event. Calling applications must create the sequencer event and set590* additional fields such as the source and destination of the sequencer event.591*592* @code{.cpp}593* // ... get MIDI event, e.g. using player_callback()594*595* // Send MIDI event to sequencer to play596* fluid_event_t *evt = new_fluid_event();597* fluid_event_set_source(evt, -1);598* fluid_event_set_dest(evt, seqid);599* fluid_event_from_midi_event(evt, event);600* fluid_sequencer_send_at(sequencer, evt, 50, 0); // relative time601* delete_fluid_event(evt);602* @endcode603*604* @since 2.2.7605*/606int fluid_event_from_midi_event(fluid_event_t *evt, const fluid_midi_event_t *event)607{608int chan;609fluid_return_val_if_fail(event != NULL, FLUID_FAILED);610611chan = fluid_midi_event_get_channel(event);612613switch (fluid_midi_event_get_type(event))614{615case NOTE_OFF:616fluid_event_noteoff(evt, chan, (short)fluid_midi_event_get_key(event));617break;618619case NOTE_ON:620fluid_event_noteon(evt,621fluid_midi_event_get_channel(event),622(short)fluid_midi_event_get_key(event),623(short)fluid_midi_event_get_velocity(event));624break;625626case CONTROL_CHANGE:627fluid_event_control_change(evt,628chan,629(short)fluid_midi_event_get_control(event),630(short)fluid_midi_event_get_value(event));631break;632633case PROGRAM_CHANGE:634fluid_event_program_change(evt, chan, (short)fluid_midi_event_get_program(event));635break;636637case PITCH_BEND:638fluid_event_pitch_bend(evt, chan, fluid_midi_event_get_pitch(event));639break;640641case CHANNEL_PRESSURE:642fluid_event_channel_pressure(evt, chan, (short)fluid_midi_event_get_program(event));643break;644645case KEY_PRESSURE:646fluid_event_key_pressure(evt,647chan,648(short)fluid_midi_event_get_key(event),649(short)fluid_midi_event_get_value(event));650break;651652case MIDI_SYSTEM_RESET:653fluid_event_system_reset(evt);654break;655656default: /* Not yet implemented */657return FLUID_FAILED;658}659660return FLUID_OK;661}662663/*664* Accessing event data665*/666667/**668* Get the event type (#fluid_seq_event_type) field from a sequencer event structure.669* @param evt Sequencer event structure670* @return Event type (#fluid_seq_event_type).671*/672int fluid_event_get_type(fluid_event_t *evt)673{674return evt->type;675}676677/**678* @internal679* Get the time field from a sequencer event structure.680* @param evt Sequencer event structure681* @return Time value682*/683unsigned int fluid_event_get_time(fluid_event_t *evt)684{685return evt->time;686}687688/**689* @internal690* Get the time field from a sequencer event structure.691* @param evt Sequencer event structure692* @return Time value693*/694fluid_note_id_t fluid_event_get_id(fluid_event_t *evt)695{696return evt->id;697}698699/**700* Get the source sequencer client from a sequencer event structure.701* @param evt Sequencer event structure702* @return source field of the sequencer event703*/704fluid_seq_id_t fluid_event_get_source(fluid_event_t *evt)705{706return evt->src;707}708709/**710* Get the dest sequencer client from a sequencer event structure.711* @param evt Sequencer event structure712* @return dest field of the sequencer event713*/714fluid_seq_id_t fluid_event_get_dest(fluid_event_t *evt)715{716return evt->dest;717}718719/**720* Get the MIDI channel field from a sequencer event structure.721* @param evt Sequencer event structure722* @return MIDI zero-based channel number723*/724int fluid_event_get_channel(fluid_event_t *evt)725{726return evt->channel;727}728729/**730* Get the MIDI note field from a sequencer event structure.731* @param evt Sequencer event structure732* @return MIDI note number (0-127)733*/734short fluid_event_get_key(fluid_event_t *evt)735{736return evt->key;737}738739/**740* Get the MIDI velocity field from a sequencer event structure.741* @param evt Sequencer event structure742* @return MIDI velocity value (0-127)743*/744short fluid_event_get_velocity(fluid_event_t *evt)745746{747return evt->vel;748}749750/**751* Get the MIDI control number field from a sequencer event structure.752* @param evt Sequencer event structure753* @return MIDI control number (0-127)754*/755short fluid_event_get_control(fluid_event_t *evt)756{757return evt->control;758}759760/**761* Get the value field from a sequencer event structure.762* @param evt Sequencer event structure763* @return Value field of event.764*765* The Value field is used by the following event types:766* #FLUID_SEQ_PROGRAMCHANGE, #FLUID_SEQ_PROGRAMSELECT (preset_num),767* #FLUID_SEQ_PITCHWHEELSENS, #FLUID_SEQ_MODULATION, #FLUID_SEQ_SUSTAIN,768* #FLUID_SEQ_CONTROLCHANGE, #FLUID_SEQ_PAN, #FLUID_SEQ_VOLUME,769* #FLUID_SEQ_REVERBSEND, #FLUID_SEQ_CHORUSSEND.770*/771int fluid_event_get_value(fluid_event_t *evt)772{773return evt->value;774}775776/**777* Get the data field from a sequencer event structure.778* @param evt Sequencer event structure779* @return Data field of event.780*781* Used by the #FLUID_SEQ_TIMER event type.782*/783void *fluid_event_get_data(fluid_event_t *evt)784{785return evt->data;786}787788/**789* Get the duration field from a sequencer event structure.790* @param evt Sequencer event structure791* @return Note duration value in the time scale used by the sequencer (by default milliseconds)792*793* Used by the #FLUID_SEQ_NOTE event type.794*/795unsigned int fluid_event_get_duration(fluid_event_t *evt)796{797return evt->duration;798}799800/**801* Get the MIDI bank field from a sequencer event structure.802* @param evt Sequencer event structure803* @return MIDI bank number (0-16383)804*805* Used by the #FLUID_SEQ_BANKSELECT and #FLUID_SEQ_PROGRAMSELECT806* event types.807*/808short fluid_event_get_bank(fluid_event_t *evt)809{810return evt->control;811}812813/**814* Get the pitch field from a sequencer event structure.815* @param evt Sequencer event structure816* @return MIDI pitch bend pitch value (0-16383, 8192 = no bend)817*818* Used by the #FLUID_SEQ_PITCHBEND event type.819*/820int fluid_event_get_pitch(fluid_event_t *evt)821{822return evt->pitch;823}824825/**826* Get the MIDI program field from a sequencer event structure.827* @param evt Sequencer event structure828* @return MIDI program number (0-127)829*830* Used by the #FLUID_SEQ_PROGRAMCHANGE and #FLUID_SEQ_PROGRAMSELECT831* event types.832*/833int834fluid_event_get_program(fluid_event_t *evt)835{836return evt->value;837}838839/**840* Get the SoundFont ID field from a sequencer event structure.841* @param evt Sequencer event structure842* @return SoundFont identifier value.843*844* Used by the #FLUID_SEQ_PROGRAMSELECT event type.845*/846unsigned int847fluid_event_get_sfont_id(fluid_event_t *evt)848{849return evt->duration;850}851852/**853* Gets time scale field from a sequencer event structure.854* @param evt Sequencer event structure855* @return SoundFont identifier value.856*857* Used by the #FLUID_SEQ_SCALE event type.858*/859double fluid_event_get_scale(fluid_event_t *evt)860{861return evt->scale;862}863864865