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 /*#define BRISTOL_DBG */
22 /*
23 * Need to have basic template for an operator. Will consist of
24 *
25 * arpdcoinit()
26 * operate()
27 * reset()
28 * destroy()
29 *
30 * destroy() is in the library.
31 *
32 * Operate will be called when all the inputs have been loaded, and the result
33 * will be an output buffer written to the next operator.
34 */
35
36 #include <math.h>
37
38 #include "bristol.h"
39 #include "bristolblo.h"
40 #include "arpdco.h"
41
42 float note_diff, *zbuf;
43
44 #define BRISTOL_SQR 4
45
46 /*
47 * The name of this operator, IO count, and IO names. This is where possible
48 * identical to the Prophet DCO, but we need separated outputs. We could use
49 * it for the Prophet as well but that would incur the cost of extra mixing
50 * code.
51 */
52 #define OPNAME "DCO"
53 #define OPDESCRIPTION "ARP Digitally Controlled Oscillator"
54 #define PCOUNT 8
55 #define IOCOUNT 7
56
57 #define DCO_IN_IND 0
58 #define DCO_MOD_IND 1
59 #define DCO_OUT_RAMP 2
60 #define DCO_SYNC_IND 3
61 #define DCO_OUT_SQUARE 4
62 #define DCO_OUT_SINE 5
63 #define DCO_OUT_TRIANGLE 6
64
65 #define DCO_WAVE_COUNT 6
66
67 static void fillWave();
68
69 /*
70 * We should not be doing this however I need a quick resolution to some issues
71 * with sync of square waves and this is a scratch buffer for the edge detector
72 */
73 static float *sbuf = NULL;
74
75 /*
76 * Reset any local memory information.
77 */
destroy(bristolOP * operator)78 static int destroy(bristolOP *operator)
79 {
80 #ifdef BRISTOL_DBG
81 printf("destroy(%x)\n", operator);
82 #endif
83
84 /*
85 * Unmalloc anything we added to this structure
86 */
87 bristolfree(((bristolARPDCO *) operator)->wave[0]);
88 bristolfree(((bristolARPDCO *) operator)->wave[1]);
89 bristolfree(((bristolARPDCO *) operator)->wave[2]);
90 bristolfree(((bristolARPDCO *) operator)->wave[3]);
91 bristolfree(((bristolARPDCO *) operator)->wave[4]);
92 bristolfree(((bristolARPDCO *) operator)->wave[5]);
93 bristolfree(((bristolARPDCO *) operator)->wave[6]);
94 bristolfree(((bristolARPDCO *) operator)->wave[7]);
95
96 bristolfree(operator->specs);
97
98 /*
99 * Free any local memory. We should also free ourselves, since we did the
100 * initial allocation.
101 */
102 cleanup(operator);
103
104 return(0);
105 }
106
107 /*
108 * Reset any local memory information.
109 */
reset(bristolOP * operator,bristolOPParams * param)110 static int reset(bristolOP *operator, bristolOPParams *param)
111 {
112 #ifdef BRISTOL_DBG
113 printf("arpreset(%x)\n", operator);
114 #endif
115
116 param->param[0].int_val = ARPDCO_WAVE_SZE / 2;
117 if (param->param[0].mem != NULL) bristolfree(param->param[0].mem);
118 param->param[0].mem = bristolmalloc0(sizeof(float) * ARPDCO_WAVE_SZE);
119 if (param->param[1].mem != NULL) bristolfree(param->param[1].mem);
120 param->param[1].mem = bristolmalloc0(sizeof(float) * ARPDCO_WAVE_SZE);
121 param->param[1].float_val = 1.0;
122 param->param[2].float_val = 1.0;
123 param->param[3].float_val = 1.0;
124 param->param[6].int_val = 1;
125 param->param[7].int_val = 0;
126 param->param[9].float_val = 1.0;
127 param->param[10].float_val = 1.0;
128 param->param[11].float_val = 1.0;
129
130 return(0);
131 }
132
133 /*
134 * Alter an internal parameter of an operator.
135 */
param(bristolOP * operator,bristolOPParams * param,unsigned char index,float value)136 static int param(bristolOP *operator, bristolOPParams *param,
137 unsigned char index, float value)
138 {
139 #ifdef BRISTOL_DBG
140 printf("arpdcoparam(%i, %f/%f)\n",
141 index, value, (int) (value*CONTROLLER_RANGE));
142 #endif
143
144 switch (index) {
145 case 0: /* PW */
146 param->param[index].float_val = value * ARPDCO_WAVE_SZE * 0.5;
147 break;
148 case 1:
149 /*
150 * Transpose in octaves. 0 to 5, down 2 up 3.
151 */
152 {
153 int note = value * CONTROLLER_RANGE;
154
155 param->param[1].int_val = 0;
156
157 switch (note) {
158 case 0:
159 param->param[1].float_val = 0.25;
160 break;
161 case 1:
162 param->param[1].float_val = 0.50;
163 break;
164 case 2:
165 param->param[1].float_val = 1.0;
166 break;
167 case 3:
168 param->param[1].float_val = 2.0;
169 break;
170 case 4:
171 param->param[1].float_val = 4.0;
172 break;
173 case 5:
174 param->param[1].float_val = 8.0;
175 break;
176 case 10:
177 /* This should set values for LFO operation. */
178 param->param[1].float_val = 0.125;
179 param->param[1].int_val = 1;
180 break;
181 }
182 }
183 break;
184 case 2: /* Tune in "small" amounts */
185 {
186 float tune, notes = 1.0;
187 int i;
188
189 tune = (value - 0.5) * 2;
190
191 /*
192 * Up or down 7 notes.
193 */
194 for (i = 0; i < 7;i++)
195 {
196 if (tune > 0)
197 notes *= note_diff;
198 else
199 notes /= note_diff;
200 }
201
202 if (tune > 0)
203 param->param[index].float_val =
204 1.0 + (notes - 1) * tune;
205 else
206 param->param[index].float_val =
207 1.0 - (1 - notes) * -tune;
208
209 break;
210 }
211 case 3: /* gain */
212 param->param[index].float_val = value;
213 break;
214 case 4: /* mix ramp */
215 case 5: /* mix tri */
216 case 8: /* mix sine */
217 case 6: /* mix PWM square */
218 /*
219 * These were dropped, we always mix all waveforms. Perhaps there
220 * will be an odyssey/2600 option where we produce either
221 * ramp/square or ramp/square/sine/triangle, but this can also
222 * be achieved with null pointers.
223 */
224 break;
225 case 7: /* sync flag */
226 if (value == 0)
227 param->param[index].int_val = 0;
228 else
229 param->param[index].int_val = 1;
230 break;
231 /* case 8: used for waveform mix. */
232 case 9: /* semitone tuning. */
233 /*
234 * Transpose in semitones upwards.
235 */
236 {
237 int semitone = value * CONTROLLER_RANGE;
238
239 param->param[index].float_val = 1.0;
240
241 while (semitone-- > 0) {
242 param->param[index].float_val *= (note_diff);
243 }
244 }
245 break;
246 case 10: /* semitone fine tuning. */
247 /*
248 * finetune by a semitones up/down.
249 */
250 {
251 float tune, notes = 1.0;
252
253 tune = (value - 0.5);
254
255 /*
256 * Up or down 7 notes.
257 */
258 if (tune > 0)
259 notes *= note_diff;
260 else
261 notes /= note_diff;
262
263 if (tune > 0)
264 param->param[index].float_val =
265 1.0 + (notes - 1) * tune;
266 else param->param[index].float_val =
267 1.0 - (1 - notes) * -tune;
268
269 break;
270 }
271 case 11: /* This will be used by the OBX pitch bend */
272 {
273 float tune, notes = 1.0;
274 int i;
275
276 tune = (value - 0.5) * 2;
277
278 /*
279 * Up or down 12 notes.
280 */
281 for (i = 0; i < 12;i++)
282 {
283 if (tune > 0)
284 notes *= note_diff;
285 else
286 notes /= note_diff;
287 }
288
289 if (tune > 0)
290 param->param[index].float_val =
291 1.0 + (notes - 1) * tune;
292 else
293 param->param[index].float_val =
294 1.0 - (1 - notes) * -tune;
295
296 break;
297 }
298 }
299
300 return(0);
301 }
302
303 static float
genSyncPoints(register float * sbuf,float * sb,register float lsv,register int count)304 genSyncPoints(register float *sbuf, float *sb, register float lsv,
305 register int count)
306 {
307 /*
308 * Take the sync buffer and look for zero crossings. When they are found
309 * do a resample to find out where the crossing happened as sample level
310 * resolution results in distortion and shimmer
311 *
312 * Resampling, or rather interpolation to zero, means we have to look at
313 * the respective above and below zero values.
314 */
315 for (; count > 0; count--, lsv = *sb++)
316 *sbuf++ = ((lsv < 0) && (*sb >= 0))? lsv / (lsv - *sb) : 0;
317
318 return(lsv);
319 }
320
321 #define S_DEC 0.999f
322
323 /*
324 * As of the first write, 9/11/01, this takes nearly 20mips to operate a single
325 * oscillator. Will work on optimisation of the code, using non-referenced
326 * variables in register workspace.
327 *
328 * output buffer pointer.
329 * output buffer index.
330 * input buffer index.
331 * wavetable.
332 * wavetable index.
333 * count.
334 * gain.
335 *
336 * With optimisations this is reduced to a nominal amount. Put most parameters
337 * in registers, and then stretched the for loop to multiples of 16 samples.
338 *
339 * I would prefer to have this turned into a linear input, rated at 1float per
340 * octave. This would require some considerable alterations to the oscillator
341 * sample step code, though. The basic operation is reasonably simple - we take
342 * a (midikey/12) and it gives us a step rate. We need to work in portamento and
343 * some more subtle oscillator driver changes.
344 */
operate(bristolOP * operator,bristolVoice * voice,bristolOPParams * param,void * lcl)345 static int operate(bristolOP *operator,
346 bristolVoice *voice,
347 bristolOPParams *param,
348 void *lcl)
349 {
350 bristolARPDCOlocal *local = lcl;
351 int obp, count, dosquare;
352 float *ramp, wtpSqr, gdelta, width, ssg;
353 float *ib, *ob, *ob2, *mb, *sb, *wt, wtp, gain, transp, cpwm, lsv;
354 float *obsin, *obtri, *sinwave, *triwave;
355 bristolARPDCO *specs;
356
357 specs = (bristolARPDCO *) operator->specs;
358
359 #ifdef BRISTOL_DBG
360 printf("arpdco(%x, %x, %x)\n", operator, param, local);
361 #endif
362
363 count = specs->spec.io[DCO_OUT_RAMP].samplecount;
364 ib = specs->spec.io[DCO_IN_IND].buf;
365 mb = specs->spec.io[DCO_MOD_IND].buf;
366 ob = specs->spec.io[DCO_OUT_RAMP].buf;
367 ob2 = specs->spec.io[DCO_OUT_SQUARE].buf;
368 if ((obsin = specs->spec.io[DCO_OUT_SINE].buf) == 0)
369 obsin = zbuf;
370 if ((obtri = specs->spec.io[DCO_OUT_TRIANGLE].buf) == 0)
371 obtri = zbuf;
372
373 lsv = local->lsv;
374
375 /*
376 * Hm, this was not necessary - could just have taken a zero bufptr.
377 */
378 if ((param->param[7].int_val)
379 && ((sb = specs->spec.io[DCO_SYNC_IND].buf) != 0))
380 local->lsv = genSyncPoints(sbuf, sb, lsv, count);
381 else
382 sb = 0;
383
384 width = param->param[0].float_val; /* Pulse width */
385 dosquare = param->param[6].int_val;
386 /* wtp = local->wtp; */
387 gain = param->param[3].float_val;
388 ssg = local->ssg >= 0? gain:-gain;
389
390 /*
391 * We are going to add another tune parameter - number of semitones from
392 * zero - an addition to octave transpose and fine tune. We should add
393 * another fine tune for just +/- semitone
394 */
395 transp = param->param[1].float_val * param->param[2].float_val
396 * param->param[9].float_val * param->param[10].float_val
397 * param->param[11].float_val;
398 wtp = local->wtp;
399 cpwm = local->cpwm;
400
401 sinwave = specs->wave[0];
402 if (bristolBLOcheck(voice->dFreq*transp))
403 {
404 /* Need to restuff tri, ramp */
405 memset(param->param[0].mem, 0, ARPDCO_WAVE_SZE * sizeof(float));
406 memset(param->param[1].mem, 0, ARPDCO_WAVE_SZE * sizeof(float));
407 ramp = param->param[0].mem;
408 wt = ramp;
409 triwave = param->param[1].mem;
410 generateBLOwaveformF(voice->cFreq*transp, ramp, BLO_SAW);
411 generateBLOwaveformF(voice->cFreq*transp, triwave, BLO_TRI);
412 } else {
413 wt = ramp = specs->wave[3];
414 triwave = specs->wave[4];
415 }
416
417 /*
418 * Go jumping through the wavetable, with each jump defined by the value
419 * given on our input line, making sure we fill one output buffer.
420 */
421 for (obp = 0; obp < count;obp++)
422 {
423 /*
424 * Take a sample from the wavetable into the output buffer. This
425 * should also be scaled by gain parameter.
426 *
427 * We can seperate this into subroutine calls, or we can take our
428 * values and take each wave?
429 */
430 gdelta = wtp - ((float) ((int) wtp));
431
432 if (wtp >= ARPDCO_WAVE_SZE_M) {
433 ob[obp] += (wt[(int) wtp] + (wt[0] - wt[(int) wtp])
434 * gdelta) * gain;
435 obsin[obp] += (sinwave[(int) wtp]
436 + (sinwave[0] - sinwave[(int) wtp])
437 * gdelta) * gain;
438 obtri[obp] += (triwave[(int) wtp]
439 + (triwave[0] - triwave[(int) wtp])
440 * gdelta) * gain;
441 } else {
442 ob[obp] += (wt[(int) wtp] + ((wt[(int) wtp + 1] - wt[(int) wtp])
443 * gdelta)) * gain;
444 obsin[obp] += (sinwave[(int) wtp]
445 + ((sinwave[(int) wtp + 1] - sinwave[(int) wtp])
446 * gdelta)) * gain;
447 obtri[obp] += (triwave[(int) wtp]
448 + ((triwave[(int) wtp + 1] - triwave[(int) wtp])
449 * gdelta)) * gain;
450 }
451
452 /*
453 * The square has to be computed real time as we are going to have
454 * pulse width modulation. Width is a faction of the wavetable size
455 * from zero to 50% (should be 5 to 50%?).
456 *
457 * This is a phased difference between two ramps.
458 *
459 * Fill in the ramp wave, then subtract the same waveform with a
460 * phase offset related to the width.
461 */
462 if ((wtpSqr = width + *mb++) < ARPDCO_WAVE_PWMIN)
463 wtpSqr = ARPDCO_WAVE_PWMIN;
464 else if (wtpSqr > ARPDCO_WAVE_PWMAX)
465 wtpSqr = ARPDCO_WAVE_PWMAX;
466
467 if ((wtpSqr = wtp + wtpSqr) > ARPDCO_WAVE_SZE_M)
468 wtpSqr -= ARPDCO_WAVE_SZE;
469
470 if (wtp >= ARPDCO_WAVE_SZE_M)
471 ob2[obp] += (ramp[(int) wtp] + (ramp[0] - ramp[(int) wtp])
472 * gdelta) * ssg;
473 else
474 ob2[obp] +=
475 (ramp[(int) wtp] + ((ramp[(int) wtp + 1] - ramp[(int) wtp])
476 * gdelta)) * ssg;
477
478 gdelta = wtpSqr - ((float) ((int) wtpSqr));
479
480 if (wtpSqr == ARPDCO_WAVE_SZE_M)
481 ob2[obp] -= (ramp[(int) wtpSqr] + (ramp[0] - ramp[(int) wtpSqr])
482 * gdelta) * ssg;
483 else
484 ob2[obp] -=
485 (ramp[(int) wtpSqr] + ((ramp[(int) wtpSqr + 1]
486 - ramp[(int) wtpSqr]) * gdelta)) * ssg;
487
488 if (sb && (sbuf[obp] != 0))
489 {
490 /*
491 * These are positive edged zero crossings on the sync buffer. If
492 * we find them, wtp is moved to zero resampled from buffer.
493 */
494 wtp = sbuf[obp];
495 ssg = -ssg;
496
497 /* We may need to resample here */
498
499 continue;
500 }
501
502 /*
503 * Move the wavetable pointer forward by amount indicated in input
504 * buffer for this sample.
505 */
506 if ((wtp += ib[obp] * transp) >= ARPDCO_WAVE_SZE)
507 {
508 while (wtp >= ARPDCO_WAVE_SZE)
509 wtp -= ARPDCO_WAVE_SZE;
510 }
511
512 /*
513 * If we have gone negative, round back up. Allows us to run the
514 * oscillator backwards.
515 */
516 while (wtp < 0)
517 wtp += ARPDCO_WAVE_SZE;
518 }
519
520 local->wtp = wtp;
521 local->cpwm = cpwm;
522 local->ssg = ssg;
523
524 return(0);
525 }
526
527 /*
528 * Setup any variables in our OP structure, in our IO structures, and malloc
529 * any memory we need.
530 */
531 bristolOP *
arpdcoinit(bristolOP ** operator,int index,int samplerate,int samplecount)532 arpdcoinit(bristolOP **operator, int index, int samplerate, int samplecount)
533 {
534 bristolARPDCO *specs;
535
536 *operator = bristolOPinit(operator, index, samplecount);
537
538 #ifdef BRISTOL_DBG
539 printf("arpdcoinit(%x(%x), %i, %i, %i)\n",
540 operator, *operator, index, samplerate, samplecount);
541 #endif
542
543 note_diff = pow(2, ((double) 1)/12);
544
545 if (sbuf == NULL)
546 sbuf = bristolmalloc(sizeof(float) * samplecount);
547
548 /*
549 * Then the local parameters specific to this operator. These will be
550 * the same for each operator, but must be inited in the local code.
551 */
552 (*operator)->operate = operate;
553 (*operator)->destroy = destroy;
554 (*operator)->reset = reset;
555 (*operator)->param= param;
556
557 specs = (bristolARPDCO *) bristolmalloc0(sizeof(bristolARPDCO));
558 (*operator)->specs = (bristolOPSpec *) specs;
559 (*operator)->size = sizeof(bristolARPDCO);
560
561 /*
562 * These are specific to this operator, and will need to be altered for
563 * each operator.
564 */
565 specs->spec.opname = OPNAME;
566 specs->spec.description = OPDESCRIPTION;
567 specs->spec.pcount = PCOUNT;
568 specs->spec.iocount = IOCOUNT;
569 specs->spec.localsize = sizeof(bristolARPDCOlocal);
570
571 /*
572 * We are going to assign multiple waves to this oscillator.
573 * sine, ramp, square, triangle?
574 */
575 specs->wave[0] =
576 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
577 specs->wave[1] =
578 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
579 specs->wave[2] =
580 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
581 specs->wave[3] =
582 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
583 specs->wave[4] =
584 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
585 specs->wave[5] =
586 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
587 specs->wave[6] =
588 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
589 specs->wave[7] =
590 (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
591 zbuf = (float *) bristolmalloc(ARPDCO_WAVE_SZE * sizeof(float));
592
593 /*
594 * FillWave is something that should be called as a parameter change, but
595 * for testing will load it here.
596 */
597 fillWave(specs->wave[0], ARPDCO_WAVE_SZE, 0);
598 fillWave(specs->wave[1], ARPDCO_WAVE_SZE, 1);
599 fillWave(specs->wave[2], ARPDCO_WAVE_SZE, 2);
600 fillWave(specs->wave[3], ARPDCO_WAVE_SZE, 3);
601 fillWave(specs->wave[4], ARPDCO_WAVE_SZE, 4);
602 fillWave(specs->wave[5], ARPDCO_WAVE_SZE, 5);
603 fillWave(specs->wave[6], ARPDCO_WAVE_SZE, 6);
604 fillWave(specs->wave[7], ARPDCO_WAVE_SZE, 7);
605
606 /*
607 * Now fill in the dco specs for this operator. These are specific to an
608 * oscillator.
609 */
610 specs->spec.param[0].pname = "Pulse";
611 specs->spec.param[0].description = "Pulse width";
612 specs->spec.param[0].type = BRISTOL_FLOAT;
613 specs->spec.param[0].low = 0;
614 specs->spec.param[0].high = 1;
615 specs->spec.param[0].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
616
617 specs->spec.param[1].pname = "Transpose";
618 specs->spec.param[1].description = "Octave transposition";
619 specs->spec.param[1].type = BRISTOL_INT;
620 specs->spec.param[1].low = 0;
621 specs->spec.param[1].high = 12;
622 specs->spec.param[1].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
623
624 specs->spec.param[2].pname = "Tune";
625 specs->spec.param[2].description = "fine tuning of frequency";
626 specs->spec.param[2].type = BRISTOL_FLOAT;
627 specs->spec.param[2].low = 0;
628 specs->spec.param[2].high = 1;
629 specs->spec.param[2].flags = BRISTOL_ROTARY|BRISTOL_SLIDER;
630
631 specs->spec.param[3].pname = "gain";
632 specs->spec.param[3].description = "output gain on signal";
633 specs->spec.param[3].type = BRISTOL_FLOAT;
634 specs->spec.param[3].low = 0;
635 specs->spec.param[3].high = 2;
636 specs->spec.param[3].flags = BRISTOL_ROTARY|BRISTOL_SLIDER|BRISTOL_HIDE;
637
638 specs->spec.param[4].pname = "Ramp";
639 specs->spec.param[4].description = "harmonic inclusion of ramp wave";
640 specs->spec.param[4].type = BRISTOL_INT;
641 specs->spec.param[4].low = 0;
642 specs->spec.param[4].high = 1;
643 specs->spec.param[4].flags = BRISTOL_BUTTON;
644
645 specs->spec.param[5].pname = "Triangle";
646 specs->spec.param[5].description = "harmonic inclusion of triagular wave";
647 specs->spec.param[5].type = BRISTOL_INT;
648 specs->spec.param[5].low = 0;
649 specs->spec.param[5].high = 1;
650 specs->spec.param[5].flags = BRISTOL_BUTTON;
651
652 specs->spec.param[6].pname = "PWM";
653 specs->spec.param[6].description = "harmonic inclusion of square/pwm wave";
654 specs->spec.param[6].type = BRISTOL_INT;
655 specs->spec.param[6].low = 0;
656 specs->spec.param[6].high = 1;
657 specs->spec.param[6].flags = BRISTOL_BUTTON;
658
659 specs->spec.param[7].pname = "Square";
660 specs->spec.param[7].description = "harmonic inclusion of square wave";
661 specs->spec.param[7].type = BRISTOL_INT;
662 specs->spec.param[7].low = 0;
663 specs->spec.param[7].high = 1;
664 specs->spec.param[7].flags = BRISTOL_BUTTON;
665
666 specs->spec.param[8].pname = "Sine";
667 specs->spec.param[8].description = "harmonic inclusion of sine wave";
668 specs->spec.param[8].type = BRISTOL_INT;
669 specs->spec.param[8].low = 0;
670 specs->spec.param[8].high = 1;
671 specs->spec.param[8].flags = BRISTOL_BUTTON;
672
673 /*
674 * Now fill in the dco IO specs.
675 */
676 specs->spec.io[0].ioname = "input";
677 specs->spec.io[0].description = "input rate modulation signal";
678 specs->spec.io[0].samplerate = samplerate;
679 specs->spec.io[0].samplecount = samplecount;
680 specs->spec.io[0].flags = BRISTOL_DC|BRISTOL_INPUT;
681
682 specs->spec.io[1].ioname = "mod";
683 specs->spec.io[1].description = "pulse width modulation";
684 specs->spec.io[1].samplerate = samplerate;
685 specs->spec.io[1].samplecount = samplecount;
686 specs->spec.io[1].flags = BRISTOL_DC|BRISTOL_INPUT;
687
688 specs->spec.io[2].ioname = "ramp output";
689 specs->spec.io[2].description = "oscillator ramp output signal";
690 specs->spec.io[2].samplerate = samplerate;
691 specs->spec.io[2].samplecount = samplecount;
692 specs->spec.io[2].flags = BRISTOL_AC|BRISTOL_OUTPUT;
693
694 specs->spec.io[3].ioname = "sync";
695 specs->spec.io[3].description = "synchronisation signal";
696 specs->spec.io[3].samplerate = samplerate;
697 specs->spec.io[3].samplecount = samplecount;
698 specs->spec.io[3].flags = BRISTOL_DC|BRISTOL_INPUT;
699
700 specs->spec.io[4].ioname = "square output";
701 specs->spec.io[4].description = "oscillator pulse/square output signal";
702 specs->spec.io[4].samplerate = samplerate;
703 specs->spec.io[4].samplecount = samplecount;
704 specs->spec.io[4].flags = BRISTOL_AC|BRISTOL_OUTPUT;
705
706 specs->spec.io[5].ioname = "sine output";
707 specs->spec.io[5].description = "oscillator sine output signal";
708 specs->spec.io[5].samplerate = samplerate;
709 specs->spec.io[5].samplecount = samplecount;
710 specs->spec.io[5].flags = BRISTOL_AC|BRISTOL_OUTPUT;
711
712 specs->spec.io[6].ioname = "triangle output";
713 specs->spec.io[6].description = "oscillator triangle output signal";
714 specs->spec.io[6].samplerate = samplerate;
715 specs->spec.io[6].samplecount = samplecount;
716 specs->spec.io[6].flags = BRISTOL_AC|BRISTOL_OUTPUT;
717
718 return(*operator);
719 }
720
721 static void
fillPDsine(float * mem,int count,int compress)722 fillPDsine(float *mem, int count, int compress)
723 {
724 float j = 0, i, inc1, inc2;
725
726 /*
727 * Resample the sine wave with a phase distortion algorithm.
728 *
729 * We have to get to M_PI/2 in compress steps, hence
730 *
731 * inc1 = M_PI/(2 * compress)
732 *
733 * Then we have to scan M_PI in (count - 2 * compress), hence:
734 *
735 * inc2 = M_PI/(count - 2 * compress)
736 */
737 inc1 = ((float) M_PI) / (((float) 2) * ((float) compress));
738 inc2 = ((float) M_PI) / ((float) (count - 2 * compress));
739
740 for (i = 0;i < count; i++)
741 {
742 *mem++ = sinf(j) * BRISTOL_VPO;
743
744 if (i < compress)
745 j += inc1;
746 else if (i > (count - 2 * compress))
747 j += inc1;
748 else
749 j += inc2;
750 }
751 }
752
753 /*
754 * Waves have a range of 24, which is basically two octaves. For larger
755 * differences will have to apply apms.
756 */
757 static void
fillWave(float * mem,int count,int type)758 fillWave(float *mem, int count, int type)
759 {
760 int i;
761
762 #ifdef BRISTOL_DBG
763 printf("fillWave(%x, %i, %i)\n", mem, count, type);
764 #endif
765
766 switch (type) {
767 case 0:
768 /*
769 * This will be a sine wave. We have count samples, and
770 * 2PI radians in a full sine wave. Thus we take
771 * (2PI * i / count) * 2048.
772 */
773 for (i = 0;i < count; i++)
774 mem[i] = sin(2 * M_PI * ((double) i) / count) * BRISTOL_VPO;
775 return;
776 case 1:
777 default:
778 {
779 float value = BRISTOL_SQR;
780 /*
781 * This is a square wave, with decaying plateaus.
782 */
783 if (blo.flags & BRISTOL_BLO)
784 {
785 for (i = 0;i < count; i++)
786 mem[i] = blosquare[i];
787 return;
788 }
789 for (i = 0;i < count / 2; i++)
790 mem[i] = (value * S_DEC);
791 value = -BRISTOL_SQR;
792 for (;i < count; i++)
793 mem[i] = (value * S_DEC);
794 return;
795 }
796 case 2:
797 /*
798 * This is a pulse wave - the arp dco does pwm.
799 */
800 for (i = 0;i < count / 5; i++)
801 mem[i] = BRISTOL_VPO * 2 / 3;
802 for (;i < count; i++)
803 mem[i] = -BRISTOL_VPO * 2 / 3;
804 return;
805 case 3:
806 /*
807 * This is a ramp wave. We scale the index from -.5 to .5, and
808 * multiply by the range. We go from rear to front to table to make
809 * the ramp wave have a positive leading edge.
810 for (i = 0; i < count / 2; i++)
811 mem[i] = ((float) i / count) * BRISTOL_VPO * 2.0;
812 for (; i < count; i++)
813 mem[i] = ((float) i / count) * BRISTOL_VPO * 2.0 -
814 BRISTOL_VPO * 2;
815 for (i = count - 1;i >= 0; i--)
816 mem[i] = (((float) i / count) - 0.5) * BRISTOL_VPO * 2.0;
817 mem[0] = 0;
818 mem[count - 1] = mem[1]
819 = BRISTOL_VPO;
820 */
821 if (blo.flags & BRISTOL_BLO)
822 {
823 for (i = 0;i < count; i++)
824 mem[i] = bloramp[i];
825 return;
826 }
827 fillPDsine(mem, count, 5);
828 return;
829 case 4:
830 /*
831 * Triangular wave. From MIN point, ramp up at twice the rate of
832 * the ramp wave, then ramp down at same rate.
833 */
834 if (blo.flags & BRISTOL_BLO)
835 {
836 for (i = 0;i < count; i++)
837 mem[i] = blotriangle[i];
838 return;
839 }
840 for (i = 0;i < count / 2; i++)
841 mem[i] = -BRISTOL_VPO
842 + ((float) i / (count / 2)) * BRISTOL_VPO * 2;
843 for (;i < count; i++)
844 mem[i] = BRISTOL_VPO -
845 (((float) (i - count / 2) * 2) / (count / 2)) * BRISTOL_VPO;
846 return;
847 case 5:
848 /*
849 * Would like to put in a jagged edged ramp wave. Should make some
850 * interesting strings sounds.
851 */
852 {
853 float accum = -BRISTOL_VPO;
854
855 for (i = 0; i < count / 2; i++)
856 {
857 mem[i] = accum +
858 (0.5 - (((float) i) / count)) * BRISTOL_VPO * 4;
859 if (i == count / 8)
860 accum = -BRISTOL_VPO * 3 / 4;
861 if (i == count / 4)
862 accum = -BRISTOL_VPO / 2;
863 if (i == count * 3 / 8)
864 accum = -BRISTOL_VPO / 4;
865 }
866 for (; i < count; i++)
867 mem[i] = -mem[count - i];
868 }
869 return;
870 case 6:
871 /*
872 * Tangiential wave. We limit some of the values, since they do get
873 * excessive. This is only half a tan as well, to maintain the
874 * base frequency.
875 */
876 for (i = 0;i < count; i++)
877 {
878 if ((mem[i] =
879 tan(M_PI * ((double) i) / count) * BRISTOL_VPO / 16)
880 > BRISTOL_VPO * 8)
881 mem[i] = BRISTOL_VPO * 6;
882 if (mem[i] < -(BRISTOL_VPO * 6))
883 mem[i] = -BRISTOL_VPO * 6;
884 }
885 return;
886 case 7:
887 /*
888 * Sine wave - added as a part of the OBX extensions.
889 */
890 for (i = 0;i < count; i++)
891 mem[i] = sin(2 * M_PI * ((double) i) / count) * BRISTOL_VPO;
892 return;
893 }
894 }
895
896