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 (¶mpointer->buffer);
556 delete_buffer (¶mpointer->buffer2);
557 delete_buffer (¶mpointer->buffer3);
558 delete_buffer (¶mpointer->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 (¶mpointer->buffer, offset - 1);
579 sum.left += sample.left;
580 sum.right += sample.right;
581 sample = get_from_buffer (¶mpointer->buffer, offset);
582 sum.left -= 2 * (long) sample.left;
583 sum.right -= 2 * (long) sample.right;
584 sample = get_from_buffer (¶mpointer->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 (¶mpointer->buffer, offset - 1);
597 sum.left += sample.left;
598 sum.left -= sample.right;
599 sample = get_from_buffer (¶mpointer->buffer, offset);
600 sum.left -= 2 * (long) sample.left;
601 sum.left += 2 * (long) sample.right;
602 sample = get_from_buffer (¶mpointer->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 (¶mpointer->buffer, offset - 2);
613 sum.left += sample.left;
614 sum.right += sample.right;
615 sample = get_from_buffer (¶mpointer->buffer, offset - 1);
616 sum.left -= 4 * (long) sample.left;
617 sum.right -= 4 * (long) sample.right;
618 sample = get_from_buffer (¶mpointer->buffer, offset);
619 sum.left += 6 * (long) sample.left;
620 sum.right += 6 * (long) sample.right;
621 sample = get_from_buffer (¶mpointer->buffer, offset + 1);
622 sum.left -= 4 * (long) sample.left;
623 sum.right -= 4 * (long) sample.right;
624 sample = get_from_buffer (¶mpointer->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 (¶mpointer->buffer, offset - 3);
633 sum.left -= sample.left;
634 sum.right -= sample.right;
635 sample = get_from_buffer (¶mpointer->buffer, offset - 2);
636 sum.left += 6 * (long) sample.left;
637 sum.right += 6 * (long) sample.right;
638 sample = get_from_buffer (¶mpointer->buffer, offset - 1);
639 sum.left -= 15 * (long) sample.left;
640 sum.right -= 15 * (long) sample.right;
641 sample = get_from_buffer (¶mpointer->buffer, offset);
642 sum.left += 20 * (long) sample.left;
643 sum.right += 20 * (long) sample.right;
644 sample = get_from_buffer (¶mpointer->buffer, offset + 1);
645 sum.left -= 15 * (long) sample.left;
646 sum.right -= 15 * (long) sample.right;
647 sample = get_from_buffer (¶mpointer->buffer, offset + 2);
648 sum.left += 6 * (long) sample.left;
649 sum.right += 6 * (long) sample.right;
650 sample = get_from_buffer (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->buffer3,
738 cond_median2_rms_pointer,
739 offset + offset_zero,
740 parampointer);
741
742 w_t = get_from_buffer (¶mpointer->buffer3, 0);
743
744 /* The RMF Filter */
745
746 for (i = 0; i < parampointer->postlength3; i++)
747 {
748 sample = get_from_buffer (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->buffer, parampointer->filterno);
820 #else
821 advance_current_pos (¶mpointer->buffer, parampointer->filterno, filter_type);
822 #endif
823
824 advance_current_pos_custom (¶mpointer->buffer4,
825 cond_median2_gate_pointer,
826 0,
827 parampointer);
828
829 gate = get_from_buffer (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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 (¶mpointer->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