home *** CD-ROM | disk | FTP | other *** search
- /* periods.c */
-
- /* Computes the period table */
- /* $Author: Espie $
- * $Date: 91/05/12 19:54:18 $
- * $Revision: 1.7 $
- * $Log: periods.c,v $
- * Revision 1.7 91/05/12 19:54:18 Espie
- * Experimental find_note, handle stray periods with less space.
- *
- * Revision 1.6 91/05/06 23:34:24 Espie
- * New finetunes from 0 to 15 with 8 as default value.
- * Gives an idea that something is wrong in the window
- * title bar.
- *
- * Revision 1.5 91/05/05 19:07:07 Espie
- * *** empty log message ***
- *
- * Revision 1.4 91/05/05 15:39:58 Espie
- * The period_table to fill is now an argument.
- *
- * Revision 1.3 91/04/30 00:36:03 Espie
- * Stable version III.
- *
- * Revision 1.2 91/04/28 22:54:30 Espie
- * Now computes the periods.
- *
- * Revision 1.1 91/04/21 20:03:33 Espie
- * Initial revision
- *
- */
-
- #include <exec/types.h>
- #include <dos/dos.h>
- #include "proto.h"
- #include "periods.h"
-
- /* This file computes the period for all notes with all tuning.
- * It is also able to find a note from a given period.
- * Standard tuning has been moved to a middle value (8).
- */
-
-
- /* to compute the note periods, we deal with finite precision arithmetic
- * note/2^precision ~ 2^(1/12), adjust/2^precision ~ 2^(1/96)
- */
-
- #define precision (16)
- #define note 69433
- #define adjust 66011
- #define rounded_div(a,b) ((a+b/2)/b)
- #define rounded_shift(a,i) ((a+(1<<((i)-1)))>>(i))
-
-
-
- LOCAL UWORD **lookup_table;
-
- void init_periods(UWORD **period_table)
- {
- int i, k;
- /* everything MUST be unsigned */
- unsigned long starting_period, period;
- ULONG buffer[12];
- lookup_table = period_table;
- starting_period = rounded_div(3579545, 440) <<precision;
- period = starting_period;
- for (k = 0; k < NUMBER_TUNING-1; k++)
- {
- /* get the basic period ok */
- buffer[0] = period;
- /* compute one high precision octave */
- for (i = 1; i < 12; i++)
- buffer[i] = rounded_div(buffer[i-1], note)<<precision;
- /* use it to get every octave */
- for (i = 0; i < NUMBER_NOTES; i++)
- period_table[k][i] =
- rounded_shift(buffer[i%12], precision+i/12);
- /* for a better precision: 96/8 = 12 */
- if (k == 7)
- period = rounded_div(starting_period, note)<<precision;
- else
- period = rounded_div(period, adjust)<<precision;
- }
- lookup_table[NUMBER_TUNING-1][0] = 1;
- }
-
-
- /* this routine was taking too much time as a dumb linear scan (half
- * the running time, said the lattice profiler), so it got optimized.
- * Also, Lattice C wasn't able to fact the period_table[fine] constant,
- * had to do it by hand. Shesh !
- */
-
- UBYTE find_note(UWORD period, UBYTE fine)
- {
- UWORD *t;
- UBYTE a, b, i;
- if (period == 0)
- return NO_NOTE;
- t = lookup_table[fine];
- a = 0;
- b = NUMBER_NOTES-1;
- while(b-a > 1)
- {
- i = (a+b)/2;
- if (t[i] == period)
- return i;
- if (t[i] > period)
- a = i;
- else
- b = i;
- }
- /* at that point we have t[b]<= period <= t[a]
- * We want to allow for rounding errors.
- */
- check_abort();
- if (t[a] - 2 <= period)
- return a;
- if (t[b] + 2 >= period)
- return b;
- temporary_title("Read problem");
- t = lookup_table[NUMBER_TUNING-1];
- for (a = 1; a < t[0]; a++)
- if (period - t[a] <= 2 && period - t[a] >= -2)
- {
- return FINE_PERIOD + a;
- }
- t[t[0]] = period;
- if (t[0] >= NUMBER_NOTES - 1)
- return 0;
- return FINE_PERIOD + t[0]++;
- }
-
- /* remap the tuning so that 8 is now in the middle... MUCH more sensible. */
-
- LOCAL BYTE remap_tunes[16] = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7};
-
- BYTE normalize_finetune(UBYTE fine)
- {
- if (fine > 15)
- return -1;
- else
- return remap_tunes[fine];
- }
-