CSL  6.0
ShoeBox.cpp
Go to the documentation of this file.
1 //
2 // ShoeBox.m
3 // ShoeBox
4 //
5 // Created by Jorge Castellanos & Will Wolcott on 4/29/05.
6 // Copyright 2005 Jorge Castellanos & Will Wolcott. All rights reserved.
7 //
8 
9 
10 // IMPORTANT NOTES:
11 // 6) WRITE ALL INITIALIZERS NEEDED
12 // 7) WE MUST CHECK (IN THE INIT) THAT LISTENER AND SOURCE ARE ACTUALLY INSIDE THE ROOM.
13 
14 
15 #include "ShoeBox.h"
16 
17 #include "CSL_Core.h"
18 
19 const float kWoodCoefficient = 0.85; // 1/4" Plywood
20 const float kMarbleCoefficient = 0.99;
21 const float kConcreteCoefficient = 0.98;
22 const float kBrockCoefficient = 0.97;
23 const float kGlassCoefficient = 0.96;
24 
25 #define SPEED_OF_SOUND 0.341
26 
27 using namespace csl;
28 
29 // This will be one of the many constructors to set up the object.
30 
31 ShoeBox::ShoeBox() : mRoomSize(3, 4, 3), mSource(1, 2, 1), mListenerPosition(1.5, 2., 1.) {
32 
36 
37  mDuration = 50;
38 
39 
40 }
41 
43 
44 
45 }
46 
47 void ShoeBox::setWallMaterialsDamp(int dampX, int dampY, int dampZ) {
48 
49  switch(dampX) {
50  case kMarble:
52  break;
53  case kConcrete:
55  break;
56  case kBrick:
58  break;
59  case kGlass:
61  break;
62  case kWood:
64  break;
65  }
66  switch(dampY) {
67  case kMarble:
69  break;
70  case kConcrete:
72  break;
73  case kBrick:
75  break;
76  case kGlass:
78  break;
79  case kWood:
81  break;
82  }
83  switch(dampZ) {
84  case kMarble:
86  break;
87  case kConcrete:
89  break;
90  case kBrick:
92  break;
93  case kGlass:
95  break;
96  case kWood:
98  break;
99  }
100 
101 }
102 
103 void ShoeBox::setSourceLocation(float x, float y, float z) {
104 
105  mSource.x = x;
106  mSource.y = y;
107  mSource.z = z;
108 
109  logMsg("setSourceCalled: X = %g, Y = %g, Z = %g", mSource.x, mSource.y, mSource.z);
110 
112 }
113 
114 void ShoeBox::setListenerLocation(float x, float y, float z) {
115 
116  mListenerPosition.x = x;
117  mListenerPosition.y = y;
118  mListenerPosition.z = z;
119 
121 }
122 
123 void ShoeBox::setRoomSize(float x, float y, float z) {
124 
125  mRoomSize.x = x;
126  mRoomSize.y = y;
127  mRoomSize.z = z;
128 
130 }
131 
133 
135  return 1;
137  return 1;
139  return 1;
140 
141  return 0;
142 }
143 
145  int i, j, increment;
146  float temp, pairTemp, anglesTemp;
147 
148  increment = 3;
149  while (increment > 0)
150  {
151  for (i=0; i < mNumReflections; i++)
152  {
153  j = i;
154  temp = mReflectionsArray[i];
155  pairTemp = mGainsArray[i];
156  anglesTemp = mAnglesArray[i];
157  while ((j >= increment) && (mReflectionsArray[j-increment] > temp)) {
158  mReflectionsArray[j] = mReflectionsArray[j - increment];
159  mGainsArray[j] = mGainsArray[j - increment];
160  mAnglesArray[j] = mAnglesArray[j - increment];
161  j = j - increment;
162  }
163  mReflectionsArray[j] = temp;
164  mGainsArray[j] = pairTemp;
165  mAnglesArray[j] = anglesTemp;
166  }
167 
168  if (increment/2 != 0)
169  increment = increment/2;
170  else if (increment == 1)
171  increment = 0;
172  else
173  increment = 1;
174  }
175 
176 }
177 
178 
179 void ShoeBox::setDuration(int ms) { mDuration = ms; }
180 
181 
183 
184  // VERY FAST AND UGLY HACK TO NOT OVER CALCULATE REFLECTIONS. WE'LL NEED TO ADD A TIMETOREF FUNCT.
185  mDuration = (mRoomSize.x + mRoomSize.y + mRoomSize.z) * 3;
186 // 0.341 is the speed of sound in mm/s @ 20 Celsius
187  float clippingRadius = SPEED_OF_SOUND * mDuration; // clippingRadius is the maximum ray length to be traced.
188  mMaxBouncesX = (int)ceil(clippingRadius / (mRoomSize.x));
189  mMaxBouncesY = (int)ceil(clippingRadius / (mRoomSize.y));
190  mMaxBouncesZ = (int)ceil(clippingRadius / (mRoomSize.z));
191 
193 
194  if(mReflectionsArray != NULL)
195  free (mReflectionsArray);
196  if(mGainsArray != NULL)
197  free (mGainsArray);
198  if(mAnglesArray != NULL)
199  free (mAnglesArray);
200 
201  mReflectionsArray = (float *)calloc(mNumReflections, sizeof(float)); // Allocating twice, because we are also storing the gain.
202  mGainsArray = (float *)calloc(mNumReflections, sizeof(float));
203  mAnglesArray = (float *)calloc(mNumReflections, sizeof(float));
205  logMsg("Allocated memory for the reflections and gains. Total %d bytes", mNumReflections);
206 
207  logMsg("Reflection time = %d, bounces = %d, %d, %d", mDuration, mMaxBouncesX, mMaxBouncesY, mMaxBouncesZ);
208 
209 }
210 
212 
213 // Called in here because memory needs to be allocated accordingly to the sizes and reflection time requested.
215 
216  float imageX[mMaxBouncesX],imageY[mMaxBouncesY],imageZ[mMaxBouncesZ];
217  float powOfXDelta, powOfMiusXDelta, powOfYDelta, powOfMiusYDelta, powOfZDelta, powOfMiusZDelta;
218  float distanceFromSource, initalDistance, initialDelay, reflections;
219  float reflectionAngleI, reflectionAngleII, reflectionAngleIII, reflectionAngleIV;
220  int reflXpos,reflXneg,reflYpos,reflYneg,reflZpos,reflZneg;
221  int i, j, k;
222 
224  initialDelay = initalDistance / SPEED_OF_SOUND;
225 
226 // setting the first (real) room coordinates. It's done outside the loop to avoid a phantom double calculation.
227  imageX[0] = mSource.x;
228  imageY[0] = mSource.y;
229  imageZ[0] = mSource.z;
230 
231 // We are pre-calculating the COORDINATES for all the image (virtual) sources
232 // as the real room is set above, we'll start with [1] (meaning room two.
233  for(i = 1; i < mMaxBouncesX; i+= 2)
234  imageX[i] = (mRoomSize.x * (i+ 1)) - mSource.x; // Even rooms
235 
236  for(i = 2; i < mMaxBouncesX; i+= 2)
237  imageX[i] = (mRoomSize.x * i) + mSource.x; // Odd rooms
238 
239  for(i = 1; i < mMaxBouncesY; i+= 2)
240  imageY[i] = (mRoomSize.y * (i+ 1)) - mSource.y;
241 
242  for(i = 2; i < mMaxBouncesY; i+= 2)
243  imageY[i] = (mRoomSize.y * i) + mSource.y;
244 
245  for(i = 1; i < mMaxBouncesZ; i+= 2)
246  imageZ[i] = (mRoomSize.z * (i+ 1)) - mSource.z;
247 
248  for(i = 2; i < mMaxBouncesZ; i+= 2)
249  imageZ[i] = (mRoomSize.z * i) + mSource.z;
250 
251 
252 // Here is where we calculate the distance from the source to the listener.
253 // we are doing four rooms at a time: even, odd, negativeEven, negativeOdd
254 // this way we don't need to calculate the negative values, just reusing the already caluculated.
255  for(i = 0; i < mMaxBouncesX; i++) {
256  powOfXDelta = (imageX[i] - mListenerPosition.x)*(imageX[i] - mListenerPosition.x);
257  reflXpos = (int)floor(imageX[i]/mRoomSize.x);
258  powOfMiusXDelta = (imageX[i] + mListenerPosition.x)*(imageX[i] + mListenerPosition.x);
259  reflXneg = abs((int)floor(-imageX[i]/mRoomSize.x));
260  for(j = 0; j < mMaxBouncesY; j++) {
261  powOfYDelta = (imageY[j] - mListenerPosition.y)*(imageY[j] - mListenerPosition.y);
262  reflYpos = (int)floor(imageY[j]/mRoomSize.y);
263  powOfMiusYDelta = (imageY[j] + mListenerPosition.y)*(imageY[j] + mListenerPosition.y);
264  reflYneg = abs((int)floor(-imageY[j]/mRoomSize.y));
265  reflectionAngleI = atan2((imageY[j] - mListenerPosition.y),(imageX[i] - mListenerPosition.x));
266  reflectionAngleII = atan2((imageY[j] - mListenerPosition.y),(-imageX[i] - mListenerPosition.x));
267  reflectionAngleIII = atan2((-imageY[j] - mListenerPosition.y),(-imageX[i] - mListenerPosition.x));
268  reflectionAngleIV = atan2((-imageY[j] - mListenerPosition.y),(imageX[i] - mListenerPosition.x));
269  for(k = 0; k < mMaxBouncesZ; k++) {
270  powOfZDelta = (imageZ[k] - mListenerPosition.z)*(imageZ[k] - mListenerPosition.z);
271  reflZpos = (int)floor(imageZ[k]/mRoomSize.z);
272  powOfMiusZDelta = (imageZ[k] + mListenerPosition.z)*(imageZ[k] + mListenerPosition.z);
273  reflZneg = abs((int)floor(-imageZ[k]/mRoomSize.z));
274 
275 // calculating x, y, z, positive
276  reflections = pow(mDampX,reflXpos) * pow(mDampY,reflYpos) * pow(mDampZ,reflZpos);
277  distanceFromSource = sqrt(powOfXDelta + powOfYDelta + powOfZDelta);
278  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
279  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
280  *mAnglesArray++ = reflectionAngleI;
281 // NSLog(@"Reflections %d", reflections );
282 
283 // calculating x negative, y, z positive
284  reflections = pow(mDampX,reflXneg) * pow(mDampY,reflYpos) * pow(mDampZ,reflZpos);
285  distanceFromSource = sqrt(powOfMiusXDelta + powOfYDelta + powOfZDelta);
286  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
287  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
288  *mAnglesArray++ = reflectionAngleII;
289 // NSLog(@"Reflections %d", reflections );
290 
291 // calculating x positive, y negative, z positive
292  reflections = pow(mDampX,reflXpos) * pow(mDampY,reflYneg) * pow(mDampZ,reflZpos);
293  distanceFromSource = sqrt(powOfXDelta + powOfMiusYDelta + powOfZDelta);
294  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
295  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
296  *mAnglesArray++ = reflectionAngleIV;
297 // NSLog(@"Reflections %d", reflections );
298 
299 // calculating x, y negative, z positive
300  reflections = pow(mDampX,reflXneg) * pow(mDampY,reflYneg) * pow(mDampZ,reflZpos);
301  distanceFromSource = sqrt(powOfMiusXDelta + powOfMiusYDelta + powOfZDelta);
302  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
303  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
304  *mAnglesArray++ = reflectionAngleIII;
305 // NSLog(@"Reflections %d", reflections );
306 
307 // calculating x, y positive, z negative
308  reflections = pow(mDampX,reflXpos) * pow(mDampY,reflYpos) * pow(mDampZ,reflZneg);
309  distanceFromSource = sqrt(powOfXDelta + powOfYDelta + powOfMiusZDelta);
310  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
311  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
312  *mAnglesArray++ = reflectionAngleI;
313 // NSLog(@"Reflections %d", reflections );
314 
315 // calculating x negative, y positive, z negative
316  reflections = pow(mDampX,reflXneg) * pow(mDampY,reflYpos) * pow(mDampZ,reflZneg);
317  distanceFromSource = sqrt(powOfMiusXDelta + powOfYDelta + powOfMiusZDelta);
318  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
319  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
320  *mAnglesArray++ = reflectionAngleII;
321 // NSLog(@"Reflections %d", reflections );
322 
323 // calculating x positive, y, z negative
324  reflections = pow(mDampX,reflXpos) * pow(mDampY,reflYneg) * pow(mDampZ,reflZneg);
325  distanceFromSource = sqrt(powOfXDelta + powOfMiusYDelta + powOfMiusZDelta);
326  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
327  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
328  *mAnglesArray++ = reflectionAngleIV;
329 // NSLog(@"Reflections %d", reflections );
330 
331 // calculating x, y, z negative
332  reflections = pow(mDampX,reflXneg) * pow(mDampY,reflYneg) * pow(mDampZ,reflZneg);
333  distanceFromSource = sqrt(powOfMiusXDelta + powOfMiusYDelta + powOfMiusZDelta);
334  *mReflectionsArray++ = (distanceFromSource / SPEED_OF_SOUND) - initialDelay;
335  *mGainsArray++ = reflections * initalDistance / distanceFromSource;
336  *mAnglesArray++ = reflectionAngleIII;
337 // NSLog(@"Reflections %d", reflections );
338 
339 // NSLog(@"%g, %g, Number of Reflections:%i", timeFromSource, gain, reflections);
340 
341  }
342  }
343  }
344 
345 // We need to reset the pointers to the original address.
349 
350  shellSort();
351 
352  for(i = 0; i < mNumReflections; i++)
353  logMsg("Reflection #%d, after %g s & gain of %g angle is: %g", i, mReflectionsArray[i], mGainsArray[i], (mAnglesArray[i] * 180)/3.14159 );
354 
355 }
356 
357 void ShoeBox::getReflections(float *ref, float *gains, float *angles, int num) {
358 // write if statement that returns a non zero value if there are less reflections than requested.
359  memcpy(ref, mReflectionsArray, num * sizeof(float));
360  memcpy(gains, mGainsArray, num * sizeof(float));
361  memcpy(angles, mAnglesArray, num * sizeof(float));
362 }
363 
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
void findNumReflectionsFromTime()
Definition: ShoeBox.cpp:182
void setWallMaterialsDamp(int dampX, int dampY, int dampZ)
Definition: ShoeBox.cpp:47
#define SPEED_OF_SOUND
Definition: ShoeBox.cpp:25
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
float * mGainsArray
Definition: ShoeBox.h:50
void getReflections(float *ref, float *gains, float *angles, int num)
Definition: ShoeBox.cpp:357
int mMaxBouncesX
Definition: ShoeBox.h:51
float mDampY
Definition: ShoeBox.h:49
float mDampX
Definition: ShoeBox.h:49
void setSourceLocation(float x, float y, float z)
Definition: ShoeBox.cpp:103
float * mReflectionsArray
Definition: ShoeBox.h:50
float * mAnglesArray
Definition: ShoeBox.h:50
void setRoomSize(float x, float y, float z)
Definition: ShoeBox.cpp:123
void calculateReflections()
Definition: ShoeBox.cpp:211
bool checkPositionValues()
Definition: ShoeBox.cpp:132
COORD_TYPE x
Definition: CPoint.h:41
int mMaxBouncesZ
Definition: ShoeBox.h:51
const float kGlassCoefficient
Definition: ShoeBox.cpp:23
COORD_TYPE z
Definition: CPoint.h:41
void setListenerLocation(float x, float y, float z)
Definition: ShoeBox.cpp:114
CPoint mSource
Definition: ShoeBox.h:48
COORD_TYPE y
Definition: CPoint.h:41
const float kConcreteCoefficient
Definition: ShoeBox.cpp:21
float mDampZ
Definition: ShoeBox.h:49
const float kMarbleCoefficient
Definition: ShoeBox.cpp:20
void shellSort()
Definition: ShoeBox.cpp:144
CPoint mRoomSize
Definition: ShoeBox.h:48
int mMaxBouncesY
Definition: ShoeBox.h:51
const float kWoodCoefficient
Definition: ShoeBox.cpp:19
void setDuration(int ms)
Definition: ShoeBox.cpp:179
const float kBrockCoefficient
Definition: ShoeBox.cpp:22
int mDuration
Definition: ShoeBox.h:51
CPoint mListenerPosition
Definition: ShoeBox.h:48
int mNumReflections
Definition: ShoeBox.h:51