Path: blob/master/libs/fluidsynth/src/rvoice/fluid_rvoice_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*/1920#include "fluid_rvoice_event.h"21#include "fluid_rvoice.h"22#include "fluid_rvoice_mixer.h"23#include "fluid_iir_filter.h"24#include "fluid_lfo.h"25#include "fluid_adsr_env.h"2627static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event);2829static FLUID_INLINE void30fluid_rvoice_event_dispatch(fluid_rvoice_event_t *event)31{32event->method(event->object, event->param);33}343536/**37* In order to be able to push more than one event atomically,38* use push for all events, then use flush to commit them to the39* queue. If threadsafe is false, all events are processed immediately. */40int41fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t *handler,42fluid_rvoice_function_t method, void *object, int intparam,43fluid_real_t realparam)44{45fluid_rvoice_event_t local_event;4647local_event.method = method;48local_event.object = object;49local_event.param[0].i = intparam;50local_event.param[1].real = realparam;5152return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);53}5455int56fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t *handler, fluid_rvoice_function_t method, void *object, fluid_rvoice_param_t param[MAX_EVENT_PARAMS])57{58fluid_rvoice_event_t local_event;5960local_event.method = method;61local_event.object = object;62FLUID_MEMCPY(&local_event.param, param, sizeof(*param) * MAX_EVENT_PARAMS);6364return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);65}6667int68fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t *handler,69fluid_rvoice_function_t method, void *object, void *ptr)70{71fluid_rvoice_event_t local_event;7273local_event.method = method;74local_event.object = object;75local_event.param[0].ptr = ptr;7677return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);78}7980static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event)81{82fluid_rvoice_event_t *event;83int old_queue_stored = fluid_atomic_int_add(&handler->queue_stored, 1);8485event = fluid_ringbuffer_get_inptr(handler->queue, old_queue_stored);8687if(event == NULL)88{89fluid_atomic_int_add(&handler->queue_stored, -1);90FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing synth.polyphony!");91return FLUID_FAILED; // Buffer full...92}9394FLUID_MEMCPY(event, src_event, sizeof(*event));9596return FLUID_OK;97}9899100void101fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t *eventhandler, fluid_rvoice_t *rvoice)102{103fluid_rvoice_t **vptr = fluid_ringbuffer_get_inptr(eventhandler->finished_voices, 0);104105if(vptr == NULL)106{107return; // Buffer full108}109110*vptr = rvoice;111fluid_ringbuffer_next_inptr(eventhandler->finished_voices, 1);112}113114fluid_rvoice_eventhandler_t *115new_fluid_rvoice_eventhandler(int queuesize,116int finished_voices_size, int bufs, int fx_bufs, int fx_units,117fluid_real_t sample_rate_max, fluid_real_t sample_rate,118int extra_threads, int prio)119{120fluid_rvoice_eventhandler_t *eventhandler = FLUID_NEW(fluid_rvoice_eventhandler_t);121122if(eventhandler == NULL)123{124FLUID_LOG(FLUID_ERR, "Out of memory");125return NULL;126}127128eventhandler->mixer = NULL;129eventhandler->queue = NULL;130eventhandler->finished_voices = NULL;131132fluid_atomic_int_set(&eventhandler->queue_stored, 0);133134eventhandler->finished_voices = new_fluid_ringbuffer(finished_voices_size,135sizeof(fluid_rvoice_t *));136137if(eventhandler->finished_voices == NULL)138{139goto error_recovery;140}141142eventhandler->queue = new_fluid_ringbuffer(queuesize, sizeof(fluid_rvoice_event_t));143144if(eventhandler->queue == NULL)145{146goto error_recovery;147}148149eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, fx_units,150sample_rate_max, sample_rate, eventhandler, extra_threads, prio);151152if(eventhandler->mixer == NULL)153{154goto error_recovery;155}156157return eventhandler;158159error_recovery:160delete_fluid_rvoice_eventhandler(eventhandler);161return NULL;162}163164int165fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t *handler)166{167return fluid_ringbuffer_get_count(handler->queue);168}169170171/**172* Call fluid_rvoice_event_dispatch for all events in queue173* @return number of events dispatched174*/175int176fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t *handler)177{178fluid_rvoice_event_t *event;179int result = 0;180181while(NULL != (event = fluid_ringbuffer_get_outptr(handler->queue)))182{183fluid_rvoice_event_dispatch(event);184result++;185fluid_ringbuffer_next_outptr(handler->queue);186}187188return result;189}190191192void193delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t *handler)194{195fluid_return_if_fail(handler != NULL);196197delete_fluid_rvoice_mixer(handler->mixer);198delete_fluid_ringbuffer(handler->queue);199delete_fluid_ringbuffer(handler->finished_voices);200FLUID_FREE(handler);201}202203204