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