Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/fluidsynth/src/rvoice/fluid_rvoice_event.c
4396 views
1
/* FluidSynth - A Software Synthesizer
2
*
3
* Copyright (C) 2003 Peter Hanappe and others.
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public License
7
* as published by the Free Software Foundation; either version 2.1 of
8
* the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
* 02110-1301, USA
19
*/
20
21
#include "fluid_rvoice_event.h"
22
#include "fluid_rvoice.h"
23
#include "fluid_rvoice_mixer.h"
24
#include "fluid_iir_filter.h"
25
#include "fluid_lfo.h"
26
#include "fluid_adsr_env.h"
27
28
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event);
29
30
static FLUID_INLINE void
31
fluid_rvoice_event_dispatch(fluid_rvoice_event_t *event)
32
{
33
event->method(event->object, event->param);
34
}
35
36
37
/**
38
* In order to be able to push more than one event atomically,
39
* use push for all events, then use flush to commit them to the
40
* queue. If threadsafe is false, all events are processed immediately. */
41
int
42
fluid_rvoice_eventhandler_push_int_real(fluid_rvoice_eventhandler_t *handler,
43
fluid_rvoice_function_t method, void *object, int intparam,
44
fluid_real_t realparam)
45
{
46
fluid_rvoice_event_t local_event;
47
48
local_event.method = method;
49
local_event.object = object;
50
local_event.param[0].i = intparam;
51
local_event.param[1].real = realparam;
52
53
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
54
}
55
56
int
57
fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t *handler, fluid_rvoice_function_t method, void *object, fluid_rvoice_param_t param[MAX_EVENT_PARAMS])
58
{
59
fluid_rvoice_event_t local_event;
60
61
local_event.method = method;
62
local_event.object = object;
63
FLUID_MEMCPY(&local_event.param, param, sizeof(*param) * MAX_EVENT_PARAMS);
64
65
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
66
}
67
68
int
69
fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t *handler,
70
fluid_rvoice_function_t method, void *object, void *ptr)
71
{
72
fluid_rvoice_event_t local_event;
73
74
local_event.method = method;
75
local_event.object = object;
76
local_event.param[0].ptr = ptr;
77
78
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
79
}
80
81
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t *handler, const fluid_rvoice_event_t *src_event)
82
{
83
fluid_rvoice_event_t *event;
84
int old_queue_stored = fluid_atomic_int_add(&handler->queue_stored, 1);
85
86
event = fluid_ringbuffer_get_inptr(handler->queue, old_queue_stored);
87
88
if(event == NULL)
89
{
90
fluid_atomic_int_add(&handler->queue_stored, -1);
91
FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing synth.polyphony!");
92
return FLUID_FAILED; // Buffer full...
93
}
94
95
FLUID_MEMCPY(event, src_event, sizeof(*event));
96
97
return FLUID_OK;
98
}
99
100
101
void
102
fluid_rvoice_eventhandler_finished_voice_callback(fluid_rvoice_eventhandler_t *eventhandler, fluid_rvoice_t *rvoice)
103
{
104
fluid_rvoice_t **vptr = fluid_ringbuffer_get_inptr(eventhandler->finished_voices, 0);
105
106
if(vptr == NULL)
107
{
108
return; // Buffer full
109
}
110
111
*vptr = rvoice;
112
fluid_ringbuffer_next_inptr(eventhandler->finished_voices, 1);
113
}
114
115
fluid_rvoice_eventhandler_t *
116
new_fluid_rvoice_eventhandler(int queuesize,
117
int finished_voices_size, int bufs, int fx_bufs, int fx_units,
118
fluid_real_t sample_rate_max, fluid_real_t sample_rate,
119
int extra_threads, int prio)
120
{
121
fluid_rvoice_eventhandler_t *eventhandler = FLUID_NEW(fluid_rvoice_eventhandler_t);
122
123
if(eventhandler == NULL)
124
{
125
FLUID_LOG(FLUID_ERR, "Out of memory");
126
return NULL;
127
}
128
129
eventhandler->mixer = NULL;
130
eventhandler->queue = NULL;
131
eventhandler->finished_voices = NULL;
132
133
fluid_atomic_int_set(&eventhandler->queue_stored, 0);
134
135
eventhandler->finished_voices = new_fluid_ringbuffer(finished_voices_size,
136
sizeof(fluid_rvoice_t *));
137
138
if(eventhandler->finished_voices == NULL)
139
{
140
goto error_recovery;
141
}
142
143
eventhandler->queue = new_fluid_ringbuffer(queuesize, sizeof(fluid_rvoice_event_t));
144
145
if(eventhandler->queue == NULL)
146
{
147
goto error_recovery;
148
}
149
150
eventhandler->mixer = new_fluid_rvoice_mixer(bufs, fx_bufs, fx_units,
151
sample_rate_max, sample_rate, eventhandler, extra_threads, prio);
152
153
if(eventhandler->mixer == NULL)
154
{
155
goto error_recovery;
156
}
157
158
return eventhandler;
159
160
error_recovery:
161
delete_fluid_rvoice_eventhandler(eventhandler);
162
return NULL;
163
}
164
165
int
166
fluid_rvoice_eventhandler_dispatch_count(fluid_rvoice_eventhandler_t *handler)
167
{
168
return fluid_ringbuffer_get_count(handler->queue);
169
}
170
171
172
/**
173
* Call fluid_rvoice_event_dispatch for all events in queue
174
* @return number of events dispatched
175
*/
176
int
177
fluid_rvoice_eventhandler_dispatch_all(fluid_rvoice_eventhandler_t *handler)
178
{
179
fluid_rvoice_event_t *event;
180
int result = 0;
181
182
while(NULL != (event = fluid_ringbuffer_get_outptr(handler->queue)))
183
{
184
fluid_rvoice_event_dispatch(event);
185
result++;
186
fluid_ringbuffer_next_outptr(handler->queue);
187
}
188
189
return result;
190
}
191
192
193
void
194
delete_fluid_rvoice_eventhandler(fluid_rvoice_eventhandler_t *handler)
195
{
196
fluid_return_if_fail(handler != NULL);
197
198
delete_fluid_rvoice_mixer(handler->mixer);
199
delete_fluid_ringbuffer(handler->queue);
200
delete_fluid_ringbuffer(handler->finished_voices);
201
FLUID_FREE(handler);
202
}
203
204