home *** CD-ROM | disk | FTP | other *** search
/ Audio Version 4.94 / audioversion4.94knowledgemediaresourcelibraryoctober1994.iso / amiga / utils / exp_iv / periods.c < prev    next >
C/C++ Source or Header  |  1991-05-12  |  4KB  |  145 lines

  1. /* periods.c */
  2.  
  3. /* Computes the period table */
  4. /* $Author: Espie $
  5.  * $Date: 91/05/12 19:54:18 $
  6.  * $Revision: 1.7 $
  7.  * $Log:    periods.c,v $
  8.  * Revision 1.7  91/05/12  19:54:18  Espie
  9.  * Experimental find_note, handle stray periods with less space.
  10.  * 
  11.  * Revision 1.6  91/05/06  23:34:24  Espie
  12.  * New finetunes from 0 to 15 with 8 as default value.
  13.  * Gives an idea that something is wrong in the window
  14.  * title bar.
  15.  * 
  16.  * Revision 1.5  91/05/05  19:07:07  Espie
  17.  * *** empty log message ***
  18.  * 
  19.  * Revision 1.4  91/05/05  15:39:58  Espie
  20.  * The period_table to fill is now an argument.
  21.  * 
  22.  * Revision 1.3  91/04/30  00:36:03  Espie
  23.  * Stable version III.
  24.  * 
  25.  * Revision 1.2  91/04/28  22:54:30  Espie
  26.  * Now computes the periods.
  27.  * 
  28.  * Revision 1.1  91/04/21  20:03:33  Espie
  29.  * Initial revision
  30.  * 
  31.  */
  32.  
  33. #include <exec/types.h>
  34. #include <dos/dos.h>
  35. #include "proto.h"
  36. #include "periods.h"
  37.  
  38. /* This file computes the period for all notes with all tuning.
  39.  * It is also able to find a note from a given period.
  40.  * Standard tuning has been moved to a middle value (8).
  41.  */
  42.  
  43.  
  44. /* to compute the note periods, we deal with finite precision arithmetic
  45.  * note/2^precision ~ 2^(1/12), adjust/2^precision ~ 2^(1/96)
  46.  */
  47.  
  48. #define precision (16)
  49. #define note 69433
  50. #define adjust 66011
  51. #define rounded_div(a,b) ((a+b/2)/b)
  52. #define rounded_shift(a,i) ((a+(1<<((i)-1)))>>(i))
  53.  
  54.  
  55.  
  56. LOCAL UWORD **lookup_table;
  57.  
  58. void init_periods(UWORD **period_table)
  59.     {
  60.     int i, k;
  61.         /* everything MUST be unsigned */
  62.     unsigned long starting_period, period;
  63.     ULONG buffer[12];
  64.         lookup_table = period_table;
  65.         starting_period = rounded_div(3579545, 440) <<precision;
  66.         period = starting_period;
  67.         for (k = 0; k < NUMBER_TUNING-1; k++)
  68.             {
  69.                     /* get the basic period ok */
  70.                 buffer[0] = period;
  71.                     /* compute one high precision octave */
  72.                 for (i = 1; i < 12; i++)
  73.                     buffer[i] = rounded_div(buffer[i-1], note)<<precision;
  74.                     /* use it to get every octave */
  75.                 for (i = 0; i < NUMBER_NOTES; i++)
  76.                     period_table[k][i] = 
  77.                         rounded_shift(buffer[i%12], precision+i/12);
  78.                     /* for a better precision: 96/8 = 12 */
  79.                 if (k == 7)
  80.                     period = rounded_div(starting_period, note)<<precision;
  81.                 else
  82.                     period = rounded_div(period, adjust)<<precision;
  83.             }
  84.         lookup_table[NUMBER_TUNING-1][0] = 1;
  85.     }
  86.                 
  87.  
  88. /* this routine was taking too much time as a dumb linear scan (half
  89.  * the running time, said the lattice profiler), so it got optimized.
  90.  * Also, Lattice C wasn't able to fact the period_table[fine] constant,
  91.  * had to do it by hand. Shesh !
  92.  */
  93.  
  94. UBYTE find_note(UWORD period, UBYTE fine)
  95.     {
  96.     UWORD *t;
  97.     UBYTE a, b, i;    
  98.         if (period == 0)
  99.             return NO_NOTE;
  100.         t = lookup_table[fine];
  101.         a = 0;
  102.         b = NUMBER_NOTES-1;
  103.         while(b-a > 1)
  104.             {
  105.                 i = (a+b)/2;
  106.                 if (t[i] == period)
  107.                     return i;
  108.                 if (t[i] > period)
  109.                     a = i;
  110.                 else
  111.                     b = i;
  112.             }
  113.             /* at that point we have t[b]<= period <= t[a]
  114.              * We want to allow for rounding errors.
  115.              */
  116.         check_abort();
  117.         if (t[a] - 2 <= period)
  118.             return a;
  119.         if (t[b] + 2 >= period)
  120.             return b;
  121.         temporary_title("Read problem");
  122.         t = lookup_table[NUMBER_TUNING-1];
  123.         for (a = 1; a < t[0]; a++)
  124.             if (period - t[a] <= 2 && period - t[a] >= -2)
  125.                 {
  126.                     return FINE_PERIOD + a;
  127.                 }
  128.         t[t[0]] = period;
  129.         if (t[0] >= NUMBER_NOTES - 1)
  130.             return 0;
  131.         return FINE_PERIOD + t[0]++;
  132.     }        
  133.  
  134. /* remap the tuning so that 8 is now in the middle... MUCH more sensible. */
  135.  
  136. LOCAL BYTE remap_tunes[16] = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7};
  137.     
  138. BYTE normalize_finetune(UBYTE fine)
  139.     {
  140.         if (fine > 15)
  141.             return -1;
  142.         else
  143.             return remap_tunes[fine];
  144.     }
  145.