CSL  6.0
BinauralDB.cpp
Go to the documentation of this file.
1 ///
2 /// BinauralDB.cpp -- HRTF-based binaural panner/spatializers
3 ///
4 /// Classes
5 /// HRTF: holds the data that corresponds to an HRTF for a single position.
6 /// HRTFDatabase: vector of HRTFs; implemented as a Singleton because it's large.
7 /// BinauralPanner: place sources in 3D using block-wise convolution with an HRTF.
8 /// BinauralSourceCache: used for caching previous state of spatial sources.
9 ///
10 /// See the copyright notice and acknowledgment of authors in the file COPYRIGHT
11 /// Created by Jorge Castellanos on 7/19/06.
12 /// Rewritten for FFT wrappers and pluggable sound file APIs in 8/09 by STP.
13 /// Inspired by and partially based on the VST HRTF Plug-in written by Ryan Avery.
14 ///
15 
16 #include "BinauralDB.h"
17 
18 using namespace csl;
19 using namespace std;
20 
21 // HRTF Constructor allocates memory for the HRTF data
22 
24  unsigned hrirLength = HRIR_SIZE;
25  unsigned framesPerBlock = HRTF_BLOCK_SIZE;
26  unsigned mWindowSize = 2 * framesPerBlock;
27  mNumFFTBlocks = hrirLength / framesPerBlock;
28  unsigned hrtfLength = framesPerBlock + 1;
29  // allocate HRTF: L/R vectors of complex buffers
30  SAFE_MALLOC(mHrtfL, SampleComplexVector, mNumFFTBlocks);
31  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
32  SAFE_MALLOC(mHrtfL[i], SampleComplex, hrtfLength);
33  }
34  SAFE_MALLOC(mHrtfR, SampleComplexVector, mNumFFTBlocks);
35  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
36  SAFE_MALLOC(mHrtfR[i], SampleComplex, hrtfLength);
37  }
38 }
39 
40 // HRTF Constructor allocates memory for the HRTF data and then reads the HRIR file
41 // and performs the block-wise FFT into the complex arrays mHrtfL[i] and mHrtfR[i]
42 
43 HRTF::HRTF(char * filename, FFT_Wrapper & fft) {
44  unsigned hrirLength = HRIR_SIZE;
45  unsigned framesPerBlock = HRTF_BLOCK_SIZE;
46  unsigned mWindowSize = 2 * framesPerBlock;
47  mNumFFTBlocks = hrirLength / framesPerBlock;
48  unsigned hrtfLength = framesPerBlock + 1;
49  float theta, phi;
50  // allocate HRTF data storage
51  SAFE_MALLOC(mHrtfL, SampleComplexVector, mNumFFTBlocks);
52  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
53  SAFE_MALLOC(mHrtfL[i], SampleComplex, hrtfLength);
54  }
55  SAFE_MALLOC(mHrtfR, SampleComplexVector, mNumFFTBlocks);
56  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
57  SAFE_MALLOC(mHrtfR[i], SampleComplex, hrtfLength);
58  }
59  // I/O buffers
60  Buffer mInBuf(1, mWindowSize), mOutBuf(1, mWindowSize);
61  mInBuf.allocateBuffers(); // mInBuf has actual storage
62 
63  char *cursor = strstr(filename, "_T"); // parse the name to get theta and phi
64  if (cursor == NULL) { // e.g., IRC_1012_R_R0195_T000_P330.wav
65  logMsg(kLogError, "Cannot parse HRIR file name for theta: \"%s\"\n", filename);
66  throw IOError("Cannot parse HRIR filename");
67  }
68  theta = strtof((cursor + 2), (char **)NULL); // Read the number (degree) for theta, in filename.
69 
70  cursor = strstr(filename, "_P");
71  if (cursor == NULL) {
72  logMsg(kLogError, "Cannot parse HRIR file namefor phi: \"%s\"\n", filename);
73  throw IOError("Cannot parse HRIR filename");
74  }
75  phi = strtof((cursor + 2), (char **)NULL); // Read the number (degree) for phi, in filename.
76  mPosition.set('s', 1.0f, theta / CSL_DEGS_PER_RAD, phi / CSL_DEGS_PER_RAD);
77 // logMsg("HRTF reading %g @ %g", theta, phi);
78 
79  SoundFile hrirFile(filename); // open the HRIR file
80  hrirFile.openForRead(); // load HRIR file
81 
82  if ( ! hrirFile.isValid()) { // check validity
83  logMsg("Cannot open sound file \"%s\"", filename);
84  throw IOError("Sound file open error");
85  } // Check file's #channels and #frames
86  if ((hrirFile.channels() != 2) || (hrirFile.duration() < HRIR_SIZE)) {
87  logMsg("Sound file \"%s\" is wrong format: %d ch, %d frames",
88  filename, hrirFile.channels(), hrirFile.duration());
89  throw IOError("Sound file open error");
90  }
91  // Load in HRIR file and convert it to HRTF buffers
92  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
93  mInBuf.zeroBuffers(); // clear buffer (no zero-padding needed this way)
94  memcpy(mInBuf.buffer(0), // copy samples from file to buffer
95  (hrirFile.mWavetable.buffer(0)) + (i * framesPerBlock),
96  (framesPerBlock * sizeof(sample)));
97  mOutBuf.setBuffer(0, (SampleBuffer) mHrtfL[i]);
98 
99  fft.nextBuffer(mInBuf, mOutBuf); // execute Left FFT
100 
101  mInBuf.zeroBuffers();
102  memcpy(mInBuf.buffer(0),
103  (hrirFile.mWavetable.buffer(1)) + (i * framesPerBlock),
104  (framesPerBlock * sizeof(sample)));
105  mOutBuf.setBuffer(0, (SampleBuffer) mHrtfR[i]);
106 
107  fft.nextBuffer(mInBuf, mOutBuf); // execute Right FFT
108  }
109  hrirFile.close(); // Close the file.
110 }
111 
112 // destructor clears memory
113 
115  for (unsigned i = 0; i < mNumFFTBlocks; i++) {
116  SAFE_FREE(mHrtfL[i]);
117  SAFE_FREE(mHrtfR[i]);
118  }
119  SAFE_FREE(mHrtfR);
120  SAFE_FREE(mHrtfR);
121 }
122 
123 // pretty print
124 
125 void HRTF::dump() {
126  logMsg("HRTF with Azimuth: %f \t Elevation: %f",
127  mPosition.theta() * CSL_DEGS_PER_RAD,
128  mPosition.ele() * CSL_DEGS_PER_RAD);
129 }
130 
131 // Answer the HRTF's storage size in Bytes
132 
133 unsigned HRTF::size() {
134  return ((mNumFFTBlocks * 2 * (HRTF_BLOCK_SIZE + 1) * sizeof(SampleComplex))
135  + (mNumFFTBlocks * 2 * sizeof(SampleComplexVector)));
136 }
137 
138 //////////////////////////////////////////////////////////////////////////////////////
139 /// HRTFDatabase
140 ///
141 
142 // Static "Singleton" HRTF Database
143 
145 
146 // Static Methods
147 
148 // Access the DB, initializing it lazily
149 
151  if (mDatabase == NULL) {
152  string folder(CGestalt::dataFolder());
153  folder += DEFAULT_HRTF_FOLDER;
154  mDatabase = new HRTFDatabase(folder.c_str());
155  }
156  return mDatabase;
157 }
158 
159 // Flush the DB
160 
162  if (mDatabase) {
163  delete mDatabase;
164  mDatabase = NULL;
165  }
166 }
167 
168 // constructor that takes an HRTF vector
169 
170 //void HRTFDatabase::Reload(vector <HRTF *> hrtfs) {
171 // // create new DB
172 // HRTFDatabase * newDB = new HRTFDatabase(hrtfs);
173 // // be careful to avoid race conditions
174 // HRTFDatabase * oldDB = mDatabase;
175 // mDatabase = newDB; // set new DB
176 // if (oldDB)
177 // delete oldDB; // free old one
178 //}
179 
180 // load a new folder into the DB
181 
182 void HRTFDatabase::Reload(char * folder) {
183  // create new DB
184  HRTFDatabase * newDB = new HRTFDatabase(folder);
185  // be careful to avoid race conditions
186  HRTFDatabase * oldDB = mDatabase;
187  mDatabase = newDB; // set new DB
188  if (oldDB)
189  delete oldDB; // free old one
190 }
191 
192 // HRTFDatabase Constructor (is private)
193 
194 HRTFDatabase::HRTFDatabase(const char * folder) {
195  mWindowSize = 2 * HRTF_BLOCK_SIZE;
196  mHRTFLength = HRTF_BLOCK_SIZE ; // + 1;
197  mHRIRLength = HRIR_SIZE;
198 
199  logMsg("Loading the HRTFDatabase %s", folder);
200  if (strcasestr(folder, ".dat") != NULL) { // if the name looks like a DB name
201  try {
202  loadFromDB(folder);
203  } catch (CException ex) { // handler: log error and exit the program.
204  logMsg(kLogError, "Loading the HRTFDatabase: %s\n", ex.mMessage.c_str());
205  exit(0);
206  }
207  } else if (folder[strlen(folder) - 1] == '/') { // if the name looks like a folder name
208  try {
209  char realFolder[CSL_NAME_LEN] = "";
210  if (folder[0] == '~') { // handle paths relative to "~"
211  strcpy(realFolder, getenv("HOME"));
212  if (strlen(folder) > 1)
213  strcat(realFolder, &folder[1]);
214  } else
215  strcpy(realFolder, folder);
216  logMsg("Loading HRTF data from %s", realFolder);
217 
218  this->loadFromFolder(realFolder); // load the folder
219 
220  } catch (CException ex) { // handler: log error and exit the program.
221  logMsg(kLogError, "Loading the HRTFDatabase: %s\n", ex.mMessage.c_str());
222  exit(0);
223  }
224  } else { // if the name looks like the list file name
225  try {
226 // logMsg("Loading HRTF files from %s", folder);
227  loadFromFile(folder); // load the folder
228  } catch (CException ex) { // handler: log error and exit the program.
229  logMsg(kLogError, "Loading the HRTFDatabase: %s\n", ex.mMessage.c_str());
230  exit(0);
231  }
232  }
233 }
234 
235 // HRTFDatabase::loadFromFolder: load an IRCAM-format HRTF database folder.
236 // This assumes there's a file named "files.txt" in the folder with a list of files.
237 // Create this with "ls IRC* > files"
238 // ToDo: use directory enumeration or popen("ls IRC*") for this
239 
240 void HRTFDatabase::loadFromFolder (const char *folder) throw (CException) {
241  char filename[CSL_NAME_LEN];
242  strcpy(filename, folder); // Copy the path to the folder into the "filename" string
243  strcat(filename, FLIST_NAME); // Append the name of the file containing the list of hrtf files
244  this->loadFromFile(filename);
245 }
246 
247 // Load HRTF data from the given file list
248 
249 void HRTFDatabase::loadFromFile (const char *listname) throw (CException) {
250  char lineBuffer[CSL_NAME_LEN];
251  char dirname[CSL_NAME_LEN];
252  char filename[CSL_NAME_LEN];
253  FILE * listFile; // text file with the list of HRTF files in the directory
254  FFT_Wrapper fft(mWindowSize, CSL_FFT_COMPLEX); // create a raw-format forward FFT
255 
256  listFile = fopen(listname, "r"); // Open the file that contains the list.
257  if ( ! listFile) {
258  logMsg("Cannot open list file %s for reading.\n", listname);
259  return;
260  }
261  strcpy(dirname, listname); // copy list file name to get directory name
262  char * ext = rindex(dirname, '/');
263  ext++;
264  *ext = 0;
265  while ( ! feof(listFile)) { // Go thru the file list
266  fgets(lineBuffer, 1024, listFile); // Read one full line
267 // logMsg("Read HRTF file %s", lineBuffer);
268  int len = strlen(lineBuffer) - 1;
269  if (len < 2)
270  continue;
271  if (lineBuffer[len] == '\n') // remove EOL from line
272  lineBuffer[len] = '\0';
273  strcpy(filename, dirname); // Copy the path to the files directory into filename
274  strcat(filename, lineBuffer); // Copy the name from the line in
275 // cout << " Read HRTF file " << filename << endl;
276 
277  HRTF * tHRTF = new HRTF(filename, fft); // Create the HRTF from the file
278  mHRTFVector.push_back(tHRTF); // Add the HRTF to the vector.
279  }
280  fclose(listFile); // Close the list file.
281 //#endif
282 #ifdef CSL_DEBUG
283  dump();
284 #endif
285 }
286 
287 // byte-swap the buffer
288 
289 #ifdef IPHONE // byte-swap floats
290 void swapBuffer(float * buf, unsigned numFloats) {
291  float * ptr = buf;
292  for (unsigned b = 0; b < numFloats; b++) {
293  unsigned int val = (unsigned int) *ptr;
294  val = CFSwapInt32LittleToHost(val);
295  *ptr++ = (float) val;
296  }
297 }
298 #endif
299 
300 // Load HRTF data from the given file list
301 
302 void HRTFDatabase::loadFromDB (const char *dbName) throw (CException) {
303  char lineBuffer[CSL_NAME_LEN];
304  char tok[8];
305  char nam[16];
306  int nHRTFs, nBlocks, hrirLen, fftLen;
307  FILE * dbFile; // text file with the list of HRTF files in the directory
308  PointVector hrtfPoints;
309  int azim, elev;
310 
311  dbFile = fopen(dbName, "r"); // Open the file that contains the list.
312  if ( ! dbFile) {
313  logMsg("Cannot open DB file %s for reading.\n", dbName);
314  return;
315  }
316  fgets(lineBuffer, 1024, dbFile); // Read magic # = "HRTF"
317  if (strncmp(lineBuffer, "HRTF", 4) != 0) {
318  logMsg("DB file %s wrong format.\n", dbName);
319  fclose(dbFile);
320  return;
321  } // read header line
322  int numFound = sscanf(lineBuffer, "%s\t%s\t%d\t%d\t%d\t%d",
323  tok, nam, & nHRTFs, & hrirLen, & fftLen, & nBlocks);
324  if (numFound != 6) {
325  logMsg("Line format: %s\n", lineBuffer);
326  fclose(dbFile);
327  return;
328  }
329  mWindowSize = 2 * fftLen; // set receiver's members from line
330  mHRTFLength = fftLen;
331  mHRIRLength = hrirLen;
332  if (nBlocks != numBlocks()) {
333  logMsg("Line format: %s\n", lineBuffer);
334  fclose(dbFile);
335  return;
336  }
337  fgets(lineBuffer, CSL_LINE_LEN, dbFile); // read the first geometry line
338  while(strlen(lineBuffer) > 1) { // loop through file to an empty line
339  // Read 2 ints from a line
340  if(sscanf(lineBuffer, "%d\t%d", & azim, & elev) != 2) {
341  logMsg("Line format: %s\n", lineBuffer);
342  fclose(dbFile);
343  return;
344  } // create a point
345  CPoint * cpt = new CPoint(kPolar, 1.0f, azim / CSL_DEGS_PER_RAD, elev / CSL_DEGS_PER_RAD);
346 // cpt->dumpPol(); // verbose list of points
347  hrtfPoints.push_back(cpt); // add pt to list
348  fgets(lineBuffer, CSL_LINE_LEN, dbFile); // read next line
349  } // end of loop; empty line read
350 // logMsg("Found %d positions (%d)", hrtfPoints.size(), nHRTFs);
351 
352  if (hrtfPoints.size() != nHRTFs) {
353  logMsg("Found %d positions ( ! = %d)", hrtfPoints.size(), nHRTFs);
354  fclose(dbFile);
355  return;
356  }
357 
358  int hdrSize = (int) ftell(dbFile); // start of data section
359  for (unsigned i = 0; i < nHRTFs; i++) { // loop over 180 HRTFs
360  HRTF * hrtf = new HRTF(); // Create an empty HRTF
361  hrtf->mPosition.set('s', 1.0f, // set its pos
362  hrtfPoints[i]->theta(),
363  hrtfPoints[i]->ele());
364  for (unsigned b = 0; b < nBlocks; b++) { // loop over 16 blocks
365  // read 2 complex buffers from file
366  size_t nRead = fread(hrtf->mHrtfL[b], sizeof(SampleComplex), mHRTFLength, dbFile);
367  if (nRead != mHRTFLength) {
368  logMsg(kLogError, "HRTF load read error %d\n", nRead);
369  perror("Error reading HRTF ");
370  throw IOError("Error reading HRTF");
371  }
372  nRead = fread(hrtf->mHrtfR[b], sizeof(SampleComplex), mHRTFLength, dbFile);
373  if (nRead != mHRTFLength) {
374  logMsg(kLogError, "HRTF load read error %d\n", nRead);
375  perror("Error reading HRTF ");
376  throw IOError("Error reading HRTF");
377  }
378  }
379  mHRTFVector.push_back(hrtf); // Add the HRTF to the vector.
380  }
381  int dataSize = (int) ftell(dbFile) - hdrSize; // end of file
382  fgets(lineBuffer, 1024, dbFile); // Read "HRTF" trailer from the file
383  if (strncmp(lineBuffer, "HRTF", 4) != 0)
384  logMsg("Error: Trailer format: %s\n", lineBuffer);
385  fclose(dbFile);
386 // printf("\nLoad HRTF DB \"%s\"\n\t%d HRTFs of %d blocks of %d-len complex arrays;\n\thdr = %d data = %5.2f\n",
387 // dbName, nHRTFs, nBlocks, fftLen, hdrSize, ((float) dataSize / 1000000.0f));
388 }
389 
390 // copy constructor
391 
392 //HRTFDatabase::HRTFDatabase(HRTFVector hrtfs) {
393 // mWindowSize = 2 * HRTF_BLOCK_SIZE;
394 // mHRTFLength = mWindowSize / 2 + 1;
395 // mHRIRLength = HRIR_SIZE;
396 // for (HRTFVector::iterator it = hrtfs.begin(); it != hrtfs.end(); it++)
397 // mHRTFVector.push_back(*it);
398 //}
399 
400 // Prints the number of HRTFs in the database, and then calls dump() an each of them, printing their position.
401 // :: HRTF: 188 files = 24.7 MB (w: 1024 i: 8192 f: 511 b: 16)
402 
403 void HRTFDatabase::dump(bool verbose) {
404  logMsg("HRTF: %d files = %4.1f MB (w: %d i: %d f: %d b: %d)",
405  numHRTFs(), ((float) size() / 1000000.0f),
406  windowSize(), hrirLength(), hrtfLength(), numBlocks());
407  if (verbose)
408  for (unsigned i = 0; i < numHRTFs(); i++)
409  mHRTFVector[i]->dump();
410 }
411 
412 // Answer the HRTFDatabase's storage size in Bytes
413 
414 unsigned HRTFDatabase::size() {
415  unsigned siz = 0;
416  for (unsigned i = 0; i < this->numHRTFs(); i++)
417  siz += mHRTFVector[i]->size();
418  return siz;
419 }
420 
421 // the main HRTFDatabase accessor by index
422 
423 HRTF * HRTFDatabase::hrtfAt(unsigned index) {
424  unsigned numHRTFs = this->numHRTFs();
425  if ( ! numHRTFs) { // empty HRTF
426  logMsg(kLogError, "HRTFDatabase::hrtfAt - empty data");
427  return 0;
428  }
429  return mHRTFVector[index];
430 }
431 
432 // answer the index of the HRTF closest to the given source position by linear search
433 
434 unsigned HRTFDatabase::hrtfAt(CPoint sourcePos) {
435  double tmpVal = 0;
436  double lowVal = 10000; // > than the largest reasonable distance
437  unsigned localHRTF = 0;
438  unsigned numHRTFs = this->numHRTFs();
439  if ( ! numHRTFs) { // empty HRTF
440  logMsg(kLogError, "HRTFDatabase::hrtfAt - empty data");
441  return 0;
442  }
443  CPoint sPt = sourcePos;
444  sPt.normalize(); // Make it a unit vector, so its at the same distance as the hrtfs
445  for (unsigned j = 0; j < numHRTFs - 1; j++) {
446  tmpVal = sPt.distance2(mHRTFVector[j]->mPosition); // Get the distance from one point to the other.
447  if (tmpVal < lowVal) {
448  lowVal = tmpVal;
449  localHRTF = j;
450  }
451  }
452  return localHRTF;
453 }
454 
455 // Total number of HRTFs loaded into the database.
456 
458  return mHRTFVector.size();
459 }
460 
461 // The size of the analysis window (in samples).
462 
464  return mWindowSize;
465 }
466 
467 // The length (in samples) of the Transfer Function buffer.
468 
470  return mHRTFLength;
471 }
472 
473 // The length (in samples) of the impulse responses loaded.
474 
476  return mHRIRLength;
477 }
478 
479 // The length (in blocks) of the impulse responses loaded.
480 
482  return mHRIRLength / (windowSize() / 2);
483 }
484 
485 // dump the DB as a single binary file
486 // format is:
487 // a nul-term string with the label and geometry list,
488 // label is name #-hrtfs #-blocks blk-size
489 // e.g., HRTF 1047 188 16 513
490 // name list is in the same format as the files.txt list,
491 // followed by the blocks of complex, blocked HRTFs
492 // 16 blocks/set, each has 513 complex values for L and R
493 // = 8 * 2 * 513 * 16 = 131 kB / HRTF * 188 = 24.6 MB / DB
494 
495 void HRTFDatabase::storeToDB(const char *filename, const char *sname) throw (CException) {
496  unsigned numBlocks = hrirLength() / (windowSize() / 2);
497  unsigned num2Store = numHRTFs(); // store all by default
498 
499  FILE * store = fopen(filename, "w");
500  if ( ! store) {
501  printf("Error saving HRTF DB - cannot open file\n");
502  return;
503  }
504  fprintf(store, "HRTF %s\t%d\t%d\t%d\t%d\n", // write store header
505  sname, num2Store, hrirLength(), hrtfLength(), numBlocks);
506  // write store HRTF position list
507  for (unsigned j = 0; j < num2Store; j++) {
508 // for (unsigned j = 0; j < numHRTFs() /* num2Store */; j++) {
509 // if (mHRTFVector[j]->mPosition.ele() == 0)
510  fprintf(store, "%g\t%g\n",
511  mHRTFVector[j]->mPosition.theta() * CSL_DEGS_PER_RAD,
512  mHRTFVector[j]->mPosition.ele() * CSL_DEGS_PER_RAD);
513  }
514  fprintf(store, "\n"); // write a blank line to end list
515  int hdrSize = (int) ftell(store);
516  // write HRTF data
517  for (unsigned i = 0; i < num2Store; i++) { // loop over 180 HRTFs
518 // for (unsigned i = 0; i < numHRTFs() /* num2Store */; i++) { // loop over 180 HRTFs
519 // if (mHRTFVector[i]->mPosition.ele() == 0) { // store only elev = 0
520  HRTF * hrtf = mHRTFVector[i];
521  for (unsigned b = 0; b < numBlocks; b++) { // loop over 16 blocks
522  // write 2 complex buffers
523  fwrite(hrtf->mHrtfL[b], sizeof(SampleComplex), mHRTFLength, store);
524  fwrite(hrtf->mHrtfR[b], sizeof(SampleComplex), mHRTFLength, store);
525  }
526  fflush(store);
527 // }
528  }
529  int dataSize = (int) ftell(store) - hdrSize;
530  fprintf(store, "HRTF\n"); // write footer
531  fclose(store);
532  printf("Saved HRTF DB %s with %d HRTFs %d blocks of %d-len arrays;\n\thdr = %d B, data = %5.2f MB\n\n",
533  sname, num2Store, numBlocks, hrtfLength(), hdrSize, ((float) dataSize / 1000000.0f));
534 }
535 
536 // bulk translation of IRCAM HRTFs to CSL-format block data files
537 
538 void HRTFDatabase::convertDB(const char *listname) throw (CException) {
539  char lineBuffer[CSL_NAME_LEN];
540  char filename[CSL_NAME_LEN];
541  char tok[8];
542  FILE * listFile; // text file with the list of HRTF files in the directory
543 
544  listFile = fopen(listname, "r"); // Open the file that contains the list.
545  if ( ! listFile) {
546  logMsg("Cannot open list file %s for reading.\n", listname);
547  return;
548  }
549  while ( ! feof(listFile)) { // Go thru the file list
550  fgets(lineBuffer, 1024, listFile); // Read one full line
551  int len = strlen(lineBuffer) - 1;
552  if (lineBuffer[len] == '\n') // remove EOL from line
553  lineBuffer[len] = '\0';
554  logMsg("Read HRTF folder %s", lineBuffer);
555  sprintf(filename, "%sIRCAM_HRTF/%s/",
556  CGestalt::dataFolder().c_str(), lineBuffer);
557 
558  HRTFDatabase::Reload(filename); // Load the new data
559  logMsg("Loaded %d HRTF files = %4.1f MB",
560  HRTFDatabase::Database()->numHRTFs(),
561  ((float) HRTFDatabase::Database()->size() / 1000000.0f));
562 
563  char * cpos = strstr(filename, "IRC_");
564  if (cpos) {
565  int index = atoi(cpos + 4);
566  sprintf(filename, "%sIRCAM_HRTF/HRTF_%d.dat",
567  CGestalt::dataFolder().c_str(), index); // CSL data folder location
568  sprintf(tok, "%d", index);
569  HRTFDatabase::Database()->storeToDB(filename, tok);
570  }
571  }
572 }
573 
574 // Stale
575 //
576 //#ifdef IPHONE
577 // NSBundle * bundle = [NSBundle mainBundle];
578 // CFURLRef fileURL = (CFURLRef)[[NSURL fileURLWithPath:
579 // [bundle pathForResource: @"IRC_1047_R" ofType: @""]]
580 // retain];
581 // CFStringRef namestring = CFURLGetString (fileURL);
582 // char theName[CSL_NAME_LEN];
583 // Boolean aok = CFStringGetCString (namestring, theName, CSL_NAME_LEN, kCFStringEncodingMacRoman);
584 // logMsg("Loading HRTF files from %s", theName);
585 // NSArray * pathsArray =[[NSBundle mainBundle]
586 // pathsForResourcesOfType: @"wav"
587 // inDirectory: [NSString stringWithCString: HRTF_RESOURCE]];
588 // int pathCount = [pathsArray count];
589 // int i;
590 // NSString* presetPath = NULL;
591 // for(i = 0; i < pathCount; i++) {
592 // presetPath = [pathsArray objectAtIndex:i];
593 // aok = CFStringGetCString (presetPath, theName, CSL_NAME_LEN, kCFStringEncodingMacRoman);
594 // mHRTFVector.push_back(new HRTF(theName, fft)); //// Add the HRTF to the vector.
595 // }
596 //#else
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
Definition: CSL_Types.h:194
COORD_TYPE distance2(CPoint *)
Definition: CPoint.cpp:360
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
SampleComplex * SampleComplexVector
complex vector
Definition: CSL_Types.h:202
SampleComplexVector * mHrtfR
2 arrays of arrays of mNumFFTBlocks * complex[513]: the HRTF data in blocks of complex # for stereo ...
Definition: BinauralDB.h:112
static HRTFDatabase * Database()
accessor for the singleton instance (lazy init)
Definition: BinauralDB.cpp:150
void loadFromFolder(const char *folder)
Definition: BinauralDB.cpp:240
virtual void setBuffer(unsigned bufNum, SampleBuffer sPtr)
Definition: CSL_Core.h:158
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
unsigned numBlocks()
The length (in windows) of the impulse responses loaded.
Definition: BinauralDB.cpp:481
unsigned hrtfLength()
The length (in samples) of the Transfer Function buffer.
Definition: BinauralDB.cpp:469
#define HRTF_BLOCK_SIZE
BinauralDB.h – Specification of the HRTF file format and database This is the CSL 5 version that use...
Definition: BinauralDB.h:65
unsigned hrirLength()
The length (in samples) of the impulse responses loaded.
Definition: BinauralDB.cpp:475
CPoint mPosition
The Position at which the HRIR was recorded.
Definition: BinauralDB.h:111
unsigned numHRTFs()
Total number of HRTFs loaded into the database.
Definition: BinauralDB.cpp:457
static HRTFDatabase * mDatabase
The protected single instance of the HRTF Database.
Definition: BinauralDB.h:165
#define FLIST_NAME
name of file list file
Definition: BinauralDB.h:72
static void Reload(char *folder)
load the singleton from the given data folder
Definition: BinauralDB.cpp:182
void normalize()
Definition: CPoint.cpp:423
#define HRIR_SIZE
Definition: BinauralDB.h:66
std::vector< CPoint * > PointVector
Forward declaration.
Definition: CSL_Types.h:215
unsigned size()
returns the size on bytes of the receiver's storage
Definition: BinauralDB.cpp:414
unsigned windowSize()
The size of the analysis window (in samples).
Definition: BinauralDB.cpp:463
#define kPolar
Definition: CPoint.h:31
#define CSL_NAME_LEN
default string length
Definition: CSL_Types.h:121
static void Destroy()
free the instance
Definition: BinauralDB.cpp:161
HRTFDatabase: has a vector of HRTFs and can access them by position – hrtfAt(CPoint) – or by index ...
Definition: BinauralDB.h:128
#define CSL_LINE_LEN
default line length
Definition: CSL_Types.h:122
float sample
(could be changed to int, or double)
Definition: CSL_Types.h:191
void loadFromDB(const char *dbName)
Definition: BinauralDB.cpp:302
#define DEFAULT_HRTF_FOLDER
where are the HRTFs under the CSL_Data folder?
Definition: BinauralDB.h:73
HRTF: holds the data that corresponds to an HRTF for a single position. It has a list of complex buff...
Definition: BinauralDB.h:101
static size_t size
Definition: fft_N.c:40
#define SAFE_FREE(ptr)
Definition: CGestalt.h:137
void storeToDB(const char *filename, const char *same)
Definition: BinauralDB.cpp:495
SampleComplexVector * mHrtfL
Definition: BinauralDB.h:112
static unsigned len
Definition: fft_N.c:39
unsigned hrtfAt(CPoint srcPos)
answer the index of the HRTF nearest the given point
Definition: BinauralDB.cpp:434
IO Error.
void dump(bool verbose=false)
Print all the HRTFs in the database.
Definition: BinauralDB.cpp:403
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
HRTFDatabase(const char *folder)
constructor that loads from a folder (protected) load a set of HRTFs from a folder or a file list fil...
Definition: BinauralDB.cpp:194
void set(int a, int b)
Definition: CPoint.h:73
void loadFromFile(const char *filename)
Definition: BinauralDB.cpp:249
static void convertDB(const char *listname)
bulk-convert DBs
Definition: BinauralDB.cpp:538
HRTF()
HRTF constructor allocates memory for the HRTF data and then reads the HRIR file and performs the blo...
Definition: BinauralDB.cpp:23
void dump()
Prints the position that corresponds to this HRTF.
Definition: BinauralDB.cpp:125
sample SampleComplex[2]
array-of-2 complex # type (like FFTW)
Definition: CSL_Types.h:198
#define SAFE_MALLOC(ptr, type, len)
Useful Macros.
Definition: CGestalt.h:103
unsigned size()
returns the size on bytes of the receiver's storage
Definition: BinauralDB.cpp:133
Base class of CSL exceptions (written upper-case). Has a string message.
#define CSL_DEGS_PER_RAD
Definition: CSL_Types.h:342
static std::string dataFolder()
the default directory for test data
Definition: CGestalt.cpp:71