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 for (int i
=0; i
<= kSineSize
; ++i
) {
58 double phase
= i
* sineIndexToPhase
;
59 float32 d
= sin(phase
);
63 double rPolarLUTSize2
= 1. / kPolarLUTSize2
;
64 for (int i
=0; i
< kPolarLUTSize
; ++i
) {
65 double slope
= (i
- kPolarLUTSize2
) * rPolarLUTSize2
;
66 double angle
= atan(slope
);
67 gPhaseLUT
[i
] = (float)angle
;
68 gMagLUT
[i
] = (float)(1.f
/ cos(angle
));
74 bool dummy
= initTables();
84 Complex(float r
, float i
) : real(r
), imag(i
) {}
85 void Set(float r
, float i
) { real
= r
; imag
= i
; }
87 Complex
& operator=(Complex b
) { real
= b
.real
; imag
= b
.imag
; return *this; }
88 Complex
& operator=(float b
) { real
= b
; imag
= 0.; return *this; }
93 * Converts cartesian to polar representation, using lookup tables.
94 * Note: in this implementation the phase values returned lie in the range [-pi/4, 7pi/4]
95 * rather than the more conventional [0, 2pi] or [-pi, pi].
99 void ToPolarInPlace();
101 void ToPolarApxInPlace();
109 Polar(float m
, float p
) : mag(m
), phase(p
) {}
110 void Set(float m
, float p
) { mag
= m
; phase
= p
; }
114 return Complex(mag
* std::cos(phase
), mag
* std::sin(phase
));
117 Complex
ToComplexApx()
119 uint32 sinindex
= (int32
)(kSinePhaseScale
* phase
) & kSineMask
;
120 uint32 cosindex
= (sinindex
+ (kSineSize
>>2)) & kSineMask
;
121 return Complex(mag
* gSine
[cosindex
], mag
* gSine
[sinindex
]);
124 void ToComplexInPlace()
126 Complex complx
= ToComplex();
131 void ToComplexApxInPlace()
133 Complex complx
= ToComplexApx();
141 inline Polar
Complex::ToPolar()
143 return Polar(hypotf(imag
, real
), std::atan2(imag
, real
));
146 inline Polar
Complex::ToPolarApx()
149 float absreal
= fabs(real
);
150 float absimag
= fabs(imag
);
151 float mag
, phase
, slope
;
152 if (absreal
> absimag
) {
154 index
= (int32
)(kPolarLUTSize2
+ kPolarLUTSize2
* slope
);
155 mag
= gMagLUT
[index
] * absreal
;
156 phase
= gPhaseLUT
[index
];
158 return Polar(mag
, phase
);
160 return Polar(mag
, (float)(pi
+ phase
));
162 } else if (absimag
> 0) {
164 index
= (int32
)(kPolarLUTSize2
+ kPolarLUTSize2
* slope
);
165 mag
= gMagLUT
[index
] * absimag
;
166 phase
= gPhaseLUT
[index
];
168 return Polar(mag
, (float)(pi2
- phase
));
170 return Polar(mag
, (float)(pi32
- phase
));
172 } else return Polar(0, 0);
175 inline void Complex::ToPolarInPlace()
177 Polar polar
= ToPolar();
182 inline void Complex::ToPolarApxInPlace()
184 Polar polar
= ToPolarApx();
192 using detail::Complex
;
206 void ToComplex(Polar in
, Complex
& out
);
208 inline Complex
operator+(Complex a
, Complex b
) { return Complex(a
.real
+ b
.real
, a
.imag
+ b
.imag
); }
209 inline Complex
operator+(Complex a
, float b
) { return Complex(a
.real
+ b
, a
.imag
); }
210 inline Complex
operator+(float a
, Complex b
) { return Complex(a
+ b
.real
, b
.imag
); }
212 inline Complex
& operator+=(Complex
& a
, const Complex
& b
) { a
.real
+= b
.real
, a
.imag
+= b
.imag
; return a
; }
213 inline Complex
& operator+=(Complex
& a
, float b
) { a
.real
+= b
; return a
; }
215 inline Complex
operator-(Complex a
, Complex b
) { return Complex(a
.real
- b
.real
, a
.imag
- b
.imag
); }
216 inline Complex
operator-(Complex a
, float b
) { return Complex(a
.real
- b
, a
.imag
); }
217 inline Complex
operator-(float a
, Complex b
) { return Complex(a
- b
.real
, b
.imag
); }
219 inline Complex
operator-=(Complex a
, Complex b
) { a
.real
-= b
.real
, a
.imag
-= b
.imag
; return a
; }
220 inline Complex
operator-=(Complex a
, float b
) { a
.real
-= b
; return a
; }
222 inline Complex
operator*(Complex a
, Complex b
)
224 return Complex(a
.real
* b
.real
- a
.imag
* b
.imag
, a
.real
* b
.imag
+ a
.imag
* b
.real
);
227 inline Complex
operator*(Complex a
, float b
)
229 return Complex(a
.real
* b
, a
.imag
* b
);
232 inline Complex
operator*(float a
, Complex b
)
234 return Complex(b
.real
* a
, b
.imag
* a
);
237 inline Complex
operator*=(Complex a
, Complex b
)
240 a
.real
* b
.real
- a
.imag
* b
.imag
,
241 a
.real
* b
.imag
+ a
.imag
* b
.real
246 inline Complex
operator*=(Complex a
, float b
)
254 inline Polar
operator*(Polar a
, float b
)
256 return Polar(a
.mag
* b
, a
.phase
);
259 inline Polar
operator*(float a
, Polar b
)
261 return Polar(a
* b
.mag
, b
.phase
);
264 inline Polar
operator*=(Polar a
, float b
)