1 /* Conditional Median Filter - Better Version
2 
3  * Copyright (C) 1998 J.A. Bezemer
4  *
5  * Licensed under the terms of the GNU General Public License.
6  * ABSOLUTELY NO WARRANTY.
7  * See the file `COPYING' in this directory.
8  */
9 
10 /* Remove the `dont' to get the gate instead of the normal output - useful
11    for verifying properties. */
12 #define dontVIEW_INTERNALS
13 
14 /* Choose the highpass filter: */
15 #define noSECOND_ORDER
16 #define FOURTH_ORDER
17 #define noSIXTH_ORDER
18 
19 /* To use the (slow) fancy interpolation routine, define FANCY_FILL here */
20 #define noFANCY_FILL
21 
22 
23 #include "signpr_cmf2.h"
24 #include "signpr_general.h"
25 #include "signpr_l1fit.h"
26 #include "errorwindow.h"
27 #ifndef SWIG
28 #include "stringinput.h"
29 #include "buttons.h"
30 #include "clrscr.h"
31 #include "boxes.h"
32 #include "helpline.h"
33 #include "yesnowindow.h"
34 #endif
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <math.h>
39 #ifndef SWIG
40 #ifndef OLD_CURSES
41 #include <ncurses.h>
42 #else
43 #include <curses.h>
44 #endif
45 #endif
46 
47 
48 void
cond_median2_param_defaults(parampointer_t parampointer)49 cond_median2_param_defaults (parampointer_t parampointer)
50 {
51   parampointer->postlength2 = 4;
52   parampointer->prelength2 = 4;
53   parampointer->postlength3 = 5;
54   parampointer->prelength3 = 5;
55   parampointer->postlength4 = 100;
56   parampointer->prelength4 = 100;
57   parampointer->int1 = 12;
58 #if defined (SECOND_ORDER)
59   parampointer->long1 = 1000;	/* Threshold to detect precise tick length. */
60   parampointer->long2 = 2500;	/* Must be above this to be a tick. */
61 #elif defined (FOURTH_ORDER)
62   parampointer->long1 = 2000;
63   parampointer->long2 = 8500;
64 #elif defined (SIXTH_ORDER)
65   parampointer->long1 = 1500;
66   parampointer->long2 = 7500;
67 #else
68 #error A Highpass version must be defined (signpr_cmf2.c)
69 #endif
70 
71 }
72 
73 
74 #ifdef FOURTH_ORDER
75 #undef SIGNPR_CMF2_PARAMSCR_HEADERTEXT
76 #define SIGNPR_CMF2_PARAMSCR_HEADERTEXT "CMF II [FOURTH ORDER] - Parameters"
77 #endif
78 
79 #ifdef SIXTH_ORDER
80 #undef SIGNPR_CMF2_PARAMSCR_HEADERTEXT
81 #define SIGNPR_CMF2_PARAMSCR_HEADERTEXT "CMF II [SIXTH ORDER] - Parameters"
82 #endif
83 
84 #ifndef SWIG
85 void
cond_median2_param_screen(parampointer_t parampointer)86 cond_median2_param_screen (parampointer_t parampointer)
87 {
88   stringinput_t rmslengthstr, rmflengthstr, decimatestr, threshold1str,
89     threshold2str;
90   button_t ok_button, cancel_button, defaults_button;
91   int dont_stop = TRUE;
92   int focus = 0;
93   int in_ch;
94   int i;
95   long helplong;
96 
97   char *helplines[8] =
98   {
99     " ^: fewer ticks detected.               v: not all of tick interpolated.       ",
100     " ^: bad following of dynamics.          v: fewer ticks detected.               ",
101     " ^: bad following of dynamics.          v: fewer ticks detected.               ",
102     " ^: detected tick length too short      v: detected tick length longer.        ",
103     " ^: only strong ticks detected.         v: music-ticks also filtered out.      ",
104     " Discard changes.                                                              ",
105     " Reset default values.                                                         ",
106     " Accept changes.                                                               "};
107 
108   rmslengthstr.maxlen = 500;
109   rmslengthstr.string = (char *) malloc (rmslengthstr.maxlen *
110 					 sizeof (char));
111   sprintf (rmslengthstr.string, "%ld", parampointer->prelength2 +
112 	   parampointer->postlength2 + 1);
113   rmslengthstr.y = 6;
114   rmslengthstr.x = 59;
115   rmslengthstr.w = 19;
116   rmslengthstr.cursorpos = strlen (rmslengthstr.string);
117   rmslengthstr.firstcharonscreen = 0;
118 
119   rmflengthstr.maxlen = 500;
120   rmflengthstr.string = (char *) malloc (rmflengthstr.maxlen *
121 					 sizeof (char));
122   sprintf (rmflengthstr.string, "%ld", parampointer->prelength3 +
123 	   parampointer->postlength3 + 1);
124   rmflengthstr.y = 8;
125   rmflengthstr.x = 59;
126   rmflengthstr.w = 19;
127   rmflengthstr.cursorpos = strlen (rmflengthstr.string);
128   rmflengthstr.firstcharonscreen = 0;
129 
130   decimatestr.maxlen = 500;
131   decimatestr.string = (char *) malloc (decimatestr.maxlen *
132 					sizeof (char));
133   sprintf (decimatestr.string, "%d", parampointer->int1);
134   decimatestr.y = 10;
135   decimatestr.x = 59;
136   decimatestr.w = 19;
137   decimatestr.cursorpos = strlen (decimatestr.string);
138   decimatestr.firstcharonscreen = 0;
139 
140   threshold1str.maxlen = 500;
141   threshold1str.string = (char *) malloc (threshold1str.maxlen *
142 					  sizeof (char));
143   sprintf (threshold1str.string, "%ld", parampointer->long1);
144   threshold1str.y = 12;
145   threshold1str.x = 59;
146   threshold1str.w = 19;
147   threshold1str.cursorpos = strlen (threshold1str.string);
148   threshold1str.firstcharonscreen = 0;
149 
150   threshold2str.maxlen = 500;
151   threshold2str.string = (char *) malloc (threshold2str.maxlen *
152 					  sizeof (char));
153   sprintf (threshold2str.string, "%ld", parampointer->long2);
154   threshold2str.y = 14;
155   threshold2str.x = 59;
156   threshold2str.w = 19;
157   threshold2str.cursorpos = strlen (threshold2str.string);
158   threshold2str.firstcharonscreen = 0;
159 
160   ok_button.text = " OK ";
161   ok_button.y = 20;
162   ok_button.x = 71;
163   ok_button.selected = FALSE;
164 
165   cancel_button.text = " Cancel ";
166   cancel_button.y = 20;
167   cancel_button.x = 5;
168   cancel_button.selected = FALSE;
169 
170   defaults_button.text = " Defaults ";
171   defaults_button.y = 20;
172   defaults_button.x = 36;
173   defaults_button.selected = FALSE;
174 
175   clearscreen (SIGNPR_CMF2_PARAMSCR_HEADERTEXT);
176 
177   do
178     {
179       header (SIGNPR_CMF2_PARAMSCR_HEADERTEXT);
180 
181       if (focus == 5)
182 	cancel_button.selected = TRUE;
183       else
184 	cancel_button.selected = FALSE;
185 
186       if (focus == 6)
187 	defaults_button.selected = TRUE;
188       else
189 	defaults_button.selected = FALSE;
190 
191       if (focus == 7)
192 	ok_button.selected = TRUE;
193       else
194 	ok_button.selected = FALSE;
195 
196       mvprintw (3, 2,
197        "See also the Signproc.txt file for the meaning of the parameters.");
198 
199       stringinput_display (&rmslengthstr);
200       mvprintw (rmslengthstr.y, 2,
201 		"Length of the RMS operation (samples):");
202 
203       stringinput_display (&rmflengthstr);
204       mvprintw (rmflengthstr.y, 2,
205 		"Length of the recursive median operation (samples):");
206 
207       stringinput_display (&decimatestr);
208       mvprintw (decimatestr.y, 2,
209 		"Decimation factor for the recursive median:");
210 
211       stringinput_display (&threshold1str);
212       mvprintw (threshold1str.y, 2,
213 		"Fine threshold for tick start/end (thousandths):");
214 
215       stringinput_display (&threshold2str);
216       mvprintw (threshold2str.y, 2,
217 		"Threshold for detection of tick presence (thousandths):");
218 
219       button_display (&cancel_button);
220       mybox (cancel_button.y - 1, cancel_button.x - 1,
221 	     3, strlen (cancel_button.text) + 2);
222       button_display (&defaults_button);
223       mybox (defaults_button.y - 1, defaults_button.x - 1,
224 	     3, strlen (defaults_button.text) + 2);
225       button_display (&ok_button);
226       mybox (ok_button.y - 1, ok_button.x - 1,
227 	     3, strlen (ok_button.text) + 2);
228 
229       helpline (helplines[focus]);
230 
231       switch (focus)
232 	{
233 	case 0:
234 	  stringinput_display (&rmslengthstr);
235 	  break;
236 	case 1:
237 	  stringinput_display (&rmflengthstr);
238 	  break;
239 	case 2:
240 	  stringinput_display (&decimatestr);
241 	  break;
242 	case 3:
243 	  stringinput_display (&threshold1str);
244 	  break;
245 	case 4:
246 	  stringinput_display (&threshold2str);
247 	  break;
248 	default:
249 	  move (0, 79);
250 	}
251 
252       refresh ();
253 
254       in_ch = getch ();
255 
256       switch (focus)
257 	{
258 	case 0:		/* rmslengthstr */
259 	  stringinput_stdkeys (in_ch, &rmslengthstr);
260 	  switch (in_ch)
261 	    {
262 	    case KEY_ENTER:
263 	    case 13:
264 	      i = sscanf (rmslengthstr.string, "%li", &helplong);
265 	      if (i < 1 || helplong < 1 || helplong % 2 == 0)
266 		error_window ("A whole, odd number, greater than 0, must \
267 be specified.");
268 	      else
269 		focus++;
270 	      break;
271 
272 	    case KEY_UP:
273 	      focus--;
274 	      break;
275 	    case KEY_DOWN:
276 	      focus++;
277 	      break;
278 	    }
279 	  break;
280 
281 	case 1:		/* rmflengthstr */
282 	  stringinput_stdkeys (in_ch, &rmflengthstr);
283 	  switch (in_ch)
284 	    {
285 	    case KEY_ENTER:
286 	    case 13:
287 	      i = sscanf (rmflengthstr.string, "%li", &helplong);
288 	      if (i < 1 || helplong < 1 || helplong % 2 == 0)
289 		error_window ("A whole, odd number, greater than 0, must \
290 be specified.");
291 	      else
292 		focus++;
293 	      break;
294 
295 	    case KEY_UP:
296 	      focus--;
297 	      break;
298 	    case KEY_DOWN:
299 	      focus++;
300 	      break;
301 	    }
302 	  break;
303 
304 	case 2:		/* decimatestr */
305 	  stringinput_stdkeys (in_ch, &decimatestr);
306 	  switch (in_ch)
307 	    {
308 	    case KEY_ENTER:
309 	    case 13:
310 	      i = sscanf (decimatestr.string, "%li", &helplong);
311 	      if (i < 1 || helplong < 1)
312 		error_window ("A whole number, greater than 0, must \
313 be specified.");
314 	      else
315 		focus++;
316 	      break;
317 
318 	    case KEY_UP:
319 	      focus--;
320 	      break;
321 	    case KEY_DOWN:
322 	      focus++;
323 	      break;
324 	    }
325 	  break;
326 
327 	case 3:		/* threshold1str */
328 	  stringinput_stdkeys (in_ch, &threshold1str);
329 	  switch (in_ch)
330 	    {
331 	    case KEY_ENTER:
332 	    case 13:
333 	      i = sscanf (threshold1str.string, "%li", &helplong);
334 	      if (i < 1 || helplong < 1)
335 		error_window ("A whole, positive number must be specified.");
336 	      else
337 		focus++;
338 	      break;
339 
340 	    case KEY_UP:
341 	      focus--;
342 	      break;
343 	    case KEY_DOWN:
344 	      focus++;
345 	      break;
346 	    }
347 	  break;
348 
349 	case 4:		/* threshold2str */
350 	  stringinput_stdkeys (in_ch, &threshold2str);
351 	  switch (in_ch)
352 	    {
353 	    case KEY_ENTER:
354 	    case 13:
355 	      i = sscanf (threshold2str.string, "%li", &helplong);
356 	      if (i < 1 || helplong < 1)
357 		error_window ("A whole, positive number must be specified.");
358 	      else
359 		focus = 7;
360 	      break;
361 
362 	    case KEY_UP:
363 	      focus--;
364 	      break;
365 	    case KEY_DOWN:
366 	      focus++;
367 	      break;
368 	    }
369 	  break;
370 
371 	case 5:		/* Cancel */
372 	  switch (in_ch)
373 	    {
374 	    case KEY_ENTER:
375 	    case 13:
376 	      dont_stop = FALSE;
377 	      break;
378 
379 	    case KEY_LEFT:
380 	    case KEY_UP:
381 	      focus--;
382 	      break;
383 	    case KEY_RIGHT:
384 	    case KEY_DOWN:
385 	      focus++;
386 	      break;
387 	    }
388 	  break;
389 
390 	case 6:		/* Defaults */
391 	  switch (in_ch)
392 	    {
393 	    case KEY_ENTER:
394 	    case 13:
395 	      if (yesno_window ("Restore default parameters?", " Yes ",
396 				" No ", 0))
397 		{
398 		  cond_median2_param_defaults (parampointer);
399 		  dont_stop = FALSE;
400 		}
401 	      break;
402 
403 	    case KEY_LEFT:
404 	    case KEY_UP:
405 	      focus--;
406 	      break;
407 	    case KEY_RIGHT:
408 	    case KEY_DOWN:
409 	      focus++;
410 	      break;
411 	    }
412 	  break;
413 
414 	case 7:		/* OK */
415 	  switch (in_ch)
416 	    {
417 	    case KEY_ENTER:
418 	    case 13:
419 
420 	      i = sscanf (rmslengthstr.string, "%li", &helplong);
421 	      if (i < 1 || helplong < 1 || helplong % 2 == 0)
422 		{
423 		  error_window ("A whole, odd number, greater than 0, must \
424 be specified as RMS length.");
425 		  rmslengthstr.cursorpos =
426 		    strlen (rmslengthstr.string);
427 		  focus = 0;
428 		  break;
429 		}
430 
431 	      parampointer->prelength2 = (helplong - 1) / 2;
432 	      parampointer->postlength2 = (helplong - 1) / 2;
433 
434 	      i = sscanf (rmflengthstr.string, "%li", &helplong);
435 	      if (i < 1 || helplong < 1 || helplong % 2 == 0)
436 		{
437 		  error_window ("A whole, odd number, greater than 0, must \
438 be specified as length of the recursive median.");
439 		  rmflengthstr.cursorpos =
440 		    strlen (rmflengthstr.string);
441 		  focus = 1;
442 		  break;
443 		}
444 
445 	      parampointer->prelength3 = (helplong - 1) / 2;
446 	      parampointer->postlength3 = (helplong - 1) / 2;
447 
448 	      i = sscanf (decimatestr.string, "%li", &helplong);
449 	      if (i < 1 || helplong < 1)
450 		{
451 		  error_window ("A whole number, greater than 0, must \
452 be specified as decimation factor.");
453 		  decimatestr.cursorpos =
454 		    strlen (decimatestr.string);
455 		  focus = 2;
456 		  break;
457 		}
458 
459 	      parampointer->int1 = helplong;
460 
461 	      i = sscanf (threshold1str.string, "%li", &helplong);
462 	      if (i < 1 || helplong < 1)
463 		{
464 		  error_window ("A whole, positive number must be \
465 specified as threshold.");
466 		  threshold1str.cursorpos =
467 		    strlen (threshold1str.string);
468 		  focus = 3;
469 		  break;
470 		}
471 
472 	      parampointer->long1 = helplong;
473 
474 	      i = sscanf (threshold2str.string, "%li", &helplong);
475 	      if (i < 1 || helplong < 1000)
476 		{
477 		  error_window ("A whole, positive number must be \
478 specified as threshold.");
479 		  threshold2str.cursorpos =
480 		    strlen (threshold2str.string);
481 		  focus = 4;
482 		  break;
483 		}
484 
485 	      parampointer->long2 = helplong;
486 
487 	      dont_stop = FALSE;
488 	      break;
489 
490 	    case KEY_LEFT:
491 	    case KEY_UP:
492 	      focus--;
493 	      break;
494 	    case KEY_RIGHT:
495 	    case KEY_DOWN:
496 	      focus++;
497 	      break;
498 	    }
499 	  break;
500 	}
501 
502       if (in_ch == 9)		/* TAB */
503 	focus++;
504 
505       if (in_ch == 27)
506 	dont_stop = FALSE;
507 
508       if (focus > 7)
509 	focus = 0;
510       if (focus < 0)
511 	focus = 7;
512     }
513   while (dont_stop);
514 
515   free (rmslengthstr.string);
516   free (rmflengthstr.string);
517   free (decimatestr.string);
518   free (threshold1str.string);
519   free (threshold2str.string);
520 }
521 #endif /* SWIG */
522 
523 void
init_cond_median2_filter(int filterno,parampointer_t parampointer)524 init_cond_median2_filter (int filterno, parampointer_t parampointer)
525 {
526   long total_post;
527   long total_pre;
528   long l;
529 
530   total_post = parampointer->postlength4 + parampointer->prelength4 + 1 + 4;
531   /* +1+4=+5 : for highpass, max. 11th order */
532 
533   total_pre = parampointer->postlength4 + parampointer->prelength4 + 1;
534   l = parampointer->prelength4 + parampointer->prelength3 *
535     parampointer->int1 + parampointer->prelength2 + 5;
536   /* + 5 : for highpass, max. 11th order */
537   if (l > total_pre)
538     total_pre = l;
539 
540   parampointer->buffer = init_buffer (total_post, total_pre);
541   parampointer->buffer2 = init_buffer (parampointer->postlength2,
542 				       parampointer->prelength2);
543   parampointer->buffer3 = init_buffer (parampointer->postlength3,
544 			     parampointer->prelength3 * parampointer->int1);
545   parampointer->buffer4 = init_buffer (parampointer->postlength4,
546 				       parampointer->prelength4);
547 
548   parampointer->filterno = filterno;
549 }
550 
551 
552 void
delete_cond_median2_filter(parampointer_t parampointer)553 delete_cond_median2_filter (parampointer_t parampointer)
554 {
555   delete_buffer (&parampointer->buffer);
556   delete_buffer (&parampointer->buffer2);
557   delete_buffer (&parampointer->buffer3);
558   delete_buffer (&parampointer->buffer4);
559 }
560 
561 
562 sample_t
cond_median2_highpass(long offset,long offset_zero,parampointer_t parampointer)563 cond_median2_highpass (long offset, long offset_zero,
564 		       parampointer_t parampointer)
565 {
566   sample_t sample;
567   longsample_t sum;
568 
569   offset += offset_zero;	/* middle for highpass filter in
570 				   'big buffer' */
571   sum.left = 0;
572   sum.right = 0;
573 
574 #if defined (SECOND_ORDER)
575 #define notTEST_DAVE_PLATT
576 #ifndef TEST_DAVE_PLATT
577   /* Original: */
578   sample = get_from_buffer (&parampointer->buffer, offset - 1);
579   sum.left += sample.left;
580   sum.right += sample.right;
581   sample = get_from_buffer (&parampointer->buffer, offset);
582   sum.left -= 2 * (long) sample.left;
583   sum.right -= 2 * (long) sample.right;
584   sample = get_from_buffer (&parampointer->buffer, offset + 1);
585   sum.left += sample.left;
586   sum.right += sample.right;
587 
588   sum.left /= 4;
589   sum.right /= 4;
590 #else /* TEST_DAVE_PLATT */
591   /* Testing, suggested by Dave Platt. Invert phase of one channel, then
592      do tick detection using the sum signal. This is because most ticks
593      are out-of-phase signals. I've not really tested this - it might
594      require other settings for thresholds etc.
595      Note: implemented for second_order only! */
596   sample = get_from_buffer (&parampointer->buffer, offset - 1);
597   sum.left += sample.left;
598   sum.left -= sample.right;
599   sample = get_from_buffer (&parampointer->buffer, offset);
600   sum.left -= 2 * (long) sample.left;
601   sum.left += 2 * (long) sample.right;
602   sample = get_from_buffer (&parampointer->buffer, offset + 1);
603   sum.left += sample.left;
604   sum.left -= sample.right;
605 
606   /* just in case L/R: 32000/-32000 -32000/32000 32000/-32000 : */
607   sum.left /= 8;
608   sum.right = sum.left;
609 #endif /* TEST_DAVE_PLATT */
610 
611 #elif defined (FOURTH_ORDER)
612   sample = get_from_buffer (&parampointer->buffer, offset - 2);
613   sum.left += sample.left;
614   sum.right += sample.right;
615   sample = get_from_buffer (&parampointer->buffer, offset - 1);
616   sum.left -= 4 * (long) sample.left;
617   sum.right -= 4 * (long) sample.right;
618   sample = get_from_buffer (&parampointer->buffer, offset);
619   sum.left += 6 * (long) sample.left;
620   sum.right += 6 * (long) sample.right;
621   sample = get_from_buffer (&parampointer->buffer, offset + 1);
622   sum.left -= 4 * (long) sample.left;
623   sum.right -= 4 * (long) sample.right;
624   sample = get_from_buffer (&parampointer->buffer, offset + 2);
625   sum.left += sample.left;
626   sum.right += sample.right;
627 
628   sum.left /= 4;
629   sum.right /= 4;
630 
631 #elif defined (SIXTH_ORDER)
632   sample = get_from_buffer (&parampointer->buffer, offset - 3);
633   sum.left -= sample.left;
634   sum.right -= sample.right;
635   sample = get_from_buffer (&parampointer->buffer, offset - 2);
636   sum.left += 6 * (long) sample.left;
637   sum.right += 6 * (long) sample.right;
638   sample = get_from_buffer (&parampointer->buffer, offset - 1);
639   sum.left -= 15 * (long) sample.left;
640   sum.right -= 15 * (long) sample.right;
641   sample = get_from_buffer (&parampointer->buffer, offset);
642   sum.left += 20 * (long) sample.left;
643   sum.right += 20 * (long) sample.right;
644   sample = get_from_buffer (&parampointer->buffer, offset + 1);
645   sum.left -= 15 * (long) sample.left;
646   sum.right -= 15 * (long) sample.right;
647   sample = get_from_buffer (&parampointer->buffer, offset + 2);
648   sum.left += 6 * (long) sample.left;
649   sum.right += 6 * (long) sample.right;
650   sample = get_from_buffer (&parampointer->buffer, offset + 3);
651   sum.left -= sample.left;
652   sum.right -= sample.right;
653 
654   /* Should be /64, but the signal is extremely soft, so divide by less to
655      get more quantization levels (more accurate) */
656   sum.left /= 4;
657   sum.right /= 4;
658 #endif
659 
660   if (sum.left > 32767)
661     sample.left = 32767;
662   else if (sum.left < -32768)
663     sample.left = -32768;
664   else
665     sample.left = sum.left;
666 
667 
668   if (sum.right > 32767)
669     sample.right = 32767;
670   else if (sum.right < -32768)
671     sample.right = -32768;
672   else
673     sample.right = sum.right;
674 
675 
676   return sample;
677 }
678 
679 fillfuncpointer_t cond_median2_highpass_pointer = cond_median2_highpass;
680 
681 sample_t
cond_median2_rms(long offset,long offset_zero,parampointer_t parampointer)682 cond_median2_rms (long offset, long offset_zero,
683 		  parampointer_t parampointer)
684 {
685   sample_t sample;
686   doublesample_t doublesample;
687   doublesample_t sum;
688   long i;
689 
690   advance_current_pos_custom (&parampointer->buffer2,
691 			      cond_median2_highpass_pointer,
692 			      offset + offset_zero,
693 			      parampointer);
694 
695   sum.left = 0;
696   sum.right = 0;
697 
698   for (i = -parampointer->postlength2; i <= parampointer->prelength2;
699        i++)
700     {
701       sample = get_from_buffer (&parampointer->buffer2, i);
702       doublesample.left = sample.left;
703       doublesample.right = sample.right;
704       sum.left += doublesample.left * doublesample.left;
705       sum.right += doublesample.right * doublesample.right;
706     }
707 
708   sum.left /= (parampointer->postlength2 +
709 	       parampointer->prelength2 + 1);
710   sum.right /= (parampointer->postlength2 +
711 		parampointer->prelength2 + 1);
712 
713   sample.left = sqrt (sum.left + 1);
714   sample.right = sqrt (sum.right + 1);
715 
716   return sample;
717 }
718 
719 fillfuncpointer_t cond_median2_rms_pointer = cond_median2_rms;
720 
721 sample_t
cond_median2_gate(long offset,long offset_zero,parampointer_t parampointer)722 cond_median2_gate (long offset, long offset_zero,
723 		   parampointer_t parampointer)
724 /* Well, not a `gate' any more - just (w[t]-b[t])/b[t], comparision to
725    make the real gate is done later. */
726 {
727   sample_t sample;
728   sample_t w_t;
729   sample_t b_t;
730   sample_t returnval;
731   signed short list1[parampointer->postlength3 +
732 		     parampointer->prelength3 * parampointer->int1 + 1];
733   signed short list2[parampointer->postlength3 +
734 		     parampointer->prelength3 * parampointer->int1 + 1];
735   long i, j;
736 
737   advance_current_pos_custom (&parampointer->buffer3,
738 			      cond_median2_rms_pointer,
739 			      offset + offset_zero,
740 			      parampointer);
741 
742   w_t = get_from_buffer (&parampointer->buffer3, 0);
743 
744   /* The RMF Filter */
745 
746   for (i = 0; i < parampointer->postlength3; i++)
747     {
748       sample = get_from_buffer (&parampointer->buffer3,
749 				i - parampointer->postlength3);
750       list1[i] = sample.left;
751       list2[i] = sample.right;
752     }
753 
754   j = i;
755 
756   for (; i <= parampointer->postlength3 +
757        parampointer->prelength3 * parampointer->int1;
758        i += parampointer->int1)
759     {
760       sample = get_from_buffer (&parampointer->buffer3,
761 				i - parampointer->postlength3);
762       list1[j] = sample.left;
763       list2[j] = sample.right;
764       j++;
765     }
766 
767   b_t.left = median (list1, j);
768   b_t.right = median (list2, j);
769 
770   put_in_buffer (&parampointer->buffer3, 0, b_t);
771 
772 
773   i = (labs (w_t.left - b_t.left) * 1000)
774     /
775     b_t.left;
776   if (i > 32767)
777     i = 32767;
778   else if (i < -32768)
779     i = -32768;
780 
781   returnval.left = i;
782 
783   i = (labs (w_t.right - b_t.right) * 1000)
784     /
785     b_t.right;
786   if (i > 32767)
787     i = 32767;
788   else if (i < -32768)
789     i = -32768;
790   returnval.right = i;
791 
792   return returnval;
793 }
794 
795 fillfuncpointer_t cond_median2_gate_pointer = cond_median2_gate;
796 
797 sample_t
798 #ifndef SWIG
cond_median2_filter(parampointer_t parampointer)799 cond_median2_filter (parampointer_t parampointer)
800 #else
801 cond_median2_filter (parampointer_t parampointer, int *filter_type)
802 #endif
803 {
804   sample_t sample, gate, returnval;
805   /* max. length if toleft=postlength4 and toright=prelength4 */
806   signed short list3[2 * (parampointer->postlength4 +
807 			  parampointer->prelength4 + 1) + 1];
808 #ifdef FANCY_FILL
809   signed short list4[2 * (parampointer->postlength4 +
810 			  parampointer->prelength4 + 1) + 1];
811   double a1, b1;
812 #endif
813 
814   long i;
815   int toleft, toright;
816   signed short maxval;
817 
818 #ifndef SWIG
819   advance_current_pos (&parampointer->buffer, parampointer->filterno);
820 #else
821   advance_current_pos (&parampointer->buffer, parampointer->filterno, filter_type);
822 #endif
823 
824   advance_current_pos_custom (&parampointer->buffer4,
825 			      cond_median2_gate_pointer,
826 			      0,
827 			      parampointer);
828 
829   gate = get_from_buffer (&parampointer->buffer4, 0);
830 
831 #ifdef VIEW_INTERNALS
832   returnval.left = 0;
833   returnval.right = 0;
834 #else
835   /* 'Default' value - unchanged if there is no tick */
836   returnval = get_from_buffer (&parampointer->buffer, 0);
837 #endif
838 
839   if (gate.left > parampointer->long1)
840     {
841       maxval = gate.left;
842 
843       toleft = -1;
844       sample.left = 0;
845       do
846 	{
847 	  toleft++;
848 	  if (toleft < parampointer->postlength4)
849 	    {
850 	      sample = get_from_buffer (&parampointer->buffer4, -toleft - 1);
851 	      if (sample.left > maxval)
852 		/* if so, the `while' will continue anyway, so maxval may
853 		   be adjusted here already (if necessary) */
854 		maxval = sample.left;
855 	    }
856 	}
857       while (toleft < parampointer->postlength4 &&
858 	     sample.left > parampointer->long1);
859 
860       toright = -1;
861       sample.left = 0;
862       do
863 	{
864 	  toright++;
865 	  if (toright < parampointer->prelength4)
866 	    {
867 	      sample = get_from_buffer (&parampointer->buffer4, toright + 1);
868 	      if (sample.left > maxval)
869 		/* if so, the `while' will continue anyway, so maxval may
870 		   be adjusted here already (if necessary) */
871 		maxval = sample.left;
872 	    }
873 	}
874       while (toright < parampointer->prelength4 &&
875 	     sample.left > parampointer->long1);
876 
877       /* total length of gate is toleft+toright+1, so a median with
878          size 2*(toleft+toright+1)+1 is needed. */
879 
880       /* only interpolate if there really is a tick */
881       if (maxval > parampointer->long2)
882 	{
883 
884 #ifdef VIEW_INTERNALS
885 	  returnval.left = (toright + toleft + 1) * 500;
886 #else
887 #ifdef FANCY_FILL
888 	  for (i = 0; i <= 2 * (toleft + toright + 1); i++)
889 	    {
890 	      list3[i] = get_from_buffer (&parampointer->buffer,
891 					  i - (toleft + toright + 1)).left;
892 	      list4[i] = i - (toleft + toright + 1);
893 	    }
894 	  l1fit (list4, list3, 2 * (toleft + toright + 1), &a1, &b1);
895 	  returnval.left = (signed short) rint (a1);
896 #else
897 	  for (i = 0; i <= 2 * (toleft + toright + 1); i++)
898 	    list3[i] = get_from_buffer (&parampointer->buffer,
899 					i - (toleft + toright + 1)).left;
900 
901 	  returnval.left = median (list3, 2 * (toleft + toright + 1) + 1);
902 #endif
903 #endif
904 	}
905     }
906 
907   if (gate.right > parampointer->long1)
908     {
909       maxval = gate.right;
910 
911       toleft = -1;
912       sample.right = 0;
913       do
914 	{
915 	  toleft++;
916 	  if (toleft < parampointer->postlength4)
917 	    {
918 	      sample = get_from_buffer (&parampointer->buffer4, -toleft - 1);
919 	      if (sample.right > maxval)
920 		/* if so, the `while' will continue anyway, so maxval may
921 		   be adjusted here already (if necessary) */
922 		maxval = sample.right;
923 	    }
924 	}
925       while (toleft < parampointer->postlength4 &&
926 	     sample.right > parampointer->long1);
927 
928       toright = -1;
929       sample.right = 0;
930       do
931 	{
932 	  toright++;
933 	  if (toright < parampointer->prelength4)
934 	    {
935 	      sample = get_from_buffer (&parampointer->buffer4, toright + 1);
936 	      if (sample.right > maxval)
937 		/* if so, the `while' will continue anyway, so maxval may
938 		   be adjusted here already (if necessary) */
939 		maxval = sample.right;
940 	    }
941 	}
942       while (toright < parampointer->prelength4 &&
943 	     sample.right > parampointer->long1);
944 
945       /* total length of gate is toleft+toright+1, so a median with
946          size 2*(toleft+toright+1)+1 is needed. */
947 
948       /* only interpolate if there really is a tick */
949       if (maxval > parampointer->long2)
950 	{
951 
952 #ifdef VIEW_INTERNALS
953 	  returnval.right = (toright + toleft + 1) * 500;
954 #else
955 #ifdef FANCY_FILL
956 	  for (i = 0; i <= 2 * (toleft + toright + 1); i++)
957 	    {
958 	      list3[i] = get_from_buffer (&parampointer->buffer,
959 					  i - (toleft + toright + 1)).right;
960 	      list4[i] = i - (toleft + toright + 1);
961 	    }
962 	  l1fit (list4, list3, 2 * (toleft + toright + 1), &a1, &b1);
963 	  returnval.right = (signed short) rint (a1);
964 #else
965 	  for (i = 0; i <= 2 * (toleft + toright + 1); i++)
966 	    list3[i] = get_from_buffer (&parampointer->buffer,
967 					i - (toleft + toright + 1)).right;
968 
969 	  returnval.right = median (list3, 2 * (toleft + toright + 1) + 1);
970 #endif
971 #endif
972 	}
973     }
974 
975   return returnval;
976 }
977