1 /************************************************************************/
2 /* */
3 /* MAME - Discrete sound system emulation library */
4 /* */
5 /* Written by Keith Wilkins (mame@esplexo.co.uk) */
6 /* */
7 /* (c) K.Wilkins 2000 */
8 /* */
9 /************************************************************************/
10 /* */
11 /* DSS_SINEWAVE - Sinewave generator source code */
12 /* DSS_SQUAREWAVE - Squarewave generator source code */
13 /* DSS_TRIANGLEWAVE - Triangle waveform generator */
14 /* DSS_SAWTOOTHWAVE - Sawtooth waveform generator */
15 /* DSS_NOISE - Noise Source - Random source */
16 /* DSS_LFSR_NOISE - Linear Feedback Shift Register Noise */
17 /* */
18 /************************************************************************/
19
20 #define PI 3.14159
21
22 struct dss_sinewave_context
23 {
24 float phase;
25 };
26
27 struct dss_noise_context
28 {
29 float phase;
30 };
31
32 struct dss_lfsr_context
33 {
34 float phase;
35 int lfsr_reg;
36 };
37
38 struct dss_squarewave_context
39 {
40 float phase;
41 float trigger;
42 };
43
44 struct dss_trianglewave_context
45 {
46 float phase;
47 };
48
49 struct dss_sawtoothwave_context
50 {
51 float phase;
52 int type;
53 };
54
55 /************************************************************************/
56 /* */
57 /* DSS_SINWAVE - Usage of node_description values for step function */
58 /* */
59 /* input0 - Enable input value */
60 /* input1 - Frequency input value */
61 /* input2 - Amplitde input value */
62 /* input3 - DC Bias */
63 /* input4 - Starting phase */
64 /* input5 - NOT USED */
65 /* */
66 /************************************************************************/
dss_sinewave_step(struct node_description * node)67 int dss_sinewave_step(struct node_description *node)
68 {
69 struct dss_sinewave_context *context=(struct dss_sinewave_context*)node->context;
70 float newphase;
71
72 /* Work out the phase step based on phase/freq & sample rate */
73 /* The enable input only curtails output, phase rotation */
74 /* still occurs */
75
76 /* phase step = 2Pi/(output period/sample period) */
77 /* boils out to */
78 /* phase step = (2Pi*output freq)/sample freq) */
79 newphase=context->phase+((2.0*PI*node->input1)/Machine->sample_rate);
80 /* Keep the new phasor in thw 2Pi range.*/
81 context->phase=fmod(newphase,2.0*PI);
82
83 if(node->input0)
84 {
85 node->output=(node->input2/2.0) * sin(newphase);
86 /* Add DC Bias component */
87 node->output=node->output+node->input3;
88 }
89 else
90 {
91 /* Just output DC Bias */
92 node->output=node->input3;
93 }
94 return 0;
95 }
96
dss_sinewave_reset(struct node_description * node)97 int dss_sinewave_reset(struct node_description *node)
98 {
99 struct dss_sinewave_context *context;
100 float start;
101 context=(struct dss_sinewave_context*)node->context;
102 /* Establish starting phase, convert from degrees to radians */
103 start=(node->input4/360.0)*(2.0*PI);
104 /* Make sure its always mod 2Pi */
105 context->phase=fmod(start,2.0*PI);
106 return 0;
107 }
108
dss_sinewave_init(struct node_description * node)109 int dss_sinewave_init(struct node_description *node)
110 {
111 /* Allocate memory for the context array and the node execution order array */
112 if((node->context=(struct dss_sinewave_context*)malloc(sizeof(struct dss_sinewave_context)))==NULL)
113 {
114 return 1;
115 }
116 else
117 {
118 /* Initialise memory */
119 memset(node->context,0,sizeof(struct dss_sinewave_context));
120 }
121
122 /* Initialise the object */
123 dss_sinewave_reset(node);
124
125 return 0;
126 }
127
dss_sinewave_kill(struct node_description * node)128 int dss_sinewave_kill(struct node_description *node)
129 {
130 free(node->context);
131 node->context=NULL;
132 return 0;
133 }
134
135
136
137 /************************************************************************/
138 /* */
139 /* DSS_SQUAREWAVE - Usage of node_description values for step function */
140 /* */
141 /* input0 - Enable input value */
142 /* input1 - Frequency input value */
143 /* input2 - Amplitude input value */
144 /* input3 - Duty Cycle */
145 /* input4 - DC Bias level */
146 /* input5 - Start Phase */
147 /* */
148 /************************************************************************/
dss_squarewave_step(struct node_description * node)149 int dss_squarewave_step(struct node_description *node)
150 {
151 struct dss_squarewave_context *context=(struct dss_squarewave_context*)node->context;
152 float newphase;
153
154 /* Establish trigger phase from duty */
155 context->trigger=((100-node->input3)/100)*(2.0*PI);
156
157 /* Work out the phase step based on phase/freq & sample rate */
158 /* The enable input only curtails output, phase rotation */
159 /* still occurs */
160
161 /* phase step = 2Pi/(output period/sample period) */
162 /* boils out to */
163 /* phase step = (2Pi*output freq)/sample freq) */
164 newphase=context->phase+((2.0*PI*node->input1)/Machine->sample_rate);
165 /* Keep the new phasor in thw 2Pi range.*/
166 context->phase=fmod(newphase,2.0*PI);
167
168 if(node->input0)
169 {
170 if(context->phase>context->trigger)
171 node->output=(node->input2/2.0);
172 else
173 node->output=-(node->input2/2.0);
174
175 /* Add DC Bias component */
176 node->output=node->output+node->input4;
177 }
178 else
179 {
180 /* Just output DC Bias */
181 node->output=node->input4;
182 }
183 return 0;
184 }
185
dss_squarewave_reset(struct node_description * node)186 int dss_squarewave_reset(struct node_description *node)
187 {
188 struct dss_squarewave_context *context;
189 float start;
190 context=(struct dss_squarewave_context*)node->context;
191
192 /* Establish starting phase, convert from degrees to radians */
193 start=(node->input5/360.0)*(2.0*PI);
194 /* Make sure its always mod 2Pi */
195 context->phase=fmod(start,2.0*PI);
196
197 return 0;
198 }
199
dss_squarewave_init(struct node_description * node)200 int dss_squarewave_init(struct node_description *node)
201 {
202 /* Allocate memory for the context array and the node execution order array */
203 if((node->context=(struct dss_squarewave_context*)malloc(sizeof(struct dss_squarewave_context)))==NULL)
204 {
205 return 1;
206 }
207 else
208 {
209 /* Initialise memory */
210 memset(node->context,0,sizeof(struct dss_squarewave_context));
211 }
212
213 /* Initialise the object */
214 dss_squarewave_reset(node);
215
216 return 0;
217 }
218
dss_squarewave_kill(struct node_description * node)219 int dss_squarewave_kill(struct node_description *node)
220 {
221 free(node->context);
222 node->context=NULL;
223 return 0;
224 }
225
226
227 /************************************************************************/
228 /* */
229 /* DSS_TRIANGLEWAVE - Usage of node_description values for step function*/
230 /* */
231 /* input0 - Enable input value */
232 /* input1 - Frequency input value */
233 /* input2 - Amplitde input value */
234 /* input3 - DC Bias value */
235 /* input4 - Initial Phase */
236 /* input5 - NOT USED */
237 /* */
238 /************************************************************************/
dss_trianglewave_step(struct node_description * node)239 int dss_trianglewave_step(struct node_description *node)
240 {
241 struct dss_trianglewave_context *context=(struct dss_trianglewave_context*)node->context;
242 float newphase;
243
244 /* Work out the phase step based on phase/freq & sample rate */
245 /* The enable input only curtails output, phase rotation */
246 /* still occurs */
247
248 /* phase step = 2Pi/(output period/sample period) */
249 /* boils out to */
250 /* phase step = (2Pi*output freq)/sample freq) */
251 newphase=context->phase+((2.0*PI*node->input1)/Machine->sample_rate);
252 /* Keep the new phasor in thw 2Pi range.*/
253 newphase=fmod(newphase,2.0*PI);
254 context->phase=newphase;
255
256 if(node->input0)
257 {
258 node->output=newphase < PI ? (node->input2 * (newphase / (PI/2.0) - 1.0))/2.0 :
259 (node->input2 * (3.0 - newphase / (PI/2.0)))/2.0 ;
260
261 /* Add DC Bias component */
262 node->output=node->output+node->input3;
263 }
264 else
265 {
266 /* Just output DC Bias */
267 node->output=node->input3;
268 }
269 return 0;
270 }
271
dss_trianglewave_reset(struct node_description * node)272 int dss_trianglewave_reset(struct node_description *node)
273 {
274 struct dss_trianglewave_context *context;
275 float start;
276
277 context=(struct dss_trianglewave_context*)node->context;
278 /* Establish starting phase, convert from degrees to radians */
279 start=(node->input4/360.0)*(2.0*PI);
280 /* Make sure its always mod 2Pi */
281 context->phase=fmod(start,2.0*PI);
282 return 0;
283 }
284
dss_trianglewave_init(struct node_description * node)285 int dss_trianglewave_init(struct node_description *node)
286 {
287 /* Allocate memory for the context array and the node execution order array */
288 if((node->context=(struct dss_trianglewave_context*)malloc(sizeof(struct dss_trianglewave_context)))==NULL)
289 {
290 return 1;
291 }
292 else
293 {
294 /* Initialise memory */
295 memset(node->context,0,sizeof(struct dss_trianglewave_context));
296 }
297
298 /* Initialise the object */
299 dss_trianglewave_reset(node);
300 return 0;
301 }
302
dss_trianglewave_kill(struct node_description * node)303 int dss_trianglewave_kill(struct node_description *node)
304 {
305 free(node->context);
306 node->context=NULL;
307 return 0;
308 }
309
310
311
312 /************************************************************************/
313 /* */
314 /* DSS_SAWTOOTHWAVE - Usage of node_description values for step function*/
315 /* */
316 /* input0 - Enable input value */
317 /* input1 - Frequency input value */
318 /* input2 - Amplitde input value */
319 /* input3 - DC Bias Value */
320 /* input4 - Gradient */
321 /* input5 - Initial Phase */
322 /* */
323 /************************************************************************/
dss_sawtoothwave_step(struct node_description * node)324 int dss_sawtoothwave_step(struct node_description *node)
325 {
326 struct dss_sawtoothwave_context *context=(struct dss_sawtoothwave_context*)node->context;
327 float newphase;
328
329 /* Work out the phase step based on phase/freq & sample rate */
330 /* The enable input only curtails output, phase rotation */
331 /* still occurs */
332
333 /* phase step = 2Pi/(output period/sample period) */
334 /* boils out to */
335 /* phase step = (2Pi*output freq)/sample freq) */
336 newphase=context->phase+((2.0*PI*node->input1)/Machine->sample_rate);
337 /* Keep the new phasor in thw 2Pi range.*/
338 newphase=fmod(newphase,2.0*PI);
339 context->phase=newphase;
340
341 if(node->input0)
342 {
343 node->output=(context->type==0)?newphase*(node->input2/(2.0*PI)):node->input2-(newphase*(node->input2/(2.0*PI)));
344 node->output-=node->input2/2.0;
345 /* Add DC Bias component */
346 node->output=node->output+node->input3;
347 }
348 else
349 {
350 /* Just output DC Bias */
351 node->output=node->input3;
352 }
353 return 0;
354 }
355
dss_sawtoothwave_reset(struct node_description * node)356 int dss_sawtoothwave_reset(struct node_description *node)
357 {
358 struct dss_sawtoothwave_context *context;
359 float start;
360
361 context=(struct dss_sawtoothwave_context*)node->context;
362 /* Establish starting phase, convert from degrees to radians */
363 start=(node->input5/360.0)*(2.0*PI);
364 /* Make sure its always mod 2Pi */
365 context->phase=fmod(start,2.0*PI);
366
367 /* Invert gradient depending on sawtooth type /|/|/|/|/| or |\|\|\|\|\ */
368 context->type=(node->input4)?1:0;
369
370 return 0;
371 }
372
dss_sawtoothwave_init(struct node_description * node)373 int dss_sawtoothwave_init(struct node_description *node)
374 {
375 /* Allocate memory for the context array and the node execution order array */
376 if((node->context=(struct dss_sawtoothwave_context*)malloc(sizeof(struct dss_sawtoothwave_context)))==NULL)
377 {
378 return 1;
379 }
380 else
381 {
382 /* Initialise memory */
383 memset(node->context,0,sizeof(struct dss_sawtoothwave_context));
384 }
385
386 /* Initialise the object */
387 dss_sawtoothwave_reset(node);
388 return 0;
389 }
390
dss_sawtoothwave_kill(struct node_description * node)391 int dss_sawtoothwave_kill(struct node_description *node)
392 {
393 free(node->context);
394 node->context=NULL;
395 return 0;
396 }
397
398
399
400 /************************************************************************/
401 /* */
402 /* DSS_NOISE - Usage of node_description values for white nose generator*/
403 /* */
404 /* input0 - Enable input value */
405 /* input1 - Noise sample frequency */
406 /* input2 - Amplitude input value */
407 /* input3 - DC Bias value */
408 /* input4 - NOT USED */
409 /* input5 - NOT USED */
410 /* */
411 /************************************************************************/
dss_noise_step(struct node_description * node)412 int dss_noise_step(struct node_description *node)
413 {
414 struct dss_noise_context *context;
415 float newphase;
416 context=(struct dss_noise_context*)node->context;
417
418 newphase=context->phase+((2.0*PI*node->input1)/Machine->sample_rate);
419
420 /* Keep the new phasor in thw 2Pi range.*/
421 context->phase=fmod(newphase,2.0*PI);
422
423 if(node->input0)
424 {
425 /* Only sample noise on rollover to next cycle */
426 if(newphase>(2.0*PI))
427 {
428 int newval=rand() & 0x7fff;
429 node->output=node->input2*(1-(newval/16384.0));
430
431 /* Add DC Bias component */
432 node->output=node->output+node->input3;
433 }
434 }
435 else
436 {
437 /* Just output DC Bias */
438 node->output=node->input3;
439 }
440 return 0;
441 }
442
443
dss_noise_reset(struct node_description * node)444 int dss_noise_reset(struct node_description *node)
445 {
446 struct dss_noise_context *context=(struct dss_noise_context*)node->context;
447 context->phase=0;
448 return 0;
449 }
450
dss_noise_init(struct node_description * node)451 int dss_noise_init(struct node_description *node)
452 {
453 /* Allocate memory for the context array and the node execution order array */
454 if((node->context=(struct dss_noise_context*)malloc(sizeof(struct dss_noise_context)))==NULL)
455 {
456 return 1;
457 }
458 else
459 {
460 /* Initialise memory */
461 memset(node->context,0,sizeof(struct dss_noise_context));
462 }
463
464 /* Initialise the object */
465 dss_noise_reset(node);
466
467 return 0;
468 }
469
dss_noise_kill(struct node_description * node)470 int dss_noise_kill(struct node_description *node)
471 {
472 free(node->context);
473 node->context=NULL;
474 return 0;
475 }
476
477
478 /************************************************************************/
479 /* */
480 /* DSS_LFSR_NOISE - Usage of node_description values for LFSR noise gen */
481 /* */
482 /* input0 - Enable input value */
483 /* input1 - Register reset */
484 /* input2 - Noise sample frequency */
485 /* input3 - Amplitude input value */
486 /* input4 - Input feed bit */
487 /* input5 - Bias */
488 /* */
489 /************************************************************************/
dss_lfsr_function(int myfunc,int in0,int in1,int bitmask)490 int dss_lfsr_function(int myfunc,int in0,int in1,int bitmask)
491 {
492 int retval;
493
494 in0&=bitmask;
495 in1&=bitmask;
496
497 switch(myfunc)
498 {
499 case DISC_LFSR_XOR:
500 retval=in0^in1;
501 break;
502 case DISC_LFSR_OR:
503 retval=in0|in1;
504 break;
505 case DISC_LFSR_AND:
506 retval=in0&in1;
507 break;
508 case DISC_LFSR_XNOR:
509 retval=in0^in1;
510 retval=retval^bitmask; /* Invert output */
511 break;
512 case DISC_LFSR_NOR:
513 retval=in0|in1;
514 retval=retval^bitmask; /* Invert output */
515 break;
516 case DISC_LFSR_NAND:
517 retval=in0&in1;
518 retval=retval^bitmask; /* Invert output */
519 break;
520 case DISC_LFSR_IN0:
521 retval=in0;
522 break;
523 case DISC_LFSR_IN1:
524 retval=in1;
525 break;
526 case DISC_LFSR_NOT_IN0:
527 retval=in0^bitmask;
528 break;
529 case DISC_LFSR_NOT_IN1:
530 retval=in1^bitmask;
531 break;
532 case DISC_LFSR_REPLACE:
533 retval=in0&~in1;
534 retval=in0|in1;
535 break;
536 default:
537 retval=0;
538 break;
539 }
540 return retval;
541 }
542
543 /* reset prototype so that it can be used in init function */
544 int dss_lfsr_reset(struct node_description *node);
545
dss_lfsr_step(struct node_description * node)546 int dss_lfsr_step(struct node_description *node)
547 {
548 struct dss_lfsr_context *context;
549 float newphase;
550 context=(struct dss_lfsr_context*)node->context;
551
552 newphase=context->phase+((2.0*PI*node->input2)/Machine->sample_rate);
553
554 /* Keep the new phasor in thw 2Pi range.*/
555 context->phase=fmod(newphase,2.0*PI);
556
557 /* Reset everything if necessary */
558 if(node->input1)
559 {
560 dss_lfsr_reset(node);
561 }
562
563 /* Only sample noise on rollover to next cycle */
564 if(newphase>(2.0*PI))
565 {
566 int fb0,fb1,fbresult;
567 struct discrete_lfsr_desc *lfsr_desc;
568
569 /* Fetch the LFSR descriptor structure in a local for quick ref */
570 lfsr_desc=(struct discrete_lfsr_desc*)(node->custom);
571
572 /* Fetch the last feedback result */
573 fbresult=((context->lfsr_reg)>>(lfsr_desc->bitlength))&0x01;
574
575 /* Stage 2 feedback combine fbresultNew with infeed bit */
576 fbresult=dss_lfsr_function(lfsr_desc->feedback_function1,fbresult,((node->input4)?0x01:0x00),0x01);
577
578 /* Stage 3 first we setup where the bit is going to be shifted into */
579 fbresult=fbresult*lfsr_desc->feedback_function2_mask;
580 /* Then we left shift the register, */
581 context->lfsr_reg=(context->lfsr_reg)<<1;
582 /* Now move the fbresult into the shift register and mask it to the bitlength */
583 context->lfsr_reg=dss_lfsr_function(lfsr_desc->feedback_function2,fbresult, (context->lfsr_reg), ((1<<(lfsr_desc->bitlength))-1));
584
585 /* Now get and store the new feedback result */
586 /* Fetch the feedback bits */
587 fb0=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel0))&0x01;
588 fb1=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel1))&0x01;
589 /* Now do the combo on them */
590 fbresult=dss_lfsr_function(lfsr_desc->feedback_function0,fb0,fb1,0x01);
591 context->lfsr_reg=dss_lfsr_function(DISC_LFSR_REPLACE,(context->lfsr_reg), fbresult<<(lfsr_desc->bitlength), ((2<<(lfsr_desc->bitlength))-1));
592
593 /* Now select the output bit */
594 node->output=((context->lfsr_reg)>>(lfsr_desc->output_bit))&0x01;
595
596 /* Final inversion if required */
597 if(lfsr_desc->output_invert) node->output=(node->output)?0.0:1.0;
598
599 /* Gain stage */
600 node->output=(node->output)?(node->input3)/2:-(node->input3)/2;
601 /* Bias input as required */
602 node->output=node->output+node->input5;
603 }
604
605 /* If disabled then clamp the output to DC Bias */
606 if(!node->input0)
607 {
608 node->output=node->input5;
609 }
610
611 return 0;
612 }
613
dss_lfsr_reset(struct node_description * node)614 int dss_lfsr_reset(struct node_description *node)
615 {
616 struct dss_lfsr_context *context;
617 struct discrete_lfsr_desc *lfsr_desc;
618
619 context=(struct dss_lfsr_context*)node->context;
620 lfsr_desc=(struct discrete_lfsr_desc*)(node->custom);
621
622 context->lfsr_reg=((struct discrete_lfsr_desc*)(node->custom))->reset_value;
623
624 context->lfsr_reg=dss_lfsr_function(DISC_LFSR_REPLACE,0, (dss_lfsr_function(lfsr_desc->feedback_function0,0,0,0x01))<<(lfsr_desc->bitlength),((2<<(lfsr_desc->bitlength))-1));
625
626 /* Now select and setup the output bit */
627 node->output=((context->lfsr_reg)>>(lfsr_desc->output_bit))&0x01;
628
629 /* Final inversion if required */
630 if(lfsr_desc->output_invert) node->output=(node->output)?0.0:1.0;
631
632 /* Gain stage */
633 node->output=(node->output)?(node->input3)/2:-(node->input3)/2;
634 /* Bias input as required */
635 node->output=node->output+node->input5;
636
637 return 0;
638 }
639
dss_lfsr_init(struct node_description * node)640 int dss_lfsr_init(struct node_description *node)
641 {
642 /* Allocate memory for the context array and the node execution order array */
643 if((node->context=(struct dss_lfsr_context*)malloc(sizeof(struct dss_lfsr_context)))==NULL)
644 {
645 return 1;
646 }
647 else
648 {
649 /* Initialise memory */
650 memset(node->context,0,sizeof(struct dss_lfsr_context));
651 }
652
653 /* Initialise the object */
654 dss_lfsr_reset(node);
655 ((struct dss_lfsr_context*)node->context)->phase=0.0;
656
657 return 0;
658 }
659
dss_lfsr_kill(struct node_description * node)660 int dss_lfsr_kill(struct node_description *node)
661 {
662 free(node->context);
663 node->context=NULL;
664 return 0;
665 }
666