Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / icedax / resample.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
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).
6  *
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.
10  *
11  */
12
13 /* @(#)resample.c       1.15 02/11/21 Copyright 1998,1999,2000 Heiko Eissfeldt */
14 /* resampling module 
15  *
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
19  * lower sample rate.
20  *
21  */
22
23 #undef DEBUG_VOTE_ENDIANESS
24 #undef DEBUG_SHIFTS             /* simulate bad cdrom drives */
25 #undef DEBUG_MATCHING
26 #undef SHOW_JITTER
27 #undef CHECK_MEM
28
29 #include "config.h"
30 #include <timedefs.h>
31 #include <stdio.h>
32 #include <stdxlib.h>
33 #include <utypes.h>
34 #include <unixstd.h>
35 #include <standard.h>
36 #include <strdefs.h>
37 #include <limits.h>
38 #include <assert.h>
39 #include <math.h>
40
41 #include <usal/scsitransp.h>
42
43 #include "mytype.h"
44 #include "icedax.h"
45 #include "interface.h"
46 #include "byteorder.h"
47 #include "ringbuff.h"
48 #include "resample.h"
49 #include "toc.h"
50 #include "sndfile.h"
51 #include "sndconfig.h"
52 #include "global.h"
53 #include "exitcodes.h"
54
55
56 int waitforsignal = 0;  /* flag: wait for any audio response */
57 int any_signal = 0;
58
59 short undersampling;    /* conversion factor */
60 short samples_to_do;    /* loop variable for conversion */
61 int Halved;             /* interpolate due to non integral divider */
62
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;
65
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);
84
85
86 #ifdef CHECK_MEM
87 static void check_mem(const unsigned char *p, unsigned long amount, 
88                                                          const unsigned char *q, unsigned line, char *file);
89
90 static void check_mem(const unsigned char *p, unsigned long amount, 
91                       const unsigned char *q, unsigned line, char *file)
92 {
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);
96                 exit(INTERNAL_ERROR);
97         }
98 }
99 #endif
100
101
102 #ifdef DEBUG_MATCHING
103 int memcmp(const void * a, const void * b, size_t c)
104 {
105   return 1;
106 }
107 #endif
108
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)
112 {
113   const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN - 1;
114   const unsigned char * HAYSTACK2 = HAYSTACK-1;
115
116   while (HAYSTACK <= UPPER_LIMIT) {
117     if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
118       return HAYSTACK;
119     } else {
120       if (memcmp(NEEDLE, HAYSTACK2, NEEDLE_LEN) == 0) {
121         return HAYSTACK2;
122       }
123       HAYSTACK2--;
124       HAYSTACK++;
125     }
126   }
127 #ifdef DEBUG_MATCHING
128   HAYSTACK2++;
129   HAYSTACK--;
130   fprintf(stderr, "scompared %p-%p with %p-%p (%p)\n",
131          NEEDLE, NEEDLE + NEEDLE_LEN-1,
132          HAYSTACK2, HAYSTACK + NEEDLE_LEN-1, HAYSTACK);
133 #endif
134   return NULL;
135 }
136
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)
140 {
141   const unsigned char * const UPPER_LIMIT = HAYSTACK + HAYSTACK_LEN - NEEDLE_LEN;
142
143   while (HAYSTACK <= UPPER_LIMIT) {
144     if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
145       return HAYSTACK;
146     } else {
147       HAYSTACK++;
148     }
149   }
150 #ifdef DEBUG_MATCHING
151   HAYSTACK--;
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,
155          HAYSTACK);
156 #endif
157   return NULL;
158 }
159
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)
163 {
164   const unsigned char * const LOWER_LIMIT = HAYSTACK - (HAYSTACK_LEN - 1);
165
166   while (HAYSTACK >= LOWER_LIMIT) {
167     if (memcmp(NEEDLE, HAYSTACK, NEEDLE_LEN) == 0) {
168       return HAYSTACK;
169     } else {
170       HAYSTACK--;
171     }
172   }
173 #ifdef DEBUG_MATCHING
174   HAYSTACK++;
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);
179 #endif
180   return NULL;
181 }
182
183 /* find continuation in new buffer */
184 static const unsigned char *
185 sync_buffers(const unsigned char * const newbuf)
186 {
187     const unsigned char *retval = newbuf;
188
189     if (global.overlap != 0) {
190       /* find position of SYNC_SIZE bytes 
191          of the old buffer in the new buffer */
192       size_t haystack_len;
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;
197
198       /* compare the previous buffer with the new one
199        *
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).
203        *
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).
207        *   
208        */
209
210       haystack_len = min((global.nsectors - global.overlap)*CD_FRAMESIZE_RAW
211                          +SYNC_SIZE+1,
212                          global.overlap*CD_FRAMESIZE_RAW);
213       /* expected here */
214       haystack = newbuf + CD_FRAMESIZE_RAW*global.overlap - SYNC_SIZE;
215       needle = oldbuf + CD_FRAMESIZE_RAW*global.nsectors - SYNC_SIZE; 
216
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);
222 #endif
223
224       retval = my_symmemmem(haystack, haystack_len, needle, needle_len);
225       if (retval != NULL) {
226         retval += SYNC_SIZE;
227       } else {
228         /* fallback to asymmetrical search */
229
230         /* if there is no asymmetrical part left, return with 'not found' */
231         if (2*global.overlap == global.nsectors) {
232           retval = NULL;
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);
238         } else {
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);
243         }
244         if (retval != NULL)
245           retval += SYNC_SIZE;
246       }
247
248 #ifdef SHOW_JITTER
249       if (retval) {
250         fprintf(stderr,"%d\n",
251                 retval-(newbuf+global.overlap*CD_FRAMESIZE_RAW));
252       } else {
253         fprintf(stderr,"no match\n");
254       }
255 #endif
256     }
257
258     return retval;
259 }
260
261 /* quadratic interpolation
262  * p1, p3 span the interval 0 - 2. give interpolated value for 1/2 */
263 static long int 
264 interpolate(long int p1, long int p2, long int p3)
265 {
266   return (3L*p1 + 6L*p2 - p3)/8L;
267 }
268
269 static unsigned char *pStart;   /* running ptr defining end of output buffer */
270 static unsigned char *pDst;     /* start of output buffer */
271 /*
272  * Write the filtered sample into the output buffer.
273  */
274 static void 
275 emit_sample(long lsumval, long rsumval, long channels)
276 {
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;
282     }
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;
292                     any_signal = 1;
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 );
297         } else {
298             Int16_t * myptr = (Int16_t *) pDst;
299             if ( waitforsignal == 1 ) {
300               if ( any_signal == 0 ) {
301                 if ( sum != 0 ) {
302                     pStart = (unsigned char *) pDst;
303                     any_signal = 1;
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 ); }
308         }
309     } else {
310         /* stereo section */
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;
318                     any_signal = 1;
319                     *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
320                     *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
321                 } else global.SkippedSamples++;
322               } else {
323                 *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
324                 *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
325               }
326             } else {
327                 *pDst++ = ( unsigned char )( short ) lsumval + ( 1 << 7 );
328                 *pDst++ = ( unsigned char )( short ) rsumval + ( 1 << 7 );
329             }
330         } else {
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;
336                     any_signal = 1;
337                     *myptr++ = ( Int16_t ) lsumval;
338                     *myptr   = ( Int16_t ) rsumval;
339                     pDst += 2*sizeof( Int16_t );
340                 } else global.SkippedSamples++;
341               } else {
342                 *myptr++ = ( Int16_t ) lsumval;
343                 *myptr   = ( Int16_t ) rsumval;
344                 pDst += 2*sizeof( Int16_t );
345               }
346             } else {
347               *myptr++ = ( Int16_t ) lsumval;
348               *myptr   = ( Int16_t ) rsumval;
349               pDst += 2*sizeof( Int16_t );
350             }
351         }
352     }
353 }
354
355 static void change_endianness(UINT4 *pSam, unsigned int Samples)
356 {
357   UINT4 *pend = (pSam + Samples);
358
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
362 #endif
363
364 #if (SIZEOF_LONG_INT == 4)
365
366   unsigned long *plong = (unsigned long *)pSam;
367
368   for (; plong < pend;) {
369     *plong = ((*plong >> 8L) & UINT_C(0x00ff00ff)) |
370              ((*plong << 8L) & UINT_C(0xff00ff00));
371     plong++;
372   }
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);
378
379   if (((unsigned long) pSam) & INTEGRAL_LONGS) {
380     *pSam = ((*pSam >> 8L) & UINT_C(0x00ff00ff)) |
381             ((*pSam << 8L) & UINT_C(0xff00ff00));
382     pSam++;
383   }
384
385   plong = (unsigned long *)pSam;
386
387   for (; plong < pend0;) {
388     *plong = ((*plong >> 8L) & ULONG_C(0x00ff00ff00ff00ff)) |
389              ((*plong << 8L) & ULONG_C(0xff00ff00ff00ff00));
390     plong++;
391   }
392
393   if (((unsigned long *) pend) != pend0) {
394     UINT4 *pint = (UINT4 *) pend0;
395
396     for (;pint < pend;) {
397       *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
398               ((*pint << 8) & UINT_C(0xff00ff00));
399       pint++;
400     }
401   }
402 #else  /* sizeof long unsigned > 4 bytes but not 8 */
403   {
404     UINT4 *pint = pSam;
405
406     for (;pint < pend;) {
407       *pint = ((*pint >> 8) & UINT_C(0x00ff00ff)) |
408               ((*pint << 8) & UINT_C(0xff00ff00));
409       pint++;
410     }
411   }
412 #endif
413 #endif
414 }
415
416 static void swap_channels(UINT4 *pSam, unsigned int Samples)
417 {
418   UINT4 *pend = (pSam + Samples);
419
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
423 #endif
424
425 #if (SIZEOF_LONG_INT == 4)
426
427   unsigned long *plong = (unsigned long *)pSam;
428
429   for (; plong < pend;) {
430     *plong = ((*plong >> 16L) & UINT_C(0x0000ffff)) |
431              ((*plong << 16L) & UINT_C(0xffff0000));
432     plong++;
433   }
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);
439
440   if (((unsigned long) pSam) & INTEGRAL_LONGS) {
441     *pSam = ((*pSam >> 16L) & UINT_C(0x0000ffff)) |
442             ((*pSam << 16L) & UINT_C(0xffff0000));
443     pSam++;
444   }
445
446   plong = (unsigned long *)pSam;
447
448   for (; plong < pend0;) {
449     *plong = ((*plong >> 16L) & ULONG_C(0x0000ffff0000ffff)) |
450              ((*plong << 16L) & ULONG_C(0xffff0000ffff0000));
451     plong++;
452   }
453
454   if (((unsigned long *) pend) != pend0) {
455     UINT4 *pint = (UINT4 *) pend0;
456
457     for (;pint < pend;) {
458       *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
459               ((*pint << 16L) & UINT_C(0xffff0000));
460       pint++;
461     }
462   }
463 #else  /* sizeof long unsigned > 4 bytes but not 8 */
464   {
465     UINT4 *pint = pSam;
466
467     for (;pint < pend;) {
468       *pint = ((*pint >> 16L) & UINT_C(0x0000ffff)) |
469               ((*pint << 16L) & UINT_C(0xffff0000));
470       pint++;
471     }
472   }
473 #endif
474 #endif
475 }
476
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)
482 {
483         double idx=0.0;
484         UINT4  di=0,si=0;
485
486         if (global.playback_rate == 100.0) {
487                 memcpy(newp, p, samplesize* samples);
488                 di = samples;
489         } else while( si < (UINT4)samples ){
490                 memcpy( newp+(di*samplesize), p+(si*samplesize), samplesize );
491                 idx += (double)(global.playback_rate/100.0);
492                 si = (UINT4)idx;
493                 di++;
494         }
495         return di*samplesize;
496 }
497 #endif
498
499 static int guess_endianess(UINT4 *p, Int16_t *p2, unsigned SamplesToDo)
500 {
501     /* analyse samples */
502     int vote_for_little = 0;
503     int vote_for_big = 0;
504     int total_votes;
505
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));
513 #else
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);
518 #endif
519
520       if ((abs(diff_lowl) + abs(diff_lowr)) <
521           (abs(diff_bigl) + abs(diff_bigr))) {
522         vote_for_little++;
523       } else {
524         if ((abs(diff_lowl) + abs(diff_lowr)) >
525             (abs(diff_bigl) + abs(diff_bigr))) {
526           vote_for_big++;
527         }
528       }
529       p2 += 2;
530    }
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);
535 #endif
536    total_votes = vote_for_big + vote_for_little;
537    if (total_votes < 3
538        || abs(vote_for_big - vote_for_little) < total_votes/3) {
539      return -1;
540    } else {
541         if (vote_for_big > vote_for_little)
542                 return 1;
543         else
544                 return 0;
545    }
546 }
547
548 int jitterShift = 0; 
549
550 void handle_inputendianess(UINT4 *p, unsigned SamplesToDo)
551 {
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
555      opposite byte order.
556    */
557   if ((*in_lendian) < 0) {
558     Int16_t *p2 = (Int16_t *)p;
559
560     /* skip constant samples */
561     while ((((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo)
562            && *p2 == *(p2+2)) p2++;
563
564     if (((UINT4 *)p2 - p) + (unsigned) 1 < SamplesToDo) {
565       switch (guess_endianess(p, p2, SamplesToDo)) {
566         case -1: break;
567         case  1: (*in_lendian) = 0;
568 #if 0
569                  if (global.quiet != 1)
570                    fprintf(stderr, "big endian detected\n");
571 #endif
572         break;
573         case  0: (*in_lendian) = 1;
574 #if 0
575                  if (global.quiet != 1)
576                    fprintf(stderr, "little endian detected\n");
577 #endif
578         break;
579       }
580     }
581   }
582
583   /* ENDIAN ISSUES:
584    * the individual endianess of cdrom/cd-writer, cpu, 
585    * sound card and audio output format need a careful treatment.
586    *
587    * For possible sample processing (rate conversion) we need
588    * the samples in cpu byte order. This is the first conversion.
589    *
590    * After processing it depends on the endianness of the output
591    * format, whether a second conversion is needed.
592    *
593    */
594
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);
598   }
599 }
600
601 unsigned char *
602 synchronize(UINT4 *p, unsigned SamplesToDo, unsigned TotSamplesDone)
603 {
604   static int jitter = 0;
605   char *pSrc;                   /* start of cdrom buffer */
606
607   /* synchronisation code */
608   if (TotSamplesDone != 0 && global.overlap != 0 && SamplesToDo > CD_FRAMESAMPLES) {
609
610     pSrc = (char *) sync_buffers((unsigned char *)p);
611     if (!pSrc ) {
612       return NULL;
613     }
614     if (pSrc) {
615       jitter = ((unsigned char *)pSrc - (((unsigned char *)p) + global.overlap*CD_FRAMESIZE_RAW))/4;
616       jitterShift += jitter;
617       SamplesToDo -= jitter + global.overlap*CD_FRAMESAMPLES;
618 #if 0
619       fprintf(stderr,
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)));
624 #endif
625     }
626   } else {
627     pSrc = ( char * ) p;
628   }
629   return (unsigned char *) pSrc;
630 }
631
632 /* convert cdda data to required output format
633  * sync code for unreliable cdroms included
634  * 
635  */
636 long 
637 SaveBuffer(UINT4 *p, unsigned long SamplesToDo, unsigned long *TotSamplesDone)
638 {
639   UINT4 *pSrc;                   /* start of cdrom buffer */
640   UINT4 *pSrcStop;               /* end of cdrom buffer */
641
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");
655          return 1;
656        }
657      }
658      memcpy(localoutputbuffer, p, SamplesToDo*4);
659      p = localoutputbuffer;
660   }
661
662   pSrc = p;
663   pDst = (unsigned char *) p;
664   pStart = ( unsigned char * ) pSrc;
665   pSrcStop = pSrc + SamplesToDo;
666
667   /* code for subsampling and output stage */
668
669   if (global.ismono && global.findmono) {
670     Int16_t *pmm;
671     for (pmm = (Int16_t *)pStart; (UINT4 *) pmm < pSrcStop; pmm += 2) {
672       if (*pmm != *(pmm+1)) {
673         global.ismono = 0;
674         break;
675       }
676     }
677   }
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 
683      */
684       
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 */
692         any_signal = 1;
693         global.SkippedSamples += ((UINT4 *)pStart - p);
694       } else {
695         global.SkippedSamples += (pSrcStop - p);
696       }
697     }
698     pDst = (unsigned char *) pSrcStop;          /* set pDst to end */
699
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 };
706       Int16_t *pmm;
707
708       /* Here is the gnuplot file for the frequency response
709          of the deemphasis. The error is below +-0.1dB
710
711 # first define the ideal filter. We use the tenfold sampling frequency.
712 T=1./441000.
713 OmegaU=1./15E-6
714 OmegaL=15./50.*OmegaU
715 V0=OmegaL/OmegaU
716 H0=V0-1.
717 B=V0*tan(OmegaU*T/2.)
718 # the coefficients follow
719 a1=(B - 1.)/(B + 1.)
720 b0=(1.0 + (1.0 - a1) * H0/2.)
721 b1=(a1 + (a1 - 1.0) * H0/2.)
722 # helper variables
723 D=b1/b0
724 o=2*pi*T
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
727 # of 44100 Hz.
728 T2=1./44100.
729 V02=0.3365
730 OmegaU2=1./19E-6
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.)
736 # helper variables
737 D2=b12/b02
738 o2=2*pi*T2
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
742 set logscale x
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"
746        */
747
748 #ifdef TEST
749 #define V0      0.3365
750 #define OMEGAG  (1./19e-6)
751 #define T       (1./44100.)
752 #define H0      (V0-1.)
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)
757 #undef  V0
758 #undef  OMEGAG
759 #undef  T
760 #undef  H0
761 #undef  B
762 #else
763 #define a1      -0.62786881719628784282
764 #define b0      0.45995451989513153057
765 #define b1      -0.08782333709141937339
766 #endif
767
768       for (pmm = (Int16_t *)pStart; pmm < (Int16_t *)pDst;) {
769         lastout[0] = *pmm * b0 + lastin[0] * b1 - lastout[0] * a1;
770         lastin[0] = *pmm;
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;
773         lastin[1] = *pmm;
774         *pmm++ = lastout[1] > 0.0 ? lastout[1] + 0.5 : lastout[1] - 0.5;
775       }
776 #undef  a1
777 #undef  b0
778 #undef  b1
779     }
780
781     if (global.swapchannels == 1) {
782         swap_channels((UINT4 *)pStart, SamplesToDo);
783     }
784
785     if (global.findminmax) {
786       Int16_t *pmm;
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;
790         pmm++;
791         if (*pmm < global.minamp[0]) global.minamp[0] = *pmm;
792         if (*pmm > global.maxamp[0]) global.maxamp[0] = *pmm;
793       }
794     }
795   } else {
796
797 #define none_missing    0
798 #define one_missing     1
799 #define two_missing     2
800 #define collecting      3
801
802     static int sample_state = collecting;
803     static int Toggle_on = 0;
804
805     if (global.channels == 2 && global.swapchannels == 1) {
806         swap_channels((UINT4 *)pStart, SamplesToDo);
807     }
808
809     /* conversion required */
810     while ( pSrc < pSrcStop ) {
811           
812         long l,r;
813
814         long iSamples_left = (pSrcStop - pSrc) / sizeof(Int16_t) / 2;
815         Int16_t *myptr = (Int16_t *) pSrc;
816
817         /* LSB l, MSB l */
818         l = *myptr++;   /* left channel */
819         r = *myptr++;   /* right channel */
820         pSrc = (UINT4 *) myptr;
821
822         switch (sample_state) {
823         case two_missing:
824 two__missing:
825             ls2 += l; rs2 += r;
826             if (undersampling > 1) {
827                 ls3 += l; rs3 += r;
828             }
829             sample_state = one_missing;
830             break;
831         case one_missing:
832             auxl = l; auxr = r;
833
834             ls3 += l; rs3 += r;
835             sample_state = none_missing;
836
837             /* FALLTHROUGH */
838 none__missing:
839         case none_missing:
840             /* Filtered samples are complete. Now interpolate and scale. */
841
842             if (Halved != 0 && Toggle_on == 0) {
843                 lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
844                 rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
845             } else {
846                 lsum /= (int) undersampling;
847                 rsum /= (int) undersampling;
848             }
849             emit_sample(lsum, rsum, global.channels);
850             /* reload counter */
851             samples_to_do = undersampling - 1;
852             lsum = auxl;
853             rsum = auxr;
854             /* reset sample register */
855             auxl = ls2 = ls3 = 0;
856             auxr = rs2 = rs3 = 0;
857             Toggle_on ^= 1;
858             sample_state = collecting;
859             break;
860         case collecting:
861             if ( samples_to_do > 0) {
862                 samples_to_do--;
863                 if (Halved != 0 && Toggle_on == 0) {
864                     /* Divider x.5 : we need data for quadratic interpolation */
865                     iSamples_left--;
866
867                     lsum += l; rsum += r;
868                     if ( samples_to_do < undersampling - 1) {
869                         ls2 += l; rs2 += r;
870                     }
871                     if ( samples_to_do < undersampling - 2) {
872                         ls3 += l; rs3 += r;
873                     }
874                 } else {
875                     /* integral divider */
876                     lsum += l;
877                     rsum += r;
878                     iSamples_left--;
879                 }
880             } else {
881                 if (Halved != 0 && Toggle_on == 0) {
882                     sample_state = two_missing;
883                     goto two__missing;
884                 } else {
885                     auxl = l;
886                     auxr = r;
887                     sample_state = none_missing;
888                     goto none__missing;
889                 }
890             }
891             break;
892         } /* switch state */
893
894     } /* while */
895
896     /* flush_buffer */
897     if ((samples_to_do == 0 && Halved == 0))
898     {
899         if (Halved != 0 && Toggle_on == 0) {
900             lsum = interpolate(lsum, ls2, ls3)/(int) undersampling;
901             rsum = interpolate(rsum, rs2, rs3)/(int) undersampling;
902         } else {
903             lsum /= (int) undersampling;
904             rsum /= (int) undersampling;
905         }
906         emit_sample(lsum, rsum, global.channels);
907         
908         /* reload counter */
909         samples_to_do = undersampling;
910         
911         /* reset sample register */
912         lsum = auxl = ls2 = ls3 = 0;
913         rsum = auxr = rs2 = rs3 = 0;
914         Toggle_on ^= 1;
915         sample_state = collecting;
916     }
917
918   } /* if optimize else */
919
920   if ( waitforsignal == 0 ) pStart = (unsigned char *)p;
921
922   if ( waitforsignal == 0 || any_signal != 0) {
923     int retval = 0;
924     unsigned outlen;
925     unsigned todo;
926
927     assert(pDst >= pStart);
928     outlen = (size_t) (pDst - pStart);
929
930     if (outlen <= 0) return 0;
931
932 #ifdef  ECHO_TO_SOUNDCARD
933
934     /* this assumes the soundcard needs samples in native cpu byte order */
935     if (global.echo != 0) {
936                static unsigned char *newp;
937                unsigned    newlen;
938
939                newlen = (100*(outlen/4))/global.playback_rate;
940                newlen = (newlen*4);
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);
944                }
945     }
946 #endif
947
948     if ( global.no_file != 0 ) {
949         *TotSamplesDone += SamplesToDo;
950         return 0;
951     }
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);
958       }
959     }
960     {
961       unsigned char * p2 = pStart;
962
963       todo = outlen;
964       while (todo != 0) {
965         int retval_;
966         retval_ = global.audio_out->WriteSound ( global.audio, p2, todo );
967         if (retval_ < 0) break;
968
969         p2 += retval_;
970         todo -= retval_;
971       }
972     }
973     if (todo == 0) {
974         *TotSamplesDone += SamplesToDo;
975         return 0;
976     } else {
977         fprintf(stderr, "write(audio, 0x%p, %u) = %d\n",pStart,outlen,retval);
978         perror("Probably disk space exhausted");
979         return 1;
980     }
981   } else {
982     *TotSamplesDone += SamplesToDo;
983     return 0;
984   }
985 }