Set the FPU into single-precision mode for mixer updates
[openal-soft/android.git] / OpenAL32 / Include / alu.h
blobbd00e86dde42a0db0b3d755743620312fc7ee01b
1 #ifndef _ALU_H_
2 #define _ALU_H_
4 #include "AL/al.h"
5 #include "AL/alc.h"
6 #include "AL/alext.h"
8 #include <limits.h>
9 #include <math.h>
10 #ifdef HAVE_FLOAT_H
11 #include <float.h>
12 #endif
13 #ifdef HAVE_IEEEFP_H
14 #include <ieeefp.h>
15 #endif
17 #ifndef M_PI
18 #define M_PI 3.14159265358979323846 /* pi */
19 #define M_PI_2 1.57079632679489661923 /* pi/2 */
20 #endif
22 #define F_PI ((float)M_PI)
23 #define F_PI_2 ((float)M_PI_2)
25 #ifdef HAVE_POWF
26 #define aluPow(x,y) (powf((x),(y)))
27 #else
28 #define aluPow(x,y) ((ALfloat)pow((double)(x),(double)(y)))
29 #endif
31 #ifdef HAVE_SQRTF
32 #define aluSqrt(x) (sqrtf((x)))
33 #else
34 #define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
35 #endif
37 #ifdef HAVE_COSF
38 #define aluCos(x) (cosf((x)))
39 #else
40 #define aluCos(x) ((ALfloat)cos((double)(x)))
41 #endif
43 #ifdef HAVE_SINF
44 #define aluSin(x) (sinf((x)))
45 #else
46 #define aluSin(x) ((ALfloat)sin((double)(x)))
47 #endif
49 #ifdef HAVE_ACOSF
50 #define aluAcos(x) (acosf((x)))
51 #else
52 #define aluAcos(x) ((ALfloat)acos((double)(x)))
53 #endif
55 #ifdef HAVE_ASINF
56 #define aluAsin(x) (asinf((x)))
57 #else
58 #define aluAsin(x) ((ALfloat)asin((double)(x)))
59 #endif
61 #ifdef HAVE_ATANF
62 #define aluAtan(x) (atanf((x)))
63 #else
64 #define aluAtan(x) ((ALfloat)atan((double)(x)))
65 #endif
67 #ifdef HAVE_ATAN2F
68 #define aluAtan2(x,y) (atan2f((x),(y)))
69 #else
70 #define aluAtan2(x,y) ((ALfloat)atan2((double)(x),(double)(y)))
71 #endif
73 #ifdef HAVE_FABSF
74 #define aluFabs(x) (fabsf((x)))
75 #else
76 #define aluFabs(x) ((ALfloat)fabs((double)(x)))
77 #endif
79 #ifdef HAVE_LOG10F
80 #define aluLog10(x) (log10f((x)))
81 #else
82 #define aluLog10(x) ((ALfloat)log10((double)(x)))
83 #endif
85 #ifdef HAVE_FLOORF
86 #define aluFloor(x) (floorf((x)))
87 #else
88 #define aluFloor(x) ((ALfloat)floor((double)(x)))
89 #endif
91 #define QUADRANT_NUM 128
92 #define LUT_NUM (4 * QUADRANT_NUM)
94 #ifdef __cplusplus
95 extern "C" {
96 #endif
98 struct ALsource;
99 struct ALbuffer;
101 typedef ALvoid (*MixerFunc)(struct ALsource *self, ALCdevice *Device,
102 const ALvoid *RESTRICT data,
103 ALuint *DataPosInt, ALuint *DataPosFrac,
104 ALuint OutPos, ALuint SamplesToDo,
105 ALuint BufferSize);
107 enum Resampler {
108 POINT_RESAMPLER = 0,
109 LINEAR_RESAMPLER,
110 CUBIC_RESAMPLER,
112 RESAMPLER_MAX,
113 RESAMPLER_MIN = -1,
114 RESAMPLER_DEFAULT = LINEAR_RESAMPLER
117 enum Channel {
118 FRONT_LEFT = 0,
119 FRONT_RIGHT,
120 FRONT_CENTER,
121 LFE,
122 BACK_LEFT,
123 BACK_RIGHT,
124 BACK_CENTER,
125 SIDE_LEFT,
126 SIDE_RIGHT,
128 MAXCHANNELS
131 enum DistanceModel {
132 InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
133 LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
134 ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
135 InverseDistance = AL_INVERSE_DISTANCE,
136 LinearDistance = AL_LINEAR_DISTANCE,
137 ExponentDistance = AL_EXPONENT_DISTANCE,
138 DisableDistance = AL_NONE
141 #define BUFFERSIZE 4096
143 #define FRACTIONBITS (14)
144 #define FRACTIONONE (1<<FRACTIONBITS)
145 #define FRACTIONMASK (FRACTIONONE-1)
147 /* Size for temporary stack storage of buffer data. Larger values need more
148 * stack, while smaller values may need more iterations. The value needs to be
149 * a sensible size, however, as it constrains the max stepping value used for
150 * mixing.
151 * The mixer requires being able to do two samplings per mixing loop. A 16KB
152 * buffer can hold 512 sample frames for a 7.1 float buffer. With the cubic
153 * resampler (which requires 3 padding sample frames), this limits the maximum
154 * step to about 508. This means that buffer_freq*source_pitch cannot exceed
155 * device_freq*508 for an 8-channel 32-bit buffer. */
156 #ifndef STACK_DATA_SIZE
157 #define STACK_DATA_SIZE 16384
158 #endif
161 static __inline ALfloat minf(ALfloat a, ALfloat b)
162 { return ((a > b) ? b : a); }
163 static __inline ALfloat maxf(ALfloat a, ALfloat b)
164 { return ((a > b) ? a : b); }
165 static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
166 { return minf(max, maxf(min, val)); }
168 static __inline ALuint minu(ALuint a, ALuint b)
169 { return ((a > b) ? b : a); }
170 static __inline ALuint maxu(ALuint a, ALuint b)
171 { return ((a > b) ? a : b); }
172 static __inline ALuint clampu(ALuint val, ALuint min, ALuint max)
173 { return minu(max, maxu(min, val)); }
175 static __inline ALint mini(ALint a, ALint b)
176 { return ((a > b) ? b : a); }
177 static __inline ALint maxi(ALint a, ALint b)
178 { return ((a > b) ? a : b); }
179 static __inline ALint clampi(ALint val, ALint min, ALint max)
180 { return mini(max, maxi(min, val)); }
183 static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
185 return val1 + (val2-val1)*mu;
187 static __inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu)
189 ALfloat mu2 = mu*mu;
190 ALfloat a0 = -0.5f*val0 + 1.5f*val1 + -1.5f*val2 + 0.5f*val3;
191 ALfloat a1 = val0 + -2.5f*val1 + 2.0f*val2 + -0.5f*val3;
192 ALfloat a2 = -0.5f*val0 + 0.5f*val2;
193 ALfloat a3 = val1;
195 return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
199 static __inline int SetMixerFPUMode(void)
201 #if defined(_FPU_GETCW) && defined(_FPU_SETCW)
202 fpu_control_t fpuState, newState;
203 _FPU_GETCW(fpuState);
204 newState = fpuState&~(_FPU_EXTENDED|_FPU_DOUBLE|_FPU_SINGLE |
205 _FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO);
206 newState |= _FPU_SINGLE | _FPU_RC_ZERO;
207 _FPU_SETCW(newState);
208 #else
209 int fpuState;
210 #if defined(HAVE__CONTROLFP)
211 fpuState = _controlfp(0, 0);
212 (void)_controlfp(_RC_CHOP|_PC_24, _MCW_RC|_MCW_PC);
213 #elif defined(HAVE_FESETROUND)
214 fpuState = fegetround();
215 fesetround(FE_TOWARDZERO);
216 #endif
217 #endif
218 return fpuState;
221 static __inline void RestoreFPUMode(int state)
223 #if defined(_FPU_GETCW) && defined(_FPU_SETCW)
224 fpu_control_t fpuState = state;
225 _FPU_SETCW(fpuState);
226 #elif defined(HAVE__CONTROLFP)
227 _controlfp(state, _MCW_RC|_MCW_PC);
228 #elif defined(HAVE_FESETROUND)
229 fesetround(state);
230 #endif
234 ALvoid aluInitPanning(ALCdevice *Device);
235 ALint aluCart2LUTpos(ALfloat re, ALfloat im);
237 ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
238 ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
240 MixerFunc SelectMixer(struct ALbuffer *Buffer, enum Resampler Resampler);
241 MixerFunc SelectHrtfMixer(struct ALbuffer *Buffer, enum Resampler Resampler);
243 ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo);
245 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
246 ALvoid aluHandleDisconnect(ALCdevice *device);
248 extern ALfloat ConeScale;
249 extern ALfloat ZScale;
251 #ifdef __cplusplus
253 #endif
255 #endif