OpenWareLaboratory
ComplexTransform.h
Go to the documentation of this file.
1 #ifndef __COMPLEX_TRANSFORM_H__
2 #define __COMPLEX_TRANSFORM_H__
3 
4 #include "basicmaths.h"
5 #include "SignalProcessor.h"
6 #include "FloatMatrix.h"
7 
8 template <size_t matrix_order>
10 public:
11  AbstractMatrix() = default;
13  this->matrix = matrix;
14  resetMatrix();
15  }
17  return matrix;
18  }
19  void resetMatrix() {
20  matrix.clear();
21  for (size_t i = 0; i < matrix_order; i++) {
22  matrix[i][i] = 1;
23  }
24  }
25 
26 protected:
28 };
29 
33 template <size_t matrix_order, typename Operation>
34 class TransformationMatrix : public AbstractMatrix<matrix_order>,
35  public ComplexSignalProcessor {
36 public:
40 
42  if constexpr (matrix_order == 2) {
43  return ComplexFloat(input.re * matrix[0][0] + input.im * matrix[0][1],
44  input.re * matrix[1][0] + input.im * matrix[1][1]);
45  }
46  else if constexpr (matrix_order == 3) {
47  return ComplexFloat(
48  input.re * matrix[0][0] + input.im * matrix[0][1] + matrix[0][2],
49  input.re * matrix[1][0] + input.im * matrix[1][1] + matrix[1][2]);
50  }
51  else if constexpr (matrix_order > 3) {
52  ComplexFloat result { input.re * matrix[0][0] + input.im * matrix[0][1],
53  input.re * matrix[1][0] + input.im * matrix[1][1] };
54  for (size_t i = 2; i < matrix_order; i++) {
55  input.re += matrix[0][i];
56  input.im += matrix[0][i];
57  }
58  }
59  else {
60  return ComplexFloat {};
61  }
62  }
63  static Operation* create() {
64  FloatMatrix matrix = FloatMatrix::create(matrix_order, matrix_order);
65  return new Operation(matrix);
66  }
67  static void destroy(Operation* transform) {
68  FloatMatrix::destroy(transform->matrix);
69  delete transform;
70  }
71 };
72 
73 template <size_t matrix_order>
75  : public TransformationMatrix<matrix_order, Rotation2D<matrix_order>> {
76 public:
78  void rotate(float angle) {
80  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
81  matrix[0][0] = cos(angle);
82  matrix[1][0] = sin(angle);
83  }
84  void rotate(ComplexFloat angle) {
86  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
87  matrix[0][0] = angle.re;
88  matrix[1][0] = angle.im;
89  }
90 };
91 
94 
95 template <size_t matrix_order>
97  : public TransformationMatrix<matrix_order, Reflection2D<matrix_order>> {
98 public:
100  void reflect(float angle) {
102  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
103  matrix[0][0] = cos(angle * 2);
104  matrix[0][1] = sin(angle * 2);
105  }
106 };
107 
110 
111 template <size_t matrix_order>
112 class Scale2D : public TransformationMatrix<matrix_order, Scale2D<matrix_order>> {
113 public:
115  void scale(ComplexFloat vector) {
117  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
118  matrix[0][0] = vector.re;
119  matrix[1][1] = vector.im;
120  }
121  void scale(float factor) {
123  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
124  matrix[0][0] = factor;
125  matrix[1][1] = factor;
126  }
127 };
128 
131 
132 template <size_t matrix_order>
134  : public TransformationMatrix<matrix_order, Stretch2D<matrix_order>> {
135 public:
137  void stretch(ComplexFloat vector) {
138  stretch(vector.re, vector.im);
139  }
140  void stretch(float re, float im) {
142  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
143  matrix[0][0] = re;
144  matrix[1][1] = im;
145  }
146 };
147 
150 
151 template <size_t matrix_order>
153  : public TransformationMatrix<matrix_order, Squeeze2D<matrix_order>> {
154 public:
156  void squeeze(float scale) {
158  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
159  matrix[0][0] = scale;
160  matrix[1][1] = 1.f / scale;
161  }
162 };
163 
166 
167 template <size_t matrix_order>
168 class Shear2D : public TransformationMatrix<matrix_order, Shear2D<matrix_order>> {
169 public:
171  void shearX(float scale) {
173  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
174  matrix[0][1] = scale;
175  }
176  void shearY(float scale) {
178  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
179  matrix[1][0] = scale;
180  }
181 };
182 
185 
186 template <size_t matrix_order>
188  : public TransformationMatrix<matrix_order, Translation2D<matrix_order>> {
189 public:
191  // template <std::size_t size = MatrixSource::matrix_order>
192  typename std::enable_if<matrix_order == 3>::type translate(ComplexFloat vector) {
193  translate(vector.re, vector.im);
194  }
195  typename std::enable_if<matrix_order == 3>::type translate(float re, float im) {
197  static_cast<AbstractMatrix<matrix_order>*>(this)->getMatrix();
198  matrix[0][2] = re;
199  matrix[1][2] = im;
200  }
201 };
206 
211 template <size_t matrix_order>
213  : public TransformationMatrix<matrix_order, CompositeTransform<matrix_order>> {
214 private:
216 
217 public:
219 
220  CompositeTransform() = default;
222  : TransformationMatrix<matrix_order, CompositeTransform<matrix_order>>(matrix)
225  }
226 
228  computeMatrix();
230  }
231 
233  computeMatrix();
235  }
236  void computeMatrix() {
237  FloatMatrix m = this->matrix;
238  m.copyFrom(transforms[0]->getMatrix());
239  for (size_t i = 1; i < num_transforms; i++) {
240  m.multiply(transforms[i]->getMatrix());
241  }
242  }
243 
244  template <typename... Transforms>
245  static CompositeTransform* create(Transforms*... transform_ptrs) {
246  FloatMatrix matrix = FloatMatrix::create(matrix_order, matrix_order);
247  MatrixType** transforms = new MatrixType*[sizeof...(Transforms)];
248  setTransform(transforms, 0, transform_ptrs...);
249  return new CompositeTransform(matrix, sizeof...(Transforms), transforms);
250  }
251  static void destroy(CompositeTransform* transform) {
252  FloatMatrix::destroy(transform->matrix);
253  delete[] transform->transforms;
254  delete transform;
255  }
256 
257 protected:
260 
261  template <typename... Transforms>
262  static void setTransform(MatrixType** transforms, size_t position,
263  MatrixType* transform, Transforms*... transform_ptrs) {
264  transforms[position] = transform;
265  setTransform(transforms, position + 1, transform_ptrs...);
266  }
267  static void setTransform(MatrixType** transforms, size_t position) {
268  }
269 };
270 
276 template <size_t matrix_order>
278  : public TransformationMatrix<matrix_order, InterpolatedCompositeTransform<matrix_order>> {
279 private:
281  using MatrixType::matrix;
282 
283 public:
285 
288  : TransformationMatrix<matrix_order, InterpolatedCompositeTransform<matrix_order>>(
289  matrix)
294  }
296  computeMatrix();
297  float mult = 1.f / input.getSize();
298  for (size_t i = 0; i < matrix_order; i++) {
299  for (size_t j = 0; j < matrix_order; j++) {
300  delta_matrix[i][j] = (matrix[i][j] - prev_matrix[i][j]) * mult;
301  }
302  }
303  matrix.copyFrom(prev_matrix);
304  for (size_t i = 0; i < input.getSize(); i++) {
305  matrix.add(delta_matrix);
306  output[i] = this->process(input[i]);
307  }
308  prev_matrix.copyFrom(matrix);
309  }
310  void computeMatrix() {
311  FloatMatrix m = this->matrix;
313  for (int i = num_transforms - 2; i >= 0; i--) {
314  m.multiply(transforms[i]->getMatrix());
315  }
316  }
317  template <typename... Transforms>
318  static InterpolatedCompositeTransform* create(Transforms*... transform_ptrs) {
319  FloatMatrix matrix = FloatMatrix::create(matrix_order, matrix_order);
320  FloatMatrix prev_matrix = FloatMatrix::create(matrix_order, matrix_order);
321  FloatMatrix delta_matrix = FloatMatrix::create(matrix_order, matrix_order);
322  MatrixType** transforms = new MatrixType*[sizeof...(Transforms)];
323  setTransform(transforms, 0, transform_ptrs...);
324  return new InterpolatedCompositeTransform(matrix, prev_matrix,
325  delta_matrix, sizeof...(Transforms), transforms);
326  }
327  static void destroy(InterpolatedCompositeTransform* transform) {
328  FloatMatrix::destroy(transform->matrix);
329  FloatMatrix::destroy(transform->prev_matrix);
331  delete[] transform->transforms;
332  delete transform;
333  }
334 
335 protected:
339 
340  template <typename... Transforms>
341  static void setTransform(MatrixType** transforms, size_t position,
342  MatrixType* transform, Transforms*... transform_ptrs) {
343  transforms[position] = transform;
344  setTransform(transforms, position + 1, transform_ptrs...);
345  }
346 
347  static void setTransform(MatrixType** transforms, size_t position) {
348  }
349 };
350 #endif
AbstractMatrix(FloatMatrix matrix)
FloatMatrix matrix
FloatMatrix getMatrix()
AbstractMatrix()=default
virtual ComplexFloat process(ComplexFloat input)=0
Composite transform can apply a sequence of transformation matrices.
void process(ComplexFloatArray input, ComplexFloatArray output)
ComplexFloat process(ComplexFloat input)
static void destroy(CompositeTransform *transform)
CompositeTransform(FloatMatrix matrix, size_t num_transforms, MatrixType **transforms)
static void setTransform(MatrixType **transforms, size_t position)
static void setTransform(MatrixType **transforms, size_t position, MatrixType *transform, Transforms *... transform_ptrs)
MatrixType ** transforms
static CompositeTransform * create(Transforms *... transform_ptrs)
CompositeTransform()=default
This class contains useful methods for manipulating NxN dimensioned matrices of floats.
Definition: FloatMatrix.h:10
static FloatMatrix create(size_t rows, size_t columns)
Creates a new FloatMatrix.
void clear()
Clear the array.
Definition: FloatMatrix.h:49
static void destroy(FloatMatrix array)
Destroys a FloatMatrix created with the create() method.
void multiply(FloatMatrix operand2, FloatMatrix destination)
Element-wise multiplication between arrays.
Definition: FloatMatrix.cpp:54
void add(FloatMatrix operand2, FloatMatrix destination)
Element-wise sum between matrices.
Definition: FloatMatrix.cpp:27
void copyFrom(FloatMatrix source)
Copies the content of another matrix into this matrix.
This class calculates transformation matrix once per audio block just like the CompositeTemplate.
static InterpolatedCompositeTransform * create(Transforms *... transform_ptrs)
static void destroy(InterpolatedCompositeTransform *transform)
static void setTransform(MatrixType **transforms, size_t position, MatrixType *transform, Transforms *... transform_ptrs)
static void setTransform(MatrixType **transforms, size_t position)
void process(ComplexFloatArray input, ComplexFloatArray output)
InterpolatedCompositeTransform(FloatMatrix matrix, FloatMatrix prev_matrix, FloatMatrix delta_matrix, size_t num_transforms, MatrixType **transforms)
void reflect(float angle)
void rotate(ComplexFloat angle)
void rotate(float angle)
void scale(ComplexFloat vector)
void scale(float factor)
void shearY(float scale)
void shearX(float scale)
size_t getSize() const
Definition: SimpleArray.h:31
void squeeze(float scale)
void stretch(ComplexFloat vector)
void stretch(float re, float im)
This template creates classes that can manage a single transformation matrix.
static Operation * create()
static void destroy(Operation *transform)
ComplexFloat process(ComplexFloat input)
std::enable_if< matrix_order==3 >::type translate(float re, float im)
std::enable_if< matrix_order==3 >::type translate(ComplexFloat vector)
A structure defining a floating point complex number as two members of type float.
float im
The imaginary part of the complex number.
float re
The real part of the complex number.