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 /* Korg Poly800 algo */
23 
24 /*#define DEBUG */
25 
26 #include "bristol.h"
27 #include "bristolmm.h"
28 #include "bristolpoly800.h"
29 
30 /*
31  * Use of these poly800 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 
36 int
poly800Controller(Baudio * baudio,u_char operator,u_char controller,float value)37 poly800Controller(Baudio *baudio, u_char operator, u_char controller, float value)
38 {
39 //	int ivalue = value * CONTROLLER_RANGE;
40 
41 #ifdef DEBUG
42 	printf("bristolPoly800Control(%i, %i, %f)\n", operator, controller, value);
43 #endif
44 
45 	/*
46 	 * These will be for our chorus.
47 	 */
48 	if (operator == 100)
49 	{
50 		if (baudio->effect[0] == NULL)
51 			return(0);
52 
53 		switch (controller) {
54 			case 0:
55 				baudio->effect[0]->param->param[controller].float_val = value;
56 					(0.1 + (value * value) * 20) * 1024 / baudio->samplerate;
57 				break;
58 			case 1:
59 			case 2:
60 			case 3:
61 				baudio->effect[0]->param->param[controller].float_val = value;
62 				break;
63 		}
64 		return(0);
65 	}
66 
67 	if (operator != 126)
68 		return(0);
69 
70 	switch (controller) {
71 		case 0:
72 			baudio->glide = value * value * baudio->glidemax;
73 			break;
74 		case 1:
75 			baudio->gtune = 1.0
76 				+ (baudio->note_diff - 1)
77 				* (value * 2 - 1);
78 
79 			buildCurrentTable(baudio, baudio->gtune);
80 			alterAllNotes(baudio);
81 			break;
82 		case 2:
83 			P800LOCAL->volume = value * 4;
84 			break;
85 		case 3:
86 			if (value < 0.5)
87 				P800LOCAL->bend = 1.0 - value;
88 			else
89 				P800LOCAL->bend = 1.0 + (value - 0.5) * 2;
90 			break;
91 		case 4:
92 			P800LOCAL->dco1pwm = value * 0.5;
93 			break;
94 		case 5:
95 			P800LOCAL->dco2pwm = value * 0.5;
96 			break;
97 		case 6:
98 			P800LOCAL->mod2vcodepth = 0.1 + value * 1.9;
99 			break;
100 		case 10:
101 			if (value == 0) {
102 				baudio->mixflags &= ~P800_DOUBLE;
103 				baudio->voicecount = P800LOCAL->voicecount;
104 			} else {
105 				baudio->mixflags |= P800_DOUBLE;
106 				baudio->voicecount = P800LOCAL->voicecount / 2;
107 			}
108 			break;
109 		case 11:
110 			if (value == 0)
111 				baudio->mixflags &= ~P800_LFOMULTI;
112 			else
113 				baudio->mixflags |= P800_LFOMULTI;
114 			break;
115 		case 12:
116 			if (value == 0)
117 				baudio->mixflags &= ~P800_FILTMULTI;
118 			else
119 				baudio->mixflags |= P800_FILTMULTI;
120 			break;
121 		case 13:
122 			if (value == 0)
123 				baudio->mixflags &= ~P800_SYNC;
124 			else
125 				baudio->mixflags |= P800_SYNC;
126 			break;
127 		case 20:
128 			if (value != 0) {
129 				baudio->mixflags &= ~P800_POLARITY;
130 				if (P800LOCAL->envamount < 0)
131 					P800LOCAL->envamount = -P800LOCAL->envamount;
132 			} else {
133 				baudio->mixflags |= P800_POLARITY;
134 				if (P800LOCAL->envamount > 0)
135 					P800LOCAL->envamount = -P800LOCAL->envamount;
136 			}
137 			break;
138 		case 21:
139 			if (baudio->mixflags & P800_POLARITY)
140 				P800LOCAL->envamount = -value * 2;
141 			else
142 				P800LOCAL->envamount = value * 2;
143 			break;
144 		case 22:
145 			P800LOCAL->vcomod = value * value * 4;
146 			break;
147 		case 23:
148 			P800LOCAL->vcfmod = value * value * 8;
149 			break;
150 		case 24:
151 			if ((P800LOCAL->lfodelay = value * baudio->samplerate * 15) == 0)
152 				P800LOCAL->lforate = 1;
153 			else
154 				P800LOCAL->lforate = 1 / (value * baudio->samplerate * 15);
155 			break;
156 	}
157 	return(0);
158 }
159 
160 static float
fillLFOgainTable(float * buf,float current,float slope,float target,int i)161 fillLFOgainTable(float *buf, float current, float slope, float target, int i)
162 {
163 	for (; i > 0; i-=4)
164 	{
165 		if ((current += slope) > target) current = target; *buf++ = current;
166 		if ((current += slope) > target) current = target; *buf++ = current;
167 		if ((current += slope) > target) current = target; *buf++ = current;
168 		if ((current += slope) > target) current = target; *buf++ = current;
169 	}
170 	return(current);
171 }
172 
173 int
poly800Preops(audioMain * audiomain,Baudio * baudio,bristolVoice * voice,register float * startbuf)174 poly800Preops(audioMain *audiomain, Baudio *baudio,
175 bristolVoice *voice, register float *startbuf)
176 {
177 	/*
178 	 * Preops will do the LFO and noise, unless multi.
179 	 */
180 
181 	P800LOCAL->maxkey = voice->index;
182 	P800LOCAL->maxvoice = voice;
183 
184 	if ((baudio->mixflags & P800_LFOMULTI) == 0)
185 	{
186 		/*
187 		 * This needs to be done legato style here.
188 		 */
189 		if ((voice->flags & (BRISTOL_KEYON|BRISTOL_KEYREON))
190 			&& (baudio->lvoices == 0))
191 		{
192 			/* Put in up to 10s of delay */
193 			P800LOCAL->lfodelays[0] = P800LOCAL->lfodelay;
194 			P800LOCAL->lfogains[0] = 0;
195 		}
196 
197 		if ((P800LOCAL->lfodelays[0] -= audiomain->samplecount) <= 0)
198 		{
199 			P800LOCAL->lfodelays[0] = 0;
200 
201 			/*
202 			 * Operate LFO if we have a single LFO per synth.
203 			 */
204 			audiomain->palette[B_LFO]->specs->io[1].buf
205 				= audiomain->palette[B_LFO]->specs->io[2].buf
206 				= audiomain->palette[B_LFO]->specs->io[3].buf
207 				= audiomain->palette[B_LFO]->specs->io[5].buf
208 				= audiomain->palette[B_LFO]->specs->io[6].buf
209 					= NULL;
210 
211 			audiomain->palette[B_LFO]->specs->io[0].buf = P800LOCAL->zerobuf;
212 			audiomain->palette[B_LFO]->specs->io[4].buf = P800LOCAL->oscabuf;
213 
214 			(*baudio->sound[8]).operate(
215 				(audiomain->palette)[B_LFO],
216 				voice,
217 				(*baudio->sound[8]).param,
218 				baudio->locals[0][8]);
219 
220 			bufadd(P800LOCAL->oscabuf, 1.0, audiomain->samplecount);
221 
222 			bristolbzero(P800LOCAL->lfobuf, audiomain->segmentsize);
223 
224 			P800LOCAL->lfogains[0] =
225 				fillLFOgainTable(P800LOCAL->adsrbuf, P800LOCAL->lfogains[0],
226 					P800LOCAL->lforate, 1.0, audiomain->samplecount);
227 
228 			audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->oscabuf;
229 			audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
230 			audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->lfobuf;
231 
232 			(*baudio->sound[7]).operate(
233 				(audiomain->palette)[B_DCA],
234 				voice,
235 				(*baudio->sound[7]).param,
236 				baudio->locals[0][7]);
237 		} else
238 			bristolbzero(P800LOCAL->lfobuf, audiomain->segmentsize);
239 
240 		bristolbzero(P800LOCAL->noisebuf, audiomain->segmentsize);
241 		audiomain->palette[B_NOISE]->specs->io[0].buf = P800LOCAL->noisebuf;
242 		(*baudio->sound[3]).operate(
243 			(audiomain->palette)[B_NOISE],
244 			voice,
245 			(*baudio->sound[3]).param,
246 			voice->locals[0][3]);
247 	}
248 
249 	/* We only need to do this once for all voices */
250 	if (baudio->contcontroller[1] < 0.5) {
251 		P800LOCAL->mod2vcf = 0;
252 		P800LOCAL->mod2vco = (0.5 - baudio->contcontroller[1]) *
253 			P800LOCAL->mod2vcodepth;
254 	} else {
255 		P800LOCAL->mod2vco = 0;
256 		P800LOCAL->mod2vcf = (baudio->contcontroller[1] - 0.5) * 4;
257 	}
258 
259 	return(0);
260 }
261 
262 /*
263  * This looks a little specific, it is used here to apply the normalised LFO
264  * to the frequency buffer - as a multiplier. That maintains frequency mod over
265  * different notes. It could be made a little more general such as all freq
266  * mods including ADSR for the prophet, etc
267  */
268 static void
mult2buf(register float * d,register float * s,register float v,register int c)269 mult2buf(register float *d, register float *s, register float v, register int c)
270 {
271 	for (; c > 0; c-=8)
272 	{
273 		*d = (1.0 + *s++) * *d * v; d++;
274 		*d = (1.0 + *s++) * *d * v; d++;
275 		*d = (1.0 + *s++) * *d * v; d++;
276 		*d = (1.0 + *s++) * *d * v; d++;
277 		*d = (1.0 + *s++) * *d * v; d++;
278 		*d = (1.0 + *s++) * *d * v; d++;
279 		*d = (1.0 + *s++) * *d * v; d++;
280 		*d = (1.0 + *s++) * *d * v; d++;
281 	}
282 }
283 
284 int
operateOnePoly800(audioMain * audiomain,Baudio * baudio,bristolVoice * voice,register float * startbuf)285 operateOnePoly800(audioMain *audiomain, Baudio *baudio,
286 bristolVoice *voice, register float *startbuf)
287 {
288 	unsigned int flags = 0;
289 /*printf("operateOnePoly800(%i, %x, %x)\n", voice->index, audiomain, baudio); */
290 
291 	if (baudio->mixflags & P800_LFOMULTI)
292 	{
293 		/*
294 		 * This needs to be done legato style here.
295 		 */
296 		if (voice->flags & (BRISTOL_KEYON|BRISTOL_KEYREON))
297 		{
298 			/* Put in up to 10s of delay */
299 			P800LOCAL->lfodelays[voice->index] = P800LOCAL->lfodelay;
300 			P800LOCAL->lfogains[voice->index] = 0;
301 		}
302 
303 		if ((P800LOCAL->lfodelays[voice->index] -= audiomain->samplecount) <= 0)
304 		{
305 			P800LOCAL->lfodelays[voice->index] = 0;
306 
307 			/*
308 			 * Operate LFO if we have a single LFO per synth.
309 			 */
310 			audiomain->palette[B_LFO]->specs->io[1].buf
311 				= audiomain->palette[B_LFO]->specs->io[2].buf
312 				= audiomain->palette[B_LFO]->specs->io[3].buf
313 				= audiomain->palette[B_LFO]->specs->io[5].buf
314 				= audiomain->palette[B_LFO]->specs->io[6].buf
315 					= NULL;
316 
317 			audiomain->palette[B_LFO]->specs->io[0].buf = P800LOCAL->zerobuf;
318 			audiomain->palette[B_LFO]->specs->io[4].buf = P800LOCAL->oscabuf;
319 
320 			(*baudio->sound[8]).operate(
321 				(audiomain->palette)[B_LFO],
322 				voice,
323 				(*baudio->sound[8]).param,
324 				baudio->locals[voice->index][8]);
325 
326 			bufadd(P800LOCAL->oscabuf, 1.0, audiomain->samplecount);
327 
328 			bristolbzero(P800LOCAL->lfobuf, audiomain->segmentsize);
329 
330 			P800LOCAL->lfogains[voice->index] =
331 				fillLFOgainTable(P800LOCAL->adsrbuf,
332 					P800LOCAL->lfogains[voice->index],
333 					P800LOCAL->lforate, 1.0, audiomain->samplecount);
334 
335 			audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->oscabuf;
336 			audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
337 			audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->lfobuf;
338 
339 			(*baudio->sound[7]).operate(
340 				(audiomain->palette)[B_DCA],
341 				voice,
342 				(*baudio->sound[7]).param,
343 				baudio->locals[voice->index][7]);
344 		} else
345 			bristolbzero(P800LOCAL->lfobuf, audiomain->segmentsize);
346 
347 		bristolbzero(P800LOCAL->noisebuf, audiomain->segmentsize);
348 		audiomain->palette[B_NOISE]->specs->io[0].buf = P800LOCAL->noisebuf;
349 		(*baudio->sound[3]).operate(
350 			(audiomain->palette)[B_NOISE],
351 			voice,
352 			(*baudio->sound[3]).param,
353 			voice->locals[voice->index][3]);
354 	}
355 
356 /* Osc-1 */
357 	/*
358 	 * This will do 1 osc with env, unless multi when it does two. Will track
359 	 * the highest note for the filter cutoff point for when filter is not
360 	 * MULTI.
361 	 */
362 	fillFreqBuf(baudio, voice, P800LOCAL->freqbuf, audiomain->samplecount, 1);
363 
364 	bristolbzero(P800LOCAL->oscabuf, audiomain->segmentsize);
365 	bristolbzero(P800LOCAL->syncbuf, audiomain->segmentsize);
366 
367 	audiomain->palette[B_NRO]->specs->io[0].buf = P800LOCAL->freqbuf;
368 	audiomain->palette[B_NRO]->specs->io[1].buf = P800LOCAL->oscabuf;
369 	audiomain->palette[B_NRO]->specs->io[2].buf = P800LOCAL->pwmbuf;
370 	audiomain->palette[B_NRO]->specs->io[3].buf = P800LOCAL->zerobuf; /* Sync */
371 	audiomain->palette[B_NRO]->specs->io[4].buf = P800LOCAL->syncbuf; /* Sout */
372 
373 	bufmerge(P800LOCAL->lfobuf, P800LOCAL->dco1pwm,
374 		P800LOCAL->pwmbuf, 0.0, audiomain->samplecount);
375 
376 	/* This seems odd, but if we have SYNC enabled only do LFO mods to DCO-2 */
377 	if ((baudio->mixflags & P800_SYNC) == 0)
378 	{
379 		bufmerge(P800LOCAL->lfobuf, P800LOCAL->vcomod,
380 			P800LOCAL->scratch, 0.0, audiomain->samplecount);
381 		mult2buf(P800LOCAL->freqbuf, P800LOCAL->scratch, 1.0,
382 			audiomain->samplecount);
383 	}
384 
385 	bufmerge(P800LOCAL->lfobuf, P800LOCAL->mod2vco,
386 		P800LOCAL->scratch, 0.0, audiomain->samplecount);
387 	mult2buf(P800LOCAL->freqbuf, P800LOCAL->scratch, 1.0,
388 		audiomain->samplecount);
389 
390 	(*baudio->sound[0]).operate(
391 		(audiomain->palette)[B_NRO],
392 		voice,
393 		(*baudio->sound[0]).param,
394 		voice->locals[voice->index][0]);
395 
396 	audiomain->palette[B_ENV5S]->specs->io[0].buf = P800LOCAL->adsrbuf;
397 	(*baudio->sound[4]).operate(
398 		(audiomain->palette)[B_ENV5S],
399 		voice,
400 		(*baudio->sound[4]).param,
401 		voice->locals[voice->index][4]);
402 
403 	audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->oscabuf;
404 	audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
405 	audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->outbuf;
406 	(*baudio->sound[7]).operate(
407 		(audiomain->palette)[B_DCA],
408 		voice,
409 		(*baudio->sound[7]).param,
410 		baudio->locals[voice->index][7]);
411 
412 	flags = voice->flags & BRISTOL_KEYDONE;
413 /* Osc-1 DONE */
414 
415 /* Osc-2 */
416 	if (baudio->mixflags & P800_DOUBLE)
417 	{
418 		bristolbzero(P800LOCAL->oscbbuf, audiomain->segmentsize);
419 
420 		audiomain->palette[B_NRO]->specs->io[0].buf = P800LOCAL->freqbuf;
421 		audiomain->palette[B_NRO]->specs->io[1].buf = P800LOCAL->oscbbuf;
422 		audiomain->palette[B_NRO]->specs->io[2].buf = P800LOCAL->pwmbuf;
423 
424 		if (baudio->mixflags & P800_SYNC) {
425 			/*
426 			 * If sync is enabled then the LFO was not fead into DCO1 but we
427 			 * do want it in DCO-2 for sync modulations. It is still possible
428 			 * to get vibrato on DCO1 with sync but it requires the joystick.
429 			 */
430 			bufmerge(P800LOCAL->lfobuf, P800LOCAL->vcomod,
431 				P800LOCAL->scratch, 0.0, audiomain->samplecount);
432 			mult2buf(P800LOCAL->freqbuf, P800LOCAL->scratch, 1.0,
433 				audiomain->samplecount);
434 			audiomain->palette[B_NRO]->specs->io[3].buf = P800LOCAL->syncbuf;
435 		} else
436 			audiomain->palette[B_NRO]->specs->io[3].buf = P800LOCAL->zerobuf;
437 		audiomain->palette[B_NRO]->specs->io[4].buf = NULL; /* S-out */
438 
439 		(*baudio->sound[1]).operate(
440 			(audiomain->palette)[B_NRO],
441 			voice,
442 			(*baudio->sound[1]).param,
443 			voice->locals[voice->index][1]);
444 
445 		audiomain->palette[B_ENV5S]->specs->io[0].buf = P800LOCAL->adsrbuf;
446 		(*baudio->sound[5]).operate(
447 			(audiomain->palette)[B_ENV5S],
448 			voice,
449 			(*baudio->sound[5]).param,
450 			voice->locals[voice->index][5]);
451 
452 		/*
453 		 * We only want a key off event when both envs have terminated
454 		 */
455 		if (flags == 0)
456 			voice->flags &= ~BRISTOL_KEYDONE;
457 
458 		bufmerge(P800LOCAL->lfobuf, P800LOCAL->dco2pwm,
459 			P800LOCAL->pwmbuf, 0.0, audiomain->samplecount);
460 
461 		audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->oscbbuf;
462 		audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
463 		audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->outbuf;
464 		(*baudio->sound[7]).operate(
465 			(audiomain->palette)[B_DCA],
466 			voice,
467 			(*baudio->sound[7]).param,
468 			baudio->locals[voice->index][7]);
469 	}
470 /* Osc-2 DONE */
471 
472 	bufmerge(P800LOCAL->outbuf, 7.0,
473 		P800LOCAL->outbuf, 1.0, audiomain->samplecount);
474 
475 /* Env-3, filter (MULTI supported) */
476 	if (baudio->mixflags & P800_FILTMULTI) {
477 		flags = voice->flags;
478 		audiomain->palette[B_ENV5S]->specs->io[0].buf = P800LOCAL->adsrbuf;
479 		(*baudio->sound[6]).operate(
480 			(audiomain->palette)[B_ENV5S],
481 			voice,
482 			(*baudio->sound[6]).param,
483 			voice->locals[voice->index][6]);
484 		voice->flags = flags;
485 
486 		bufmerge(P800LOCAL->adsrbuf, P800LOCAL->envamount,
487 			P800LOCAL->scratch, 0.0, audiomain->samplecount);
488 		bufmerge(P800LOCAL->lfobuf,
489 			P800LOCAL->vcfmod + P800LOCAL->mod2vcf,
490 			P800LOCAL->scratch, 1.0, audiomain->samplecount);
491 
492 		/* Amp the noise into the output */
493 		audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->noisebuf;
494 		audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
495 		audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->outbuf;
496 		(*baudio->sound[7]).operate(
497 			(audiomain->palette)[B_DCA],
498 			voice,
499 			(*baudio->sound[7]).param,
500 			baudio->locals[voice->index][7]);
501 
502 		audiomain->palette[B_FILTER]->specs->io[0].buf = P800LOCAL->outbuf;
503 		audiomain->palette[B_FILTER]->specs->io[1].buf = P800LOCAL->scratch;
504 		audiomain->palette[B_FILTER]->specs->io[2].buf = baudio->leftbuf;
505 		(*baudio->sound[2]).operate(
506 			(audiomain->palette)[B_FILTER],
507 			voice,
508 			(*baudio->sound[2]).param,
509 			voice->locals[voice->index][2]);
510 
511 		bristolbzero(P800LOCAL->outbuf, audiomain->segmentsize);
512 	} else if (P800LOCAL->maxkey < voice->key.key) {
513 		P800LOCAL->maxkey = voice->key.key;
514 		P800LOCAL->maxvoice = voice;
515 	}
516 
517 	return(0);
518 }
519 
520 int
poly800PostOps(audioMain * audiomain,Baudio * baudio,bristolVoice * voice,register float * startbuf)521 poly800PostOps(audioMain *audiomain, Baudio *baudio,
522 bristolVoice *voice, register float *startbuf)
523 {
524 	/*
525 	 * This will do the Filter, unless multi. If done here we should be
526 	 * careful with the envelope flags since this one does not control the
527 	 * voice.
528 	 */
529 /* Env-3, filter (MULTI supported) */
530 	/*
531 	 * This jumps and clicks too much. Consider just using voice-0 and doing
532 	 * some manipulations on the voice->key.key to change the keyboard tracking
533 	 */
534 	if ((baudio->mixflags & P800_FILTMULTI) == 0) {
535 		int flags = P800LOCAL->maxvoice->flags;
536 
537 		/*
538 		 * We need to check our preOps to see if we have a legato ON event, if
539 		 * not then clear this flag. This should really just be lvoices - if
540 		 * last was zero then this has to have a note on flag.
541 		 */
542 		if (baudio->lvoices != 0)
543 			voice->flags &= ~(BRISTOL_KEYON|BRISTOL_KEYREON);
544 
545 		audiomain->palette[B_ENV5S]->specs->io[0].buf = P800LOCAL->adsrbuf;
546 		(*baudio->sound[6]).operate(
547 			(audiomain->palette)[B_ENV5S],
548 			P800LOCAL->maxvoice,
549 			(*baudio->sound[6]).param,
550 			P800LOCAL->maxvoice->locals[P800LOCAL->maxvoice->index][6]);
551 		P800LOCAL->maxvoice->flags = flags;
552 
553 		bufmerge(P800LOCAL->adsrbuf, P800LOCAL->envamount,
554 			P800LOCAL->scratch, 0.0, audiomain->samplecount);
555 		bufmerge(P800LOCAL->lfobuf,
556 			P800LOCAL->vcfmod + P800LOCAL->mod2vcf,
557 			P800LOCAL->scratch, 1.0, audiomain->samplecount);
558 
559 		/* Amp the noise into the output */
560 		audiomain->palette[B_DCA]->specs->io[0].buf = P800LOCAL->noisebuf;
561 		audiomain->palette[B_DCA]->specs->io[1].buf = P800LOCAL->adsrbuf;
562 		audiomain->palette[B_DCA]->specs->io[2].buf = P800LOCAL->outbuf;
563 		(*baudio->sound[7]).operate(
564 			(audiomain->palette)[B_DCA],
565 			P800LOCAL->maxvoice,
566 			(*baudio->sound[7]).param,
567 			baudio->locals[P800LOCAL->maxvoice->index][7]);
568 
569 		audiomain->palette[B_FILTER]->specs->io[0].buf = P800LOCAL->outbuf;
570 		audiomain->palette[B_FILTER]->specs->io[1].buf = P800LOCAL->scratch;
571 		audiomain->palette[B_FILTER]->specs->io[2].buf = baudio->leftbuf;
572 		(*baudio->sound[2]).operate(
573 			(audiomain->palette)[B_FILTER],
574 			P800LOCAL->maxvoice,
575 			(*baudio->sound[2]).param,
576 			P800LOCAL->maxvoice->locals[P800LOCAL->maxvoice->index][2]);
577 
578 		bristolbzero(P800LOCAL->outbuf, audiomain->segmentsize);
579 	}
580 
581 	bufmerge(baudio->leftbuf, 0.0,
582 		baudio->leftbuf, P800LOCAL->volume, audiomain->samplecount);
583 	return(0);
584 }
585 
586 int
bristolPoly800Destroy(audioMain * audiomain,Baudio * baudio)587 static bristolPoly800Destroy(audioMain *audiomain, Baudio *baudio)
588 {
589 	printf("removing one poly800\n");
590 
591 	bristolfree(P800LOCAL->freqbuf);
592 	bristolfree(P800LOCAL->oscabuf);
593 	bristolfree(P800LOCAL->oscbbuf);
594 	bristolfree(P800LOCAL->noisebuf);
595 	bristolfree(P800LOCAL->zerobuf);
596 	bristolfree(P800LOCAL->scratch);
597 	bristolfree(P800LOCAL->syncbuf);
598 	bristolfree(P800LOCAL->pwmbuf);
599 	bristolfree(P800LOCAL->lfobuf);
600 	bristolfree(P800LOCAL->filtbuf);
601 	bristolfree(P800LOCAL->adsrbuf);
602 	bristolfree(P800LOCAL->outbuf);
603 
604 	return(0);
605 }
606 
607 int
bristolPoly800Init(audioMain * audiomain,Baudio * baudio)608 bristolPoly800Init(audioMain *audiomain, Baudio *baudio)
609 {
610 	printf("initialising poly800\n");
611 
612 	baudio->soundCount = 9; /* Number of operators in this voice */
613 	/*
614 	 * Assign an array of sound pointers.
615 	 */
616 	baudio->sound = (bristolSound **)
617 		bristolmalloc0(sizeof(bristolOP *) * baudio->soundCount);
618 	baudio->effect = (bristolSound **)
619 		bristolmalloc0(sizeof(bristolOP *) * baudio->soundCount);
620 
621 	/*
622 	 * Two oscillators
623 	 * Filter
624 	 * Noise
625 	 * Three Env
626 	 * LFO
627 	 * AMP
628 	 */
629 	/* Two oscillator */
630 	initSoundAlgo(B_NRO,	0, baudio, audiomain, baudio->sound);
631 	initSoundAlgo(B_NRO,	1, baudio, audiomain, baudio->sound);
632 	/* A filter */
633 	initSoundAlgo(B_FILTER, 2, baudio, audiomain, baudio->sound);
634 	/* An noise source */
635 	initSoundAlgo(B_NOISE,	3, baudio, audiomain, baudio->sound);
636 	/* Three ADSR with AMP */
637 	initSoundAlgo(B_ENV5S,	4, baudio, audiomain, baudio->sound);
638 	initSoundAlgo(B_ENV5S,	5, baudio, audiomain, baudio->sound);
639 	initSoundAlgo(B_ENV5S,	6, baudio, audiomain, baudio->sound);
640 	initSoundAlgo(B_DCA,	7, baudio, audiomain, baudio->sound);
641 	/* LFO */
642 	initSoundAlgo(B_LFO,	8, baudio, audiomain, baudio->sound);
643 
644 	baudio->param = poly800Controller;
645 	baudio->destroy = bristolPoly800Destroy;
646 	baudio->operate = operateOnePoly800;
647 	baudio->preops = poly800Preops;
648 	baudio->postops = poly800PostOps;
649 
650 	/*
651 	 * Put in a vibrachorus on our effects list.
652 	 */
653 	initSoundAlgo(12, 0, baudio, audiomain, baudio->effect);
654 
655 	baudio->mixlocals = (float *) bristolmalloc0(sizeof(p800mods));
656 	((p800mods *) baudio->mixlocals)->voicecount = baudio->voicecount;
657 
658 	if (P800LOCAL->freqbuf == NULL)
659 		P800LOCAL->freqbuf = (float *) bristolmalloc0(audiomain->segmentsize);
660 	if (P800LOCAL->oscabuf == NULL)
661 		P800LOCAL->oscabuf = (float *) bristolmalloc0(audiomain->segmentsize);
662 	if (P800LOCAL->oscbbuf == NULL)
663 		P800LOCAL->oscbbuf = (float *) bristolmalloc0(audiomain->segmentsize);
664 	if (P800LOCAL->adsrbuf == NULL)
665 		P800LOCAL->adsrbuf = (float *) bristolmalloc0(audiomain->segmentsize);
666 	if (P800LOCAL->outbuf == NULL)
667 		P800LOCAL->outbuf = (float *) bristolmalloc0(audiomain->segmentsize);
668 	if (P800LOCAL->zerobuf == NULL)
669 		P800LOCAL->zerobuf = (float *) bristolmalloc0(audiomain->segmentsize);
670 	if (P800LOCAL->scratch == NULL)
671 		P800LOCAL->scratch = (float *) bristolmalloc0(audiomain->segmentsize);
672 	if (P800LOCAL->syncbuf == NULL)
673 		P800LOCAL->syncbuf = (float *) bristolmalloc0(audiomain->segmentsize);
674 	if (P800LOCAL->pwmbuf == NULL)
675 		P800LOCAL->pwmbuf = (float *) bristolmalloc0(audiomain->segmentsize);
676 	if (P800LOCAL->lfobuf == NULL)
677 		P800LOCAL->lfobuf = (float *) bristolmalloc0(audiomain->segmentsize);
678 	if (P800LOCAL->noisebuf == NULL)
679 		P800LOCAL->noisebuf = (float *) bristolmalloc0(audiomain->segmentsize);
680 	if (P800LOCAL->filtbuf == NULL)
681 		P800LOCAL->filtbuf = (float *) bristolmalloc0(audiomain->segmentsize);
682 
683 	return(0);
684 }
685 
686