home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Sound / SoX / Source / rate.c < prev    next >
C/C++ Source or Header  |  1999-07-18  |  8KB  |  320 lines

  1. #ifndef USE_OLD_RATE
  2. /*
  3.  * August 21, 1998
  4.  * Copyright 1998 Fabrice Bellard.
  5.  *
  6.  * [Rewrote completly the code of Lance Norskog And Sundry
  7.  * Contributors with a more efficient algorithm.]
  8.  *
  9.  * This source code is freely redistributable and may be used for
  10.  * any purpose.  This copyright notice must be maintained. 
  11.  * Lance Norskog And Sundry Contributors are not responsible for 
  12.  * the consequences of using this software.  
  13.  */
  14.  
  15. /*
  16.  * Sound Tools rate change effect file.
  17.  */
  18.  
  19. #include <math.h>
  20. #include "st.h"
  21.  
  22. /*
  23.  * Linear Interpolation.
  24.  *
  25.  * The use of fractional increment allows us to use no buffer. It
  26.  * avoid the problems at the end of the buffer we had with the old
  27.  * method which stored a possibly big buffer of size
  28.  * lcm(in_rate,out_rate).
  29.  *
  30.  * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
  31.  * the input & output frequencies are equal, a delay of one sample is
  32.  * introduced 
  33.  *
  34.  * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
  35.  * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
  36.  */
  37.  
  38. #define FRAC_BITS 16
  39.  
  40. /* Private data */
  41. typedef struct ratestuff {
  42.         u_l opos_frac;  /* fractional position of the output stream in input stream unit */
  43.         u_l opos;
  44.  
  45.         u_l opos_inc_frac;  /* fractional position increment in the output stream */
  46.         u_l opos_inc; 
  47.  
  48.         u_l ipos;      /* position in the input stream (integer) */
  49.  
  50.         LONG ilast; /* last sample in the input stream */
  51. } *rate_t;
  52.  
  53. /*
  54.  * Process options
  55.  */
  56. void rate_getopts(effp, n, argv) 
  57. eff_t effp;
  58. int n;
  59. char **argv;
  60. {
  61.     if (n)
  62.         fail("Rate effect takes no options.");
  63. }
  64.  
  65. /*
  66.  * Prepare processing.
  67.  */
  68. void rate_start(effp)
  69. eff_t effp;
  70. {
  71.     rate_t rate = (rate_t) effp->priv;
  72.         u_l incr;
  73.  
  74.         rate->opos_frac=0;
  75.         rate->opos=0;
  76.  
  77.         /* increment */
  78.         incr=(u_l)((double)effp->ininfo.rate / (double)effp->outinfo.rate * 
  79.                    (double) ((unsigned long) 1 << FRAC_BITS));
  80.  
  81.         rate->opos_inc_frac = incr & (((unsigned long) 1 << FRAC_BITS)-1);
  82.         rate->opos_inc = incr >> FRAC_BITS;
  83.         
  84.         rate->ipos=0;
  85.  
  86.     rate->ilast = 0;
  87. }
  88.  
  89. /*
  90.  * Processed signed long samples from ibuf to obuf.
  91.  * Return number of samples processed.
  92.  */
  93.  
  94. void rate_flow(effp, ibuf, obuf, isamp, osamp)
  95. eff_t effp;
  96. LONG *ibuf, *obuf;
  97. int *isamp, *osamp;
  98. {
  99.     rate_t rate = (rate_t) effp->priv;
  100.     LONG *istart,*iend;
  101.     LONG *ostart,*oend;
  102.     LONG ilast,icur,out;
  103.         u_l tmp;
  104.         double t;
  105.  
  106.         ilast=rate->ilast;
  107.  
  108.         istart = ibuf;
  109.         iend = ibuf + *isamp;
  110.         
  111.         ostart = obuf;
  112.         oend = obuf + *osamp;
  113.  
  114.         while (obuf < oend) {
  115.  
  116.                 /* read as many input samples so that ipos > opos */
  117.                 
  118.                 while (rate->ipos <= rate->opos) {
  119.                         if (ibuf >= iend) goto the_end;
  120.                         ilast = *ibuf++;
  121.                         rate->ipos++;
  122.                 }
  123.                 icur = *ibuf;
  124.         
  125.                 /* interpolate */
  126.                 t=(double) rate->opos_frac / ((unsigned long) 1 << FRAC_BITS);
  127.                 out = (double) ilast * (1.0 - t) + (double) icur * t;
  128.  
  129.                 /* output sample & increment position */
  130.                 
  131.                 *obuf++=(LONG) out;
  132.                 
  133.                 tmp = rate->opos_frac + rate->opos_inc_frac;
  134.                 rate->opos = rate->opos + rate->opos_inc + (tmp >> FRAC_BITS);
  135.                 rate->opos_frac = tmp & (((unsigned long) 1 << FRAC_BITS)-1);
  136.         }
  137. the_end:
  138.     *isamp = ibuf - istart;
  139.     *osamp = obuf - ostart;
  140.     rate->ilast = ilast;
  141. }
  142.  
  143. /*
  144.  * Do anything required when you stop reading samples.  
  145.  * Don't close input file! 
  146.  */
  147. void rate_stop(effp)
  148. eff_t effp;
  149. {
  150.     /* nothing to do */
  151. }
  152.  
  153. #else /* USE_OLD_RATE */
  154.  
  155. /*
  156.  * July 5, 1991
  157.  * Copyright 1991 Lance Norskog And Sundry Contributors
  158.  * This source code is freely redistributable and may be used for
  159.  * any purpose.  This copyright notice must be maintained. 
  160.  * Lance Norskog And Sundry Contributors are not responsible for 
  161.  * the consequences of using this software.
  162.  */
  163.  
  164. /*
  165.  * Sound Tools rate change effect file.
  166.  */
  167.  
  168. #include <math.h>
  169. #include "st.h"
  170.  
  171. /*
  172.  * Least Common Multiple Linear Interpolation 
  173.  *
  174.  * Find least common multiple of the two sample rates.
  175.  * Construct the signal at the LCM by interpolating successive
  176.  * input samples as straight lines.  Pull output samples from
  177.  * this line at output rate.
  178.  *
  179.  * Of course, actually calculate only the output samples.
  180.  *
  181.  * LCM must be 32 bits or less.  Two prime number sample rates
  182.  * between 32768 and 65535 will yield a 32-bit LCM, so this is 
  183.  * stretching it.
  184.  */
  185.  
  186. /*
  187.  * Algorithm:
  188.  *  
  189.  *  Generate a master sample clock from the LCM of the two rates.
  190.  *  Interpolate linearly along it.  Count up input and output skips.
  191.  *
  192.  *  Input:   |inskip |       |       |       |       |
  193.  *                                                                      
  194.  *                                                                      
  195.  *                                                                      
  196.  *  LCM:     |   |   |   |   |   |   |   |   |   |   |
  197.  *                                                                      
  198.  *                                                                      
  199.  *                                                                      
  200.  *  Output:  |  outskip  |           |           | 
  201.  *
  202.  *                                                                      
  203.  */
  204.  
  205.  
  206. /* Private data for Lerp via LCM file */
  207. typedef struct ratestuff {
  208.     u_l    lcmrate;        /* least common multiple of rates */
  209.     u_l    inskip, outskip;    /* LCM increments for I & O rates */
  210.     u_l    total;
  211.     u_l    intot, outtot;        /* total samples in LCM basis */
  212.     LONG    lastsamp;        /* history */
  213. } *rate_t;
  214.  
  215. /*
  216.  * Process options
  217.  */
  218. void rate_getopts(effp, n, argv) 
  219. eff_t effp;
  220. int n;
  221. char **argv;
  222. {
  223.     if (n)
  224.         fail("Rate effect takes no options.");
  225. }
  226.  
  227. /*
  228.  * Prepare processing.
  229.  */
  230. void rate_start(effp)
  231. eff_t effp;
  232. {
  233.     rate_t rate = (rate_t) effp->priv;
  234.     IMPORT LONG lcm();
  235.     
  236.     rate->lcmrate = lcm((LONG)effp->ininfo.rate, (LONG)effp->outinfo.rate);
  237.     /* Cursory check for LCM overflow.  
  238.      * If both rate are below 65k, there should be no problem.
  239.      * 16 bits x 16 bits = 32 bits, which we can handle.
  240.      */
  241.     rate->inskip = rate->lcmrate / effp->ininfo.rate;
  242.     rate->outskip = rate->lcmrate / effp->outinfo.rate; 
  243.     rate->total = rate->intot = rate->outtot = 0;
  244.     rate->lastsamp = 0;
  245. }
  246.  
  247. /*
  248.  * Processed signed long samples from ibuf to obuf.
  249.  * Return number of samples processed.
  250.  */
  251.  
  252. void rate_flow(effp, ibuf, obuf, isamp, osamp)
  253. eff_t effp;
  254. LONG *ibuf, *obuf;
  255. int *isamp, *osamp;
  256. {
  257.     rate_t rate = (rate_t) effp->priv;
  258.     int len, done;
  259.     LONG *istart = ibuf;
  260.     LONG last;
  261.  
  262.     done = 0;
  263.     if (rate->total == 0) {
  264.         /* Emit first sample.  We know the fence posts meet. */
  265.         *obuf = *ibuf++;
  266.         rate->lastsamp = *obuf++ / 65536L;
  267.         done = 1;
  268.         rate->total = 1;
  269.         /* advance to second output */
  270.         rate->outtot += rate->outskip;
  271.         /* advance input range to span next output */
  272.         while ((rate->intot + rate->inskip) <= rate->outtot){
  273.             last = *ibuf++ / 65536L;
  274.             rate->intot += rate->inskip;
  275.         }
  276.     } 
  277.  
  278.     /* start normal flow-through operation */
  279.     last = rate->lastsamp;
  280.         
  281.     /* number of output samples the input can feed */
  282.     len = (*isamp * rate->inskip) / rate->outskip;
  283.     if (len > *osamp)
  284.         len = *osamp;
  285.     for(; done < len; done++) {
  286.         *obuf = last;
  287.         *obuf += ((float)((*ibuf / 65536L)  - last)* ((float)rate->outtot -
  288.                 rate->intot))/rate->inskip;
  289.         *obuf *= 65536L;
  290.         obuf++;
  291.         /* advance to next output */
  292.         rate->outtot += rate->outskip;
  293.         /* advance input range to span next output */
  294.         while ((rate->intot + rate->inskip) <= rate->outtot){
  295.             last = *ibuf++ / 65536L;
  296.             rate->intot += rate->inskip;
  297.             if (ibuf - istart == *isamp)
  298.                 goto out;
  299.         }
  300.         /* long samples with high LCM's overrun counters! */
  301.         if (rate->outtot == rate->intot)
  302.             rate->outtot = rate->intot = 0;
  303.     }
  304. out:
  305.     *isamp = ibuf - istart;
  306.     *osamp = len;
  307.     rate->lastsamp = last;
  308. }
  309.  
  310. /*
  311.  * Do anything required when you stop reading samples.  
  312.  * Don't close input file! 
  313.  */
  314. void rate_stop(effp)
  315. eff_t effp;
  316. {
  317.     /* nothing to do */
  318. }
  319. #endif /* USE_OLD_RATE */
  320.