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