2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "SC_Constants.h"
32 // hypotf is c99, but not c++
33 #define hypotf _hypotf
36 ////////////////////////////////////////////////////////////////////////////////
40 const int kSineSize
= 8192;
41 const int kSineMask
= kSineSize
- 1;
42 const double kSinePhaseScale
= kSineSize
/ twopi
;
43 const int32 kPolarLUTSize
= 2049;
44 const int32 kPolarLUTSize2
= kPolarLUTSize
>> 1;
47 /* each object file that is including this header will have separate lookup tables */
50 float gMagLUT
[kPolarLUTSize
];
51 float gPhaseLUT
[kPolarLUTSize
];
52 float gSine
[kSineSize
+1];
54 static bool initTables(void)
56 double sineIndexToPhase
= twopi
/ kSineSize
;
57 double pmf
= (1L << 29) / twopi
;
58 for (int i
=0; i
<= kSineSize
; ++i
) {
59 double phase
= i
* sineIndexToPhase
;
60 float32 d
= sin(phase
);
64 double rPolarLUTSize2
= 1. / kPolarLUTSize2
;
65 for (int i
=0; i
< kPolarLUTSize
; ++i
) {
66 double slope
= (i
- kPolarLUTSize2
) * rPolarLUTSize2
;
67 double angle
= atan(slope
);
68 gPhaseLUT
[i
] = (float)angle
;
69 gMagLUT
[i
] = (float)(1.f
/ cos(angle
));
75 bool dummy
= initTables();
85 Complex(float r
, float i
) : real(r
), imag(i
) {}
86 void Set(float r
, float i
) { real
= r
; imag
= i
; }
88 Complex
& operator=(Complex b
) { real
= b
.real
; imag
= b
.imag
; return *this; }
89 Complex
& operator=(float b
) { real
= b
; imag
= 0.; return *this; }
94 * Converts cartesian to polar representation, using lookup tables.
95 * Note: in this implementation the phase values returned lie in the range [-pi/4, 7pi/4]
96 * rather than the more conventional [0, 2pi] or [-pi, pi].
100 void ToPolarInPlace();
102 void ToPolarApxInPlace();
110 Polar(float m
, float p
) : mag(m
), phase(p
) {}
111 void Set(float m
, float p
) { mag
= m
; phase
= p
; }
115 return Complex(mag
* std::cos(phase
), mag
* std::sin(phase
));
118 Complex
ToComplexApx()
120 uint32 sinindex
= (int32
)(kSinePhaseScale
* phase
) & kSineMask
;
121 uint32 cosindex
= (sinindex
+ (kSineSize
>>2)) & kSineMask
;
122 return Complex(mag
* gSine
[cosindex
], mag
* gSine
[sinindex
]);
125 void ToComplexInPlace()
127 Complex complx
= ToComplex();
132 void ToComplexApxInPlace()
134 Complex complx
= ToComplexApx();
142 inline Polar
Complex::ToPolar()
144 return Polar(hypotf(imag
, real
), std::atan2(imag
, real
));
147 inline Polar
Complex::ToPolarApx()
150 float absreal
= fabs(real
);
151 float absimag
= fabs(imag
);
152 float mag
, phase
, slope
;
153 if (absreal
> absimag
) {
155 index
= (int32
)(kPolarLUTSize2
+ kPolarLUTSize2
* slope
);
156 mag
= gMagLUT
[index
] * absreal
;
157 phase
= gPhaseLUT
[index
];
159 return Polar(mag
, phase
);
161 return Polar(mag
, (float)(pi
+ phase
));
163 } else if (absimag
> 0) {
165 index
= (int32
)(kPolarLUTSize2
+ kPolarLUTSize2
* slope
);
166 mag
= gMagLUT
[index
] * absimag
;
167 phase
= gPhaseLUT
[index
];
169 return Polar(mag
, (float)(pi2
- phase
));
171 return Polar(mag
, (float)(pi32
- phase
));
173 } else return Polar(0, 0);
176 inline void Complex::ToPolarInPlace()
178 Polar polar
= ToPolar();
183 inline void Complex::ToPolarApxInPlace()
185 Polar polar
= ToPolarApx();
193 using detail::Complex
;
207 void ToComplex(Polar in
, Complex
& out
);
209 inline Complex
operator+(Complex a
, Complex b
) { return Complex(a
.real
+ b
.real
, a
.imag
+ b
.imag
); }
210 inline Complex
operator+(Complex a
, float b
) { return Complex(a
.real
+ b
, a
.imag
); }
211 inline Complex
operator+(float a
, Complex b
) { return Complex(a
+ b
.real
, b
.imag
); }
213 inline Complex
& operator+=(Complex
& a
, const Complex
& b
) { a
.real
+= b
.real
, a
.imag
+= b
.imag
; return a
; }
214 inline Complex
& operator+=(Complex
& a
, float b
) { a
.real
+= b
; return a
; }
216 inline Complex
operator-(Complex a
, Complex b
) { return Complex(a
.real
- b
.real
, a
.imag
- b
.imag
); }
217 inline Complex
operator-(Complex a
, float b
) { return Complex(a
.real
- b
, a
.imag
); }
218 inline Complex
operator-(float a
, Complex b
) { return Complex(a
- b
.real
, b
.imag
); }
220 inline Complex
operator-=(Complex a
, Complex b
) { a
.real
-= b
.real
, a
.imag
-= b
.imag
; return a
; }
221 inline Complex
operator-=(Complex a
, float b
) { a
.real
-= b
; return a
; }
223 inline Complex
operator*(Complex a
, Complex b
)
225 return Complex(a
.real
* b
.real
- a
.imag
* b
.imag
, a
.real
* b
.imag
+ a
.imag
* b
.real
);
228 inline Complex
operator*(Complex a
, float b
)
230 return Complex(a
.real
* b
, a
.imag
* b
);
233 inline Complex
operator*(float a
, Complex b
)
235 return Complex(b
.real
* a
, b
.imag
* a
);
238 inline Complex
operator*=(Complex a
, Complex b
)
241 a
.real
* b
.real
- a
.imag
* b
.imag
,
242 a
.real
* b
.imag
+ a
.imag
* b
.real
247 inline Complex
operator*=(Complex a
, float b
)
255 inline Polar
operator*(Polar a
, float b
)
257 return Polar(a
.mag
* b
, a
.phase
);
260 inline Polar
operator*(float a
, Polar b
)
262 return Polar(a
* b
.mag
, b
.phase
);
265 inline Polar
operator*=(Polar a
, float b
)