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