1 /* @(#)resample.c	1.36 16/02/14 Copyright 1998-2000,2015 Heiko Eissfeldt, Copyright 2004-2010 J. Schilling */
2 #include "config.h"
3 #ifndef lint
4 static	UConst char sccsid[] =
5 "@(#)resample.c	1.36 16/02/14 Copyright 1998-2000,2015 Heiko Eissfeldt, Copyright 2004-2010 J. Schilling";
6 #endif
7 /*
8  * resampling module
9  *
10  * The audio data has been read. Here are the
11  * functions to ensure a correct continuation
12  * of the output stream and to convert to a
13  * lower sample rate.
14  *
15  */
16 /*
17  * The contents of this file are subject to the terms of the
18  * Common Development and Distribution License, Version 1.0 only
19  * (the "License").  You may not use this file except in compliance
20  * with the License.
21  *
22  * See the file CDDL.Schily.txt in this distribution for details.
23  * A copy of the CDDL is also available via the Internet at
24  * http://www.opensource.org/licenses/cddl1.txt
25  *
26  * When distributing Covered Code, include this CDDL HEADER in each
27  * file and include the License file CDDL.Schily.txt from this distribution.
28  */
29 
30 #undef DEBUG_VOTE_ENDIANESS
31 #undef DEBUG_SHIFTS		/* simulate bad cdrom drives */
32 #undef DEBUG_MATCHING
33 #undef SHOW_JITTER
34 #undef CHECK_MEM
35 
36 #include "config.h"
37 #include <schily/time.h>
38 #include <schily/stdio.h>
39 #include <schily/stdlib.h>
40 #include <schily/utypes.h>
41 #include <schily/unistd.h>
42 #include <schily/standard.h>
43 #include <schily/string.h>
44 #include <schily/limits.h>
45 #include <schily/assert.h>
46 #include <schily/math.h>
47 #include <schily/schily.h>
48 #include <schily/nlsdefs.h>
49 
50 #include <scg/scsitransp.h>
51 
52 #include "mytype.h"
53 #include "cdda2wav.h"
54 #include "interface.h"
55 #include "byteorder.h"
56 #include "ringbuff.h"
57 #include "resample.h"
58 #include "toc.h"
59 #include "sndfile.h"
60 #include "sndconfig.h"
61 #include "global.h"
62 #include "exitcodes.h"
63 
64 
65 int waitforsignal = 0;	/* flag: wait for any audio response */
66 int any_signal = 0;
67 
68 short undersampling;	/* conversion factor */
69 short samples_to_do;	/* loop variable for conversion */
70 int Halved;		/* interpolate due to non integral divider */
71 
72 static long lsum = 0, rsum = 0;		/* accumulator for left/right channel */
73 static long ls2 = 0, rs2 = 0, ls3 = 0, rs3 = 0, auxl = 0, auxr = 0;
74 
75 static const unsigned char *my_symmemmem __PR((const unsigned char *HAYSTACK,
76 					const size_t HAYSTACK_LEN,
77 					const unsigned char *const NEEDLE,
78 					const size_t NEEDLE_LEN));
79 static const unsigned char *my_memmem	__PR((const unsigned char *HAYSTACK,
80 					const size_t HAYSTACK_LEN,
81 					const unsigned char *const NEEDLE,
82 					const size_t NEEDLE_LEN));
83 static const unsigned char *my_memrmem	__PR((const unsigned char *HAYSTACK,
84 					const size_t HAYSTACK_LEN,
85 					const unsigned char *const NEEDLE,
86 					const size_t NEEDLE_LEN));
87 static const unsigned char *sync_buffers __PR((const unsigned char *const newbuf));
88 static long interpolate			__PR((long p1, long p2, long p3));
89 static void emit_sample			__PR((long lsumval, long rsumval,
90 						long channels));
91 static void change_endianness		__PR((UINT4 *pSam,
92 						unsigned int Samples));
93 static void swap_channels		__PR((UINT4 *pSam,
94 						unsigned int Samples));
95 static int guess_endianess		__PR((UINT4 *p, Int16_t *p2,
96 						unsigned int SamplesToDo));
97 
98 
99 #ifdef CHECK_MEM
100 static void
101 check_mem __PR((const unsigned char *p, unsigned long amount,
102 				const unsigned char *q,
103 				unsigned line, char *file));
104 
105 static void
check_mem(p,amount,q,line,file)106 check_mem(p, amount, q, line, file)
107 	const unsigned char	*p;
108 	unsigned long		amount;
109 	const unsigned char	*q;
110 	unsigned		line;
111 	char			*file;
112 {
113 	if (p < q || p+amount > q + ENTRY_SIZE) {
114 		errmsgno(EX_BAD,
115 		_("File %s, line %u: invalid buffer range (%p - %p), allowed is (%p - %p).\n"),
116 			file, line, p, p+amount-1, q, q + ENTRY_SIZE-1);
117 		exit(INTERNAL_ERROR);
118 	}
119 }
120 #endif
121 
122 
123 #ifdef DEBUG_MATCHING
124 int
memcmp(const void * a,const void * b,size_t c)125 memcmp(const void * a, const void * b, size_t c)
126 {
127 	return (1);
128 }
129 #endif
130 
131 static const unsigned char *
my_symmemmem(HAYSTACK,HAYSTACK_LEN,NEEDLE,NEEDLE_LEN)132 my_symmemmem(HAYSTACK, HAYSTACK_LEN, NEEDLE, NEEDLE_LEN)
133 	const unsigned char	*HAYSTACK;
134 	const size_t		HAYSTACK_LEN;
135 	const unsigned char	*const NEEDLE;
136 	const size_t		NEEDLE_LEN;
137 {
138 	const unsigned char	*const UPPER_LIMIT = HAYSTACK +
139 							HAYSTACK_LEN -
140 							NEEDLE_LEN - 1;
141 	const unsigned char	*HAYSTACK2 = HAYSTACK-1;
142 
143 	while (HAYSTACK <= UPPER_LIMIT) {
144 		if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
145 			return (HAYSTACK);
146 		} else {
147 			if (memcmp(NEEDLE, HAYSTACK2, NEEDLE_LEN) == 0) {
148 				return (HAYSTACK2);
149 			}
150 			HAYSTACK2--;
151 			HAYSTACK++;
152 		}
153 	}
154 #ifdef DEBUG_MATCHING
155 	HAYSTACK2++;
156 	HAYSTACK--;
157 	fprintf(stderr, "scompared %p-%p with %p-%p (%p)\n",
158 			NEEDLE, NEEDLE + NEEDLE_LEN-1,
159 			HAYSTACK2, HAYSTACK + NEEDLE_LEN-1, HAYSTACK);
160 #endif
161 	return (NULL);
162 }
163 
164 static const unsigned char *
my_memmem(HAYSTACK,HAYSTACK_LEN,NEEDLE,NEEDLE_LEN)165 my_memmem(HAYSTACK, HAYSTACK_LEN, NEEDLE, NEEDLE_LEN)
166 	const unsigned char	*HAYSTACK;
167 	const size_t		HAYSTACK_LEN;
168 	const unsigned char	*const NEEDLE;
169 	const size_t		NEEDLE_LEN;
170 {
171 	const unsigned char	*const UPPER_LIMIT = HAYSTACK +
172 							HAYSTACK_LEN -
173 							NEEDLE_LEN;
174 
175 	while (HAYSTACK <= UPPER_LIMIT) {
176 		if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
177 			return (HAYSTACK);
178 		} else {
179 			HAYSTACK++;
180 		}
181 	}
182 #ifdef DEBUG_MATCHING
183 	HAYSTACK--;
184 	fprintf(stderr, "fcompared %p-%p with %p-%p (%p)\n",
185 		NEEDLE, NEEDLE + NEEDLE_LEN-1,
186 		HAYSTACK - HAYSTACK_LEN + NEEDLE_LEN,
187 		HAYSTACK + NEEDLE_LEN-1,
188 		HAYSTACK);
189 #endif
190 	return (NULL);
191 }
192 
193 static const unsigned char *
my_memrmem(HAYSTACK,HAYSTACK_LEN,NEEDLE,NEEDLE_LEN)194 my_memrmem(HAYSTACK, HAYSTACK_LEN, NEEDLE, NEEDLE_LEN)
195 	const unsigned char	*HAYSTACK;
196 	const size_t		HAYSTACK_LEN;
197 	const unsigned char	*const NEEDLE;
198 	const size_t		NEEDLE_LEN;
199 {
200 	const unsigned char	*const LOWER_LIMIT = HAYSTACK -
201 							(HAYSTACK_LEN - 1);
202 
203 	while (HAYSTACK >= LOWER_LIMIT) {
204 		if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
205 			return (HAYSTACK);
206 		} else {
207 			HAYSTACK--;
208 		}
209 	}
210 #ifdef DEBUG_MATCHING
211 	HAYSTACK++;
212 	fprintf(stderr, "bcompared %p-%p with %p-%p (%p)\n",
213 		NEEDLE, NEEDLE + NEEDLE_LEN-1,
214 		HAYSTACK, HAYSTACK + (HAYSTACK_LEN - 1),
215 		HAYSTACK + (HAYSTACK_LEN - 1) - NEEDLE_LEN - 1);
216 #endif
217 	return (NULL);
218 }
219 
220 /* find continuation in new buffer */
221 static const unsigned char *
sync_buffers(newbuf)222 sync_buffers(newbuf)
223 	const unsigned char	*const newbuf;
224 {
225 	const unsigned char *retval = newbuf;
226 
227 	if (global.overlap != 0) {
228 		/*
229 		 * find position of SYNC_SIZE bytes
230 		 * of the old buffer in the new buffer
231 		 */
232 		size_t			haystack_len;
233 		const size_t		needle_len = SYNC_SIZE;
234 		const unsigned char	*const oldbuf =
235 					    (const unsigned char *)
236 					    (get_previous_read_buffer()->data);
237 		const unsigned char	*haystack;
238 		const unsigned char	*needle;
239 
240 		/*
241 		 * compare the previous buffer with the new one
242 		 *
243 		 * 1. symmetrical search:
244 		 *   look for the last SYNC_SIZE bytes of the previous buffer
245 		 *   in the new buffer (from the optimum to the outer
246 		 *   positions).
247 		 *
248 		 * 2. if the first approach did not find anything do forward
249 		 *   search look for the last SYNC_SIZE bytes of the previous
250 		 *   buffer in the new buffer (from behind the overlap to the
251 		 *   end).
252 		 */
253 		haystack_len = min((global.nsectors - global.overlap) *
254 					CD_FRAMESIZE_RAW
255 					+SYNC_SIZE+1,
256 					global.overlap*CD_FRAMESIZE_RAW);
257 		/*
258 		 * expected here
259 		 */
260 		haystack = newbuf + CD_FRAMESIZE_RAW *
261 					global.overlap - SYNC_SIZE;
262 		needle = oldbuf + CD_FRAMESIZE_RAW*global.nsectors - SYNC_SIZE;
263 
264 #ifdef DEBUG_MATCHING
265 		fprintf(stderr, "oldbuf    %p-%p  new %p-%p %u %u %u\n",
266 			oldbuf, oldbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
267 			newbuf, newbuf + CD_FRAMESIZE_RAW*global.nsectors - 1,
268 			CD_FRAMESIZE_RAW*global.nsectors, global.nsectors,
269 			global.overlap);
270 #endif
271 
272 		retval = my_symmemmem(haystack, haystack_len, needle,
273 								needle_len);
274 		if (retval != NULL) {
275 			retval += SYNC_SIZE;
276 		} else {
277 			/*
278 			 * fallback to asymmetrical search
279 			 *
280 			 * if there is no asymmetrical part left,
281 			 * return with 'not found'
282 			 */
283 			if (2*global.overlap == global.nsectors) {
284 				retval = NULL;
285 			} else if (2*global.overlap > global.nsectors) {
286 				/*
287 				 * the asymmetrical part is in front,
288 				 * search backwards
289 				 */
290 				haystack_len = (2*global.overlap-global.nsectors)*CD_FRAMESIZE_RAW;
291 				haystack = newbuf + haystack_len - 1;
292 				retval = my_memrmem(haystack, haystack_len, needle, needle_len);
293 			} else {
294 				/*
295 				 * the asymmetrical part is at the end,
296 				 * search forward
297 				 */
298 				haystack = newbuf + 2*(global.overlap*CD_FRAMESIZE_RAW - SYNC_SIZE);
299 				haystack_len = (global.nsectors-2*global.overlap)*CD_FRAMESIZE_RAW + 2*SYNC_SIZE;
300 				retval = my_memmem(haystack, haystack_len, needle, needle_len);
301 			}
302 			if (retval != NULL)
303 				retval += SYNC_SIZE;
304 		}
305 
306 #ifdef SHOW_JITTER
307 		if (retval) {
308 			fprintf(stderr, "%d\n",
309 			retval-(newbuf+global.overlap*CD_FRAMESIZE_RAW));
310 		} else {
311 			fprintf(stderr, _("no match\n"));
312 		}
313 #endif
314 	}
315 	return (retval);
316 }
317 
318 /*
319  * quadratic interpolation
320  * p1, p3 span the interval 0 - 2. give interpolated value for 1/2
321  */
322 static long int
interpolate(p1,p2,p3)323 interpolate(p1, p2, p3)
324 	long int	p1;
325 	long int	p2;
326 	long int	p3;
327 {
328 	return ((3L*p1 + 6L*p2 - p3)/8L);
329 }
330 
331 static unsigned char *pStart;	/* running ptr defining end of output buffer */
332 static unsigned char *pDst;	/* start of output buffer */
333 /*
334  * Write the filtered sample into the output buffer.
335  */
336 static void
emit_sample(lsumval,rsumval,channels)337 emit_sample(lsumval, rsumval, channels)
338 	long	lsumval;
339 	long	rsumval;
340 	long	channels;
341 {
342 	if (global.findminmax) {
343 		if (rsumval > global.maxamp[0])
344 			global.maxamp[0] = rsumval;
345 		if (rsumval < global.minamp[0])
346 			global.minamp[0] = rsumval;
347 		if (lsumval < global.minamp[1])
348 			global.minamp[1] = lsumval;
349 		if (lsumval > global.maxamp[1])
350 			global.maxamp[1] = lsumval;
351 	}
352 	/*
353 	 * convert to output format
354 	 */
355 	if (channels == 1) {
356 		Int16_t	sum;
357 
358 		/*
359 		 * mono section
360 		 */
361 		sum = (lsumval + rsumval) >> (global.sh_bits + 1);
362 		if (global.sh_bits == 8) {
363 			if (waitforsignal == 1) {
364 				if (any_signal == 0) {
365 					if (((char) sum) != '\0') {
366 						pStart = (unsigned char *) pDst;
367 						any_signal = 1;
368 						*pDst++ = (unsigned char) sum + (1 << 7);
369 					} else
370 						global.SkippedSamples++;
371 				} else
372 					*pDst++ = (unsigned char) sum + (1 << 7);
373 			} else
374 				*pDst++ = (unsigned char) sum + (1 << 7);
375 		} else {
376 			Int16_t	*myptr = (Int16_t *) pDst;
377 
378 			if (waitforsignal == 1) {
379 				if (any_signal == 0) {
380 					if (sum != 0) {
381 						pStart = (unsigned char *) pDst;
382 						any_signal = 1;
383 						*myptr = sum; pDst += sizeof (Int16_t);
384 					} else
385 						global.SkippedSamples++;
386 				} else {
387 					*myptr = sum; pDst += sizeof (Int16_t);
388 				}
389 			} else {
390 				*myptr = sum; pDst += sizeof (Int16_t);
391 			}
392 		}
393 
394 	} else {
395 		/*
396 		 * stereo section
397 		 */
398 		lsumval >>= global.sh_bits;
399 		rsumval >>= global.sh_bits;
400 		if (global.sh_bits == 8) {
401 			if (waitforsignal == 1) {
402 				if (any_signal == 0) {
403 					if ((((char) lsumval != '\0') || ((char) rsumval != '\0'))) {
404 						pStart = (unsigned char *) pDst;
405 						any_signal = 1;
406 						*pDst++ = (unsigned char)(short) lsumval + (1 << 7);
407 						*pDst++ = (unsigned char)(short) rsumval + (1 << 7);
408 					} else
409 						global.SkippedSamples++;
410 				} else {
411 					*pDst++ = (unsigned char)(short) lsumval + (1 << 7);
412 					*pDst++ = (unsigned char)(short) rsumval + (1 << 7);
413 				}
414 			} else {
415 				*pDst++ = (unsigned char)(short) lsumval + (1 << 7);
416 				*pDst++ = (unsigned char)(short) rsumval + (1 << 7);
417 			}
418 		} else {
419 			Int16_t	*myptr = (Int16_t *) pDst;
420 
421 			if (waitforsignal == 1) {
422 				if (any_signal == 0) {
423 					if ((((Int16_t) lsumval != 0) || ((Int16_t) rsumval != 0))) {
424 						pStart = (unsigned char *) pDst;
425 						any_signal = 1;
426 						*myptr++ = (Int16_t) lsumval;
427 						*myptr   = (Int16_t) rsumval;
428 						pDst += 2*sizeof (Int16_t);
429 					} else
430 						global.SkippedSamples++;
431 				} else {
432 					*myptr++ = (Int16_t) lsumval;
433 					*myptr   = (Int16_t) rsumval;
434 					pDst += 2*sizeof (Int16_t);
435 				}
436 			} else {
437 				*myptr++ = (Int16_t) lsumval;
438 				*myptr   = (Int16_t) rsumval;
439 				pDst += 2*sizeof (Int16_t);
440 			}
441 		}
442 	}
443 }
444 
445 static void
change_endianness(pSam,Samples)446 change_endianness(pSam, Samples)
447 	UINT4		*pSam;
448 	unsigned int	Samples;
449 {
450 	UINT4	*pend = (pSam + Samples);
451 
452 	/*
453 	 * type UINT4 may not be greater than the assumed biggest type
454 	 */
455 #if (SIZEOF_LONG_INT < 4)
456 error type unsigned long is too small
457 #endif
458 
459 #if (SIZEOF_LONG_INT == 4)
460 
461 	unsigned long	*plong = (unsigned long *)pSam;
462 
463 	for (; plong < pend; ) {
464 		*plong = ((*plong >> 8L) & UINT_C(0x00ff00ff)) |
465 			((*plong << 8L) & UINT_C(0xff00ff00));
466 		plong++;
467 	}
468 #else  /* sizeof long unsigned > 4 bytes */
469 #if (SIZEOF_LONG_INT == 8)
470 #define	INTEGRAL_LONGS	(SIZEOF_LONG_INT-1UL)
471 	register unsigned long	*plong;
472 	unsigned long		*pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
473 
474 	if (((unsigned long) pSam) & INTEGRAL_LONGS) {
475 		*pSam = ((*pSam >> 8L) & UINT_C(0x00ff00ff)) |
476 			((*pSam << 8L) & UINT_C(0xff00ff00));
477 		pSam++;
478 	}
479 
480 	plong = (unsigned long *)pSam;
481 
482 	for (; plong < pend0; ) {
483 		*plong = ((*plong >> 8L) & ULONG_C(0x00ff00ff00ff00ff)) |
484 			((*plong << 8L) & ULONG_C(0xff00ff00ff00ff00));
485 		plong++;
486 	}
487 
488 	if (((unsigned long *) pend) != pend0) {
489 		UINT4	*pint = (UINT4 *) pend0;
490 
491 		for (; pint < pend; ) {
492 			*pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
493 				((*pint << 8) & UINT_C(0xff00ff00));
494 			pint++;
495 		}
496 	}
497 #else  /* sizeof long unsigned > 4 bytes but not 8 */
498 	{
499 	UINT4	*pint = pSam;
500 
501 	for (; pint < pend; ) {
502 		*pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
503 			((*pint << 8) & UINT_C(0xff00ff00));
504 		pint++;
505 	}
506 	}
507 #endif
508 #endif
509 }
510 
511 static void
swap_channels(pSam,Samples)512 swap_channels(pSam, Samples)
513 	UINT4		*pSam;
514 	unsigned int	Samples;
515 {
516 	UINT4	*pend = (pSam + Samples);
517 
518 	/*
519 	 * type UINT4 may not be greater than the assumed biggest type
520 	 */
521 #if (SIZEOF_LONG_INT < 4)
522 error type unsigned long is too small
523 #endif
524 
525 #if (SIZEOF_LONG_INT == 4)
526 
527 	unsigned long	*plong = (unsigned long *)pSam;
528 
529 	for (; plong < pend; ) {
530 		*plong = ((*plong >> 16L) & UINT_C(0x0000ffff)) |
531 			((*plong << 16L) & UINT_C(0xffff0000));
532 		plong++;
533 	}
534 #else  /* sizeof long unsigned > 4 bytes */
535 #if (SIZEOF_LONG_INT == 8)
536 #define	INTEGRAL_LONGS	(SIZEOF_LONG_INT-1UL)
537 	register unsigned long	*plong;
538 	unsigned long		*pend0 = (unsigned long *) (((unsigned long) pend) & ~ INTEGRAL_LONGS);
539 
540 	if (((unsigned long) pSam) & INTEGRAL_LONGS) {
541 		*pSam = ((*pSam >> 16L) & UINT_C(0x0000ffff)) |
542 			((*pSam << 16L) & UINT_C(0xffff0000));
543 		pSam++;
544 	}
545 
546 	plong = (unsigned long *)pSam;
547 
548 	for (; plong < pend0; ) {
549 		*plong = ((*plong >> 16L) & ULONG_C(0x0000ffff0000ffff)) |
550 			((*plong << 16L) & ULONG_C(0xffff0000ffff0000));
551 		plong++;
552 	}
553 
554 	if (((unsigned long *) pend) != pend0) {
555 		UINT4	*pint = (UINT4 *) pend0;
556 
557 		for (; pint < pend; ) {
558 			*pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
559 				((*pint << 16L) & UINT_C(0xffff0000));
560 			pint++;
561 		}
562 	}
563 #else  /* sizeof long unsigned > 4 bytes but not 8 */
564 	{
565 	UINT4	*pint = pSam;
566 
567 	for (; pint < pend; ) {
568 		*pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
569 			((*pint << 16L) & UINT_C(0xffff0000));
570 		pint++;
571 	}
572 	}
573 #endif
574 #endif
575 }
576 
577 #ifdef	ECHO_TO_SOUNDCARD
578 static long ReSampleBuffer __PR((unsigned char *p, unsigned char *newp,
579 						long samples, int samplesize));
580 static long
ReSampleBuffer(p,newp,samples,samplesize)581 ReSampleBuffer(p, newp, samples, samplesize)
582 	unsigned char	*p;
583 	unsigned char	*newp;
584 	long		samples;
585 	int		samplesize;
586 {
587 	UINT4	di = 0;
588 
589 	if (global.playback_rate == 100.0) {
590 		memcpy(newp, p, samplesize* samples);
591 		di = samples;
592 	} else {
593 		UINT4	si = 0;
594 		double	idx = 0.0;
595 
596 		while (si < (UINT4)samples) {
597 			memcpy(newp+(di*samplesize), p+(si*samplesize),
598 								samplesize);
599 			idx += (double)(global.playback_rate/100.0);
600 			si = (UINT4)idx;
601 			di++;
602 		}
603 	}
604 	return ((long)di*samplesize);
605 }
606 #endif
607 
608 static int
guess_endianess(p,p2,SamplesToDo)609 guess_endianess(p, p2, SamplesToDo)
610 	UINT4		*p;
611 	Int16_t		*p2;
612 	unsigned	SamplesToDo;
613 {
614 	/*
615 	 * analyse samples
616 	 */
617 	int	vote_for_little = 0;
618 	int	vote_for_big = 0;
619 	int	total_votes;
620 
621 	while (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
622 		unsigned char	*p3 = (unsigned char *)p2;
623 #if MY_LITTLE_ENDIAN == 1
624 		int diff_lowl = *(p2+0) - *(p2+2);
625 		int diff_lowr = *(p2+1) - *(p2+3);
626 		int diff_bigl = ((*(p3)   << 8) + *(p3+1)) - ((*(p3+4) << 8) + *(p3+5));
627 		int diff_bigr = ((*(p3+2) << 8) + *(p3+3)) - ((*(p3+6) << 8) + *(p3+7));
628 #else
629 		int diff_lowl = ((*(p3+1) << 8) + *(p3))   - ((*(p3+5) << 8) + *(p3+4));
630 		int diff_lowr = ((*(p3+3) << 8) + *(p3+2)) - ((*(p3+7) << 8) + *(p3+6));
631 		int diff_bigl = *(p2+0) - *(p2+2);
632 		int diff_bigr = *(p2+1) - *(p2+3);
633 #endif
634 
635 		if ((abs(diff_lowl) + abs(diff_lowr)) <
636 		    (abs(diff_bigl) + abs(diff_bigr))) {
637 			vote_for_little++;
638 		} else {
639 			if ((abs(diff_lowl) + abs(diff_lowr)) >
640 			    (abs(diff_bigl) + abs(diff_bigr))) {
641 				vote_for_big++;
642 			}
643 		}
644 		p2 += 2;
645 	}
646 #ifdef DEBUG_VOTE_ENDIANESS
647 	if (global.quiet != 1) {
648 		fprintf(stderr,
649 		"votes for little: %4d,  votes for big: %4d\n",
650 			vote_for_little, vote_for_big);
651 	}
652 #endif
653 	total_votes = vote_for_big + vote_for_little;
654 	if (total_votes < 3 ||
655 	    abs(vote_for_big - vote_for_little) < total_votes/3) {
656 		return (-1);
657 	} else {
658 		if (vote_for_big > vote_for_little)
659 			return (1);
660 		else
661 			return (0);
662 	}
663 }
664 
665 int	jitterShift = 0;
666 
667 void
handle_inputendianess(p,SamplesToDo)668 handle_inputendianess(p, SamplesToDo)
669 	UINT4		*p;
670 	unsigned	SamplesToDo;
671 {
672 	/*
673 	 * if endianess is unknown, guess endianess based on
674 	 * differences between succesive samples. If endianess
675 	 * is correct, the differences are smaller than with the
676 	 * opposite byte order.
677 	 */
678 	if ((*in_lendian) < 0) {
679 		Int16_t	*p2 = (Int16_t *)p;
680 
681 		/*
682 		 * skip constant samples
683 		 */
684 		while ((((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) &&
685 						*p2 == *(p2+2))
686 			p2++;
687 
688 		if (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
689 			switch (guess_endianess(p, p2, SamplesToDo)) {
690 			case -1: break;
691 			case  1: (*in_lendian) = 0;
692 #if 0
693 				if (global.quiet != 1) {
694 					fprintf(stderr,
695 						"big endian detected\n");
696 				}
697 #endif
698 				break;
699 			case  0: (*in_lendian) = 1;
700 #if 0
701 				if (global.quiet != 1) {
702 					fprintf(stderr,
703 						"little endian detected\n");
704 				}
705 #endif
706 				break;
707 			}
708 		}
709 	}
710 
711 	/*
712 	 * ENDIAN ISSUES:
713 	 * the individual endianess of cdrom/cd-writer, cpu,
714 	 * sound card and audio output format need a careful treatment.
715 	 *
716 	 * For possible sample processing (rate conversion) we need
717 	 * the samples in cpu byte order. This is the first conversion.
718 	 *
719 	 * After processing it depends on the endianness of the output
720 	 * format, whether a second conversion is needed.
721 	 *
722 	 */
723 
724 	if (global.need_hostorder && (*in_lendian) != MY_LITTLE_ENDIAN) {
725 		/*
726 		 * change endianess of delivered samples to native cpu order
727 		 */
728 		change_endianness(p, SamplesToDo);
729 	}
730 }
731 
732 unsigned char *
synchronize(p,SamplesToDo,TotSamplesDone)733 synchronize(p, SamplesToDo, TotSamplesDone)
734 	UINT4		*p;
735 	unsigned	SamplesToDo;
736 	unsigned	TotSamplesDone;
737 {
738 	char	*pSrc;		/* start of cdrom buffer */
739 
740 	/*
741 	 * synchronisation code
742 	 */
743 	if (TotSamplesDone != 0 && global.overlap != 0 &&
744 	    SamplesToDo > CD_FRAMESAMPLES) {
745 
746 		pSrc = (char *) sync_buffers((unsigned char *)p);
747 		if (!pSrc) {
748 			return (NULL);
749 		}
750 		if (pSrc) {
751 			int	jitter;
752 
753 			jitter = ((unsigned char *)pSrc -
754 				(((unsigned char *)p) +
755 				global.overlap*CD_FRAMESIZE_RAW))/4;
756 			jitterShift += jitter;
757 			SamplesToDo -= jitter + global.overlap*CD_FRAMESAMPLES;
758 #if 0
759 			fprintf(stderr,
760 			"Length: pre %d, diff1 %ld, diff2 %ld, min %ld\n",
761 			SamplesToDo,
762 			(TotSamplesWanted - TotSamplesDone),
763 			SamplesNeeded((TotSamplesWanted - TotSamplesDone),
764 			undersampling),
765 			min(SamplesToDo,
766 			    SamplesNeeded((TotSamplesWanted - TotSamplesDone),
767 			    undersampling)));
768 #endif
769 		}
770 	} else {
771 		pSrc = (char *) p;
772 	}
773 	return ((unsigned char *) pSrc);
774 }
775 
776 /*
777  * convert cdda data to required output format
778  * sync code for unreliable cdroms included
779  */
780 long
SaveBuffer(p,SamplesToDo,TotSamplesDone)781 SaveBuffer(p, SamplesToDo, TotSamplesDone)
782 	UINT4		*p;
783 	unsigned long	SamplesToDo;
784 	unsigned long	*TotSamplesDone;
785 {
786 	UINT4	*pSrc;		/* start of cdrom buffer */
787 	UINT4	*pSrcStop;	/* end of cdrom buffer */
788 
789 	/*
790 	 * in case of different endianness between host and output format,
791 	 * or channel swaps, or deemphasizing
792 	 * copy in a separate buffer and modify the local copy
793 	 */
794 	if (((((!global.need_hostorder &&
795 	    global.need_big_endian == (*in_lendian)) ||
796 	    (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)) ||
797 	    (global.deemphasize != 0)) && (global.OutSampleSize > 1)) ||
798 	    global.swapchannels != 0) {
799 		static UINT4	*localoutputbuffer;
800 
801 		if (localoutputbuffer == NULL) {
802 			localoutputbuffer = malloc(global.nsectors*CD_FRAMESIZE_RAW);
803 			if (localoutputbuffer == NULL) {
804 				errmsg(_("Cannot allocate local buffer.\n"));
805 				return (1);
806 			}
807 		}
808 		memcpy(localoutputbuffer, p, SamplesToDo*4);
809 		p = localoutputbuffer;
810 	}
811 
812 	pSrc = p;
813 	pDst = (unsigned char *) p;
814 	pStart = (unsigned char *) pSrc;
815 	pSrcStop = pSrc + SamplesToDo;
816 
817 	/*
818 	 * code for subsampling and output stage
819 	 */
820 	if (global.ismono && global.findmono) {
821 		Int16_t	*pmm;
822 
823 		for (pmm = (Int16_t *)pStart;
824 				(UINT4 *) pmm < pSrcStop; pmm += 2) {
825 			if (*pmm != *(pmm+1)) {
826 				global.ismono = 0;
827 				break;
828 			}
829 		}
830 	}
831 
832 	/*
833 	 * optimize the case of no conversion
834 	 */
835 	if (1 && undersampling == 1 && samples_to_do == 1 &&
836 	    global.channels == 2 && global.OutSampleSize == 2 && Halved == 0) {
837 		/*
838 		 * output format is the original cdda format ->
839 		 * just forward the buffer
840 		 */
841 		if (waitforsignal != 0 && any_signal == 0) {
842 			UINT4	*myptr = (UINT4 *)pStart;
843 
844 			while (myptr < pSrcStop && *myptr == 0)
845 				myptr++;
846 			pStart = (unsigned char *) myptr;
847 			/*
848 			 * scan for first signal
849 			 */
850 			if ((UINT4 *)pStart != pSrcStop) {
851 				/*
852 				 * first non null amplitude is found in buffer
853 				 */
854 				any_signal = 1;
855 				global.SkippedSamples += ((UINT4 *)pStart - p);
856 			} else {
857 				global.SkippedSamples += (pSrcStop - p);
858 			}
859 		}
860 		pDst = (unsigned char *) pSrcStop;	/* set pDst to end */
861 
862 		if (global.deemphasize &&
863 		    (Get_Preemphasis(get_current_track_writing()))) {
864 			/*
865 			 * this implements an attenuation treble shelving
866 			 * filter to undo the effect of pre-emphasis.
867 			 * The filter is of a recursive first order
868 			 */
869 			static Int16_t	lastin[2] = { 0, 0 };
870 			static double	lastout[2] = { 0.0, 0.0 };
871 			Int16_t		*pmm;
872 
873 			/*
874 			 * Here is the gnuplot file for the frequency response
875 			 * of the deemphasis. The error is below +-0.1dB
876 			 */
877 #ifdef	GNU_PLOT_PROGRAM
878 /* BEGIN CSTYLED */
879 /*
880 # first define the ideal filter. We use the tenfold sampling frequency.
881 T=1./441000.
882 OmegaU=1./15E-6
883 OmegaL=15./50.*OmegaU
884 V0=OmegaL/OmegaU
885 H0=V0-1.
886 B=V0*tan(OmegaU*T/2.)
887 # the coefficients follow
888 a1=(B - 1.)/(B + 1.)
889 b0=(1.0 + (1.0 - a1) * H0/2.)
890 b1=(a1 + (a1 - 1.0) * H0/2.)
891 # helper variables
892 D=b1/b0
893 o=2*pi*T
894 H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
895 # now approximate the ideal curve with a fitted one for sampling frequency
896 # of 44100 Hz.
897 T2=1./44100.
898 V02=0.3365
899 OmegaU2=1./19E-6
900 B2=V02*tan(OmegaU2*T2/2.)
901 # the coefficients follow
902 a12=(B2 - 1.)/(B2 + 1.)
903 b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
904 b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
905 # helper variables
906 D2=b12/b02
907 o2=2*pi*T2
908 H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
909 # plot best, real, ideal, level with halved attenuation,
910 # level at full attentuation, 10fold magnified error
911 set logscale x
912 set grid xtics ytics mxtics mytics
913 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))
914 pause -1 "Hit return to continue"
915 */
916 /* END CSTYLED */
917 #endif
918 
919 #ifdef TEST
920 #define	V0	0.3365
921 #define	OMEGAG	(1./19e-6)
922 #define	T	(1./44100.)
923 #define	H0	(V0-1.)
924 #define	B	(V0*tan((OMEGAG * T)/2.0))
925 #define	a1	((B - 1.)/(B + 1.))
926 #define	b0 	(1.0 + (1.0 - a1) * H0/2.0)
927 #define	b1 	(a1 + (a1 - 1.0) * H0/2.0)
928 #undef	V0
929 #undef	OMEGAG
930 #undef	T
931 #undef	H0
932 #undef	B
933 #else
934 #define	a1	-0.62786881719628784282
935 #define	b0 	0.45995451989513153057
936 #define	b1 	-0.08782333709141937339
937 #endif
938 
939 			for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst; ) {
940 				lastout[0] = *pmm * b0 + lastin[0] * b1 - lastout[0] * a1;
941 				lastin[0] = *pmm;
942 				*pmm++ = lastout[0] > 0.0 ? lastout[0] + 0.5 : lastout[0] - 0.5;
943 				lastout[1] = *pmm * b0 + lastin[1] * b1 - lastout[1] * a1;
944 				lastin[1] = *pmm;
945 				*pmm++ = lastout[1] > 0.0 ? lastout[1] + 0.5 : lastout[1] - 0.5;
946 			}
947 #undef	a1
948 #undef	b0
949 #undef	b1
950 		}
951 
952 		if (global.swapchannels == 1) {
953 			swap_channels((UINT4 *)pStart, SamplesToDo);
954 		}
955 
956 		if (global.findminmax) {
957 			Int16_t	*pmm;
958 
959 			for (pmm = (Int16_t *)pStart;
960 						pmm < (Int16_t *)pDst; pmm++) {
961 				if (*pmm < global.minamp[1])
962 					global.minamp[1] = *pmm;
963 				if (*pmm > global.maxamp[1])
964 					global.maxamp[1] = *pmm;
965 				pmm++;
966 				if (*pmm < global.minamp[0])
967 					global.minamp[0] = *pmm;
968 				if (*pmm > global.maxamp[0])
969 					global.maxamp[0] = *pmm;
970 			}
971 		}
972 	} else {
973 
974 #define	none_missing	0
975 #define	one_missing	1
976 #define	two_missing	2
977 #define	collecting	3
978 
979 		static int	sample_state = collecting;
980 		static int	Toggle_on = 0;
981 
982 		if (global.channels == 2 && global.swapchannels == 1) {
983 			swap_channels((UINT4 *)pStart, SamplesToDo);
984 		}
985 
986 		/*
987 		 * conversion required
988 		 */
989 		while (pSrc < pSrcStop) {
990 			long	l;
991 			long	r;
992 
993 			long iSamples_left = (pSrcStop - pSrc) / sizeof (Int16_t) / 2;
994 			Int16_t *myptr = (Int16_t *) pSrc;
995 
996 			/*
997 			 * LSB l, MSB l
998 			 */
999 			l = *myptr++;	/* left channel */
1000 			r = *myptr++;	/* right channel */
1001 			pSrc = (UINT4 *) myptr;
1002 
1003 			switch (sample_state) {
1004 			case two_missing:
1005 two__missing:
1006 				ls2 += l; rs2 += r;
1007 				if (undersampling > 1) {
1008 					ls3 += l; rs3 += r;
1009 				}
1010 				sample_state = one_missing;
1011 				break;
1012 			case one_missing:
1013 				auxl = l; auxr = r;
1014 
1015 				ls3 += l; rs3 += r;
1016 				sample_state = none_missing;
1017 
1018 				/* FALLTHROUGH */
1019 none__missing:
1020 			case none_missing:
1021 				/*
1022 				 * Filtered samples are complete.
1023 				 * Now interpolate and scale.
1024 				 */
1025 				if (Halved != 0 && Toggle_on == 0) {
1026 					lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
1027 					rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
1028 				} else {
1029 					lsum /= (int) undersampling;
1030 					rsum /= (int) undersampling;
1031 				}
1032 				emit_sample(lsum, rsum, global.channels);
1033 				/*
1034 				 * reload counter
1035 				 */
1036 				samples_to_do = undersampling - 1;
1037 				lsum = auxl;
1038 				rsum = auxr;
1039 				/*
1040 				 * reset sample register
1041 				 */
1042 				auxl = ls2 = ls3 = 0;
1043 				auxr = rs2 = rs3 = 0;
1044 				Toggle_on ^= 1;
1045 				sample_state = collecting;
1046 				break;
1047 
1048 			case collecting:
1049 				if (samples_to_do > 0) {
1050 					samples_to_do--;
1051 					if (Halved != 0 && Toggle_on == 0) {
1052 						/*
1053 						 * Divider x.5 : we need data
1054 						 * for quadratic interpolation
1055 						 */
1056 						iSamples_left--;
1057 
1058 						lsum += l; rsum += r;
1059 						if (samples_to_do < undersampling - 1) {
1060 							ls2 += l; rs2 += r;
1061 						}
1062 						if (samples_to_do < undersampling - 2) {
1063 							ls3 += l; rs3 += r;
1064 						}
1065 					} else {
1066 						/*
1067 						 * integral divider
1068 						 */
1069 						lsum += l;
1070 						rsum += r;
1071 						iSamples_left--;
1072 					}
1073 				} else {
1074 					if (Halved != 0 && Toggle_on == 0) {
1075 						sample_state = two_missing;
1076 						goto two__missing;
1077 					} else {
1078 						auxl = l;
1079 						auxr = r;
1080 						sample_state = none_missing;
1081 						goto none__missing;
1082 					}
1083 				}
1084 				break;
1085 			} /* switch state */
1086 		} /* while */
1087 
1088 		/*
1089 		 * flush_buffer
1090 		 */
1091 		if ((samples_to_do == 0 && Halved == 0)) {
1092 			if (Halved != 0 && Toggle_on == 0) {
1093 				lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
1094 				rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
1095 			} else {
1096 				lsum /= (int) undersampling;
1097 				rsum /= (int) undersampling;
1098 			}
1099 			emit_sample(lsum, rsum, global.channels);
1100 
1101 			/*
1102 			 * reload counter
1103 			 */
1104 			samples_to_do = undersampling;
1105 
1106 			/*
1107 			 * reset sample register
1108 			 */
1109 			lsum = auxl = ls2 = ls3 = 0;
1110 			rsum = auxr = rs2 = rs3 = 0;
1111 			Toggle_on ^= 1;
1112 			sample_state = collecting;
1113 		}
1114 
1115 	} /* if optimize else */
1116 
1117 	if (waitforsignal == 0)
1118 		pStart = (unsigned char *)p;
1119 
1120 	if (waitforsignal == 0 || any_signal != 0) {
1121 		int		retval = 0;
1122 		unsigned	outlen;
1123 		unsigned	todo;
1124 
1125 		assert(pDst >= pStart);
1126 		outlen = (size_t) (pDst - pStart);
1127 
1128 		if (outlen == 0)
1129 			return (0);
1130 
1131 #ifdef	ECHO_TO_SOUNDCARD
1132 		/*
1133 		 * this assumes the soundcard needs samples in native
1134 		 * cpu byte order
1135 		 */
1136 		if (global.echo != 0) {
1137 			static unsigned char	*newp;
1138 				unsigned	newlen;
1139 
1140 			newlen = (100*(outlen/4))/global.playback_rate;
1141 			newlen = (newlen*4);
1142 			if ((newp != NULL) || (newp = malloc(2*global.nsectors*CD_FRAMESIZE_RAW+32))) {
1143 				newlen = ReSampleBuffer(pStart, newp, outlen/4, global.OutSampleSize*global.channels);
1144 				write_snd_device((char *)newp, newlen);
1145 			}
1146 		}
1147 #endif
1148 		if (global.no_file != 0) {
1149 			*TotSamplesDone += SamplesToDo;
1150 			return (0);
1151 		}
1152 		if ((!global.need_hostorder && global.need_big_endian == (*in_lendian)) ||
1153 		    (global.need_hostorder && global.need_big_endian != MY_BIG_ENDIAN)) {
1154 			if (global.OutSampleSize > 1) {
1155 				/*
1156 				 * change endianness from input sample or native cpu order
1157 				 * to required output endianness
1158 				 */
1159 				change_endianness((UINT4 *)pStart, outlen/4);
1160 			}
1161 		}
1162 		{
1163 			unsigned char	*p2 = pStart;
1164 
1165 			todo = outlen;
1166 			while (todo != 0) {
1167 #ifdef	MD5_SIGNATURES
1168 				if (global.md5count) {
1169 					global.md5size += todo;
1170 					MD5Update(global.context, p2, todo);
1171 					if (global.md5blocksize > 0)
1172 						global.md5count -= todo;
1173 				}
1174 #endif
1175 				retval = global.audio_out->WriteSound(global.audio, p2, todo);
1176 				if (retval < 0)
1177 					break;
1178 				p2 += retval;
1179 				todo -= retval;
1180 			}
1181 		}
1182 		if (todo == 0) {
1183 			*TotSamplesDone += SamplesToDo;
1184 			return (0);
1185 		} else {
1186 			errmsg(
1187 			_("Error in write(audio, 0x%p, %u) = %d\nProbably disk space exhausted.\n"),
1188 				pStart, outlen, retval);
1189 			return (1);
1190 		}
1191 	} else {
1192 		*TotSamplesDone += SamplesToDo;
1193 		return (0);
1194 	}
1195 }
1196