Jamoma API  0.6.0.a19
TTMatrixStencil.cpp
1 /*
2  * Jamoma MatrixProcessingLib: Stencil
3  * Copyright © 2011, Timothy Place
4  *
5  * License: This code is licensed under the terms of the "New BSD License"
6  * http://creativecommons.org/licenses/BSD/
7  */
8 
9 #include "TTMatrixStencil.h"
10 //#include <math.h>
11 
12 
13 #define thisTTClass TTMatrixStencil
14 #define thisTTClassName "matrix.stencil"
15 #define thisTTClassTags "foundationMatrixProcessingLib, matrix"
16 
17 
19  mMode(TT("average")),
20  mEdges(TT("none")),
21  mStencilType(TT("5-point"))
22 {
23  mStepSize.resize(2);
24  mStepSize[0] = 1;
25  mStepSize[1] = 1;
26 
28  addAttribute(Edges, kTypeSymbol);
29 
30  // initially limiting to _average_ of the _5-point_ stencil with _no_ special treatment at the edges
31  // and a _step size_ of 1
32  setMatrixCalculateMethod(matrixCalculateAverage);
33  setAttributeValue(TT("edges"), kTTSym_clip);
34 }
35 
36 
37 TTMatrixStencil::~TTMatrixStencil()
38 {
39  ;
40 }
41 
42 
43 TTErr TTMatrixStencil::getStepSize(TTValue& returnedStepSize)
44 {
45  returnedStepSize.resize(mStepSize.size());
46  for (TTUInt32 k=0; k<mStepSize.size(); k++)
47  returnedStepSize[k] = mStepSize[k];
48  return kTTErrNone;
49 }
50 
51 
52 TTErr TTMatrixStencil::setStepSize(const TTValue& newStepSize)
53 {
54  TTUInt32 count = newStepSize.size();
55  TTUInt32 k;
56  TTUInt32 step = 0;
57 
58  if (count > mStepSize.size())
59  mStepSize.resize(count);
60 
61  // assign all values passed-in
62  for (k=0; k<count; k++) {
63  step = newStepSize[k];
64  mStepSize[k] = step;
65  }
66 
67  // if there are fewer values passed-in than there are slots,
68  // fill in the remaining slots with the last value passed-in.
69  // for example, this means that you can set both the x and y displacement
70  // to the same value if a single value is received
71  for (k=count; k<mStepSize.size(); k++)
72  mStepSize[k] = step;
73 
74  return kTTErrNone;
75 }
76 
77 
78 
79 
80 
81 template<typename T>
82 TTErr TTMatrixStencil::doCalculateAverage2D_zeroedEdges(TTMatrixBasePtr inMatrix, TTMatrixBasePtr outMatrix)
83 {
84  TTValue dimensions;
85  TTUInt32 m;
86  TTUInt32 n;
87 
88  inMatrix->getLockedPointer();
89  outMatrix->getLockedPointer();
90  inMatrix->getDimensions(dimensions);
91  m = dimensions[0];
92  n = dimensions[1];
93 
94  for (TTUInt8 k=0; k < inMatrix->getElementCount(); k++) {
95  for (TTUInt32 i=0; i<m; i++) {
96  for (TTUInt32 j=0; j<n; j++) {
97  TTUInt32 ii;
98  TTUInt32 jj;
99  TTFloat64 accum = 0.0;
100  T value;
101 
102  // working clockwise from 12:00...
103  // first point
104  ii = i-mStepSize[1];
105  jj = j;
106  if (ii>0 && ii<=m && jj>0 && jj<=n)
107  inMatrix->get2d(ii, jj, k, value);
108  else
109  value = 0;
110  accum += value;
111 
112  // second point
113  ii = i;
114  jj = j+mStepSize[0];
115  if (ii>0 && ii<=m && jj>0 && jj<=n)
116  inMatrix->get2d(ii, jj, k, value);
117  else
118  value = 0;
119  accum += value;
120 
121  // third point
122  ii = i+mStepSize[1];
123  jj = j;
124  if (ii>0 && ii<=m && jj>0 && jj<=n)
125  inMatrix->get2d(ii, jj, k, value);
126  else
127  value = 0;
128  accum += value;
129 
130  // fourth point
131  ii = i;
132  jj = j-mStepSize[0];
133  if (ii>0 && ii<=m && jj>0 && jj<=n)
134  inMatrix->get2d(ii, jj, k, value);
135  else
136  value = 0;
137  accum += value;
138 
139  outMatrix->set2d(i, j, k, T(accum / 4.0));
140  }
141  }
142  }
143  inMatrix->releaseLockedPointer();
144  outMatrix->releaseLockedPointer();
145  return kTTErrNone;
146 }
147 
148 
149 template<typename T>
150 TTErr TTMatrixStencil::doCalculateAverage2D_clippedEdges(TTMatrixBasePtr inMatrix, TTMatrixBasePtr outMatrix)
151 {
152  TTValue dimensions;
153  TTUInt32 m;
154  TTUInt32 n;
155 
156  inMatrix->getLockedPointer();
157  outMatrix->getLockedPointer();
158  inMatrix->getDimensions(dimensions);
159  m = dimensions[0];
160  n = dimensions[1];
161 
162  for (TTUInt8 k=0; k < inMatrix->getElementCount(); k++) {
163  for (TTUInt32 i=0; i<m; i++) {
164  for (TTUInt32 j=0; j<n; j++) {
165  TTUInt32 ii;
166  TTUInt32 jj;
167  TTFloat64 accum = 0.0;
168  T value;
169 
170  // working clockwise from 12:00...
171  // first point
172  ii = i-mStepSize[1];
173  jj = j;
174  TTLimit<TTUInt32>(ii, 1, m);
175  TTLimit<TTUInt32>(jj, 1, n);
176  inMatrix->get2d(ii, jj, k, value);
177  accum += value;
178 
179  // second point
180  ii = i;
181  jj = j+mStepSize[0];
182  TTLimit<TTUInt32>(ii, 1, m);
183  TTLimit<TTUInt32>(jj, 1, n);
184  inMatrix->get2d(ii, jj, k, value);
185  accum += value;
186 
187  // third point
188  ii = i+mStepSize[1];
189  jj = j;
190  TTLimit<TTUInt32>(ii, 1, m);
191  TTLimit<TTUInt32>(jj, 1, n);
192  inMatrix->get2d(ii, jj, k, value);
193  accum += value;
194 
195  // fourth point
196  ii = i;
197  jj = j-mStepSize[0];
198  TTLimit<TTUInt32>(ii, 1, m);
199  TTLimit<TTUInt32>(jj, 1, n);
200  inMatrix->get2d(ii, jj, k, value);
201  accum += value;
202 
203  outMatrix->set2d(i, j, k, T(accum / 4.0));
204  }
205  }
206  }
207  inMatrix->releaseLockedPointer();
208  outMatrix->releaseLockedPointer();
209  return kTTErrNone;
210 }
211 
212 
213 /*
214 // Grid Relaxation (Stencil)
215 // Each value is an average of its neighbors
216 // USEFUL FOR SMOOTHING SPECTRAL AUDIO SIGNALS TOO -- PROVIDED THAT WE ONLY DO IT ON VECTORS AND **NOT** 2-DIMENSIONALLY!
217 // - so I guess that means we need an attribute to reduce the dimensionality, I guess a "mode" attribute of some kind...
218 
219 // TODO: This will be a good benchmarking example!
220 // particularly for multithreading
221 
222 TTErr TTMatrix::relax()
223 {
224 
225 
226  // we want to have an attr saying how many steps (iterations) of the averaging to run
227 
228  for (int t=0; t<mSteps; t++) {
229 
230 
231  // in 2D it looks like this:
232 
233  for (x=0; x<X; x++) {
234  for (y=0; y<Y; y++)
235  grid[x][y] = // avg of neighbors;
236  }
237 
238  // note: in the above, you can't do the operation in-place because you would be writing to cells
239  // before you had read its value for other cells depending on its old value!
240 
241  // so we need another matrix, and then we can swap the pointers when we are done
242 
243  temp_grid = grid;
244  grid = other_grid;
245  other_grid = temp_grid;
246 
247  }
248 
249 }
250 
251 */
252 
253 
254 TTErr TTMatrixStencil::matrixCalculateAverage(TTMatrixArray& inputMatrices, TTMatrixArray& outputMatrices)
255 {
256  TTMatrixBasePtr inMatrix = inputMatrices.getMatrix(0);
257  TTMatrixBasePtr outMatrix = outputMatrices.getMatrix(0);
258  TTValue dimensions;
259  TTErr err;
260 
261  inMatrix->getDimensions(dimensions);
262  if (dimensions.size() != 2) {
263  logError("This class currently only supports 2D matrices");
264  return kTTErrInvalidType;
265  }
266 
267  if (dimensions.size() > mStepSize.size())
268  setStepSize(mStepSize[0]); // TODO: make it so that TTValue can automatically be created/assigned from a vector, then pass the whole vector
269 
270  outMatrix->adaptTo(inMatrix); // set dimensions, element count, datatype, etc.
271 
272  if (mEdges == kTTSym_clip) {
273  TTMATRIX_PROCESS_MATRICES_WITH_NAMED_TEMPLATE(doCalculateAverage2D_clippedEdges, inMatrix, outMatrix);
274  }
275  else {
276  TTMATRIX_PROCESS_MATRICES_WITH_NAMED_TEMPLATE(doCalculateAverage2D_zeroedEdges, inMatrix, outMatrix);
277  }
278  return err;
279 }
280 
281 
282 
283 
284 
285 
286 /* Vector Case:
287  where t is the step size
288 
289  -f(x+2t) + 8f(x+t) - 8f(x-t) + f(x-2t)
290  f'(x) = --------------------------------------------
291  12t
292 
293  re-writing to more C-like nomenclature:
294 
295 
296  data[x] = ( -1 * data[x+2*t] + 8 * data[x+t] - 8 * data[x-t] + data[x-2*t] ) / 12 * t;
297 
298  re-ordering:
299 
300  data[x] = ( data[x-2*t] + 8 * data[x+t] - 8 * data[x-t] - data[x+2*t] ) / 12 * t;
301 
302 
303 
304 
305  Moving up to 2-dimensions (to get the Laplacian derivative):
306 
307  data[x-t][y] + data[x+t][y] + data[x][y-t] + data[x][y+t] - 4 * data[x][y]
308  data[x][y] = -----------------------------------------------------
309  t*t
310 
311 
312 
313  Is there any sensible reason to try and scale this up beyond 2 dimensions?
314 
315  */
316 
317 
318 template<typename T>
319 TTErr TTMatrixStencil::doCalculateFirstDerivative(TTMatrixBasePtr inMatrix, TTMatrixBasePtr outMatrix)
320 {
321  T* inData = (T*)inMatrix->getLockedPointer();
322  T* outData = (T*)outMatrix->getLockedPointer();
323 
324  // temporary: just pass in the input to the output
325 
326  for (int i=0;i<1;i++)
327  *outData++ = *inData++;
328 
329  inMatrix->releaseLockedPointer();
330  outMatrix->releaseLockedPointer();
331  return kTTErrNone;
332 }
333 
334 
335 TTErr TTMatrixStencil::matrixCalculateFirstDerivative(TTMatrixArray& inputMatrices, TTMatrixArray& outputMatrices)
336 {
337  TTMatrixBasePtr inMatrix = inputMatrices.getMatrix(0);
338  TTMatrixBasePtr outMatrix = outputMatrices.getMatrix(0);
339  TTErr err;
340 
341  outMatrix->adaptTo(inMatrix);
342  TTMATRIX_PROCESS_MATRICES_WITH_NAMED_TEMPLATE(doCalculateFirstDerivative, inMatrix, outMatrix);
343  return err;
344 }
345 
TTBytePtr getLockedPointer()
Return a pointer to the matrix data, and lock the matrix so that others cannot access the data...
Definition: TTMatrixBase.h:547
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
TTErr logError(TTImmutableCString fmtstring,...)
Log errors scoped to this object instance.
size_type size() const noexcept
Return the number of elements.
Bad DataType for the context.
Definition: TTBase.h:347
TTErr get2d(TTRowID i, TTColumnID j, T &data) const
Get the value of a component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:422
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
TTElementID getElementCount()
Simple data accessor.
Definition: TTMatrixBase.h:161
TTErr getDimensions(TTValue &returnedDimensions) const
Legacy attribute accessor.
TTErr adaptTo(const TTMatrixBase &anotherMatrix)
Set dimensions, element count, datatype, etc.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
2-dimensional matrix of compound values with N elements each.
Definition: TTMatrixBase.h:41
An array of TTMatrix instance pointers.
Definition: TTMatrixArray.h:25
TTErr set2d(TTRowID i, TTColumnID j, T data)
Set the value of a component located at (i,j) in a 2-dimensional matrix.
Definition: TTMatrixBase.h:481
32-bit signed integer, range is -2,147,483,648 through 2,147,483,647.
Definition: TTBase.h:277
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
void releaseLockedPointer()
Release a locked pointer obtained using getLockedPointer().
Definition: TTMatrixBase.h:556
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
No Error.
Definition: TTBase.h:343
TT_OBJECT_CONSTRUCTOR
Constructor macro.
void resize(size_type n)
Change the number of elements.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174
#define addAttributeWithGetterAndSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter and sett...
Definition: TTAttribute.h:57