1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_channel.h - Audio Engine high level control abstraction
4 ---------------------------------------------------------------------------
5 * Copyright (C) 2001, 2002, David Olofson
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifndef _A_CHANNEL_H_
23 #define _A_CHANNEL_H_
24
25 #include "a_globals.h"
26 #include "a_types.h"
27 #include "a_voice.h"
28
29
30 /*----------------------------------------------------------
31 Audio Group (Abstraction for group control)
32 ----------------------------------------------------------*/
33 typedef struct audio_group_t
34 {
35 int changed;
36 accbank_t ctl;
37 } audio_group_t;
38
39
40 /*----------------------------------------------------------
41 Audio Channel (Abstraction for channel control)
42 ----------------------------------------------------------*/
43 typedef struct audio_channel_t
44 {
45 audio_voice_t *voices; /* For "real" voices only */
46
47 int playing; /* # of "voices" playing */
48 accbank_t rctl; /* Raw controls */
49 accbank_t ctl; /* Transformed controls */
50
51 /* Event Control */
52 aev_port_t port; /* Event input port */
53
54 patch_closure_t closure; /* Per-channel data for patch */
55 } audio_channel_t;
56
57
58 /*----------------------------------------------------------
59 Audio Channel Event Interface
60 ------------------------------------------------------------
61 * These events are passed through the channel management
62 * code of the engine, where they are transformed through
63 * the groups. Then they're passed on directly to the patch
64 * plugins for custom processing.
65 *
66 * Notes:
67 * * The rctl array (raw controls) is kept up to date
68 * by the engine.
69 *
70 * * The ctl array (transformed controls) must be
71 * updated by the patch plugin as it receives the
72 * corresponding events.
73 *
74 * * For things to work properly, patch plugins must
75 * remove all events for each frame processed.
76 *
77 * * Tags passed to CE_CONTROL[2] can be any positive
78 * value including 0. Negative values are reserved
79 * for special uses: -1 means "all voices", whereas
80 * -2 means "new voices only"; ie -2 will cause no
81 * other action than updating the channel control
82 * values.
83 */
84 typedef enum channel_events_t
85 {
86 CE_START = 0, /* arg1 = tag, arg2 = pitch, arg3 = velocity */
87 CE_STOP, /* arg1 = tag, arg2 = velocity */
88 CE_CONTROL /* arg1 = tag, index = ctl, arg2 = value */
89 } channel_events_t;
90
91
92 /*
93 * Inline interface for sending the above events...
94 */
95
ce_start_i(audio_channel_t * c,Uint16 delay,int tag,int pitch,int velocity)96 static inline aev_event_t *ce_start_i(audio_channel_t *c, Uint16 delay,
97 int tag, int pitch, int velocity)
98 {
99 aev_event_t *ev = aev_new();
100 if(!ev)
101 return NULL;
102 ev->type = CE_START;
103 ev->frame = delay + aev_timer;
104 ev->arg1 = tag;
105 ev->arg2 = pitch;
106 ev->arg3 = velocity;
107 aev_insert(&c->port, ev);
108 return ev;
109 }
110
ce_stop_i(audio_channel_t * c,Uint16 delay,int tag,int velocity)111 static inline aev_event_t *ce_stop_i(audio_channel_t *c, Uint16 delay,
112 int tag, int velocity)
113 {
114 aev_event_t *ev = aev_new();
115 if(!ev)
116 return NULL;
117 ev->type = CE_STOP;
118 ev->frame = delay + aev_timer;
119 ev->arg1 = tag;
120 ev->arg2 = velocity;
121 aev_insert(&c->port, ev);
122 return ev;
123 }
124
ce_control_i(audio_channel_t * c,Uint16 delay,int tag,Uint8 ctl,int value)125 static inline aev_event_t *ce_control_i(audio_channel_t *c, Uint16 delay,
126 int tag, Uint8 ctl, int value)
127 {
128 aev_event_t *ev = aev_new();
129 if(!ev)
130 return NULL;
131 ev->type = CE_CONTROL;
132 ev->frame = delay + aev_timer;
133 ev->arg1 = tag;
134 ev->index = ctl;
135 ev->arg2 = value;
136 aev_insert(&c->port, ev);
137 return ev;
138 }
139
140
141 /*
142 * Fast, non-sorting versions.
143 */
144
ce_start(audio_channel_t * c,Uint16 delay,int tag,int pitch,int velocity)145 static inline aev_event_t *ce_start(audio_channel_t *c, Uint16 delay,
146 int tag, int pitch, int velocity)
147 {
148 aev_event_t *ev = aev_new();
149 if(!ev)
150 return NULL;
151 ev->type = CE_START;
152 ev->frame = delay + aev_timer;
153 ev->arg1 = tag;
154 ev->arg2 = pitch;
155 ev->arg3 = velocity;
156 aev_write(&c->port, ev);
157 return ev;
158 }
159
ce_stop(audio_channel_t * c,Uint16 delay,int tag,int velocity)160 static inline aev_event_t *ce_stop(audio_channel_t *c, Uint16 delay,
161 int tag, int velocity)
162 {
163 aev_event_t *ev = aev_new();
164 if(!ev)
165 return NULL;
166 ev->type = CE_STOP;
167 ev->frame = delay + aev_timer;
168 ev->arg1 = tag;
169 ev->arg2 = velocity;
170 aev_write(&c->port, ev);
171 return ev;
172 }
173
ce_control(audio_channel_t * c,Uint16 delay,int tag,Uint8 ctl,int value)174 static inline aev_event_t *ce_control(audio_channel_t *c, Uint16 delay,
175 int tag, Uint8 ctl, int value)
176 {
177 aev_event_t *ev = aev_new();
178 if(!ev)
179 return NULL;
180 ev->type = CE_CONTROL;
181 ev->frame = delay + aev_timer;
182 ev->arg1 = tag;
183 ev->index = ctl;
184 ev->arg2 = value;
185 aev_write(&c->port, ev);
186 return ev;
187 }
188
189
190 /*
191 * Brutally stop all voices on all channels.
192 *
193 * (Obviously, any other method is better - short of
194 * crashing the engine, perhaps... ;-)
195 */
196 void channel_stop_all(void);
197
198
199 /*
200 * Process events and patch plugins for all channels.
201 */
202 void channel_process_all(unsigned frames);
203
204 void audio_channel_open(void);
205 void audio_channel_close(void);
206
207
208 /*----------------------------------------------------------
209 Voice allocation stuff
210 ----------------------------------------------------------*/
211
212 /* Link voice 'v' to channel 'c'. */
chan_link_voice(audio_channel_t * c,audio_voice_t * v)213 static inline void chan_link_voice(audio_channel_t *c, audio_voice_t *v)
214 {
215 v->next = c->voices;
216 if(v->next)
217 v->next->prev = v;
218 v->prev = NULL;
219 v->channel = c;
220 c->voices = v;
221 }
222
223 /* Unlink voice 'v' from channel 'c'. */
chan_unlink_voice(audio_voice_t * v)224 static inline void chan_unlink_voice(audio_voice_t *v)
225 {
226 if(v->prev)
227 {
228 v->prev->next = v->next;
229 if(v->next)
230 v->next->prev = v->prev;
231 }
232 else
233 {
234 v->channel->voices = v->next;
235 if(v->next)
236 v->next->prev = NULL;
237 }
238 v->channel = NULL;
239 }
240
chan_get_first_voice(audio_channel_t * c)241 static inline audio_voice_t *chan_get_first_voice(audio_channel_t *c)
242 {
243 return c->voices;
244 }
245
chan_get_next_voice(audio_voice_t * v)246 static inline audio_voice_t *chan_get_next_voice(audio_voice_t *v)
247 {
248 return v->next;
249 }
250
251 #endif /*_A_CHANNEL_H_*/
252