2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)resample.c 1.15 02/11/21 Copyright 1998,1999,2000 Heiko Eissfeldt */
16 * The audio data has been read. Here are the
17 * functions to ensure a correct continuation
18 * of the output stream and to convert to a
23 #undef DEBUG_VOTE_ENDIANESS
24 #undef DEBUG_SHIFTS /* simulate bad cdrom drives */
41 #include <usal/scsitransp.h>
45 #include "interface.h"
46 #include "byteorder.h"
51 #include "sndconfig.h"
53 #include "exitcodes.h"
56 int waitforsignal = 0; /* flag: wait for any audio response */
59 short undersampling; /* conversion factor */
60 short samples_to_do; /* loop variable for conversion */
61 int Halved; /* interpolate due to non integral divider */
63 static long lsum = 0, rsum = 0; /* accumulator for left/right channel */
64 static long ls2 = 0, rs2 = 0, ls3 = 0, rs3 = 0, auxl = 0, auxr = 0;
66 static const unsigned char *my_symmemmem(const unsigned char *HAYSTACK,
67 const size_t HAYSTACK_LEN,
68 const unsigned char *const NEEDLE,
69 const size_t NEEDLE_LEN);
70 static const unsigned char *my_memmem(const unsigned char *HAYSTACK,
71 const size_t HAYSTACK_LEN,
72 const unsigned char *const NEEDLE,
73 const size_t NEEDLE_LEN);
74 static const unsigned char *my_memrmem(const unsigned char *HAYSTACK,
75 const size_t HAYSTACK_LEN,
76 const unsigned char *const NEEDLE,
77 const size_t NEEDLE_LEN);
78 static const unsigned char *sync_buffers(const unsigned char *const newbuf);
79 static long interpolate(long p1, long p2, long p3);
80 static void emit_sample(long lsumval, long rsumval, long channels);
81 static void change_endianness(UINT4 *pSam, unsigned int Samples);
82 static void swap_channels(UINT4 *pSam, unsigned int Samples);
83 static int guess_endianess(UINT4 *p, Int16_t *p2, unsigned int SamplesToDo);
87 static void check_mem(const unsigned char *p, unsigned long amount,
88 const unsigned char *q, unsigned line, char *file);
90 static void check_mem(const unsigned char *p, unsigned long amount,
91 const unsigned char *q, unsigned line, char *file)
93 if (p < q || p+amount > q + ENTRY_SIZE) {
94 fprintf(stderr, "file %s, line %u: invalid buffer range (%p - %p), allowed is (%p - %p)\n",
95 file,line,p, p+amount-1, q, q + ENTRY_SIZE-1);
102 #ifdef DEBUG_MATCHING
103 int memcmp(const void * a, const void * b, size_t c)
109 static const unsigned char *
110 my_symmemmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN,
111 const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
113 const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN - 1;
114 const unsigned char * HAYSTACK2 = HAYSTACK-1;
116 while (HAYSTACK <= UPPER_LIMIT) {
117 if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
120 if (memcmp(NEEDLE, HAYSTACK2, NEEDLE_LEN) == 0) {
127 #ifdef DEBUG_MATCHING
130 fprintf(stderr, "scompared %p-%p with %p-%p (%p)\n",
131 NEEDLE, NEEDLE + NEEDLE_LEN-1,
132 HAYSTACK2, HAYSTACK + NEEDLE_LEN-1, HAYSTACK);
137 static const unsigned char *
138 my_memmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN,
139 const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
141 const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN;
143 while (HAYSTACK <= UPPER_LIMIT) {
144 if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
150 #ifdef DEBUG_MATCHING
152 fprintf(stderr, "fcompared %p-%p with %p-%p (%p)\n",
153 NEEDLE, NEEDLE + NEEDLE_LEN-1,
154 HAYSTACK - HAYSTACK_LEN + NEEDLE_LEN, HAYSTACK + NEEDLE_LEN-1,
160 static const unsigned char *
161 my_memrmem(const unsigned char *HAYSTACK, const size_t HAYSTACK_LEN,
162 const unsigned char * const NEEDLE, const size_t NEEDLE_LEN)
164 const unsigned char * const LOWER_LIMIT = HAYSTACK - (HAYSTACK_LEN - 1);
166 while (HAYSTACK >= LOWER_LIMIT) {
167 if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
173 #ifdef DEBUG_MATCHING
175 fprintf(stderr, "bcompared %p-%p with %p-%p (%p)\n",
176 NEEDLE, NEEDLE + NEEDLE_LEN-1,
177 HAYSTACK, HAYSTACK + (HAYSTACK_LEN - 1),
178 HAYSTACK + (HAYSTACK_LEN - 1) - NEEDLE_LEN - 1);
183 /* find continuation in new buffer */
184 static const unsigned char *
185 sync_buffers(const unsigned char * const newbuf)
187 const unsigned char *retval = newbuf;
189 if (global.overlap != 0) {
190 /* find position of SYNC_SIZE bytes
191 of the old buffer in the new buffer */
193 const size_t needle_len = SYNC_SIZE;
194 const unsigned char * const oldbuf = (const unsigned char *) (get_previous_read_buffer()->data);
195 const unsigned char * haystack;
196 const unsigned char * needle;
198 /* compare the previous buffer with the new one
200 * 1. symmetrical search:
201 * look for the last SYNC_SIZE bytes of the previous buffer
202 * in the new buffer (from the optimum to the outer positions).
204 * 2. if the first approach did not find anything do forward search
205 * look for the last SYNC_SIZE bytes of the previous buffer
206 * in the new buffer (from behind the overlap to the end).
210 haystack_len = min((global.nsectors - global.overlap)*CD_FRAMESIZE_RAW
212 global.overlap*CD_FRAMESIZE_RAW);
214 haystack = newbuf + CD_FRAMESIZE_RAW*global.overlap - SYNC_SIZE;
215 needle = oldbuf + CD_FRAMESIZE_RAW*global.nsectors - SYNC_SIZE;
217 #ifdef DEBUG_MATCHING
218 fprintf(stderr, "oldbuf %p-%p new %p-%p %u %u %u\n",
219 oldbuf, oldbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
220 newbuf, newbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
221 CD_FRAMESIZE_RAW*global.nsectors, global.nsectors, global.overlap);
224 retval = my_symmemmem(haystack, haystack_len, needle, needle_len);
225 if (retval != NULL) {
228 /* fallback to asymmetrical search */
230 /* if there is no asymmetrical part left, return with 'not found' */
231 if (2*global.overlap == global.nsectors) {
233 } else if (2*global.overlap > global.nsectors) {
234 /* the asymmetrical part is in front, search backwards */
235 haystack_len = (2*global.overlap-global.nsectors)*CD_FRAMESIZE_RAW;
236 haystack = newbuf + haystack_len - 1;
237 retval = my_memrmem(haystack, haystack_len, needle, needle_len);
239 /* the asymmetrical part is at the end, search forward */
240 haystack = newbuf + 2*(global.overlap*CD_FRAMESIZE_RAW - SYNC_SIZE);
241 haystack_len = (global.nsectors-2*global.overlap)*CD_FRAMESIZE_RAW + 2*SYNC_SIZE;
242 retval = my_memmem(haystack, haystack_len, needle, needle_len);
250 fprintf(stderr,"%d\n",
251 retval-(newbuf+global.overlap*CD_FRAMESIZE_RAW));
253 fprintf(stderr,"no match\n");
261 /* quadratic interpolation
262 * p1, p3 span the interval 0 - 2. give interpolated value for 1/2 */
264 interpolate(long int p1, long int p2, long int p3)
266 return (3L*p1 + 6L*p2 - p3)/8L;
269 static unsigned char *pStart; /* running ptr defining end of output buffer */
270 static unsigned char *pDst; /* start of output buffer */
272 * Write the filtered sample into the output buffer.
275 emit_sample(long lsumval, long rsumval, long channels)
277 if (global.findminmax) {
278 if (rsumval > global.maxamp[0]) global.maxamp[0] = rsumval;
279 if (rsumval < global.minamp[0]) global.minamp[0] = rsumval;
280 if (lsumval < global.minamp[1]) global.minamp[1] = lsumval;
281 if (lsumval > global.maxamp[1]) global.maxamp[1] = lsumval;
283 /* convert to output format */
284 if ( channels == 1 ) {
285 Int16_t sum; /* mono section */
286 sum = ( lsumval + rsumval ) >> (global.sh_bits + 1);
287 if ( global.sh_bits == 8 ) {
288 if ( waitforsignal == 1 ) {
289 if ( any_signal == 0 ) {
290 if ( ( (char) sum) != '\0' ) {
291 pStart = (unsigned char *) pDst;
293 *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
294 } else global.SkippedSamples++;
295 } else *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
296 } else *pDst++ = ( unsigned char ) sum + ( 1 << 7 );
298 Int16_t * myptr = (Int16_t *) pDst;
299 if ( waitforsignal == 1 ) {
300 if ( any_signal == 0 ) {
302 pStart = (unsigned char *) pDst;
304 *myptr = sum; pDst += sizeof( Int16_t );
305 } else global.SkippedSamples++;
306 } else { *myptr = sum; pDst += sizeof( Int16_t ); }
307 } else { *myptr = sum; pDst += sizeof( Int16_t ); }
311 lsumval >>= global.sh_bits;
312 rsumval >>= global.sh_bits;
313 if ( global.sh_bits == 8 ) {
314 if ( waitforsignal == 1 ) {
315 if ( any_signal == 0 ) {
316 if ( ((( char ) lsumval != '\0') || (( char ) rsumval != '\0'))) {
317 pStart = (unsigned char *) pDst;
319 *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
320 *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
321 } else global.SkippedSamples++;
323 *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
324 *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
327 *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
328 *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
331 Int16_t * myptr = (Int16_t *) pDst;
332 if ( waitforsignal == 1 ) {
333 if ( any_signal == 0 ) {
334 if ( ((( Int16_t ) lsumval != 0) || (( Int16_t ) rsumval != 0))) {
335 pStart = (unsigned char *) pDst;
337 *myptr++ = ( Int16_t ) lsumval;
338 *myptr = ( Int16_t ) rsumval;
339 pDst += 2*sizeof( Int16_t );
340 } else global.SkippedSamples++;
342 *myptr++ = ( Int16_t ) lsumval;
343 *myptr = ( Int16_t ) rsumval;
344 pDst += 2*sizeof( Int16_t );
347 *myptr++ = ( Int16_t ) lsumval;
348 *myptr = ( Int16_t ) rsumval;
349 pDst += 2*sizeof( Int16_t );
355 static void change_endianness(UINT4 *pSam, unsigned int Samples)
357 UINT4 *pend = (pSam + Samples);
359 /* type UINT4 may not be greater than the assumed biggest type */
360 #if (SIZEOF_LONG_INT < 4)
361 error type unsigned long is too small
364 #if (SIZEOF_LONG_INT == 4)
366 unsigned long *plong = (unsigned long *)pSam;
368 for (; plong < pend;) {
369 *plong = ((*plong >> 8L) & UINT_C(0x00ff00ff)) |
370 ((*plong << 8L) & UINT_C(0xff00ff00));
373 #else /* sizeof long unsigned > 4 bytes */
374 #if (SIZEOF_LONG_INT == 8)
375 #define INTEGRAL_LONGS (SIZEOF_LONG_INT-1UL)
376 register unsigned long *plong;
377 unsigned long *pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
379 if (((unsigned long) pSam) & INTEGRAL_LONGS) {
380 *pSam = ((*pSam >> 8L) & UINT_C(0x00ff00ff)) |
381 ((*pSam << 8L) & UINT_C(0xff00ff00));
385 plong = (unsigned long *)pSam;
387 for (; plong < pend0;) {
388 *plong = ((*plong >> 8L) & ULONG_C(0x00ff00ff00ff00ff)) |
389 ((*plong << 8L) & ULONG_C(0xff00ff00ff00ff00));
393 if (((unsigned long *) pend) != pend0) {
394 UINT4 *pint = (UINT4 *) pend0;
396 for (;pint < pend;) {
397 *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
398 ((*pint << 8) & UINT_C(0xff00ff00));
402 #else /* sizeof long unsigned > 4 bytes but not 8 */
406 for (;pint < pend;) {
407 *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
408 ((*pint << 8) & UINT_C(0xff00ff00));
416 static void swap_channels(UINT4 *pSam, unsigned int Samples)
418 UINT4 *pend = (pSam + Samples);
420 /* type UINT4 may not be greater than the assumed biggest type */
421 #if (SIZEOF_LONG_INT < 4)
422 error type unsigned long is too small
425 #if (SIZEOF_LONG_INT == 4)
427 unsigned long *plong = (unsigned long *)pSam;
429 for (; plong < pend;) {
430 *plong = ((*plong >> 16L) & UINT_C(0x0000ffff)) |
431 ((*plong << 16L) & UINT_C(0xffff0000));
434 #else /* sizeof long unsigned > 4 bytes */
435 #if (SIZEOF_LONG_INT == 8)
436 #define INTEGRAL_LONGS (SIZEOF_LONG_INT-1UL)
437 register unsigned long *plong;
438 unsigned long *pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
440 if (((unsigned long) pSam) & INTEGRAL_LONGS) {
441 *pSam = ((*pSam >> 16L) & UINT_C(0x0000ffff)) |
442 ((*pSam << 16L) & UINT_C(0xffff0000));
446 plong = (unsigned long *)pSam;
448 for (; plong < pend0;) {
449 *plong = ((*plong >> 16L) & ULONG_C(0x0000ffff0000ffff)) |
450 ((*plong << 16L) & ULONG_C(0xffff0000ffff0000));
454 if (((unsigned long *) pend) != pend0) {
455 UINT4 *pint = (UINT4 *) pend0;
457 for (;pint < pend;) {
458 *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
459 ((*pint << 16L) & UINT_C(0xffff0000));
463 #else /* sizeof long unsigned > 4 bytes but not 8 */
467 for (;pint < pend;) {
468 *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
469 ((*pint << 16L) & UINT_C(0xffff0000));
477 #ifdef ECHO_TO_SOUNDCARD
478 static long ReSampleBuffer(unsigned char *p, unsigned char *newp,
479 long samples, int samplesize);
480 static long ReSampleBuffer(unsigned char *p, unsigned char *newp,
481 long samples, int samplesize)
486 if (global.playback_rate == 100.0) {
487 memcpy(newp, p, samplesize* samples);
489 } else while( si < (UINT4)samples ){
490 memcpy( newp+(di*samplesize), p+(si*samplesize), samplesize );
491 idx += (double)(global.playback_rate/100.0);
495 return di*samplesize;
499 static int guess_endianess(UINT4 *p, Int16_t *p2, unsigned SamplesToDo)
501 /* analyse samples */
502 int vote_for_little = 0;
503 int vote_for_big = 0;
506 while (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
507 unsigned char *p3 = (unsigned char *)p2;
508 #if MY_LITTLE_ENDIAN == 1
509 int diff_lowl = *(p2+0) - *(p2+2);
510 int diff_lowr = *(p2+1) - *(p2+3);
511 int diff_bigl = ((*(p3 ) << 8) + *(p3+1)) - ((*(p3+4) << 8) + *(p3+5));
512 int diff_bigr = ((*(p3+2) << 8) + *(p3+3)) - ((*(p3+6) << 8) + *(p3+7));
514 int diff_lowl = ((*(p3+1) << 8) + *(p3 )) - ((*(p3+5) << 8) + *(p3+4));
515 int diff_lowr = ((*(p3+3) << 8) + *(p3+2)) - ((*(p3+7) << 8) + *(p3+6));
516 int diff_bigl = *(p2+0) - *(p2+2);
517 int diff_bigr = *(p2+1) - *(p2+3);
520 if ((abs(diff_lowl) + abs(diff_lowr)) <
521 (abs(diff_bigl) + abs(diff_bigr))) {
524 if ((abs(diff_lowl) + abs(diff_lowr)) >
525 (abs(diff_bigl) + abs(diff_bigr))) {
531 #ifdef DEBUG_VOTE_ENDIANESS
532 if (global.quiet != 1)
533 fprintf(stderr, "votes for little: %4d, votes for big: %4d\n",
534 vote_for_little, vote_for_big);
536 total_votes = vote_for_big + vote_for_little;
538 || abs(vote_for_big - vote_for_little) < total_votes/3) {
541 if (vote_for_big > vote_for_little)
550 void handle_inputendianess(UINT4 *p, unsigned SamplesToDo)
552 /* if endianess is unknown, guess endianess based on
553 differences between succesive samples. If endianess
554 is correct, the differences are smaller than with the
557 if ((*in_lendian) < 0) {
558 Int16_t *p2 = (Int16_t *)p;
560 /* skip constant samples */
561 while ((((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo)
562 && *p2 == *(p2+2)) p2++;
564 if (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
565 switch (guess_endianess(p, p2, SamplesToDo)) {
567 case 1: (*in_lendian) = 0;
569 if (global.quiet != 1)
570 fprintf(stderr, "big endian detected\n");
573 case 0: (*in_lendian) = 1;
575 if (global.quiet != 1)
576 fprintf(stderr, "little endian detected\n");
584 * the individual endianess of cdrom/cd-writer, cpu,
585 * sound card and audio output format need a careful treatment.
587 * For possible sample processing (rate conversion) we need
588 * the samples in cpu byte order. This is the first conversion.
590 * After processing it depends on the endianness of the output
591 * format, whether a second conversion is needed.
595 if (global.need_hostorder && (*in_lendian) != MY_LITTLE_ENDIAN) {
596 /* change endianess of delivered samples to native cpu order */
597 change_endianness(p, SamplesToDo);
602 synchronize(UINT4 *p, unsigned SamplesToDo, unsigned TotSamplesDone)
604 static int jitter = 0;
605 char *pSrc; /* start of cdrom buffer */
607 /* synchronisation code */
608 if (TotSamplesDone != 0 && global.overlap != 0 && SamplesToDo > CD_FRAMESAMPLES) {
610 pSrc = (char *) sync_buffers((unsigned char *)p);
615 jitter = ((unsigned char *)pSrc - (((unsigned char *)p) + global.overlap*CD_FRAMESIZE_RAW))/4;
616 jitterShift += jitter;
617 SamplesToDo -= jitter + global.overlap*CD_FRAMESAMPLES;
620 "Length: pre %d, diff1 %ld, diff2 %ld, min %ld\n", SamplesToDo,
621 (TotSamplesWanted - TotSamplesDone),
622 SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling),
623 min(SamplesToDo, SamplesNeeded((TotSamplesWanted - TotSamplesDone), undersampling)));
629 return (unsigned char *) pSrc;
632 /* convert cdda data to required output format
633 * sync code for unreliable cdroms included
637 SaveBuffer(UINT4 *p, unsigned long SamplesToDo, unsigned long *TotSamplesDone)
639 UINT4 *pSrc; /* start of cdrom buffer */
640 UINT4 *pSrcStop; /* end of cdrom buffer */
642 /* in case of different endianness between host and output format,
643 or channel swaps, or deemphasizing
644 copy in a seperate buffer and modify the local copy */
645 if ( ((((!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||
646 (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)
647 ) || (global.deemphasize != 0)
648 ) && (global.OutSampleSize > 1)
649 ) || global.swapchannels != 0) {
650 static UINT4 *localoutputbuffer;
651 if (localoutputbuffer == NULL) {
652 localoutputbuffer = malloc(global.nsectors*CD_FRAMESIZE_RAW);
653 if (localoutputbuffer == NULL) {
654 perror("cannot allocate local buffer");
658 memcpy(localoutputbuffer, p, SamplesToDo*4);
659 p = localoutputbuffer;
663 pDst = (unsigned char *) p;
664 pStart = ( unsigned char * ) pSrc;
665 pSrcStop = pSrc + SamplesToDo;
667 /* code for subsampling and output stage */
669 if (global.ismono && global.findmono) {
671 for (pmm = (Int16_t *)pStart; (UINT4 *) pmm < pSrcStop; pmm += 2) {
672 if (*pmm != *(pmm+1)) {
678 /* optimize the case of no conversion */
679 if (1 && undersampling == 1 && samples_to_do == 1 &&
680 global.channels == 2 && global.OutSampleSize == 2 && Halved == 0) {
681 /* output format is the original cdda format ->
682 * just forward the buffer
685 if ( waitforsignal != 0 && any_signal == 0) {
686 UINT4 *myptr = (UINT4 *)pStart;
687 while (myptr < pSrcStop && *myptr == 0) myptr++;
688 pStart = (unsigned char *) myptr;
689 /* scan for first signal */
690 if ( (UINT4 *)pStart != pSrcStop ) {
691 /* first non null amplitude is found in buffer */
693 global.SkippedSamples += ((UINT4 *)pStart - p);
695 global.SkippedSamples += (pSrcStop - p);
698 pDst = (unsigned char *) pSrcStop; /* set pDst to end */
700 if (global.deemphasize && (Get_Preemphasis(get_current_track())) ) {
701 /* this implements an attenuation treble shelving filter
702 to undo the effect of pre-emphasis. The filter is of
703 a recursive first order */
704 static Int16_t lastin[2] = { 0, 0 };
705 static double lastout[2] = { 0.0, 0.0 };
708 /* Here is the gnuplot file for the frequency response
709 of the deemphasis. The error is below +-0.1dB
711 # first define the ideal filter. We use the tenfold sampling frequency.
714 OmegaL=15./50.*OmegaU
717 B=V0*tan(OmegaU*T/2.)
718 # the coefficients follow
720 b0=(1.0 + (1.0 - a1) * H0/2.)
721 b1=(a1 + (a1 - 1.0) * H0/2.)
725 H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
726 # now approximate the ideal curve with a fitted one for sampling frequency
731 B2=V02*tan(OmegaU2*T2/2.)
732 # the coefficients follow
733 a12=(B2 - 1.)/(B2 + 1.)
734 b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
735 b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
739 H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
740 # plot best, real, ideal, level with halved attenuation,
741 # level at full attentuation, 10fold magnified error
743 set grid xtics ytics mxtics mytics
744 plot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)), 20*log10(OmegaL/(2*pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))
745 pause -1 "Hit return to continue"
750 #define OMEGAG (1./19e-6)
751 #define T (1./44100.)
753 #define B (V0*tan((OMEGAG * T)/2.0))
754 #define a1 ((B - 1.)/(B + 1.))
755 #define b0 (1.0 + (1.0 - a1) * H0/2.0)
756 #define b1 (a1 + (a1 - 1.0) * H0/2.0)
763 #define a1 -0.62786881719628784282
764 #define b0 0.45995451989513153057
765 #define b1 -0.08782333709141937339
768 for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst;) {
769 lastout[0] = *pmm * b0 + lastin[0] * b1 - lastout[0] * a1;
771 *pmm++ = lastout[0] > 0.0 ? lastout[0] + 0.5 : lastout[0] - 0.5;
772 lastout[1] = *pmm * b0 + lastin[1] * b1 - lastout[1] * a1;
774 *pmm++ = lastout[1] > 0.0 ? lastout[1] + 0.5 : lastout[1] - 0.5;
781 if (global.swapchannels == 1) {
782 swap_channels((UINT4 *)pStart, SamplesToDo);
785 if (global.findminmax) {
787 for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst; pmm++) {
788 if (*pmm < global.minamp[1]) global.minamp[1] = *pmm;
789 if (*pmm > global.maxamp[1]) global.maxamp[1] = *pmm;
791 if (*pmm < global.minamp[0]) global.minamp[0] = *pmm;
792 if (*pmm > global.maxamp[0]) global.maxamp[0] = *pmm;
797 #define none_missing 0
798 #define one_missing 1
799 #define two_missing 2
802 static int sample_state = collecting;
803 static int Toggle_on = 0;
805 if (global.channels == 2 && global.swapchannels == 1) {
806 swap_channels((UINT4 *)pStart, SamplesToDo);
809 /* conversion required */
810 while ( pSrc < pSrcStop ) {
814 long iSamples_left = (pSrcStop - pSrc) / sizeof(Int16_t) / 2;
815 Int16_t *myptr = (Int16_t *) pSrc;
818 l = *myptr++; /* left channel */
819 r = *myptr++; /* right channel */
820 pSrc = (UINT4 *) myptr;
822 switch (sample_state) {
826 if (undersampling > 1) {
829 sample_state = one_missing;
835 sample_state = none_missing;
840 /* Filtered samples are complete. Now interpolate and scale. */
842 if (Halved != 0 && Toggle_on == 0) {
843 lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
844 rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
846 lsum /= (int) undersampling;
847 rsum /= (int) undersampling;
849 emit_sample(lsum, rsum, global.channels);
851 samples_to_do = undersampling - 1;
854 /* reset sample register */
855 auxl = ls2 = ls3 = 0;
856 auxr = rs2 = rs3 = 0;
858 sample_state = collecting;
861 if ( samples_to_do > 0) {
863 if (Halved != 0 && Toggle_on == 0) {
864 /* Divider x.5 : we need data for quadratic interpolation */
867 lsum += l; rsum += r;
868 if ( samples_to_do < undersampling - 1) {
871 if ( samples_to_do < undersampling - 2) {
875 /* integral divider */
881 if (Halved != 0 && Toggle_on == 0) {
882 sample_state = two_missing;
887 sample_state = none_missing;
897 if ((samples_to_do == 0 && Halved == 0))
899 if (Halved != 0 && Toggle_on == 0) {
900 lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
901 rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
903 lsum /= (int) undersampling;
904 rsum /= (int) undersampling;
906 emit_sample(lsum, rsum, global.channels);
909 samples_to_do = undersampling;
911 /* reset sample register */
912 lsum = auxl = ls2 = ls3 = 0;
913 rsum = auxr = rs2 = rs3 = 0;
915 sample_state = collecting;
918 } /* if optimize else */
920 if ( waitforsignal == 0 ) pStart = (unsigned char *)p;
922 if ( waitforsignal == 0 || any_signal != 0) {
927 assert(pDst >= pStart);
928 outlen = (size_t) (pDst - pStart);
930 if (outlen <= 0) return 0;
932 #ifdef ECHO_TO_SOUNDCARD
934 /* this assumes the soundcard needs samples in native cpu byte order */
935 if (global.echo != 0) {
936 static unsigned char *newp;
939 newlen = (100*(outlen/4))/global.playback_rate;
941 if ( (newp != NULL) || (newp = malloc( 2*global.nsectors*CD_FRAMESIZE_RAW+32 )) ) {
942 newlen = ReSampleBuffer( pStart, newp, outlen/4, global.OutSampleSize*global.channels );
943 write_snd_device((char *)newp, newlen);
948 if ( global.no_file != 0 ) {
949 *TotSamplesDone += SamplesToDo;
952 if ( (!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||
953 (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)) {
954 if ( global.OutSampleSize > 1) {
955 /* change endianness from input sample or native cpu order
956 to required output endianness */
957 change_endianness((UINT4 *)pStart, outlen/4);
961 unsigned char * p2 = pStart;
966 retval_ = global.audio_out->WriteSound ( global.audio, p2, todo );
967 if (retval_ < 0) break;
974 *TotSamplesDone += SamplesToDo;
977 fprintf(stderr, "write(audio, 0x%p, %u) = %d\n",pStart,outlen,retval);
978 perror("Probably disk space exhausted");
982 *TotSamplesDone += SamplesToDo;