OpenWareLaboratory
FloatArray.cpp
Go to the documentation of this file.
1 #include "FloatArray.h"
2 #include "basicmaths.h"
3 #include "message.h"
4 #include <string.h>
5 
6 void FloatArray::getMin(float* value, int* index){
8 #ifdef ARM_CORTEX
9  uint32_t idx;
10  arm_min_f32(data, size, value, &idx);
11  *index = (int)idx;
12 #else
13  *value=data[0];
14  *index=0;
15  for(size_t n=1; n<size; n++){
16  float currentValue=data[n];
17  if(currentValue<*value){
18  *value=currentValue;
19  *index=n;
20  }
21  }
22 #endif
23 }
24 
26  float value;
27  int index;
29  getMin(&value, &index);
30  return value;
31 }
32 
34  float value;
35  int index;
37  getMin(&value, &index);
38  return index;
39 }
40 
41 void FloatArray::getMax(float* value, int* index){
42  ASSERT(size>0, "Wrong size");
44 #ifdef ARM_CORTEX
45  uint32_t idx;
46  arm_max_f32(data, size, value, &idx);
47  *index = (int)idx;
48 #else
49  *value=data[0];
50  *index=0;
51  for(size_t n=1; n<size; n++){
52  float currentValue=data[n];
53  if(currentValue>*value){
54  *value=currentValue;
55  *index=n;
56  }
57  }
58 #endif
59 }
60 
62  float value;
63  int index;
65  getMax(&value, &index);
66  return value;
67 }
68 
70  float value;
71  int index;
73  getMax(&value, &index);
74  return index;
75 }
76 
77 void FloatArray::rectify(FloatArray& destination){ //this is actually "copy data with rectifify"
79 #ifdef ARM_CORTEX
80  arm_abs_f32(data, destination.getData(), size);
81 #else
82  size_t minSize= min(size,destination.getSize()); //TODO: shall we take this out and allow it to segfault?
83  for(size_t n=0; n<minSize; n++){
84  destination[n] = fabsf(data[n]);
85  }
86 #endif
87 }
88 
89 void FloatArray::reverse(FloatArray& destination){ //this is actually "copy data with reverse"
90  if(destination==*this){ //make sure it is not called "in-place"
91  reverse();
92  return;
93  }
94  for(size_t n=0; n<size; n++){
95  destination[n]=data[size-n-1];
96  }
97 }
98 
99 void FloatArray::reverse(){//in place
100  for(size_t n=0; n<size/2; n++){
101  float temp=data[n];
102  data[n]=data[size-n-1];
103  data[size-n-1]=temp;
104  }
105 }
106 
108  float* data = getData();
109  for(size_t n=0; n<getSize(); n++)
110  destination[n] = 1.0f/data[n];
111 }
112 
114  float result;
116 #ifdef ARM_CORTEX
117  arm_rms_f32 (data, size, &result);
118 #else
119  result=0;
120  float *pSrc= data;
121  for(size_t n=0; n<size; n++){
122  result += pSrc[n]*pSrc[n];
123  }
124  result=sqrtf(result/size);
125 #endif
126  return result;
127 }
128 
130  float result = 0;
131  for(size_t n=0; n<size; n++)
132  result += data[n];
133  return result;
134 }
135 
137  float result;
139 #ifdef ARM_CORTEX
140  arm_mean_f32 (data, size, &result);
141 #else
142  result=0;
143  for(size_t n=0; n<size; n++){
144  result+=data[n];
145  }
146  result=result/size;
147 #endif
148  return result;
149 }
150 
152  float result;
154 #ifdef ARM_CORTEX
155  arm_power_f32 (data, size, &result);
156 #else
157  result=0;
158  float *pSrc = data;
159  for(size_t n=0; n<size; n++){
160  result += pSrc[n]*pSrc[n];
161  }
162 #endif
163  return result;
164 }
165 
167  float result;
169 #ifdef ARM_CORTEX
170  arm_std_f32 (data, size, &result);
171 #else
172  result=sqrtf(getVariance());
173 #endif
174  return result;
175 }
176 
178  float result;
180 #ifdef ARM_CORTEX
181  arm_var_f32(data, size, &result);
182 #else
183  float sumOfSquares=getPower();
184  float sum=0;
185  for(size_t n=0; n<size; n++){
186  sum+=data[n];
187  }
188  result=(sumOfSquares - sum*sum/size) / (size - 1);
189 #endif
190  return result;
191 }
192 
194  clip(1);
195 }
196 
197 void FloatArray::clip(float max){
198  for(size_t n=0; n<size; n++){
199  if(data[n]>max)
200  data[n]=max;
201  else if(data[n]<-max)
202  data[n]=-max;
203  }
204 }
205 
206 void FloatArray::clip(float min, float max){
207  for(size_t n=0; n<size; n++){
208  if(data[n]>max)
209  data[n]=max;
210  else if(data[n]<min)
211  data[n]=min;
212  }
213 }
214 
215 FloatArray FloatArray::subArray(int offset, size_t length){
216  ASSERT(size >= offset+length, "Array too small");
217  return FloatArray(data+offset, length);
218 }
219 
220 void FloatArray::setAll(float value){
222 #ifdef ARM_CORTEX
223  arm_fill_f32(value, data, size);
224 #else
225  for(size_t n=0; n<size; n++){
226  data[n]=value;
227  }
228 #endif /* ARM_CORTEX */
229 }
230 
231 void FloatArray::add(FloatArray operand2, FloatArray destination){ //allows in-place
232  ASSERT(operand2.size >= size && destination.size<=size, "Arrays must be matching size");
234 #ifdef ARM_CORTEX
235  /* despite not explicitely documented in the CMSIS documentation,
236  this has been tested to behave properly even when pSrcA==pDst
237  void arm_add_f32 (float32_t *pSrcA, float32_t *pSrcB, float32_t *pDst, uint32_t blockSize)
238  */
239  arm_add_f32(data, operand2.data, destination.data, size);
240 #else
241  for(size_t n=0; n<size; n++){
242  destination[n]=data[n]+operand2[n];
243  }
244 #endif /* ARM_CORTEX */
245 }
246 
247 void FloatArray::add(FloatArray operand2){ //in-place
249  add(operand2, *this);
250 }
251 
252 void FloatArray::add(float scalar){
253  for(size_t n=0; n<size; n++){
254  data[n] += scalar;
255  }
256 }
257 
258 void FloatArray::add(float scalar, FloatArray destination){
259  for(size_t n=0; n<size; n++)
260  destination[n] = data[n]+scalar;
261 }
262 
263 void FloatArray::subtract(FloatArray operand2, FloatArray destination){ //allows in-place
264  ASSERT(operand2.size == size && destination.size >= size, "Arrays size mismatch");
266 #ifdef ARM_CORTEX
267  /* despite not explicitely documented in the CMSIS documentation,
268  this has been tested to behave properly even when pSrcA==pDst
269  void arm_sub_f32 (float32_t *pSrcA, float32_t *pSrcB, float32_t *pDst, uint32_t blockSize)
270  */
271  arm_sub_f32(data, operand2.data, destination.data, size);
272  #else
273  for(size_t n=0; n<size; n++){
274  destination[n]=data[n]-operand2[n];
275  }
276  #endif /* ARM_CORTEX */
277 }
278 
279 void FloatArray::subtract(FloatArray operand2){ //in-place
281  subtract(operand2, *this);
282 }
283 
284 void FloatArray::subtract(float scalar){
285  for(size_t n=0; n<size; n++){
286  data[n]-=scalar;
287  }
288 }
289 
290 void FloatArray::multiply(FloatArray operand2, FloatArray destination){ //allows in-place
291  ASSERT(operand2.size == size && destination.size==size, "Arrays must be same size");
293 #ifdef ARM_CORTEX
294  /* despite not explicitely documented in the CMSIS documentation,
295  this has been tested to behave properly even when pSrcA==pDst
296  void arm_mult_f32 (float32_t *pSrcA, float32_t *pSrcB, float32_t *pDst, uint32_t blockSize)
297  */
298  arm_mult_f32(data, operand2.data, destination, size);
299  #else
300  for(size_t n=0; n<size; n++){
301  destination[n]=data[n]*operand2[n];
302  }
303 
304  #endif /* ARM_CORTEX */
305 }
306 
307 void FloatArray::multiply(FloatArray operand2){ //in-place
309  multiply(operand2, *this);
310 }
311 
312 void FloatArray::multiply(float scalar){
313 #ifdef ARM_CORTEX
314  arm_scale_f32(data, scalar, data, size);
315 #else
316  for(size_t n=0; n<size; n++)
317  data[n]*=scalar;
318 #endif
319 }
320 
321 void FloatArray::multiply(float scalar, FloatArray destination){
322 #ifdef ARM_CORTEX
323  arm_scale_f32(data, scalar, destination, size);
324 #else
325  for(size_t n=0; n<size; n++)
326  destination[n] = data[n] * scalar;
327 #endif
328 }
329 
330 void FloatArray::negate(FloatArray& destination){//allows in-place
331 #ifdef ARM_CORTEX
332  arm_negate_f32(data, destination.getData(), size);
333 #else
334  for(size_t n=0; n<size; n++){
335  destination[n]=-data[n];
336  }
337 #endif /* ARM_CORTEX */
338 }
339 
341  noise(-1, 1);
342 }
343 
344 void FloatArray::noise(float min, float max){
345  float amplitude = fabsf(max-min);
346  float offset = min;
347  for(size_t n=0; n<size; n++)
348  data[n] = randf() * amplitude + offset;
349 }
350 
351 
352 void FloatArray::convolve(FloatArray operand2, FloatArray destination){
353  ASSERT(destination.size >= size + operand2.size -1, "Destination array too small");
354 #ifdef ARM_CORTEX
355  arm_conv_f32(data, size, operand2.data, operand2.size, destination);
356 #else
357  size_t size2 = operand2.getSize();
358  for(size_t n=0; n<size+size2-1; n++){
359  size_t n1 = n;
360  destination[n] = 0;
361  for(size_t k=0; k<size2; k++){
362  if(n1>=0 && n1<size)
363  destination[n] += data[n1]*operand2[k];
364  n1--;
365  }
366  }
367 #endif /* ARM_CORTEX */
368 }
369 
370 void FloatArray::convolve(FloatArray operand2, FloatArray destination, int offset, size_t samples){
371  ASSERT(destination.size >= size + operand2.size -1, "Destination array too small"); //TODO: change this condition to the actual size being written(will be samples+ tail)
373 #ifdef ARM_CORTEX
374  //TODO: I suspect a bug in arm_conv_partial_f32
375  //it seems that destination[n] is left unchanged for n<offset
376  //and the result is actually stored from destination[offset] onwards
377  //that is, in the same position where they would be if a full convolution was performed.
378  //This requires (destination.size >= size + operand2.size -1). Ideally you would want destination to be smaller
379  arm_conv_partial_f32(data, size, operand2.data, operand2.size, destination.getData(), offset, samples);
380 #else
381  //this implementations reproduces the (buggy?) behaviour of arm_conv_partial (see comment above and inline comments below)
382  /*
383  This implementation is just a copy/paste/edit from the overloaded method
384  */
385  size_t size2=operand2.getSize();
386  for (size_t n=offset; n<offset+samples; n++){
387  size_t n1=n;
388  destination[n] =0; //this should be [n-offset]
389  for(size_t k=0; k<size2; k++){
390  if(n1>=0 && n1<size)
391  destination[n]+=data[n1]*operand2[k];//this should be destination[n-offset]
392  n1--;
393  }
394  }
395 #endif /* ARM_CORTEX */
396 }
397 
398 void FloatArray::correlate(FloatArray operand2, FloatArray destination){
399  destination.setAll(0);
401  correlateInitialized(operand2, destination);
402 }
403 
405  ASSERT(destination.size >= size+operand2.size-1, "Destination array too small"); //TODO: change CMSIS docs, which state a different size
407 #ifdef ARM_CORTEX
408  arm_correlate_f32(data, size, operand2.data, operand2.size, destination);
409 #else
410  //correlation is the same as a convolution where one of the signals is flipped in time
411  //so we flip in time operand2
412  operand2.reverse();
413  //and convolve it with fa to obtain the correlation
414  convolve(operand2, destination);
415  //and we flip back operand2, so that the input is not modified
416  operand2.reverse();
417 #endif /* ARM_CORTEX */
418 }
419 
421  ASSERT(destination.getSize()>=size, "Wrong array size");
422  for(size_t i=0; i<size; i++)
423  destination[i] = log10f(data[i])*20.0;
424 }
425 
427  ASSERT(destination.getSize()>=size, "Wrong array size");
428  for(size_t i=0; i<size; i++)
429  destination[i] = exp10f(data[i]*0.05);
430 }
431 
432 void FloatArray::ramp(float from, float to){
433  float step = (to-from)/size;
434  for(size_t i=0; i<size; i++){
435  data[i] = from;
436  from += step;
437  }
438 }
439 
440 void FloatArray::scale(float from, float to, FloatArray destination){
441  float step = (to-from)/size;
442  for(size_t i=0; i<size; i++){
443  data[i] *= from;
444  from += step;
445  }
446 }
447 
448 /*
449  * Third-order static soft-clipping function.
450  * ref: T. Araya and A. Suyama, “Sound effector capable of
451  * imparting plural sound effects like distortion and other
452  * effects,” US Patent 5,570,424, 29 Oct. 1996.
453  */
455  for(size_t i=0; i<size; i++){
456  float x = data[i];
457  destination[i] = clamp((3*x/2)*(1-x*x/3), -1.0f, 1.0f);
458  }
459 }
460 
461 void FloatArray::tanh(FloatArray destination){
462  for(size_t i=0; i<size; i++)
463  destination[i] = tanhf(data[i]);
464 }
465 
467  FloatArray fa(new float[size], size);
468  fa.clear();
469  return fa;
470 }
471 
473  delete[] array.data;
474 }
float randf()
generate a random number between 0 and 1
Definition: basicmaths.c:74
#define clamp(x, lo, hi)
Definition: basicmaths.h:47
#define min(a, b)
Definition: basicmaths.h:38
#define max(a, b)
Definition: basicmaths.h:41
This class contains useful methods for manipulating arrays of floats.
Definition: FloatArray.h:12
void reverse()
Reverse the array.
Definition: FloatArray.cpp:99
float getStandardDeviation()
Standard deviation of the array.
Definition: FloatArray.cpp:166
void clear()
Clear the array.
Definition: FloatArray.h:29
void negate()
Negate the array.
Definition: FloatArray.h:127
void noise()
Random values Fills the array with random values in the range [-1, 1)
Definition: FloatArray.cpp:340
void multiply(FloatArray operand2, FloatArray destination)
Element-wise multiplication between arrays.
Definition: FloatArray.cpp:290
float getRms()
Root mean square value of the array.
Definition: FloatArray.cpp:113
int getMinIndex()
Get the index of the minimum value in the array.
Definition: FloatArray.cpp:33
void decibelToGain(FloatArray destination)
Convert decibel to gains values: gain = 10^(dB/20) -6dB = 0.5, 0dB = 1.0, +6dB = 2....
Definition: FloatArray.cpp:426
float getPower()
Power of the array.
Definition: FloatArray.cpp:151
float getMinValue()
Get the minimum value in the array.
Definition: FloatArray.cpp:25
void add(FloatArray operand2, FloatArray destination)
Element-wise sum between arrays.
Definition: FloatArray.cpp:231
float getVariance()
Variance of the array.
Definition: FloatArray.cpp:177
float getSum()
Sum of the array.
Definition: FloatArray.cpp:129
void reciprocal()
Reciprocal of the array, in-place version.
Definition: FloatArray.h:111
int getMaxIndex()
Get the index of the maximum value in the array.
Definition: FloatArray.cpp:69
void ramp(float from, float to)
Create a linear ramp from one value to another.
Definition: FloatArray.cpp:432
static void destroy(FloatArray array)
Destroys a FloatArray created with the create() method.
Definition: FloatArray.cpp:472
void rectify()
Absolute value of the array, in-place version.
Definition: FloatArray.h:83
void gainToDecibel(FloatArray destination)
Convert gains to decibel values: dB = log10(gain)*20 Gain 0.5 = -6dB, 1.0 = 0dB, 2....
Definition: FloatArray.cpp:420
void correlateInitialized(FloatArray operand2, FloatArray destination)
Correlation between arrays.
Definition: FloatArray.cpp:404
float getMean()
Mean of the array.
Definition: FloatArray.cpp:136
static FloatArray create(int size)
Creates a new FloatArray.
Definition: FloatArray.cpp:466
void subtract(FloatArray operand2, FloatArray destination)
Element-wise difference between arrays.
Definition: FloatArray.cpp:263
void clip()
Clips the elements in the array in the range [-1, 1].
Definition: FloatArray.cpp:193
void correlate(FloatArray operand2, FloatArray destination)
Correlation between arrays.
Definition: FloatArray.cpp:398
void scale(float from, float to, FloatArray destination)
Scale all values along a linear ramp from one value to another.
Definition: FloatArray.cpp:440
void getMax(float *value, int *index)
Get the maximum value in the array and its index.
Definition: FloatArray.cpp:41
void softclip()
Applies a cubic soft-clip algorithm to all elements in the array which limits them to the range [-1,...
Definition: FloatArray.h:209
void convolve(FloatArray operand2, FloatArray destination)
Convolution between arrays.
Definition: FloatArray.cpp:352
FloatArray subArray(int offset, size_t length)
A subset of the array.
Definition: FloatArray.cpp:215
void tanh()
In-place tanh.
Definition: FloatArray.h:386
void reverse(FloatArray &destination)
Reverse the array Copies the elements of the array in reversed order into destination.
Definition: FloatArray.cpp:89
void setAll(float value)
Set all the values in the array.
Definition: FloatArray.cpp:220
void getMin(float *value, int *index)
Get the minimum value in the array and its index.
Definition: FloatArray.cpp:6
float getMaxValue()
Get the maximum value in the array.
Definition: FloatArray.cpp:61
size_t getSize() const
Definition: SimpleArray.h:31
T * getData()
Get the data stored in the Array.
Definition: SimpleArray.h:27
#define ASSERT(cond, msg)
Definition: message.h:16