1
2 /*
3 * Diverse Bristol audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 /* ARP AXXE algorithm - we use two OSC, need one compound. FFS. */
23
24 /*#define DEBUG */
25
26 #include "bristol.h"
27 #include "bristolmm.h"
28 #include "bristolaxxe.h"
29
30 /*
31 * Use of these axxe global buffers will be an issue with use of multiple
32 * audio threads, unless we ensure a single thread deals with any given algo
33 * type, since then they are only used sequentially.
34 */
35 static float *freqbuf = (float *) NULL;
36 static float *filtbuf = (float *) NULL;
37 static float *noisebuf = (float *) NULL;
38 static float *adsrbuf = (float *) NULL;
39 static float *lfosh = (float *) NULL;
40 static float *lfosine = (float *) NULL;
41 static float *lfosquare = (float *) NULL;
42 static float *osc1buf = (float *) NULL;
43 static float *osc2buf = (float *) NULL;
44 static float *scratch = (float *) NULL;
45
46 int
axxeController(Baudio * baudio,u_char operator,u_char controller,float value)47 axxeController(Baudio *baudio, u_char operator, u_char controller, float value)
48 {
49 int ivalue = value * CONTROLLER_RANGE;
50
51 #ifdef DEBUG
52 printf("bristolAxxeControl(%i, %i, %f)\n", operator, controller, value);
53 #endif
54
55 if (operator != 126)
56 return(0);
57
58 switch (controller) {
59 case 0:
60 baudio->glide = value * value * baudio->glidemax;
61 break;
62 case 1:
63 baudio->gtune = 1.0
64 + (baudio->note_diff - 1)
65 * (value * 2 - 1);
66
67 buildCurrentTable(baudio, baudio->gtune);
68 alterAllNotes(baudio);
69 break;
70 case 2:
71 ((axxemods *) baudio->mixlocals)->o_f_sine = value;
72 break;
73 case 3:
74 ((axxemods *) baudio->mixlocals)->o_f_square = value;
75 break;
76 case 4:
77 ((axxemods *) baudio->mixlocals)->o_f_sh = value / 16;
78 break;
79 case 5:
80 ((axxemods *) baudio->mixlocals)->o_f_adsr = value;
81 break;
82 case 6:
83 ((axxemods *) baudio->mixlocals)->o_pwm_sine = value * 512;
84 break;
85 case 7:
86 ((axxemods *) baudio->mixlocals)->o_pwm_adsr = value * 100;
87 break;
88 case 8:
89 ((axxemods *) baudio->mixlocals)->m_noise = value;
90 break;
91 case 9:
92 ((axxemods *) baudio->mixlocals)->m_ramp = value;
93 break;
94 case 10:
95 ((axxemods *) baudio->mixlocals)->m_square = value * 96.0;
96 break;
97 case 11:
98 ((axxemods *) baudio->mixlocals)->f_sine = value;
99 break;
100 case 12:
101 ((axxemods *) baudio->mixlocals)->f_adsr = value;
102 break;
103 case 13:
104 ((axxemods *) baudio->mixlocals)->a_gain = value;
105 break;
106 case 14:
107 ((axxemods *) baudio->mixlocals)->a_adsr = value;
108 break;
109 case 15:
110 if (baudio->voicecount == 1)
111 {
112 /* Multi Env trigger */
113 if (ivalue == 0)
114 baudio->mixflags &= ~BRISTOL_MULTITRIG;
115 else
116 baudio->mixflags |= BRISTOL_MULTITRIG;
117 } else {
118 /*
119 * Else multi lfo
120 */
121 if (ivalue)
122 baudio->mixflags &= ~A_LFO_MULTI;
123 else
124 baudio->mixflags |= A_LFO_MULTI;
125 }
126 break;
127 case 16:
128 /* PPC Flatten */
129 if (ivalue)
130 ivalue = -1;
131 else
132 ivalue = 0;
133 baudio->gtune = 1.0
134 + (baudio->note_diff - 1) * (ivalue * 2);
135
136 buildCurrentTable(baudio, baudio->gtune);
137 alterAllNotes(baudio);
138 break;
139 case 17:
140 /* PPC trill */
141 if (ivalue)
142 baudio->mixflags |= A_LFO_TRILL;
143 else
144 baudio->mixflags &= ~A_LFO_TRILL;
145 break;
146 case 18:
147 /* PPC Sharpen */
148 if (ivalue)
149 ivalue = 1;
150 else
151 ivalue = 0;
152 baudio->gtune = 1.0
153 + (baudio->note_diff - 1) * (ivalue * 2);
154
155 buildCurrentTable(baudio, baudio->gtune);
156 alterAllNotes(baudio);
157 break;
158 case 19:
159 /* Auto Env repeat. */
160 if (ivalue == 0) {
161 ((axxemods *) baudio->mixlocals)->lfoAuto = -1;
162 } else {
163 float low;
164
165 /*
166 * We have been given a value between 0 and 1.0.
167 * 0 = 0.1Hz
168 * 1 = 10 Hz
169 *
170 * The delays are only going to be based on sample buffer
171 * delays, so find out the nearest number of buffers for any
172 * given rate.
173 *
174 * Buffer time = samplecount / samplerate.
175 *
176 * Low = 0.1 / btime
177 * High = 10 / btime (= 100 * Low)
178 *
179 * Rate is the value between these.
180 *
181 * count = Low + 100 * Low * (1 - value)
182 low = 0.1 / ( ((float) audiomain->samplecount)
183 / ((float) audiomain->samplerate));
184 *
185 * Bums, don't have easy access to sc and sr.
186 */
187 value = gainTable[
188 (int) ((1 - value) * (CONTROLLER_RANGE - 1))].gain;
189 low = 0.1 / ( ((float) 256)
190 / ((float) baudio->samplerate));
191 ((axxemods *) baudio->mixlocals)->lfoAuto =
192 low + 100 * low * value;
193 }
194 break;
195 }
196 return(0);
197 }
198
199 int
axxePreops(audioMain * audiomain,Baudio * baudio,bristolVoice * voice,register float * startbuf)200 axxePreops(audioMain *audiomain, Baudio *baudio,
201 bristolVoice *voice, register float *startbuf)
202 {
203 if (((axxemods *) baudio->mixlocals)->lfolocals == 0)
204 {
205 ((axxemods *) baudio->mixlocals)->lfolocals =
206 baudio->locals[voice->index][2];
207 }
208
209 /* NOISE */
210 bristolbzero(noisebuf, audiomain->segmentsize);
211 audiomain->palette[(*baudio->sound[6]).index]->specs->io[0].buf = noisebuf;
212 (*baudio->sound[6]).operate(
213 (audiomain->palette)[4],
214 voice,
215 (*baudio->sound[6]).param,
216 voice->locals[voice->index][6]);
217 /* NOISE DONE */
218
219 /* LFO produces 3 outputs, sine, square and S/H */
220 if ((baudio->mixflags & A_LFO_MULTI) == 0)
221 {
222 /*
223 * Operate LFO if we have one per voice.
224 */
225 audiomain->palette[(*baudio->sound[2]).index]->specs->io[0].buf
226 = noisebuf;
227 audiomain->palette[(*baudio->sound[2]).index]->specs->io[4].buf
228 = lfosine;
229 audiomain->palette[(*baudio->sound[2]).index]->specs->io[2].buf
230 = lfosquare;
231 audiomain->palette[(*baudio->sound[2]).index]->specs->io[3].buf
232 = lfosh;
233 (*baudio->sound[2]).operate(
234 (audiomain->palette)[16],
235 voice,
236 (*baudio->sound[2]).param,
237 ((axxemods *) baudio->mixlocals)->lfolocals);
238 }
239
240 if (((axxemods *) baudio->mixlocals)->lfoAuto >= 0)
241 {
242 if (++((axxemods *) baudio->mixlocals)->lfoAutoCount
243 >= ((axxemods *) baudio->mixlocals)->lfoAuto)
244 ((axxemods *) baudio->mixlocals)->lfoAutoCount = 0;
245 }
246 /* */
247 return(0);
248 }
249
250 int
operateOneAxxe(audioMain * audiomain,Baudio * baudio,bristolVoice * voice,register float * startbuf)251 operateOneAxxe(audioMain *audiomain, Baudio *baudio,
252 bristolVoice *voice, register float *startbuf)
253 {
254 axxemods *mods = (axxemods *) baudio->mixlocals;
255 int sc = audiomain->samplecount, flags;
256
257 /*printf("operateOneAxxe(%i, %x, %x)\n", voice->index, audiomain, baudio); */
258
259 bristolbzero(freqbuf, audiomain->segmentsize);
260 bristolbzero(osc1buf, audiomain->segmentsize);
261 bristolbzero(osc2buf, audiomain->segmentsize);
262 bristolbzero(filtbuf, audiomain->segmentsize);
263 bristolbzero(scratch, audiomain->segmentsize);
264 /*
265 * There are a lot of mods in this synth, each operator will produce its
266 * output buffer, and then they will modulate eachother.
267 *
268 * Noise is done, run the LFO and ADSR.
269 */
270
271 /* LFO produces 3 outputs, sine, square and S/H */
272 if (baudio->mixflags & A_LFO_MULTI)
273 {
274 /*
275 * Operate LFO if we have one per voice.
276 */
277 audiomain->palette[(*baudio->sound[2]).index]->specs->io[0].buf
278 = noisebuf;
279 audiomain->palette[(*baudio->sound[2]).index]->specs->io[4].buf
280 = lfosine;
281 audiomain->palette[(*baudio->sound[2]).index]->specs->io[2].buf
282 = lfosquare;
283 audiomain->palette[(*baudio->sound[2]).index]->specs->io[3].buf
284 = lfosh;
285 (*baudio->sound[2]).operate(
286 (audiomain->palette)[16],
287 voice,
288 (*baudio->sound[2]).param,
289 baudio->locals[voice->index][2]);
290 }
291
292 if (mods->lfoAuto >= 0)
293 {
294 if (mods->lfoAutoCount == 0)
295 {
296 if ((voice->flags & (BRISTOL_KEYOFF|BRISTOL_KEYOFFING)) == 0)
297 voice->flags |= BRISTOL_KEYREON;
298 /* if ((voice->flags & (BRISTOL_KEYOFF|BRISTOL_KEYOFFING)) == 0) */
299 /* { */
300 /* voice->flags |= BRISTOL_KEYREON; */
301 /* } */
302 }
303 }
304 /* */
305
306 /* ADSR */
307 /*
308 * Run the ADSR.
309 */
310 audiomain->palette[(*baudio->sound[4]).index]->specs->io[0].buf = adsrbuf;
311 (*baudio->sound[4]).operate(
312 (audiomain->palette)[1],
313 voice,
314 (*baudio->sound[4]).param,
315 voice->locals[voice->index][4]);
316 /* ADSR - OVER */
317
318 /*
319 * We now have our mods, Noise, ADSR, S/H, Sine, Square.
320 *
321 * Run the oscillators.
322 */
323 /* OSC */
324 audiomain->palette[(*baudio->sound[0]).index]->specs->io[0].buf = freqbuf;
325 audiomain->palette[(*baudio->sound[0]).index]->specs->io[1].buf = 0;
326 audiomain->palette[(*baudio->sound[0]).index]->specs->io[2].buf = osc1buf;
327
328 fillFreqTable(baudio, voice, freqbuf, sc, 1);
329
330 /*
331 * Put in any desired mods. There are two, MG and Wheel mod. Wheel mod is
332 * actually quite week, takes the LFO to freqbuf, same as MG without the
333 * env. Hm.
334 */
335 if (baudio->mixflags & A_LFO_TRILL)
336 bufmerge(lfosine, 0.2, freqbuf, 1.0, sc);
337 if (mods->o_f_sine != 0.0f)
338 bufmerge(lfosine, mods->o_f_sine, freqbuf, 1.0, sc);
339 if (mods->o_f_square != 0.0f)
340 bufmerge(lfosquare, mods->o_f_square, freqbuf, 1.0, sc);
341 if (mods->o_f_sh != 0.0f)
342 bufmerge(lfosh, mods->o_f_sh, freqbuf, 1.0, sc);
343 if (mods->o_f_adsr != 0.0f)
344 bufmerge(adsrbuf, mods->o_f_adsr, freqbuf, 1.0, sc);
345
346 (*baudio->sound[0]).operate(
347 (audiomain->palette)[8],
348 voice,
349 (*baudio->sound[0]).param,
350 voice->locals[voice->index][0]);
351
352 audiomain->palette[(*baudio->sound[1]).index]->specs->io[0].buf = freqbuf;
353 audiomain->palette[(*baudio->sound[1]).index]->specs->io[1].buf = scratch;
354 audiomain->palette[(*baudio->sound[1]).index]->specs->io[2].buf = osc2buf;
355
356 if (mods->o_pwm_sine != 0.0f)
357 bufmerge(lfosine, mods->o_pwm_sine, scratch, 0.0, sc);
358 if (mods->o_pwm_adsr != 0.0f)
359 bufmerge(adsrbuf, mods->o_pwm_adsr, scratch, 1.0, sc);
360
361 /*
362 * This was called with sound 0 rather than 1, so had two different freq
363 * and mixed output buffers. Sounded like ring mod.
364 */
365 (*baudio->sound[1]).operate(
366 (audiomain->palette)[8],
367 voice,
368 (*baudio->sound[1]).param,
369 voice->locals[voice->index][1]);
370 /* OSC done */
371
372 /* Mixer */
373 bufmerge(noisebuf, mods->m_noise, osc1buf, mods->m_ramp, sc);
374 bufmerge(osc2buf, mods->m_square, osc1buf, 96.0, sc);
375 /* */
376
377 /* Filter */
378 audiomain->palette[(*baudio->sound[3]).index]->specs->io[0].buf
379 = osc1buf;
380 audiomain->palette[(*baudio->sound[3]).index]->specs->io[1].buf
381 = scratch;
382 audiomain->palette[(*baudio->sound[3]).index]->specs->io[2].buf
383 = baudio->rightbuf;;
384
385 bristolbzero(scratch, audiomain->segmentsize);
386 if (mods->f_sine != 0.0f)
387 bufmerge(lfosine, mods->f_sine, scratch, 0.0, sc);
388 if (mods->f_adsr != 0.0f)
389 bufmerge(adsrbuf, mods->f_adsr, scratch, 1.0, sc);
390
391 (*baudio->sound[3]).operate(
392 (audiomain->palette)[3],
393 voice,
394 (*baudio->sound[3]).param,
395 voice->locals[voice->index][3]);
396 /* Filter DONE */
397
398 /* AMP */
399 /*
400 * Reworked this for dual envelope mix - key grooming - reusing the lfosine
401 * buffer....
402 bufmerge(lfosine, 0.0, adsrbuf, mods->a_adsr, sc);
403 {
404 register float gain = mods->a_gain, *ab = adsrbuf;
405 register int i = 0;
406
407 for (; i < sc; i += 8)
408 {
409 *ab++ += gain;
410 *ab++ += gain;
411 *ab++ += gain;
412 *ab++ += gain;
413 *ab++ += gain;
414 *ab++ += gain;
415 *ab++ += gain;
416 *ab++ += gain;
417 }
418 }
419 */
420
421 flags = voice->flags;
422 audiomain->palette[(*baudio->sound[7]).index]->specs->io[0].buf = lfosine;
423 (*baudio->sound[7]).operate(
424 (audiomain->palette)[1],
425 voice,
426 (*baudio->sound[7]).param,
427 voice->locals[voice->index][7]);
428 voice->flags = flags;
429
430 bufmerge(lfosine, mods->a_gain, adsrbuf, mods->a_adsr, sc);
431
432 audiomain->palette[(*baudio->sound[5]).index]->specs->io[0].buf
433 = baudio->rightbuf;
434 audiomain->palette[(*baudio->sound[5]).index]->specs->io[1].buf
435 = adsrbuf;
436 audiomain->palette[(*baudio->sound[5]).index]->specs->io[2].buf =
437 baudio->leftbuf;
438
439 (*baudio->sound[5]).operate(
440 (audiomain->palette)[2],
441 voice,
442 (*baudio->sound[5]).param,
443 voice->locals[voice->index][5]);
444 /* AMP OVER */
445 /*
446 * It is bad practice to use the rightbuf. It can be done, but must be
447 * zeroed - most efficiently in postOps but otherwise.....
448 */
449 bristolbzero(baudio->rightbuf, audiomain->segmentsize);
450
451 return(0);
452 }
453
454 static int
bristolAxxeDestroy(audioMain * audiomain,Baudio * baudio)455 bristolAxxeDestroy(audioMain *audiomain, Baudio *baudio)
456 {
457 printf("removing one axxe\n");
458 return(0);
459 bristolfree(freqbuf);
460 bristolfree(filtbuf);
461 bristolfree(noisebuf);
462 bristolfree(adsrbuf);
463 bristolfree(lfosine);
464 bristolfree(lfosquare);
465 bristolfree(lfosh);
466 bristolfree(osc1buf);
467 bristolfree(osc1buf);
468
469 return(0);
470 }
471
472 int
bristolAxxeInit(audioMain * audiomain,Baudio * baudio)473 bristolAxxeInit(audioMain *audiomain, Baudio *baudio)
474 {
475 printf("initialising one axxe\n");
476 baudio->soundCount = 8; /* Number of operators in this voice */
477 /*
478 * Assign an array of sound pointers.
479 */
480 baudio->sound = (bristolSound **)
481 bristolmalloc0(sizeof(bristolOP *) * baudio->soundCount);
482 baudio->effect = (bristolSound **)
483 bristolmalloc0(sizeof(bristolOP *) * baudio->soundCount);
484
485 /* Ramp oscillator */
486 initSoundAlgo(8, 0, baudio, audiomain, baudio->sound);
487 /* Square oscillator */
488 initSoundAlgo(8, 1, baudio, audiomain, baudio->sound);
489 /* LFO */
490 initSoundAlgo(16, 2, baudio, audiomain, baudio->sound);
491 /* A filter */
492 initSoundAlgo(3, 3, baudio, audiomain, baudio->sound);
493 /* Single ADSR */
494 initSoundAlgo(1, 4, baudio, audiomain, baudio->sound);
495 /* An amplifier */
496 initSoundAlgo(2, 5, baudio, audiomain, baudio->sound);
497 /* An noise source */
498 initSoundAlgo(4, 6, baudio, audiomain, baudio->sound);
499 /* A grooming env for direct gain to amp */
500 initSoundAlgo(1, 7, baudio, audiomain, baudio->sound);
501
502 baudio->param = axxeController;
503 baudio->destroy = bristolAxxeDestroy;
504 baudio->operate = operateOneAxxe;
505 baudio->preops = axxePreops;
506
507 if (freqbuf == NULL)
508 freqbuf = (float *) bristolmalloc0(audiomain->segmentsize);
509 if (filtbuf == NULL)
510 filtbuf = (float *) bristolmalloc0(audiomain->segmentsize);
511 if (noisebuf == NULL)
512 noisebuf = (float *) bristolmalloc0(audiomain->segmentsize);
513 if (adsrbuf == NULL)
514 adsrbuf = (float *) bristolmalloc0(audiomain->segmentsize);
515 if (lfosh == NULL)
516 lfosh = (float *) bristolmalloc0(audiomain->segmentsize);
517 if (lfosquare == NULL)
518 lfosquare = (float *) bristolmalloc0(audiomain->segmentsize);
519 if (lfosine == NULL)
520 lfosine = (float *) bristolmalloc0(audiomain->segmentsize);
521 if (osc1buf == NULL)
522 osc1buf = (float *) bristolmalloc0(audiomain->segmentsize);
523 if (osc2buf == NULL)
524 osc2buf = (float *) bristolmalloc0(audiomain->segmentsize);
525 if (scratch == NULL)
526 scratch = (float *) bristolmalloc0(audiomain->segmentsize);
527
528 baudio->mixlocals = (float *) bristolmalloc0(sizeof(axxemods));
529
530 return(0);
531 }
532
533