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 /* DST_FILTER1 - Generic 1st order filter */
12 /* DST_FILTER2 - Generic 2nd order filter */
13 /* DST_RCFILTER - Simple RC filter & also lowpass filter */
14 /* DST_RCDISC - Simple discharing RC */
15 /* */
16 /************************************************************************/
17
18 /************************************************************************/
19 /* */
20 /* DST_FILTER1 - Generic 1st order filter */
21 /* */
22 /* input[0] - Enable input value */
23 /* input[1] - input value */
24 /* input[2] - Frequency value (initialisation only) */
25 /* input[3] - Filter type (initialisation only) */
26 /* input[4] - NOT USED */
27 /* input[5] - NOT USED */
28 /* */
29 /************************************************************************/
30
31 struct dss_filter1_context
32 {
33 double x1; /* x[k-1], previous input value */
34 double y1; /* y[k-1], previous output value */
35 double a1; /* digital filter coefficients, denominator */
36 double b0, b1; /* digital filter coefficients, numerator */
37 };
38
calculate_filter1_coefficients(double fc,double type,double * a1,double * b0,double * b1)39 static void calculate_filter1_coefficients(double fc, double type,
40 double *a1, double *b0, double *b1)
41 {
42 double den, w, two_over_T;
43
44 /* calculate digital filter coefficents */
45 /*w = 2.0*M_PI*fc; no pre-warping */
46 w = Machine->sample_rate*2.0*tan(M_PI*fc/Machine->sample_rate); /* pre-warping */
47 two_over_T = 2.0*Machine->sample_rate;
48
49 den = w + two_over_T;
50 *a1 = (w - two_over_T)/den;
51 if (type == DISC_FILTER_LOWPASS)
52 {
53 *b0 = *b1 = w/den;
54 }
55 else if (type == DISC_FILTER_HIGHPASS)
56 {
57 *b0 = two_over_T/den;
58 *b1 = *b0;
59 }
60 else
61 {
62 discrete_log("calculate_filter1_coefficients() - Invalid filter type for 1st order filter.");
63 }
64 }
65
dst_filter1_step(struct node_description * node)66 int dst_filter1_step(struct node_description *node)
67 {
68 struct dss_filter1_context *context;
69 double gain = 1.0;
70
71 context=(struct dss_filter1_context*)node->context;
72 if (node->input[0] == 0.0)
73 {
74 gain = 0.0;
75 }
76
77 node->output = -context->a1*context->y1 + context->b0*gain*node->input[1] + context->b1*context->x1;
78
79 context->x1 = gain*node->input[1];
80 context->y1 = node->output;
81
82 return 0;
83 }
84
dst_filter1_reset(struct node_description * node)85 int dst_filter1_reset(struct node_description *node)
86 {
87 node->output=0;
88 return 0;
89 }
90
dst_filter1_init(struct node_description * node)91 int dst_filter1_init(struct node_description *node)
92 {
93 struct dss_filter1_context *context;
94
95 /* Allocate memory for the context array and the node execution order array */
96 if((node->context=malloc(sizeof(struct dss_filter1_context)))==NULL)
97 {
98 discrete_log("dss_filter1_init() - Failed to allocate local context memory.");
99 return 1;
100 }
101 else
102 {
103 /* Initialise memory */
104 memset(node->context,0,sizeof(struct dss_filter1_context));
105 }
106 context=(struct dss_filter1_context*)node->context;
107
108 calculate_filter1_coefficients(node->input[2], node->input[3],
109 &context->a1, &context->b0, &context->b1);
110
111 /* Initialise the object */
112 dst_filter1_reset(node);
113 return 0;
114 }
115
116 /************************************************************************/
117 /* */
118 /* DST_FILTER2 - Generic 2nd order filter */
119 /* */
120 /* input[0] - Enable input value */
121 /* input[1] - input value */
122 /* input[2] - Frequency value (initialisation only) */
123 /* input[3] - Damping value (initialisation only) */
124 /* input[4] - Filter type (initialisation only) */
125 /* input[5] - NOT USED */
126 /* */
127 /************************************************************************/
128
129 struct dss_filter2_context
130 {
131 double x1, x2; /* x[k-1], x[k-2], previous 2 input values */
132 double y1, y2; /* y[k-1], y[k-2], previous 2 output values */
133 double a1, a2; /* digital filter coefficients, denominator */
134 double b0, b1, b2; /* digital filter coefficients, numerator */
135 };
136
calculate_filter2_coefficients(double fc,double d,double type,double * a1,double * a2,double * b0,double * b1,double * b2)137 static void calculate_filter2_coefficients(double fc, double d, double type,
138 double *a1, double *a2,
139 double *b0, double *b1, double *b2)
140 {
141 double w; /* cutoff freq, in radians/sec */
142 double w_squared;
143 double den; /* temp variable */
144 double two_over_T = 2*Machine->sample_rate;
145 double two_over_T_squared = two_over_T * two_over_T;
146
147 /* calculate digital filter coefficents */
148 /*w = 2.0*M_PI*fc; no pre-warping */
149 w = Machine->sample_rate*2.0*tan(M_PI*fc/Machine->sample_rate); /* pre-warping */
150 w_squared = w*w;
151
152 den = two_over_T_squared + d*w*two_over_T + w_squared;
153
154 *a1 = 2.0*(-two_over_T_squared + w_squared)/den;
155 *a2 = (two_over_T_squared - d*w*two_over_T + w_squared)/den;
156
157 if (type == DISC_FILTER_LOWPASS)
158 {
159 *b0 = *b2 = w_squared/den;
160 *b1 = 2.0*(*b0);
161 }
162 else if (type == DISC_FILTER_BANDPASS)
163 {
164 *b0 = w*two_over_T/den;
165 *b1 = 0.0;
166 *b2 = -(*b0);
167 }
168 else if (type == DISC_FILTER_HIGHPASS)
169 {
170 *b0 = *b2 = two_over_T_squared/den;
171 *b1 = -2.0*(*b0);
172 }
173 else
174 {
175 discrete_log("calculate_filter2_coefficients() - Invalid filter type for 2nd order filter.");
176 }
177 }
178
dst_filter2_step(struct node_description * node)179 int dst_filter2_step(struct node_description *node)
180 {
181 struct dss_filter2_context *context;
182 double gain = 1.0;
183
184 context=(struct dss_filter2_context*)node->context;
185 if (node->input[0] == 0.0)
186 {
187 gain = 0.0;
188 }
189
190 node->output = -context->a1*context->y1 - context->a2*context->y2 +
191 context->b0*gain*node->input[1] + context->b1*context->x1 + context->b2*context->x2;
192
193 context->x2 = context->x1;
194 context->x1 = gain*node->input[1];
195 context->y2 = context->y1;
196 context->y1 = node->output;
197
198 return 0;
199 }
200
dst_filter2_reset(struct node_description * node)201 int dst_filter2_reset(struct node_description *node)
202 {
203 node->output=0;
204 return 0;
205 }
206
dst_filter2_init(struct node_description * node)207 int dst_filter2_init(struct node_description *node)
208 {
209 struct dss_filter2_context *context;
210
211 /* Allocate memory for the context array and the node execution order array */
212 if((node->context=malloc(sizeof(struct dss_filter2_context)))==NULL)
213 {
214 discrete_log("dss_filter2_init() - Failed to allocate local context memory.");
215 return 1;
216 }
217 else
218 {
219 /* Initialise memory */
220 memset(node->context,0,sizeof(struct dss_filter2_context));
221 }
222 context=(struct dss_filter2_context*)node->context;
223
224 calculate_filter2_coefficients(node->input[2], node->input[3], node->input[4],
225 &context->a1, &context->a2,
226 &context->b0, &context->b1, &context->b2);
227
228 /* Initialise the object */
229 dst_filter2_reset(node);
230 return 0;
231 }
232
233
234 struct dss_rcdisc_context
235 {
236 int state;
237 double t; // time
238 double step;
239 double exponent0;
240 double exponent1;
241 };
242
243 /************************************************************************/
244 /* */
245 /* DST_RCFILTER - Usage of node_description values for RC filter */
246 /* */
247 /* input[0] - Enable input value */
248 /* input[1] - input value */
249 /* input[2] - Resistor value (initialisation only) */
250 /* input[3] - Capacitor Value (initialisation only) */
251 /* input[4] - NOT USED */
252 /* input[5] - Pre-calculated value for exponent */
253 /* */
254 /************************************************************************/
dst_rcfilter_step(struct node_description * node)255 int dst_rcfilter_step(struct node_description *node)
256 {
257 /************************************************************************/
258 /* Next Value = PREV + (INPUT_VALUE - PREV)*(1-(EXP(-TIMEDELTA/RC))) */
259 /************************************************************************/
260
261 if(node->input[0])
262 {
263 node->output=node->output+((node->input[1]-node->output)*node->input[5]);
264 }
265 else
266 {
267 node->output=0;
268 }
269 return 0;
270 }
271
dst_rcfilter_reset(struct node_description * node)272 int dst_rcfilter_reset(struct node_description *node)
273 {
274 node->output=0;
275 return 0;
276 }
277
dst_rcfilter_init(struct node_description * node)278 int dst_rcfilter_init(struct node_description *node)
279 {
280 node->input[5]=-1.0/(node->input[2]*node->input[3]*Machine->sample_rate);
281 node->input[5]=1-exp(node->input[5]);
282 /* Initialise the object */
283 dst_rcfilter_reset(node);
284 return 0;
285 }
286
287 /************************************************************************/
288 /* */
289 /* DST_RCDISC - Usage of node_description values for RC discharge */
290 /* (inverse slope of DST_RCFILTER) */
291 /* */
292 /* input[0] - Enable input value */
293 /* input[1] - input value */
294 /* input[2] - Resistor value (initialisation only) */
295 /* input[3] - Capacitor Value (initialisation only) */
296 /* input[4] - NOT USED */
297 /* input[5] - NOT_USED */
298 /* */
299 /************************************************************************/
300
dst_rcdisc_step(struct node_description * node)301 int dst_rcdisc_step(struct node_description *node)
302 {
303 struct dss_rcdisc_context *context;
304 context=(struct dss_rcdisc_context*)node->context;
305
306 switch (context->state) {
307 case 0: /* waiting for trigger */
308 if(node->input[0]) {
309 context->state = 1;
310 context->t = 0;
311 }
312 node->output=0;
313 break;
314
315 case 1:
316 if (node->input[0]) {
317 node->output=node->input[1] * exp(context->t / context->exponent0);
318 context->t += context->step;
319 } else {
320 context->state = 0;
321 }
322 }
323
324 return 0;
325 }
326
dst_rcdisc_reset(struct node_description * node)327 int dst_rcdisc_reset(struct node_description *node)
328 {
329 struct dss_rcdisc_context *context;
330 context=(struct dss_rcdisc_context*)node->context;
331
332 node->output=0;
333
334 context->state = 0;
335 context->t = 0;
336 context->step = 1.0 / Machine->sample_rate;
337 context->exponent0=-1.0 * node->input[2]*node->input[3];
338
339 return 0;
340 }
341
dst_rcdisc_init(struct node_description * node)342 int dst_rcdisc_init(struct node_description *node)
343 {
344 /* Allocate memory for the context array and the node execution order array */
345 if((node->context=malloc(sizeof(struct dss_rcdisc_context)))==NULL)
346 {
347 discrete_log("dss_rcdisc_init() - Failed to allocate local context memory.");
348 return 1;
349 }
350 else
351 {
352 /* Initialise memory */
353 memset(node->context,0,sizeof(struct dss_rcdisc_context));
354 }
355
356 /* Initialise the object */
357 dst_rcdisc_reset(node);
358 return 0;
359 }
360
361
362 /************************************************************************/
363 /* */
364 /* DST_RCDISC2 - Usage of node_description values for RC discharge */
365 /* Has switchable charge resistor/input */
366 /* */
367 /* input[0] - Switch input value */
368 /* input[1] - input[0] value */
369 /* input[2] - Resistor0 value (initialisation only) */
370 /* input[3] - input[1] value */
371 /* input[4] - Resistor1 value (initialisation only) */
372 /* input[5] - Capacitor Value (initialisation only) */
373 /* */
374 /************************************************************************/
375
376
dst_rcdisc2_step(struct node_description * node)377 int dst_rcdisc2_step(struct node_description *node)
378 {
379 double diff;
380 struct dss_rcdisc_context *context;
381 context=(struct dss_rcdisc_context*)node->context;
382
383 /* Works differently to other as we always on, no enable */
384 /* exponential based in differnce between input/output */
385
386 diff = ((node->input[0]==0)?node->input[1]:node->input[3])-node->output;
387 diff = diff -(diff * exp(context->step / ((node->input[0]==0)?context->exponent0:context->exponent1)));
388 node->output+=diff;
389 return 0;
390 }
391
dst_rcdisc2_reset(struct node_description * node)392 int dst_rcdisc2_reset(struct node_description *node)
393 {
394 struct dss_rcdisc_context *context;
395 context=(struct dss_rcdisc_context*)node->context;
396
397 node->output=0;
398
399 context->state = 0;
400 context->t = 0;
401 context->step = 1.0 / Machine->sample_rate;
402 context->exponent0=-1.0 * node->input[2]*node->input[5];
403 context->exponent1=-1.0 * node->input[4]*node->input[5];
404
405 return 0;
406 }
407
dst_rcdisc2_init(struct node_description * node)408 int dst_rcdisc2_init(struct node_description *node)
409 {
410 /* Allocate memory for the context array and the node execution order array */
411 if((node->context=malloc(sizeof(struct dss_rcdisc_context)))==NULL)
412 {
413 discrete_log("dss_rcdisc2_init() - Failed to allocate local context memory.");
414 return 1;
415 }
416 else
417 {
418 /* Initialise memory */
419 memset(node->context,0,sizeof(struct dss_rcdisc_context));
420 }
421
422 /* Initialise the object */
423 dst_rcdisc2_reset(node);
424 return 0;
425 }
426
427 /* !!!!!!!!!!! NEW FILTERS for testing !!!!!!!!!!!!!!!!!!!!! */
428
429
430 /************************************************************************/
431 /* */
432 /* DST_RCFILTER - Usage of node_description values for RC filter */
433 /* */
434 /* input[0] - Enable input value */
435 /* input[1] - input value */
436 /* input[2] - Resistor value (initialisation only) */
437 /* input[3] - Capacitor Value (initialisation only) */
438 /* input[4] - NOT USED */
439 /* input[5] - NOT USED */
440 /* */
441 /************************************************************************/
442
dst_rcfilterN_init(struct node_description * node)443 int dst_rcfilterN_init(struct node_description *node)
444 {
445 double f=1.0/(2*M_PI*node->input[2]*node->input[3]);
446
447 node->input[2] = f;
448 node->input[3] = DISC_FILTER_LOWPASS;
449
450 /* Use first order filter */
451 return dst_filter1_init(node);
452 }
453
454
455 /************************************************************************/
456 /* */
457 /* DST_RCDISC - Usage of node_description values for RC discharge */
458 /* (inverse slope of DST_RCFILTER) */
459 /* */
460 /* input[0] - Enable input value */
461 /* input[1] - input value */
462 /* input[2] - Resistor value (initialisation only) */
463 /* input[3] - Capacitor Value (initialisation only) */
464 /* input[4] - NOT USED */
465 /* input[5] - NOT_USED */
466 /* */
467 /************************************************************************/
468
dst_rcdiscN_init(struct node_description * node)469 int dst_rcdiscN_init(struct node_description *node)
470 {
471 double f=1.0/(2*M_PI*node->input[2]*node->input[3]);
472
473 node->input[2] = f;
474 node->input[3] = DISC_FILTER_LOWPASS;
475
476 /* Use first order filter */
477 return dst_filter1_init(node);
478 }
479
dst_rcdiscN_step(struct node_description * node)480 int dst_rcdiscN_step(struct node_description *node)
481 {
482 struct dss_filter1_context *context;
483 double gain = 1.0;
484 context=(struct dss_filter1_context*)node->context;
485
486 if (node->input[0] == 0.0)
487 {
488 gain = 0.0;
489 }
490
491 /* A rise in the input signal results in an instant charge, */
492 /* else discharge through the RC to zero */
493 if (gain*node->input[1] > context->x1)
494 node->output = gain*node->input[1];
495 else
496 node->output = -context->a1*context->y1;
497
498 context->x1 = gain*node->input[1];
499 context->y1 = node->output;
500
501 return 0;
502 }
503
504
505 /************************************************************************/
506 /* */
507 /* DST_RCDISC2 - Usage of node_description values for RC discharge */
508 /* Has switchable charge resistor/input */
509 /* */
510 /* input[0] - Switch input value */
511 /* input[1] - input[0] value */
512 /* input[2] - Resistor0 value (initialisation only) */
513 /* input[3] - input[1] value */
514 /* input[4] - Resistor1 value (initialisation only) */
515 /* input[5] - Capacitor Value (initialisation only) */
516 /* */
517 /************************************************************************/
518
519 struct dss_rcdisc2_context
520 {
521 double x1; /* x[k-1], last input value */
522 double y1; /* y[k-1], last output value */
523 double a1_0, b0_0, b1_0; /* digital filter coefficients, filter #1 */
524 double a1_1, b0_1, b1_1; /* digital filter coefficients, filter #2 */
525 };
526
dst_rcdisc2N_step(struct node_description * node)527 int dst_rcdisc2N_step(struct node_description *node)
528 {
529 struct dss_rcdisc2_context *context;
530 double input = ((node->input[0]==0)?node->input[1]:node->input[3]);
531 context=(struct dss_rcdisc2_context*)node->context;
532
533 if (node->input[0] == 0)
534 node->output = -context->a1_0*context->y1 + context->b0_0*input + context->b1_0*context->x1;
535 else
536 node->output = -context->a1_1*context->y1 + context->b0_1*input + context->b1_1*context->x1;
537
538 context->x1 = input;
539 context->y1 = node->output;
540
541 return 0;
542 }
543
dst_rcdisc2N_reset(struct node_description * node)544 int dst_rcdisc2N_reset(struct node_description *node)
545 {
546 node->output=0;
547 return 0;
548 }
549
dst_rcdisc2N_init(struct node_description * node)550 int dst_rcdisc2N_init(struct node_description *node)
551 {
552 struct dss_rcdisc2_context *context;
553 double f1,f2;
554
555 /* Allocate memory for the context array and the node execution order array */
556 if((node->context=malloc(sizeof(struct dss_rcdisc2_context)))==NULL)
557 {
558 discrete_log("dst_rcdisc2_init() - Failed to allocate local context memory.");
559 return 1;
560 }
561 else
562 {
563 /* Initialise memory */
564 memset(node->context,0,sizeof(struct dss_rcdisc2_context));
565 }
566 context=(struct dss_rcdisc2_context*)node->context;
567
568 f1=1.0/(2*M_PI*node->input[2]*node->input[5]);
569 f2=1.0/(2*M_PI*node->input[4]*node->input[5]);
570
571 calculate_filter1_coefficients(f1, DISC_FILTER_LOWPASS, &context->a1_0, &context->b0_0, &context->b1_0);
572 calculate_filter1_coefficients(f2, DISC_FILTER_LOWPASS, &context->a1_1, &context->b0_1, &context->b1_1);
573
574 /* Initialise the object */
575 dst_rcdisc2_reset(node);
576
577 return 0;
578 }
579
580