pimp_math.c 4.34 KB
Newer Older
1
2
3
4
5
/* pimp_math.c -- Math routines for use in Pimpmobile
 * Copyright (C) 2005-2006 Jrn Nystad and Erik Faye-Lund
 * For conditions of distribution and use, see copyright notice in LICENSE.TXT
 */

Erik Faye-Lund's avatar
Erik Faye-Lund committed
6
#include "pimp_types.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
7
8
#include "pimp_math.h"
#include "pimp_debug.h"
9

10
11
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

12
const u8 __pimp_clz_lut[256] =
Erik Faye-Lund's avatar
Erik Faye-Lund committed
13
{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
	0x8, 0x7, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4,
	0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
	0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
	0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
	0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
	0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
	0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
	0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
Erik Faye-Lund's avatar
Erik Faye-Lund committed
30
31
32
};


Erik Faye-Lund's avatar
Erik Faye-Lund committed
33
#ifndef NO_LINEAR_PERIODS
Erik Faye-Lund's avatar
Erik Faye-Lund committed
34
unsigned __pimp_get_linear_period(int note, int fine_tune)
Erik Faye-Lund's avatar
Erik Faye-Lund committed
35
{
Erik Faye-Lund's avatar
Erik Faye-Lund committed
36
37
	ASSERT(fine_tune >= -8);
	ASSERT(fine_tune <   8);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
38
	
39
	int xm_note = note - (12 * 1) - 1; /* we extended our note-range with one octave. */
40
	
41
	return (10 * 12 * 16 * 4 - xm_note * 16 * 4 - fine_tune / 2);
42
/*	return 10 * 12 * 16 * 4 - note * 16 * 4 - fine_tune / 2; */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
43
}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
44

Erik Faye-Lund's avatar
Erik Faye-Lund committed
45
#include "linear_delta_lut.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
46
unsigned __pimp_get_linear_delta(unsigned period)
Erik Faye-Lund's avatar
Erik Faye-Lund committed
47
{
48
49
50
	unsigned p = (12 * 16 * 4 * 14) - period;
	unsigned octave        = p / (12 * 16 * 4);
	unsigned octave_period = p % (12 * 16 * 4);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
51
	unsigned delta = linear_delta_lut[octave_period] << octave;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
52

Erik Faye-Lund's avatar
Erik Faye-Lund committed
53
	/* BEHOLD: the expression of the devil (this compiles to one arm-instruction) */
54
	const unsigned int scale = (unsigned int)((1.0 / (SAMPLERATE)) * (1 << 3) * (1ULL << 32));
Erik Faye-Lund's avatar
Erik Faye-Lund committed
55
	delta = ((long long)delta * scale + (1ULL << 31)) >> 32;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
56
57
58
59
60
61
	return delta;
}
#endif /* NO_LINEAR_PERIODS */

#ifndef NO_AMIGA_PERIODS
#include "amiga_period_lut.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
62
unsigned __pimp_get_amiga_period(int note, int fine_tune)
Erik Faye-Lund's avatar
Erik Faye-Lund committed
63
{
64
	fine_tune /= 8; /* todo: interpolate instead? */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
65
66
	ASSERT(fine_tune >= -8);
	ASSERT(fine_tune <=  8);
Erik Faye-Lund's avatar
Erik Faye-Lund committed
67
	
68
	/* bias up one octave to prevent from negative values due to fine tune*/
69
	unsigned index = 12 * 8 + note * 8 + fine_tune;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
70
	
71
	/* handle notes outside of the mod-range by shifting up or down */
72
	if (index < (12 * 8 * 5))
73
	{
74
75
76
		unsigned octave       = index / (12 * 8);
		unsigned octave_index = index % (12 * 8);
		return (((u32)amiga_period_lut[octave_index]) * 4) << (5 - octave);
77
78
	}

79
	if (index >= ARRAY_SIZE(amiga_period_lut) + 12 * 8 * 5)
80
	{
81
82
83
		unsigned octave       = index / (12 * 8);
		unsigned octave_index = index % (12 * 8);
		return (((u32)amiga_period_lut[octave_index]) * 4) >> (octave - 5);
84
85
	}

86
	return ((u32)amiga_period_lut[index - (12 * 8 * 5)]) * 4;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
87
}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
88

Erik Faye-Lund's avatar
Erik Faye-Lund committed
89
#include "amiga_delta_lut.h"
Erik Faye-Lund's avatar
Erik Faye-Lund committed
90
unsigned __pimp_get_amiga_delta(unsigned period)
Erik Faye-Lund's avatar
Erik Faye-Lund committed
91
92
93
{
	unsigned shamt = clz16(period) - 1;
	unsigned p = period << shamt;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
94
95
	unsigned p_frac = p & ((1 << AMIGA_DELTA_LUT_FRAC_BITS) - 1);
	p >>= AMIGA_DELTA_LUT_FRAC_BITS;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
96

97
98
99
	/* interpolate table-entries for better result */
	int d1 = amiga_delta_lut[p     - (AMIGA_DELTA_LUT_SIZE / 2)]; /* (8363 * 1712) / float(p) */
	int d2 = amiga_delta_lut[p + 1 - (AMIGA_DELTA_LUT_SIZE / 2)]; /* (8363 * 1712) / float(p + 1) */
Erik Faye-Lund's avatar
Erik Faye-Lund committed
100
	unsigned delta = (d1 << AMIGA_DELTA_LUT_FRAC_BITS) + (d2 - d1) * p_frac;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
101

Erik Faye-Lund's avatar
Erik Faye-Lund committed
102
103
	if (shamt > AMIGA_DELTA_LUT_FRAC_BITS) delta <<= shamt - AMIGA_DELTA_LUT_FRAC_BITS;
	else delta >>= AMIGA_DELTA_LUT_FRAC_BITS - shamt;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
104

Erik Faye-Lund's avatar
Erik Faye-Lund committed
105
	/* BEHOLD: the expression of the devil 2.0 (this compiles to one arm-instruction) */
106
	const unsigned int scale = (unsigned int)(((1.0 / (SAMPLERATE)) * (1 << 6)) * (1LL << 32));
Erik Faye-Lund's avatar
Erik Faye-Lund committed
107
	delta = ((long long)delta * scale + (1ULL << 31)) >> 32;
108
	
Erik Faye-Lund's avatar
Erik Faye-Lund committed
109
	return delta;
Erik Faye-Lund's avatar
Erik Faye-Lund committed
110
}
Erik Faye-Lund's avatar
Erik Faye-Lund committed
111
112
#endif /* NO_AMIGA_PERIODS */