1 /*(LGPL)
2 ---------------------------------------------------------------------------
3 a_bus.c - Audio Engine bus
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 #include <stdlib.h>
23 #include <string.h>
24 #include "a_bus.h"
25 #include "a_struct.h"
26 #include "a_delay.h"
27 #include "a_tools.h"
28
29 #define BDBG(x)
30
31
__bus_run_fx(int bus,int slot,int * busses[],unsigned frames)32 static inline int __bus_run_fx(int bus, int slot, int *busses[], unsigned frames)
33 {
34 audio_bus_t *b = &bustab[bus];
35 --slot; /* No IFX on slot 0! */
36 switch(b->insert[slot].current_state)
37 {
38 case FX_STATE_RUNNING:
39 case FX_STATE_SILENT:
40 case FX_STATE_RESTING:
41 if(b->in_use) /* Do we have input? */
42 b->insert[slot].process(&b->insert[slot],
43 busses[bus], frames);
44 else
45 {
46 b->insert[slot].process_r(&b->insert[slot],
47 NULL, busses[bus], frames);
48 b->in_use = 1;
49 }
50 /* Check if the plugin actually produced valid output! */
51 return (FX_STATE_RUNNING == b->insert[slot].current_state);
52 default:
53 /* No plugin, or plugin not running. */
54 return 0;
55 }
56 }
57
58
__bus_process(int bus,int * busses[],int * master,unsigned frames)59 static inline void __bus_process(int bus, int *busses[], int *master, unsigned frames)
60 {
61 audio_bus_t *b = &bustab[bus];
62 int i, s;
63
64 /* Tail detection hack for the DC supression filter... */
65 if(!b->in_use)
66 if(!dcf6s_silent(&b->dcfilter))
67 {
68 b->in_use = 1;
69 s32clear(busses[bus], frames);
70 }
71
72 if(b->in_use) /* Only if we actually have input! */
73 {
74 /* DC suppression filter */
75 dcf6s_process(&b->dcfilter, busses[bus], frames);
76
77 /* Mix pre-insert sends */
78 s32mix(busses[bus], master, b->bctl[0][ABC_SEND_MASTER], frames);
79 for(i = bus + 1; i < AUDIO_MAX_BUSSES; ++i)
80 if(s32mix(busses[bus], busses[i],
81 b->bctl[0][ABC_SEND_BUS_0 + i],
82 frames))
83 bustab[i].in_use = 1;
84 }
85
86 /* Mix post-insert sends */
87 for(s = 1; s <= AUDIO_MAX_INSERTS; ++s)
88 {
89 /* Run the insert */
90 if(!__bus_run_fx(bus, s, busses, frames))
91 continue; /* No output, no sends! */
92
93 s32mix(busses[bus], master, b->bctl[s][ABC_SEND_MASTER], frames);
94 for(i = bus + 1; i < AUDIO_MAX_BUSSES; ++i)
95 if(s32mix(busses[bus], busses[i],
96 b->bctl[s][ABC_SEND_BUS_0 + i],
97 frames))
98 bustab[i].in_use = 1;
99 }
100
101 /* Prepare for the next engine cycle */
102 if(b->in_use)
103 {
104 s32clear(busses[bus], frames);
105 b->in_use = 0;
106 }
107 }
108
109
bus_process_all(int * bufs[],int * master,unsigned frames)110 void bus_process_all(int *bufs[], int *master, unsigned frames)
111 {
112 int i;
113 for(i = 0; i < AUDIO_MAX_BUSSES; ++i)
114 __bus_process(i, bufs, master, frames);
115 }
116
117
__remove_insert(unsigned bus,unsigned insert)118 static void __remove_insert(unsigned bus, unsigned insert)
119 {
120 audio_bus_t *b = &bustab[bus];
121 audio_plugin_close(&b->insert[insert]);
122 }
123
124
__change_insert(unsigned bus,unsigned insert,int fx)125 static void __change_insert(unsigned bus, unsigned insert, int fx)
126 {
127 int reopen = 0;
128 audio_bus_t *b = &bustab[bus];
129 audio_plugin_t *ins;
130 if(bus < 1)
131 return;
132
133 __remove_insert(bus, insert);
134 ins = &b->insert[insert-1];
135
136 switch(fx)
137 {
138 case AFX_NONE:
139 break;
140 case AFX_DELAY:
141 break;
142 case AFX_ECHO:
143 break;
144 case AFX_REVERB:
145 delay_init(ins);
146 reopen = 1;
147 break;
148 case AFX_CHORUS:
149 break;
150 case AFX_FLANGER:
151 break;
152 case AFX_FILTER:
153 break;
154 case AFX_DIST:
155 break;
156 case AFX_WAH:
157 break;
158 case AFX_EQ:
159 break;
160 case AFX_ENHANCER:
161 break;
162 case AFX_COMPRESSOR:
163 break;
164 case AFX_MAXIMIZER:
165 break;
166 }
167
168 if(!reopen)
169 return;
170
171 if(audio_plugin_open(ins, a_settings.buffersize,
172 a_settings.samplerate, a_settings.quality) < 0)
173 return;
174
175 /* FIXME: This should be done in a butler thread... */
176 if(audio_plugin_state(ins, FX_STATE_RUNNING) < 0)
177 {
178 audio_plugin_close(ins);
179 return;
180 }
181 /* /FIXME */
182
183 /*
184 FIXME: We rely on plugins loading their defaults. Plugins should
185 FIXME: probably be able to export their default settings instead.
186 */
187 #if 0
188 for(i = 0; i < 5; ++i)
189 ins->control(ins, FXC_PARAM_1 + i,
190 b->bctl[insert][ABC_FX1_PARAM_1 + i]);
191 #endif
192
193 b->bctl[insert][ABC_FX_TYPE] = fx;
194 }
195
196
bus_ctl_set(unsigned bus,unsigned slot,unsigned ctl,int arg)197 void bus_ctl_set(unsigned bus, unsigned slot, unsigned ctl, int arg)
198 {
199 if(0 BDBG(+ 1))
200 {
201 const char *ctls[] = {
202 "ABC_FX_TYPE",
203 "ABC_FX_PARAM_1",
204 "ABC_FX_PARAM_2",
205 "ABC_FX_PARAM_3",
206 "ABC_FX_PARAM_4",
207 "ABC_FX_PARAM_5",
208 "ABC_FX_PARAM_6",
209
210 "ABC_SEND_MASTER",
211
212 "ABC_SEND_BUS_0",
213 "ABC_SEND_BUS_1",
214 "ABC_SEND_BUS_2",
215 "ABC_SEND_BUS_3",
216 "ABC_SEND_BUS_4",
217 "ABC_SEND_BUS_5",
218 "ABC_SEND_BUS_6",
219 "ABC_SEND_BUS_7",
220 "<ILLEGAL!>"
221 };
222 unsigned c = ctl;
223 if(ctl < ABC_FIRST || ctl > ABC_LAST)
224 c = (unsigned)(ABC_LAST + 1);
225 log_printf(DLOG, "Bus %u, slot %u %s set to %d\n", bus, slot, ctls[c], arg);
226 }
227
228 switch(ctl)
229 {
230 case ABC_FX_TYPE:
231 if(arg != bustab[bus].bctl[slot][ctl])
232 __change_insert(bus, slot, arg);
233 break;
234 case ABC_FX_PARAM_1:
235 case ABC_FX_PARAM_2:
236 case ABC_FX_PARAM_3:
237 case ABC_FX_PARAM_4:
238 case ABC_FX_PARAM_5:
239 case ABC_FX_PARAM_6:
240 if(slot < 1)
241 break;
242 if(bustab[bus].insert[slot].current_state < FX_STATE_READY)
243 break;
244 bustab[bus].insert[slot].control(&bustab[bus].insert[slot],
245 ctl - ABC_FX_PARAM_1 + FXC_PARAM_1,
246 arg);
247 bustab[bus].bctl[slot][ctl] = arg;
248 break;
249 default:
250 if(slot >= AUDIO_MAX_INSERTS)
251 break;
252 if(ctl > ABC_LAST)
253 break;
254 bustab[bus].bctl[slot][ctl] = arg;
255 break;
256 }
257 /*
258 * This is where the "connection table" would be
259 * updated in a more optimized implementation.
260 */
261 }
262
263
264 static int _is_open = 0;
265
audio_bus_open(void)266 void audio_bus_open(void)
267 {
268 int i, s;
269 if(_is_open)
270 return;
271
272 memset(bustab, 0, sizeof(bustab));
273 for(i = 0; i < AUDIO_MAX_BUSSES; ++i)
274 {
275 for(s = 0; s < AUDIO_MAX_INSERTS; ++s)
276 memcpy(bustab[i].bctl[s], a_bus_def_ctl,
277 sizeof(a_bus_def_ctl));
278 dcf6s_init(&bustab[i].dcfilter, a_settings.samplerate);
279 dcf6s_set_f(&bustab[i].dcfilter, 10);
280 bustab[i].in_use = 0;
281 }
282 _is_open = 1;
283 }
284
285
audio_bus_close(void)286 void audio_bus_close(void)
287 {
288 unsigned i, j;
289 if(!_is_open)
290 return;
291
292 for(i = 0; i < AUDIO_MAX_BUSSES; ++i)
293 for(j = 0; j < AUDIO_MAX_INSERTS; ++j)
294 __change_insert(i, j, AFX_NONE);
295 memset(bustab, 0, sizeof(bustab));
296 _is_open = 0;
297 }
298