26 unsigned mWindowSize = 2 * framesPerBlock;
27 mNumFFTBlocks = hrirLength / framesPerBlock;
28 unsigned hrtfLength = framesPerBlock + 1;
31 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
35 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
46 unsigned mWindowSize = 2 * framesPerBlock;
47 mNumFFTBlocks = hrirLength / framesPerBlock;
48 unsigned hrtfLength = framesPerBlock + 1;
52 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
56 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
60 Buffer mInBuf(1, mWindowSize), mOutBuf(1, mWindowSize);
61 mInBuf.allocateBuffers();
63 char *cursor = strstr(filename,
"_T");
65 logMsg(
kLogError,
"Cannot parse HRIR file name for theta: \"%s\"\n", filename);
66 throw IOError(
"Cannot parse HRIR filename");
68 theta = strtof((cursor + 2), (
char **)NULL);
70 cursor = strstr(filename,
"_P");
72 logMsg(
kLogError,
"Cannot parse HRIR file namefor phi: \"%s\"\n", filename);
73 throw IOError(
"Cannot parse HRIR filename");
75 phi = strtof((cursor + 2), (
char **)NULL);
79 SoundFile hrirFile(filename);
80 hrirFile.openForRead();
82 if ( ! hrirFile.isValid()) {
83 logMsg(
"Cannot open sound file \"%s\"", filename);
84 throw IOError(
"Sound file open error");
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");
92 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
94 memcpy(mInBuf.buffer(0),
95 (hrirFile.mWavetable.buffer(0)) + (i * framesPerBlock),
96 (framesPerBlock *
sizeof(
sample)));
99 fft.nextBuffer(mInBuf, mOutBuf);
101 mInBuf.zeroBuffers();
102 memcpy(mInBuf.buffer(0),
103 (hrirFile.mWavetable.buffer(1)) + (i * framesPerBlock),
104 (framesPerBlock *
sizeof(
sample)));
107 fft.nextBuffer(mInBuf, mOutBuf);
115 for (
unsigned i = 0; i < mNumFFTBlocks; i++) {
126 logMsg(
"HRTF with Azimuth: %f \t Elevation: %f",
151 if (mDatabase == NULL) {
199 logMsg(
"Loading the HRTFDatabase %s", folder);
200 if (strcasestr(folder,
".dat") != NULL) {
207 }
else if (folder[strlen(folder) - 1] ==
'/') {
210 if (folder[0] ==
'~') {
211 strcpy(realFolder, getenv(
"HOME"));
212 if (strlen(folder) > 1)
213 strcat(realFolder, &folder[1]);
215 strcpy(realFolder, folder);
216 logMsg(
"Loading HRTF data from %s", realFolder);
218 this->loadFromFolder(realFolder);
227 loadFromFile(folder);
242 strcpy(filename, folder);
244 this->loadFromFile(filename);
256 listFile = fopen(listname,
"r");
258 logMsg(
"Cannot open list file %s for reading.\n", listname);
261 strcpy(dirname, listname);
262 char * ext = rindex(dirname,
'/');
265 while ( ! feof(listFile)) {
266 fgets(lineBuffer, 1024, listFile);
268 int len = strlen(lineBuffer) - 1;
271 if (lineBuffer[len] ==
'\n')
272 lineBuffer[
len] =
'\0';
273 strcpy(filename, dirname);
274 strcat(filename, lineBuffer);
277 HRTF * tHRTF =
new HRTF(filename, fft);
278 mHRTFVector.push_back(tHRTF);
289 #ifdef IPHONE // byte-swap floats
290 void swapBuffer(
float * buf,
unsigned numFloats) {
292 for (
unsigned b = 0; b < numFloats; b++) {
293 unsigned int val = (
unsigned int) *ptr;
294 val = CFSwapInt32LittleToHost(val);
295 *ptr++ = (float) val;
306 int nHRTFs, nBlocks, hrirLen, fftLen;
311 dbFile = fopen(dbName,
"r");
313 logMsg(
"Cannot open DB file %s for reading.\n", dbName);
316 fgets(lineBuffer, 1024, dbFile);
317 if (strncmp(lineBuffer,
"HRTF", 4) != 0) {
318 logMsg(
"DB file %s wrong format.\n", dbName);
322 int numFound = sscanf(lineBuffer,
"%s\t%s\t%d\t%d\t%d\t%d",
323 tok, nam, & nHRTFs, & hrirLen, & fftLen, & nBlocks);
325 logMsg(
"Line format: %s\n", lineBuffer);
329 mWindowSize = 2 * fftLen;
330 mHRTFLength = fftLen;
331 mHRIRLength = hrirLen;
332 if (nBlocks != numBlocks()) {
333 logMsg(
"Line format: %s\n", lineBuffer);
338 while(strlen(lineBuffer) > 1) {
340 if(sscanf(lineBuffer,
"%d\t%d", & azim, & elev) != 2) {
341 logMsg(
"Line format: %s\n", lineBuffer);
347 hrtfPoints.push_back(cpt);
352 if (hrtfPoints.size() != nHRTFs) {
353 logMsg(
"Found %d positions ( ! = %d)", hrtfPoints.size(), nHRTFs);
358 int hdrSize = (int) ftell(dbFile);
359 for (
unsigned i = 0; i < nHRTFs; i++) {
362 hrtfPoints[i]->theta(),
363 hrtfPoints[i]->ele());
364 for (
unsigned b = 0; b < nBlocks; b++) {
367 if (nRead != mHRTFLength) {
369 perror(
"Error reading HRTF ");
370 throw IOError(
"Error reading HRTF");
373 if (nRead != mHRTFLength) {
375 perror(
"Error reading HRTF ");
376 throw IOError(
"Error reading HRTF");
379 mHRTFVector.push_back(hrtf);
381 int dataSize = (int) ftell(dbFile) - hdrSize;
382 fgets(lineBuffer, 1024, dbFile);
383 if (strncmp(lineBuffer,
"HRTF", 4) != 0)
384 logMsg(
"Error: Trailer format: %s\n", lineBuffer);
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());
408 for (
unsigned i = 0; i < numHRTFs(); i++)
409 mHRTFVector[i]->dump();
416 for (
unsigned i = 0; i < this->numHRTFs(); i++)
417 siz += mHRTFVector[i]->
size();
424 unsigned numHRTFs = this->numHRTFs();
429 return mHRTFVector[index];
436 double lowVal = 10000;
437 unsigned localHRTF = 0;
438 unsigned numHRTFs = this->numHRTFs();
445 for (
unsigned j = 0; j < numHRTFs - 1; j++) {
446 tmpVal = sPt.
distance2(mHRTFVector[j]->mPosition);
447 if (tmpVal < lowVal) {
458 return mHRTFVector.size();
482 return mHRIRLength / (windowSize() / 2);
496 unsigned numBlocks = hrirLength() / (windowSize() / 2);
497 unsigned num2Store = numHRTFs();
499 FILE * store = fopen(filename,
"w");
501 printf(
"Error saving HRTF DB - cannot open file\n");
504 fprintf(store,
"HRTF %s\t%d\t%d\t%d\t%d\n",
505 sname, num2Store, hrirLength(), hrtfLength(), numBlocks);
507 for (
unsigned j = 0; j < num2Store; j++) {
510 fprintf(store,
"%g\t%g\n",
514 fprintf(store,
"\n");
515 int hdrSize = (int) ftell(store);
517 for (
unsigned i = 0; i < num2Store; i++) {
520 HRTF * hrtf = mHRTFVector[i];
521 for (
unsigned b = 0; b < numBlocks; b++) {
529 int dataSize = (int) ftell(store) - hdrSize;
530 fprintf(store,
"HRTF\n");
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));
544 listFile = fopen(listname,
"r");
546 logMsg(
"Cannot open list file %s for reading.\n", listname);
549 while ( ! feof(listFile)) {
550 fgets(lineBuffer, 1024, listFile);
551 int len = strlen(lineBuffer) - 1;
552 if (lineBuffer[len] ==
'\n')
553 lineBuffer[
len] =
'\0';
554 logMsg(
"Read HRTF folder %s", lineBuffer);
555 sprintf(filename,
"%sIRCAM_HRTF/%s/",
559 logMsg(
"Loaded %d HRTF files = %4.1f MB",
563 char * cpos = strstr(filename,
"IRC_");
565 int index = atoi(cpos + 4);
566 sprintf(filename,
"%sIRCAM_HRTF/HRTF_%d.dat",
568 sprintf(tok,
"%d", index);
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
COORD_TYPE distance2(CPoint *)
void logMsg(const char *format,...)
These are the public logging messages.
SampleComplex * SampleComplexVector
complex vector
SampleComplexVector * mHrtfR
2 arrays of arrays of mNumFFTBlocks * complex[513]: the HRTF data in blocks of complex # for stereo ...
static HRTFDatabase * Database()
accessor for the singleton instance (lazy init)
void loadFromFolder(const char *folder)
virtual void setBuffer(unsigned bufNum, SampleBuffer sPtr)
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
unsigned numBlocks()
The length (in windows) of the impulse responses loaded.
unsigned hrtfLength()
The length (in samples) of the Transfer Function buffer.
#define HRTF_BLOCK_SIZE
BinauralDB.h – Specification of the HRTF file format and database This is the CSL 5 version that use...
unsigned hrirLength()
The length (in samples) of the impulse responses loaded.
CPoint mPosition
The Position at which the HRIR was recorded.
unsigned numHRTFs()
Total number of HRTFs loaded into the database.
static HRTFDatabase * mDatabase
The protected single instance of the HRTF Database.
#define FLIST_NAME
name of file list file
static void Reload(char *folder)
load the singleton from the given data folder
std::vector< CPoint * > PointVector
Forward declaration.
unsigned size()
returns the size on bytes of the receiver's storage
unsigned windowSize()
The size of the analysis window (in samples).
#define CSL_NAME_LEN
default string length
static void Destroy()
free the instance
HRTFDatabase: has a vector of HRTFs and can access them by position – hrtfAt(CPoint) – or by index ...
#define CSL_LINE_LEN
default line length
float sample
(could be changed to int, or double)
void loadFromDB(const char *dbName)
#define DEFAULT_HRTF_FOLDER
where are the HRTFs under the CSL_Data folder?
HRTF: holds the data that corresponds to an HRTF for a single position. It has a list of complex buff...
void storeToDB(const char *filename, const char *same)
SampleComplexVector * mHrtfL
unsigned hrtfAt(CPoint srcPos)
answer the index of the HRTF nearest the given point
void dump(bool verbose=false)
Print all the HRTFs in the database.
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
HRTFDatabase(const char *folder)
constructor that loads from a folder (protected) load a set of HRTFs from a folder or a file list fil...
void loadFromFile(const char *filename)
static void convertDB(const char *listname)
bulk-convert DBs
HRTF()
HRTF constructor allocates memory for the HRTF data and then reads the HRIR file and performs the blo...
void dump()
Prints the position that corresponds to this HRTF.
sample SampleComplex[2]
array-of-2 complex # type (like FFTW)
#define SAFE_MALLOC(ptr, type, len)
Useful Macros.
unsigned size()
returns the size on bytes of the receiver's storage
Base class of CSL exceptions (written upper-case). Has a string message.
static std::string dataFolder()
the default directory for test data