Skip to content

Commit 71200e9

Browse files
authored
Merge pull request #98 from antisvin/feature/quadrature
Quadrature oscillator and complex signals
2 parents 9524724 + 60b7683 commit 71200e9

14 files changed

Lines changed: 834 additions & 15 deletions

LibSource/ComplexFloatArray.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,16 @@ ComplexFloatArray ComplexFloatArray::create(size_t size){
312312
void ComplexFloatArray::destroy(ComplexFloatArray array){
313313
delete[] array.data;
314314
}
315+
316+
void ComplexFloatArray::copyFrom(FloatArray real, FloatArray imag) {
317+
for (size_t i = 0; i < getSize(); i++) {
318+
data[i] = ComplexFloat(real[i], imag[i]);
319+
}
320+
}
321+
322+
void ComplexFloatArray::copyTo(FloatArray real, FloatArray imag) {
323+
for (size_t i = 0; i < getSize(); i++) {
324+
real[i] = data[i].re;
325+
imag[i] = data[i].im;
326+
}
327+
}

LibSource/ComplexFloatArray.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33

44
#include "FloatArray.h"
55
#include "basicmaths.h"
6+
67
/**
78
* A structure defining a floating point complex number as two members of type float.
89
*/
910
struct ComplexFloat {
11+
constexpr ComplexFloat() : re(0), im(0) {}
12+
constexpr ComplexFloat(float x) : re(x), im(0) {}
13+
constexpr ComplexFloat(float re, float im) : re(re), im(im) {}
14+
1015
/**
1116
* The real part of the complex number.
1217
*/
@@ -75,6 +80,20 @@ struct ComplexFloat {
7580
im = magnitude*sinf(phase);
7681
}
7782

83+
/**
84+
* Returns complex conjugate - a copy of current number with imaginary part inverted
85+
*/
86+
ComplexFloat getComplexConjugate() const {
87+
return ComplexFloat {re, -im};
88+
}
89+
90+
/**
91+
* Returns dot product with another complex float value
92+
*/
93+
ComplexFloat getDotProduct(ComplexFloat other) const {
94+
return ComplexFloat {re * other.re - im * other.im, re * other.im + im * other.re};
95+
}
96+
7897
bool operator<(const ComplexFloat& other) const {
7998
return getMagnitudeSquared() < other.getMagnitudeSquared();
8099
}
@@ -99,6 +118,88 @@ struct ComplexFloat {
99118
return re != other.re || im != other.im;
100119
}
101120

121+
friend const ComplexFloat operator+(const ComplexFloat&lhs, const ComplexFloat& rhs) {
122+
ComplexFloat result = lhs;
123+
result += rhs;
124+
return result;
125+
}
126+
127+
friend const ComplexFloat operator+(const ComplexFloat&lhs, float rhs) {
128+
ComplexFloat result = lhs;
129+
result += rhs;
130+
return result;
131+
}
132+
133+
ComplexFloat& operator+=(float other) {
134+
re += other;
135+
return *this;
136+
}
137+
138+
ComplexFloat& operator+=(const ComplexFloat& other) {
139+
re += other.re;
140+
im += other.im;
141+
return *this;
142+
}
143+
144+
friend const ComplexFloat operator-(const ComplexFloat&lhs, const ComplexFloat& rhs) {
145+
ComplexFloat result = lhs;
146+
result -= rhs;
147+
return result;
148+
}
149+
150+
friend const ComplexFloat operator-(const ComplexFloat&lhs, float rhs) {
151+
ComplexFloat result = lhs;
152+
result -= rhs;
153+
return result;
154+
}
155+
156+
ComplexFloat& operator-=(float other) {
157+
re -= other;
158+
return *this;
159+
}
160+
161+
ComplexFloat& operator-=(const ComplexFloat& other) {
162+
re -= other.re;
163+
im -= other.im;
164+
return *this;
165+
}
166+
167+
friend const ComplexFloat operator*(const ComplexFloat&lhs, const ComplexFloat& rhs) {
168+
ComplexFloat result = lhs;
169+
result *= rhs;
170+
return result;
171+
}
172+
173+
friend const ComplexFloat operator*(const ComplexFloat&lhs, float rhs) {
174+
ComplexFloat result = lhs;
175+
result *= rhs;
176+
return result;
177+
}
178+
179+
ComplexFloat& operator*=(float other) {
180+
re *= other;
181+
im *= other;
182+
return *this;
183+
}
184+
185+
ComplexFloat& operator*=(const ComplexFloat& other) {
186+
re = re * other.re - im * other.im;
187+
im = re * other.im + im * other.re;
188+
return *this;
189+
}
190+
191+
friend const ComplexFloat operator/(const ComplexFloat&lhs, float rhs) {
192+
ComplexFloat result = lhs;
193+
result /= rhs;
194+
return result;
195+
}
196+
197+
ComplexFloat& operator/=(float other) {
198+
re /= other;
199+
im /= other;
200+
return *this;
201+
}
202+
102203
};
103204

104205
class ComplexFloatArray : public SimpleArray<ComplexFloat> {
@@ -396,6 +497,24 @@ class ComplexFloatArray : public SimpleArray<ComplexFloat> {
396497
* @param[out] destination The destination array.
397498
*/
398499
void setMagnitude(FloatArray magnitude, int offset, size_t count, ComplexFloatArray destination);
500+
501+
using SimpleArray<ComplexFloat>::copyFrom;
502+
using SimpleArray<ComplexFloat>::copyTo;
503+
/**
504+
* Merge two channels of audio containing real and imaginary axis data into this array
505+
*
506+
* @param[in] real Real axis data
507+
* @param[in] imag Imaginary axis data
508+
*/
509+
void copyFrom(FloatArray real, FloatArray imag);
510+
511+
/**
512+
* Split complex data into two channels of audio containing real and imaginary axis data
513+
*
514+
* @param[in] real Real axis data
515+
* @param[in] imag Imaginary axis data
516+
*/
517+
void copyTo(FloatArray real, FloatArray imag);
399518
};
400519

401520
#endif // __ComplexFloatArray_h__

LibSource/ComplexOscillator.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#ifndef __COMPLEX_OSCILLATOR_H__
2+
#define __COMPLEX_OSCILLATOR_H__
3+
4+
#include "SignalGenerator.h"
5+
#include "Oscillator.h"
6+
7+
/**
8+
* A complex oscillator is a MultiSignalGenerator with 2 channels that
9+
* operates at a given frequency and that can be frequency modulated.
10+
*
11+
* A single sample is represented as a ComplexFloat value, while blocks
12+
* of audio are stored in an AudioBuffer with 2 channels.
13+
*/
14+
class ComplexOscillator : public ComplexSignalGenerator {
15+
public:
16+
ComplexOscillator() = default;
17+
virtual ~ComplexOscillator() = default;
18+
using ComplexSignalGenerator::generate;
19+
/**
20+
* Set oscillator sample rate
21+
*/
22+
virtual void setSampleRate(float value){}
23+
/**
24+
* Set oscillator frequency in Hertz
25+
*/
26+
virtual void setFrequency(float value) = 0;
27+
/**
28+
* Get oscillator frequency in Hertz
29+
*/
30+
virtual float getFrequency() = 0;
31+
/**
32+
* Set current oscillator phase in radians
33+
* @param phase a value between 0 and 2*pi
34+
*/
35+
virtual void setPhase(float phase) = 0;
36+
/**
37+
* Get current oscillator phase in radians
38+
* @return a value between 0 and 2*pi
39+
*/
40+
virtual float getPhase() = 0;
41+
/**
42+
* Reset oscillator (typically resets phase)
43+
*/
44+
virtual void reset() = 0;
45+
/**
46+
* Produce a sample with frequency modulation.
47+
*/
48+
virtual ComplexFloat generate(float fm) = 0;
49+
/**
50+
* Produce a block of samples with frequency modulation.
51+
*/
52+
virtual void generate(ComplexFloatArray output, FloatArray fm){
53+
for(size_t i=0; i<output.getSize(); ++i)
54+
output[i] = generate(fm[i]);
55+
}
56+
57+
};
58+
59+
template<typename OscillatorClass>
60+
using ComplexOscillatorTemplate = OscillatorTemplate<OscillatorClass, ComplexOscillator, ComplexFloat>;
61+
#endif

0 commit comments

Comments
 (0)