Make the bsinc table layout more efficient
[openal-soft.git] / utils / makehrtf.c
blob963528bb27fc7ee4db138b670727a56a8bdd18b5
1 /*
2 * HRTF utility for producing and demonstrating the process of creating an
3 * OpenAL Soft compatible HRIR data set.
5 * Copyright (C) 2011-2017 Christopher Fitzgerald
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * --------------------------------------------------------------------------
25 * A big thanks goes out to all those whose work done in the field of
26 * binaural sound synthesis using measured HRTFs makes this utility and the
27 * OpenAL Soft implementation possible.
29 * The algorithm for diffuse-field equalization was adapted from the work
30 * done by Rio Emmanuel and Larcher Veronique of IRCAM and Bill Gardner of
31 * MIT Media Laboratory. It operates as follows:
33 * 1. Take the FFT of each HRIR and only keep the magnitude responses.
34 * 2. Calculate the diffuse-field power-average of all HRIRs weighted by
35 * their contribution to the total surface area covered by their
36 * measurement.
37 * 3. Take the diffuse-field average and limit its magnitude range.
38 * 4. Equalize the responses by using the inverse of the diffuse-field
39 * average.
40 * 5. Reconstruct the minimum-phase responses.
41 * 5. Zero the DC component.
42 * 6. IFFT the result and truncate to the desired-length minimum-phase FIR.
44 * The spherical head algorithm for calculating propagation delay was adapted
45 * from the paper:
47 * Modeling Interaural Time Difference Assuming a Spherical Head
48 * Joel David Miller
49 * Music 150, Musical Acoustics, Stanford University
50 * December 2, 2001
52 * The formulae for calculating the Kaiser window metrics are from the
53 * the textbook:
55 * Discrete-Time Signal Processing
56 * Alan V. Oppenheim and Ronald W. Schafer
57 * Prentice-Hall Signal Processing Series
58 * 1999
61 #include "config.h"
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <stdarg.h>
66 #include <string.h>
67 #include <limits.h>
68 #include <ctype.h>
69 #include <math.h>
70 #ifdef HAVE_STRINGS_H
71 #include <strings.h>
72 #endif
74 // Rely (if naively) on OpenAL's header for the types used for serialization.
75 #include "AL/al.h"
76 #include "AL/alext.h"
78 #ifndef M_PI
79 #define M_PI (3.14159265358979323846)
80 #endif
82 #ifndef HUGE_VAL
83 #define HUGE_VAL (1.0 / 0.0)
84 #endif
86 // The epsilon used to maintain signal stability.
87 #define EPSILON (1e-9)
89 // Constants for accessing the token reader's ring buffer.
90 #define TR_RING_BITS (16)
91 #define TR_RING_SIZE (1 << TR_RING_BITS)
92 #define TR_RING_MASK (TR_RING_SIZE - 1)
94 // The token reader's load interval in bytes.
95 #define TR_LOAD_SIZE (TR_RING_SIZE >> 2)
97 // The maximum identifier length used when processing the data set
98 // definition.
99 #define MAX_IDENT_LEN (16)
101 // The maximum path length used when processing filenames.
102 #define MAX_PATH_LEN (256)
104 // The limits for the sample 'rate' metric in the data set definition and for
105 // resampling.
106 #define MIN_RATE (32000)
107 #define MAX_RATE (96000)
109 // The limits for the HRIR 'points' metric in the data set definition.
110 #define MIN_POINTS (16)
111 #define MAX_POINTS (8192)
113 // The limits to the number of 'azimuths' listed in the data set definition.
114 #define MIN_EV_COUNT (5)
115 #define MAX_EV_COUNT (128)
117 // The limits for each of the 'azimuths' listed in the data set definition.
118 #define MIN_AZ_COUNT (1)
119 #define MAX_AZ_COUNT (128)
121 // The limits for the listener's head 'radius' in the data set definition.
122 #define MIN_RADIUS (0.05)
123 #define MAX_RADIUS (0.15)
125 // The limits for the 'distance' from source to listener in the definition
126 // file.
127 #define MIN_DISTANCE (0.5)
128 #define MAX_DISTANCE (2.5)
130 // The maximum number of channels that can be addressed for a WAVE file
131 // source listed in the data set definition.
132 #define MAX_WAVE_CHANNELS (65535)
134 // The limits to the byte size for a binary source listed in the definition
135 // file.
136 #define MIN_BIN_SIZE (2)
137 #define MAX_BIN_SIZE (4)
139 // The minimum number of significant bits for binary sources listed in the
140 // data set definition. The maximum is calculated from the byte size.
141 #define MIN_BIN_BITS (16)
143 // The limits to the number of significant bits for an ASCII source listed in
144 // the data set definition.
145 #define MIN_ASCII_BITS (16)
146 #define MAX_ASCII_BITS (32)
148 // The limits to the FFT window size override on the command line.
149 #define MIN_FFTSIZE (65536)
150 #define MAX_FFTSIZE (131072)
152 // The limits to the equalization range limit on the command line.
153 #define MIN_LIMIT (2.0)
154 #define MAX_LIMIT (120.0)
156 // The limits to the truncation window size on the command line.
157 #define MIN_TRUNCSIZE (16)
158 #define MAX_TRUNCSIZE (512)
160 // The limits to the custom head radius on the command line.
161 #define MIN_CUSTOM_RADIUS (0.05)
162 #define MAX_CUSTOM_RADIUS (0.15)
164 // The truncation window size must be a multiple of the below value to allow
165 // for vectorized convolution.
166 #define MOD_TRUNCSIZE (8)
168 // The defaults for the command line options.
169 #define DEFAULT_FFTSIZE (65536)
170 #define DEFAULT_EQUALIZE (1)
171 #define DEFAULT_SURFACE (1)
172 #define DEFAULT_LIMIT (24.0)
173 #define DEFAULT_TRUNCSIZE (32)
174 #define DEFAULT_HEAD_MODEL (HM_DATASET)
175 #define DEFAULT_CUSTOM_RADIUS (0.0)
177 // The four-character-codes for RIFF/RIFX WAVE file chunks.
178 #define FOURCC_RIFF (0x46464952) // 'RIFF'
179 #define FOURCC_RIFX (0x58464952) // 'RIFX'
180 #define FOURCC_WAVE (0x45564157) // 'WAVE'
181 #define FOURCC_FMT (0x20746D66) // 'fmt '
182 #define FOURCC_DATA (0x61746164) // 'data'
183 #define FOURCC_LIST (0x5453494C) // 'LIST'
184 #define FOURCC_WAVL (0x6C766177) // 'wavl'
185 #define FOURCC_SLNT (0x746E6C73) // 'slnt'
187 // The supported wave formats.
188 #define WAVE_FORMAT_PCM (0x0001)
189 #define WAVE_FORMAT_IEEE_FLOAT (0x0003)
190 #define WAVE_FORMAT_EXTENSIBLE (0xFFFE)
192 // The maximum propagation delay value supported by OpenAL Soft.
193 #define MAX_HRTD (63.0)
195 // The OpenAL Soft HRTF format marker. It stands for minimum-phase head
196 // response protocol 01.
197 #define MHR_FORMAT ("MinPHR01")
199 #define MHR_FORMAT_EXPERIMENTAL ("MinPHRTEMPDONOTUSE")
201 // Sample and channel type enum values
202 typedef enum SampleTypeT {
203 ST_S16 = 0,
204 ST_S24 = 1
205 } SampleTypeT;
207 typedef enum ChannelTypeT {
208 CT_LEFTONLY = 0,
209 CT_LEFTRIGHT = 1
210 } ChannelTypeT;
212 // Byte order for the serialization routines.
213 typedef enum ByteOrderT {
214 BO_NONE,
215 BO_LITTLE,
216 BO_BIG
217 } ByteOrderT;
219 // Source format for the references listed in the data set definition.
220 typedef enum SourceFormatT {
221 SF_NONE,
222 SF_WAVE, // RIFF/RIFX WAVE file.
223 SF_BIN_LE, // Little-endian binary file.
224 SF_BIN_BE, // Big-endian binary file.
225 SF_ASCII // ASCII text file.
226 } SourceFormatT;
228 // Element types for the references listed in the data set definition.
229 typedef enum ElementTypeT {
230 ET_NONE,
231 ET_INT, // Integer elements.
232 ET_FP // Floating-point elements.
233 } ElementTypeT;
235 // Head model used for calculating the impulse delays.
236 typedef enum HeadModelT {
237 HM_NONE,
238 HM_DATASET, // Measure the onset from the dataset.
239 HM_SPHERE // Calculate the onset using a spherical head model.
240 } HeadModelT;
242 // Desired output format from the command line.
243 typedef enum OutputFormatT {
244 OF_NONE,
245 OF_MHR // OpenAL Soft MHR data set file.
246 } OutputFormatT;
248 // Unsigned integer type.
249 typedef unsigned int uint;
251 // Serialization types. The trailing digit indicates the number of bits.
252 typedef ALubyte uint8;
253 typedef ALint int32;
254 typedef ALuint uint32;
255 typedef ALuint64SOFT uint64;
257 // Token reader state for parsing the data set definition.
258 typedef struct TokenReaderT {
259 FILE *mFile;
260 const char *mName;
261 uint mLine;
262 uint mColumn;
263 char mRing[TR_RING_SIZE];
264 size_t mIn;
265 size_t mOut;
266 } TokenReaderT;
268 // Source reference state used when loading sources.
269 typedef struct SourceRefT {
270 SourceFormatT mFormat;
271 ElementTypeT mType;
272 uint mSize;
273 int mBits;
274 uint mChannel;
275 uint mSkip;
276 uint mOffset;
277 char mPath[MAX_PATH_LEN+1];
278 } SourceRefT;
280 // The HRIR metrics and data set used when loading, processing, and storing
281 // the resulting HRTF.
282 typedef struct HrirDataT {
283 uint mIrRate;
284 SampleTypeT mSampleType;
285 ChannelTypeT mChannelType;
286 uint mIrCount;
287 uint mIrSize;
288 uint mIrPoints;
289 uint mFftSize;
290 uint mEvCount;
291 uint mEvStart;
292 uint mAzCount[MAX_EV_COUNT];
293 uint mEvOffset[MAX_EV_COUNT];
294 double mRadius;
295 double mDistance;
296 double *mHrirs;
297 double *mHrtds;
298 double mMaxHrtd;
299 } HrirDataT;
301 // The resampler metrics and FIR filter.
302 typedef struct ResamplerT {
303 uint mP, mQ, mM, mL;
304 double *mF;
305 } ResamplerT;
308 /*****************************
309 *** Token reader routines ***
310 *****************************/
312 /* Whitespace is not significant. It can process tokens as identifiers, numbers
313 * (integer and floating-point), strings, and operators. Strings must be
314 * encapsulated by double-quotes and cannot span multiple lines.
317 // Setup the reader on the given file. The filename can be NULL if no error
318 // output is desired.
319 static void TrSetup(FILE *fp, const char *filename, TokenReaderT *tr)
321 const char *name = NULL;
323 if(filename)
325 const char *slash = strrchr(filename, '/');
326 if(slash)
328 const char *bslash = strrchr(slash+1, '\\');
329 if(bslash) name = bslash+1;
330 else name = slash+1;
332 else
334 const char *bslash = strrchr(filename, '\\');
335 if(bslash) name = bslash+1;
336 else name = filename;
340 tr->mFile = fp;
341 tr->mName = name;
342 tr->mLine = 1;
343 tr->mColumn = 1;
344 tr->mIn = 0;
345 tr->mOut = 0;
348 // Prime the reader's ring buffer, and return a result indicating that there
349 // is text to process.
350 static int TrLoad(TokenReaderT *tr)
352 size_t toLoad, in, count;
354 toLoad = TR_RING_SIZE - (tr->mIn - tr->mOut);
355 if(toLoad >= TR_LOAD_SIZE && !feof(tr->mFile))
357 // Load TR_LOAD_SIZE (or less if at the end of the file) per read.
358 toLoad = TR_LOAD_SIZE;
359 in = tr->mIn&TR_RING_MASK;
360 count = TR_RING_SIZE - in;
361 if(count < toLoad)
363 tr->mIn += fread(&tr->mRing[in], 1, count, tr->mFile);
364 tr->mIn += fread(&tr->mRing[0], 1, toLoad-count, tr->mFile);
366 else
367 tr->mIn += fread(&tr->mRing[in], 1, toLoad, tr->mFile);
369 if(tr->mOut >= TR_RING_SIZE)
371 tr->mOut -= TR_RING_SIZE;
372 tr->mIn -= TR_RING_SIZE;
375 if(tr->mIn > tr->mOut)
376 return 1;
377 return 0;
380 // Error display routine. Only displays when the base name is not NULL.
381 static void TrErrorVA(const TokenReaderT *tr, uint line, uint column, const char *format, va_list argPtr)
383 if(!tr->mName)
384 return;
385 fprintf(stderr, "Error (%s:%u:%u): ", tr->mName, line, column);
386 vfprintf(stderr, format, argPtr);
389 // Used to display an error at a saved line/column.
390 static void TrErrorAt(const TokenReaderT *tr, uint line, uint column, const char *format, ...)
392 va_list argPtr;
394 va_start(argPtr, format);
395 TrErrorVA(tr, line, column, format, argPtr);
396 va_end(argPtr);
399 // Used to display an error at the current line/column.
400 static void TrError(const TokenReaderT *tr, const char *format, ...)
402 va_list argPtr;
404 va_start(argPtr, format);
405 TrErrorVA(tr, tr->mLine, tr->mColumn, format, argPtr);
406 va_end(argPtr);
409 // Skips to the next line.
410 static void TrSkipLine(TokenReaderT *tr)
412 char ch;
414 while(TrLoad(tr))
416 ch = tr->mRing[tr->mOut&TR_RING_MASK];
417 tr->mOut++;
418 if(ch == '\n')
420 tr->mLine++;
421 tr->mColumn = 1;
422 break;
424 tr->mColumn ++;
428 // Skips to the next token.
429 static int TrSkipWhitespace(TokenReaderT *tr)
431 char ch;
433 while(TrLoad(tr))
435 ch = tr->mRing[tr->mOut&TR_RING_MASK];
436 if(isspace(ch))
438 tr->mOut++;
439 if(ch == '\n')
441 tr->mLine++;
442 tr->mColumn = 1;
444 else
445 tr->mColumn++;
447 else if(ch == '#')
448 TrSkipLine(tr);
449 else
450 return 1;
452 return 0;
455 // Get the line and/or column of the next token (or the end of input).
456 static void TrIndication(TokenReaderT *tr, uint *line, uint *column)
458 TrSkipWhitespace(tr);
459 if(line) *line = tr->mLine;
460 if(column) *column = tr->mColumn;
463 // Checks to see if a token is the given operator. It does not display any
464 // errors and will not proceed to the next token.
465 static int TrIsOperator(TokenReaderT *tr, const char *op)
467 size_t out, len;
468 char ch;
470 if(!TrSkipWhitespace(tr))
471 return 0;
472 out = tr->mOut;
473 len = 0;
474 while(op[len] != '\0' && out < tr->mIn)
476 ch = tr->mRing[out&TR_RING_MASK];
477 if(ch != op[len]) break;
478 len++;
479 out++;
481 if(op[len] == '\0')
482 return 1;
483 return 0;
486 /* The TrRead*() routines obtain the value of a matching token type. They
487 * display type, form, and boundary errors and will proceed to the next
488 * token.
491 // Reads and validates an identifier token.
492 static int TrReadIdent(TokenReaderT *tr, const uint maxLen, char *ident)
494 uint col, len;
495 char ch;
497 col = tr->mColumn;
498 if(TrSkipWhitespace(tr))
500 col = tr->mColumn;
501 ch = tr->mRing[tr->mOut&TR_RING_MASK];
502 if(ch == '_' || isalpha(ch))
504 len = 0;
505 do {
506 if(len < maxLen)
507 ident[len] = ch;
508 len++;
509 tr->mOut++;
510 if(!TrLoad(tr))
511 break;
512 ch = tr->mRing[tr->mOut&TR_RING_MASK];
513 } while(ch == '_' || isdigit(ch) || isalpha(ch));
515 tr->mColumn += len;
516 if(len < maxLen)
518 ident[len] = '\0';
519 return 1;
521 TrErrorAt(tr, tr->mLine, col, "Identifier is too long.\n");
522 return 0;
525 TrErrorAt(tr, tr->mLine, col, "Expected an identifier.\n");
526 return 0;
529 // Reads and validates (including bounds) an integer token.
530 static int TrReadInt(TokenReaderT *tr, const int loBound, const int hiBound, int *value)
532 uint col, digis, len;
533 char ch, temp[64+1];
535 col = tr->mColumn;
536 if(TrSkipWhitespace(tr))
538 col = tr->mColumn;
539 len = 0;
540 ch = tr->mRing[tr->mOut&TR_RING_MASK];
541 if(ch == '+' || ch == '-')
543 temp[len] = ch;
544 len++;
545 tr->mOut++;
547 digis = 0;
548 while(TrLoad(tr))
550 ch = tr->mRing[tr->mOut&TR_RING_MASK];
551 if(!isdigit(ch)) break;
552 if(len < 64)
553 temp[len] = ch;
554 len++;
555 digis++;
556 tr->mOut++;
558 tr->mColumn += len;
559 if(digis > 0 && ch != '.' && !isalpha(ch))
561 if(len > 64)
563 TrErrorAt(tr, tr->mLine, col, "Integer is too long.");
564 return 0;
566 temp[len] = '\0';
567 *value = strtol(temp, NULL, 10);
568 if(*value < loBound || *value > hiBound)
570 TrErrorAt(tr, tr->mLine, col, "Expected a value from %d to %d.\n", loBound, hiBound);
571 return (0);
573 return (1);
576 TrErrorAt(tr, tr->mLine, col, "Expected an integer.\n");
577 return 0;
580 // Reads and validates (including bounds) a float token.
581 static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBound, double *value)
583 uint col, digis, len;
584 char ch, temp[64+1];
586 col = tr->mColumn;
587 if(TrSkipWhitespace(tr))
589 col = tr->mColumn;
590 len = 0;
591 ch = tr->mRing[tr->mOut&TR_RING_MASK];
592 if(ch == '+' || ch == '-')
594 temp[len] = ch;
595 len++;
596 tr->mOut++;
599 digis = 0;
600 while(TrLoad(tr))
602 ch = tr->mRing[tr->mOut&TR_RING_MASK];
603 if(!isdigit(ch)) break;
604 if(len < 64)
605 temp[len] = ch;
606 len++;
607 digis++;
608 tr->mOut++;
610 if(ch == '.')
612 if(len < 64)
613 temp[len] = ch;
614 len++;
615 tr->mOut++;
617 while(TrLoad(tr))
619 ch = tr->mRing[tr->mOut&TR_RING_MASK];
620 if(!isdigit(ch)) break;
621 if(len < 64)
622 temp[len] = ch;
623 len++;
624 digis++;
625 tr->mOut++;
627 if(digis > 0)
629 if(ch == 'E' || ch == 'e')
631 if(len < 64)
632 temp[len] = ch;
633 len++;
634 digis = 0;
635 tr->mOut++;
636 if(ch == '+' || ch == '-')
638 if(len < 64)
639 temp[len] = ch;
640 len++;
641 tr->mOut++;
643 while(TrLoad(tr))
645 ch = tr->mRing[tr->mOut&TR_RING_MASK];
646 if(!isdigit(ch)) break;
647 if(len < 64)
648 temp[len] = ch;
649 len++;
650 digis++;
651 tr->mOut++;
654 tr->mColumn += len;
655 if(digis > 0 && ch != '.' && !isalpha(ch))
657 if(len > 64)
659 TrErrorAt(tr, tr->mLine, col, "Float is too long.");
660 return 0;
662 temp[len] = '\0';
663 *value = strtod(temp, NULL);
664 if(*value < loBound || *value > hiBound)
666 TrErrorAt (tr, tr->mLine, col, "Expected a value from %f to %f.\n", loBound, hiBound);
667 return 0;
669 return 1;
672 else
673 tr->mColumn += len;
675 TrErrorAt(tr, tr->mLine, col, "Expected a float.\n");
676 return 0;
679 // Reads and validates a string token.
680 static int TrReadString(TokenReaderT *tr, const uint maxLen, char *text)
682 uint col, len;
683 char ch;
685 col = tr->mColumn;
686 if(TrSkipWhitespace(tr))
688 col = tr->mColumn;
689 ch = tr->mRing[tr->mOut&TR_RING_MASK];
690 if(ch == '\"')
692 tr->mOut++;
693 len = 0;
694 while(TrLoad(tr))
696 ch = tr->mRing[tr->mOut&TR_RING_MASK];
697 tr->mOut++;
698 if(ch == '\"')
699 break;
700 if(ch == '\n')
702 TrErrorAt (tr, tr->mLine, col, "Unterminated string at end of line.\n");
703 return 0;
705 if(len < maxLen)
706 text[len] = ch;
707 len++;
709 if(ch != '\"')
711 tr->mColumn += 1 + len;
712 TrErrorAt(tr, tr->mLine, col, "Unterminated string at end of input.\n");
713 return 0;
715 tr->mColumn += 2 + len;
716 if(len > maxLen)
718 TrErrorAt (tr, tr->mLine, col, "String is too long.\n");
719 return 0;
721 text[len] = '\0';
722 return 1;
725 TrErrorAt(tr, tr->mLine, col, "Expected a string.\n");
726 return 0;
729 // Reads and validates the given operator.
730 static int TrReadOperator(TokenReaderT *tr, const char *op)
732 uint col, len;
733 char ch;
735 col = tr->mColumn;
736 if(TrSkipWhitespace(tr))
738 col = tr->mColumn;
739 len = 0;
740 while(op[len] != '\0' && TrLoad(tr))
742 ch = tr->mRing[tr->mOut&TR_RING_MASK];
743 if(ch != op[len]) break;
744 len++;
745 tr->mOut++;
747 tr->mColumn += len;
748 if(op[len] == '\0')
749 return 1;
751 TrErrorAt(tr, tr->mLine, col, "Expected '%s' operator.\n", op);
752 return 0;
755 /* Performs a string substitution. Any case-insensitive occurrences of the
756 * pattern string are replaced with the replacement string. The result is
757 * truncated if necessary.
759 static int StrSubst(const char *in, const char *pat, const char *rep, const size_t maxLen, char *out)
761 size_t inLen, patLen, repLen;
762 size_t si, di;
763 int truncated;
765 inLen = strlen(in);
766 patLen = strlen(pat);
767 repLen = strlen(rep);
768 si = 0;
769 di = 0;
770 truncated = 0;
771 while(si < inLen && di < maxLen)
773 if(patLen <= inLen-si)
775 if(strncasecmp(&in[si], pat, patLen) == 0)
777 if(repLen > maxLen-di)
779 repLen = maxLen - di;
780 truncated = 1;
782 strncpy(&out[di], rep, repLen);
783 si += patLen;
784 di += repLen;
787 out[di] = in[si];
788 si++;
789 di++;
791 if(si < inLen)
792 truncated = 1;
793 out[di] = '\0';
794 return !truncated;
798 /*********************
799 *** Math routines ***
800 *********************/
802 // Provide missing math routines for MSVC versions < 1800 (Visual Studio 2013).
803 #if defined(_MSC_VER) && _MSC_VER < 1800
804 static double round(double val)
806 if(val < 0.0)
807 return ceil(val-0.5);
808 return floor(val+0.5);
811 static double fmin(double a, double b)
813 return (a<b) ? a : b;
816 static double fmax(double a, double b)
818 return (a>b) ? a : b;
820 #endif
822 // Simple clamp routine.
823 static double Clamp(const double val, const double lower, const double upper)
825 return fmin(fmax(val, lower), upper);
828 // Performs linear interpolation.
829 static double Lerp(const double a, const double b, const double f)
831 return a + (f * (b - a));
834 static inline uint dither_rng(uint *seed)
836 *seed = (*seed * 96314165) + 907633515;
837 return *seed;
840 // Performs a triangular probability density function dither. It assumes the
841 // input sample is already scaled.
842 static inline double TpdfDither(const double in, uint *seed)
844 static const double PRNG_SCALE = 1.0 / UINT_MAX;
845 uint prn0, prn1;
847 prn0 = dither_rng(seed);
848 prn1 = dither_rng(seed);
849 return round(in + (prn0*PRNG_SCALE - prn1*PRNG_SCALE));
852 // Allocates an array of doubles.
853 static double *CreateArray(size_t n)
855 double *a;
857 if(n == 0) n = 1;
858 a = calloc(n, sizeof(double));
859 if(a == NULL)
861 fprintf(stderr, "Error: Out of memory.\n");
862 exit(-1);
864 return a;
867 // Frees an array of doubles.
868 static void DestroyArray(double *a)
869 { free(a); }
871 // Complex number routines. All outputs must be non-NULL.
873 // Magnitude/absolute value.
874 static double ComplexAbs(const double r, const double i)
876 return sqrt(r*r + i*i);
879 // Multiply.
880 static void ComplexMul(const double aR, const double aI, const double bR, const double bI, double *outR, double *outI)
882 *outR = (aR * bR) - (aI * bI);
883 *outI = (aI * bR) + (aR * bI);
886 // Base-e exponent.
887 static void ComplexExp(const double inR, const double inI, double *outR, double *outI)
889 double e = exp(inR);
890 *outR = e * cos(inI);
891 *outI = e * sin(inI);
894 /* Fast Fourier transform routines. The number of points must be a power of
895 * two. In-place operation is possible only if both the real and imaginary
896 * parts are in-place together.
899 // Performs bit-reversal ordering.
900 static void FftArrange(const uint n, const double *inR, const double *inI, double *outR, double *outI)
902 uint rk, k, m;
903 double tempR, tempI;
905 if(inR == outR && inI == outI)
907 // Handle in-place arrangement.
908 rk = 0;
909 for(k = 0;k < n;k++)
911 if(rk > k)
913 tempR = inR[rk];
914 tempI = inI[rk];
915 outR[rk] = inR[k];
916 outI[rk] = inI[k];
917 outR[k] = tempR;
918 outI[k] = tempI;
920 m = n;
921 while(rk&(m >>= 1))
922 rk &= ~m;
923 rk |= m;
926 else
928 // Handle copy arrangement.
929 rk = 0;
930 for(k = 0;k < n;k++)
932 outR[rk] = inR[k];
933 outI[rk] = inI[k];
934 m = n;
935 while(rk&(m >>= 1))
936 rk &= ~m;
937 rk |= m;
942 // Performs the summation.
943 static void FftSummation(const uint n, const double s, double *re, double *im)
945 double pi;
946 uint m, m2;
947 double vR, vI, wR, wI;
948 uint i, k, mk;
949 double tR, tI;
951 pi = s * M_PI;
952 for(m = 1, m2 = 2;m < n; m <<= 1, m2 <<= 1)
954 // v = Complex (-2.0 * sin (0.5 * pi / m) * sin (0.5 * pi / m), -sin (pi / m))
955 vR = sin(0.5 * pi / m);
956 vR = -2.0 * vR * vR;
957 vI = -sin(pi / m);
958 // w = Complex (1.0, 0.0)
959 wR = 1.0;
960 wI = 0.0;
961 for(i = 0;i < m;i++)
963 for(k = i;k < n;k += m2)
965 mk = k + m;
966 // t = ComplexMul(w, out[km2])
967 tR = (wR * re[mk]) - (wI * im[mk]);
968 tI = (wR * im[mk]) + (wI * re[mk]);
969 // out[mk] = ComplexSub (out [k], t)
970 re[mk] = re[k] - tR;
971 im[mk] = im[k] - tI;
972 // out[k] = ComplexAdd (out [k], t)
973 re[k] += tR;
974 im[k] += tI;
976 // t = ComplexMul (v, w)
977 tR = (vR * wR) - (vI * wI);
978 tI = (vR * wI) + (vI * wR);
979 // w = ComplexAdd (w, t)
980 wR += tR;
981 wI += tI;
986 // Performs a forward FFT.
987 static void FftForward(const uint n, const double *inR, const double *inI, double *outR, double *outI)
989 FftArrange(n, inR, inI, outR, outI);
990 FftSummation(n, 1.0, outR, outI);
993 // Performs an inverse FFT.
994 static void FftInverse(const uint n, const double *inR, const double *inI, double *outR, double *outI)
996 double f;
997 uint i;
999 FftArrange(n, inR, inI, outR, outI);
1000 FftSummation(n, -1.0, outR, outI);
1001 f = 1.0 / n;
1002 for(i = 0;i < n;i++)
1004 outR[i] *= f;
1005 outI[i] *= f;
1009 /* Calculate the complex helical sequence (or discrete-time analytical signal)
1010 * of the given input using the Hilbert transform. Given the natural logarithm
1011 * of a signal's magnitude response, the imaginary components can be used as
1012 * the angles for minimum-phase reconstruction.
1014 static void Hilbert(const uint n, const double *in, double *outR, double *outI)
1016 uint i;
1018 if(in == outR)
1020 // Handle in-place operation.
1021 for(i = 0;i < n;i++)
1022 outI[i] = 0.0;
1024 else
1026 // Handle copy operation.
1027 for(i = 0;i < n;i++)
1029 outR[i] = in[i];
1030 outI[i] = 0.0;
1033 FftInverse(n, outR, outI, outR, outI);
1034 for(i = 1;i < (n+1)/2;i++)
1036 outR[i] *= 2.0;
1037 outI[i] *= 2.0;
1039 /* Increment i if n is even. */
1040 i += (n&1)^1;
1041 for(;i < n;i++)
1043 outR[i] = 0.0;
1044 outI[i] = 0.0;
1046 FftForward(n, outR, outI, outR, outI);
1049 /* Calculate the magnitude response of the given input. This is used in
1050 * place of phase decomposition, since the phase residuals are discarded for
1051 * minimum phase reconstruction. The mirrored half of the response is also
1052 * discarded.
1054 static void MagnitudeResponse(const uint n, const double *inR, const double *inI, double *out)
1056 const uint m = 1 + (n / 2);
1057 uint i;
1058 for(i = 0;i < m;i++)
1059 out[i] = fmax(ComplexAbs(inR[i], inI[i]), EPSILON);
1062 /* Apply a range limit (in dB) to the given magnitude response. This is used
1063 * to adjust the effects of the diffuse-field average on the equalization
1064 * process.
1066 static void LimitMagnitudeResponse(const uint n, const double limit, const double *in, double *out)
1068 const uint m = 1 + (n / 2);
1069 double halfLim;
1070 uint i, lower, upper;
1071 double ave;
1073 halfLim = limit / 2.0;
1074 // Convert the response to dB.
1075 for(i = 0;i < m;i++)
1076 out[i] = 20.0 * log10(in[i]);
1077 // Use six octaves to calculate the average magnitude of the signal.
1078 lower = ((uint)ceil(n / pow(2.0, 8.0))) - 1;
1079 upper = ((uint)floor(n / pow(2.0, 2.0))) - 1;
1080 ave = 0.0;
1081 for(i = lower;i <= upper;i++)
1082 ave += out[i];
1083 ave /= upper - lower + 1;
1084 // Keep the response within range of the average magnitude.
1085 for(i = 0;i < m;i++)
1086 out[i] = Clamp(out[i], ave - halfLim, ave + halfLim);
1087 // Convert the response back to linear magnitude.
1088 for(i = 0;i < m;i++)
1089 out[i] = pow(10.0, out[i] / 20.0);
1092 /* Reconstructs the minimum-phase component for the given magnitude response
1093 * of a signal. This is equivalent to phase recomposition, sans the missing
1094 * residuals (which were discarded). The mirrored half of the response is
1095 * reconstructed.
1097 static void MinimumPhase(const uint n, const double *in, double *outR, double *outI)
1099 const uint m = 1 + (n / 2);
1100 double *mags;
1101 double aR, aI;
1102 uint i;
1104 mags = CreateArray(n);
1105 for(i = 0;i < m;i++)
1107 mags[i] = fmax(EPSILON, in[i]);
1108 outR[i] = log(mags[i]);
1110 for(;i < n;i++)
1112 mags[i] = mags[n - i];
1113 outR[i] = outR[n - i];
1115 Hilbert(n, outR, outR, outI);
1116 // Remove any DC offset the filter has.
1117 mags[0] = EPSILON;
1118 for(i = 0;i < n;i++)
1120 ComplexExp(0.0, outI[i], &aR, &aI);
1121 ComplexMul(mags[i], 0.0, aR, aI, &outR[i], &outI[i]);
1123 DestroyArray(mags);
1127 /***************************
1128 *** Resampler functions ***
1129 ***************************/
1131 /* This is the normalized cardinal sine (sinc) function.
1133 * sinc(x) = { 1, x = 0
1134 * { sin(pi x) / (pi x), otherwise.
1136 static double Sinc(const double x)
1138 if(fabs(x) < EPSILON)
1139 return 1.0;
1140 return sin(M_PI * x) / (M_PI * x);
1143 /* The zero-order modified Bessel function of the first kind, used for the
1144 * Kaiser window.
1146 * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
1147 * = sum_{k=0}^inf ((x / 2)^k / k!)^2
1149 static double BesselI_0(const double x)
1151 double term, sum, x2, y, last_sum;
1152 int k;
1154 // Start at k=1 since k=0 is trivial.
1155 term = 1.0;
1156 sum = 1.0;
1157 x2 = x/2.0;
1158 k = 1;
1160 // Let the integration converge until the term of the sum is no longer
1161 // significant.
1162 do {
1163 y = x2 / k;
1164 k++;
1165 last_sum = sum;
1166 term *= y * y;
1167 sum += term;
1168 } while(sum != last_sum);
1169 return sum;
1172 /* Calculate a Kaiser window from the given beta value and a normalized k
1173 * [-1, 1].
1175 * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
1176 * { 0, elsewhere.
1178 * Where k can be calculated as:
1180 * k = i / l, where -l <= i <= l.
1182 * or:
1184 * k = 2 i / M - 1, where 0 <= i <= M.
1186 static double Kaiser(const double b, const double k)
1188 if(!(k >= -1.0 && k <= 1.0))
1189 return 0.0;
1190 return BesselI_0(b * sqrt(1.0 - k*k)) / BesselI_0(b);
1193 // Calculates the greatest common divisor of a and b.
1194 static uint Gcd(uint x, uint y)
1196 while(y > 0)
1198 uint z = y;
1199 y = x % y;
1200 x = z;
1202 return x;
1205 /* Calculates the size (order) of the Kaiser window. Rejection is in dB and
1206 * the transition width is normalized frequency (0.5 is nyquist).
1208 * M = { ceil((r - 7.95) / (2.285 2 pi f_t)), r > 21
1209 * { ceil(5.79 / 2 pi f_t), r <= 21.
1212 static uint CalcKaiserOrder(const double rejection, const double transition)
1214 double w_t = 2.0 * M_PI * transition;
1215 if(rejection > 21.0)
1216 return (uint)ceil((rejection - 7.95) / (2.285 * w_t));
1217 return (uint)ceil(5.79 / w_t);
1220 // Calculates the beta value of the Kaiser window. Rejection is in dB.
1221 static double CalcKaiserBeta(const double rejection)
1223 if(rejection > 50.0)
1224 return 0.1102 * (rejection - 8.7);
1225 if(rejection >= 21.0)
1226 return (0.5842 * pow(rejection - 21.0, 0.4)) +
1227 (0.07886 * (rejection - 21.0));
1228 return 0.0;
1231 /* Calculates a point on the Kaiser-windowed sinc filter for the given half-
1232 * width, beta, gain, and cutoff. The point is specified in non-normalized
1233 * samples, from 0 to M, where M = (2 l + 1).
1235 * w(k) 2 p f_t sinc(2 f_t x)
1237 * x -- centered sample index (i - l)
1238 * k -- normalized and centered window index (x / l)
1239 * w(k) -- window function (Kaiser)
1240 * p -- gain compensation factor when sampling
1241 * f_t -- normalized center frequency (or cutoff; 0.5 is nyquist)
1243 static double SincFilter(const int l, const double b, const double gain, const double cutoff, const int i)
1245 return Kaiser(b, (double)(i - l) / l) * 2.0 * gain * cutoff * Sinc(2.0 * cutoff * (i - l));
1248 /* This is a polyphase sinc-filtered resampler.
1250 * Upsample Downsample
1252 * p/q = 3/2 p/q = 3/5
1254 * M-+-+-+-> M-+-+-+->
1255 * -------------------+ ---------------------+
1256 * p s * f f f f|f| | p s * f f f f f |
1257 * | 0 * 0 0 0|0|0 | | 0 * 0 0 0 0|0| |
1258 * v 0 * 0 0|0|0 0 | v 0 * 0 0 0|0|0 |
1259 * s * f|f|f f f | s * f f|f|f f |
1260 * 0 * |0|0 0 0 0 | 0 * 0|0|0 0 0 |
1261 * --------+=+--------+ 0 * |0|0 0 0 0 |
1262 * d . d .|d|. d . d ----------+=+--------+
1263 * d . . . .|d|. . . .
1264 * q->
1265 * q-+-+-+->
1267 * P_f(i,j) = q i mod p + pj
1268 * P_s(i,j) = floor(q i / p) - j
1269 * d[i=0..N-1] = sum_{j=0}^{floor((M - 1) / p)} {
1270 * { f[P_f(i,j)] s[P_s(i,j)], P_f(i,j) < M
1271 * { 0, P_f(i,j) >= M. }
1274 // Calculate the resampling metrics and build the Kaiser-windowed sinc filter
1275 // that's used to cut frequencies above the destination nyquist.
1276 static void ResamplerSetup(ResamplerT *rs, const uint srcRate, const uint dstRate)
1278 double cutoff, width, beta;
1279 uint gcd, l;
1280 int i;
1282 gcd = Gcd(srcRate, dstRate);
1283 rs->mP = dstRate / gcd;
1284 rs->mQ = srcRate / gcd;
1285 /* The cutoff is adjusted by half the transition width, so the transition
1286 * ends before the nyquist (0.5). Both are scaled by the downsampling
1287 * factor.
1289 if(rs->mP > rs->mQ)
1291 cutoff = 0.475 / rs->mP;
1292 width = 0.05 / rs->mP;
1294 else
1296 cutoff = 0.475 / rs->mQ;
1297 width = 0.05 / rs->mQ;
1299 // A rejection of -180 dB is used for the stop band.
1300 l = CalcKaiserOrder(180.0, width) / 2;
1301 beta = CalcKaiserBeta(180.0);
1302 rs->mM = (2 * l) + 1;
1303 rs->mL = l;
1304 rs->mF = CreateArray(rs->mM);
1305 for(i = 0;i < ((int)rs->mM);i++)
1306 rs->mF[i] = SincFilter((int)l, beta, rs->mP, cutoff, i);
1309 // Clean up after the resampler.
1310 static void ResamplerClear(ResamplerT *rs)
1312 DestroyArray(rs->mF);
1313 rs->mF = NULL;
1316 // Perform the upsample-filter-downsample resampling operation using a
1317 // polyphase filter implementation.
1318 static void ResamplerRun(ResamplerT *rs, const uint inN, const double *in, const uint outN, double *out)
1320 const uint p = rs->mP, q = rs->mQ, m = rs->mM, l = rs->mL;
1321 const double *f = rs->mF;
1322 uint j_f, j_s;
1323 double *work;
1324 uint i;
1326 if(outN == 0)
1327 return;
1329 // Handle in-place operation.
1330 if(in == out)
1331 work = CreateArray(outN);
1332 else
1333 work = out;
1334 // Resample the input.
1335 for(i = 0;i < outN;i++)
1337 double r = 0.0;
1338 // Input starts at l to compensate for the filter delay. This will
1339 // drop any build-up from the first half of the filter.
1340 j_f = (l + (q * i)) % p;
1341 j_s = (l + (q * i)) / p;
1342 while(j_f < m)
1344 // Only take input when 0 <= j_s < inN. This single unsigned
1345 // comparison catches both cases.
1346 if(j_s < inN)
1347 r += f[j_f] * in[j_s];
1348 j_f += p;
1349 j_s--;
1351 work[i] = r;
1353 // Clean up after in-place operation.
1354 if(in == out)
1356 for(i = 0;i < outN;i++)
1357 out[i] = work[i];
1358 DestroyArray(work);
1362 /*************************
1363 *** File source input ***
1364 *************************/
1366 // Read a binary value of the specified byte order and byte size from a file,
1367 // storing it as a 32-bit unsigned integer.
1368 static int ReadBin4(FILE *fp, const char *filename, const ByteOrderT order, const uint bytes, uint32 *out)
1370 uint8 in[4];
1371 uint32 accum;
1372 uint i;
1374 if(fread(in, 1, bytes, fp) != bytes)
1376 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1377 return 0;
1379 accum = 0;
1380 switch(order)
1382 case BO_LITTLE:
1383 for(i = 0;i < bytes;i++)
1384 accum = (accum<<8) | in[bytes - i - 1];
1385 break;
1386 case BO_BIG:
1387 for(i = 0;i < bytes;i++)
1388 accum = (accum<<8) | in[i];
1389 break;
1390 default:
1391 break;
1393 *out = accum;
1394 return 1;
1397 // Read a binary value of the specified byte order from a file, storing it as
1398 // a 64-bit unsigned integer.
1399 static int ReadBin8(FILE *fp, const char *filename, const ByteOrderT order, uint64 *out)
1401 uint8 in [8];
1402 uint64 accum;
1403 uint i;
1405 if(fread(in, 1, 8, fp) != 8)
1407 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1408 return 0;
1410 accum = 0ULL;
1411 switch(order)
1413 case BO_LITTLE:
1414 for(i = 0;i < 8;i++)
1415 accum = (accum<<8) | in[8 - i - 1];
1416 break;
1417 case BO_BIG:
1418 for(i = 0;i < 8;i++)
1419 accum = (accum<<8) | in[i];
1420 break;
1421 default:
1422 break;
1424 *out = accum;
1425 return 1;
1428 /* Read a binary value of the specified type, byte order, and byte size from
1429 * a file, converting it to a double. For integer types, the significant
1430 * bits are used to normalize the result. The sign of bits determines
1431 * whether they are padded toward the MSB (negative) or LSB (positive).
1432 * Floating-point types are not normalized.
1434 static int ReadBinAsDouble(FILE *fp, const char *filename, const ByteOrderT order, const ElementTypeT type, const uint bytes, const int bits, double *out)
1436 union {
1437 uint32 ui;
1438 int32 i;
1439 float f;
1440 } v4;
1441 union {
1442 uint64 ui;
1443 double f;
1444 } v8;
1446 *out = 0.0;
1447 if(bytes > 4)
1449 if(!ReadBin8(fp, filename, order, &v8.ui))
1450 return 0;
1451 if(type == ET_FP)
1452 *out = v8.f;
1454 else
1456 if(!ReadBin4(fp, filename, order, bytes, &v4.ui))
1457 return 0;
1458 if(type == ET_FP)
1459 *out = v4.f;
1460 else
1462 if(bits > 0)
1463 v4.ui >>= (8*bytes) - ((uint)bits);
1464 else
1465 v4.ui &= (0xFFFFFFFF >> (32+bits));
1467 if(v4.ui&(uint)(1<<(abs(bits)-1)))
1468 v4.ui |= (0xFFFFFFFF << abs (bits));
1469 *out = v4.i / (double)(1<<(abs(bits)-1));
1472 return 1;
1475 /* Read an ascii value of the specified type from a file, converting it to a
1476 * double. For integer types, the significant bits are used to normalize the
1477 * result. The sign of the bits should always be positive. This also skips
1478 * up to one separator character before the element itself.
1480 static int ReadAsciiAsDouble(TokenReaderT *tr, const char *filename, const ElementTypeT type, const uint bits, double *out)
1482 if(TrIsOperator(tr, ","))
1483 TrReadOperator(tr, ",");
1484 else if(TrIsOperator(tr, ":"))
1485 TrReadOperator(tr, ":");
1486 else if(TrIsOperator(tr, ";"))
1487 TrReadOperator(tr, ";");
1488 else if(TrIsOperator(tr, "|"))
1489 TrReadOperator(tr, "|");
1491 if(type == ET_FP)
1493 if(!TrReadFloat(tr, -HUGE_VAL, HUGE_VAL, out))
1495 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1496 return 0;
1499 else
1501 int v;
1502 if(!TrReadInt(tr, -(1<<(bits-1)), (1<<(bits-1))-1, &v))
1504 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1505 return 0;
1507 *out = v / (double)((1<<(bits-1))-1);
1509 return 1;
1512 // Read the RIFF/RIFX WAVE format chunk from a file, validating it against
1513 // the source parameters and data set metrics.
1514 static int ReadWaveFormat(FILE *fp, const ByteOrderT order, const uint hrirRate, SourceRefT *src)
1516 uint32 fourCC, chunkSize;
1517 uint32 format, channels, rate, dummy, block, size, bits;
1519 chunkSize = 0;
1520 do {
1521 if (chunkSize > 0)
1522 fseek (fp, (long) chunkSize, SEEK_CUR);
1523 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1524 !ReadBin4(fp, src->mPath, order, 4, &chunkSize))
1525 return 0;
1526 } while(fourCC != FOURCC_FMT);
1527 if(!ReadBin4(fp, src->mPath, order, 2, & format) ||
1528 !ReadBin4(fp, src->mPath, order, 2, & channels) ||
1529 !ReadBin4(fp, src->mPath, order, 4, & rate) ||
1530 !ReadBin4(fp, src->mPath, order, 4, & dummy) ||
1531 !ReadBin4(fp, src->mPath, order, 2, & block))
1532 return (0);
1533 block /= channels;
1534 if(chunkSize > 14)
1536 if(!ReadBin4(fp, src->mPath, order, 2, &size))
1537 return 0;
1538 size /= 8;
1539 if(block > size)
1540 size = block;
1542 else
1543 size = block;
1544 if(format == WAVE_FORMAT_EXTENSIBLE)
1546 fseek(fp, 2, SEEK_CUR);
1547 if(!ReadBin4(fp, src->mPath, order, 2, &bits))
1548 return 0;
1549 if(bits == 0)
1550 bits = 8 * size;
1551 fseek(fp, 4, SEEK_CUR);
1552 if(!ReadBin4(fp, src->mPath, order, 2, &format))
1553 return 0;
1554 fseek(fp, (long)(chunkSize - 26), SEEK_CUR);
1556 else
1558 bits = 8 * size;
1559 if(chunkSize > 14)
1560 fseek(fp, (long)(chunkSize - 16), SEEK_CUR);
1561 else
1562 fseek(fp, (long)(chunkSize - 14), SEEK_CUR);
1564 if(format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT)
1566 fprintf(stderr, "Error: Unsupported WAVE format in file '%s'.\n", src->mPath);
1567 return 0;
1569 if(src->mChannel >= channels)
1571 fprintf(stderr, "Error: Missing source channel in WAVE file '%s'.\n", src->mPath);
1572 return 0;
1574 if(rate != hrirRate)
1576 fprintf(stderr, "Error: Mismatched source sample rate in WAVE file '%s'.\n", src->mPath);
1577 return 0;
1579 if(format == WAVE_FORMAT_PCM)
1581 if(size < 2 || size > 4)
1583 fprintf(stderr, "Error: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
1584 return 0;
1586 if(bits < 16 || bits > (8*size))
1588 fprintf (stderr, "Error: Bad significant bits in WAVE file '%s'.\n", src->mPath);
1589 return 0;
1591 src->mType = ET_INT;
1593 else
1595 if(size != 4 && size != 8)
1597 fprintf(stderr, "Error: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
1598 return 0;
1600 src->mType = ET_FP;
1602 src->mSize = size;
1603 src->mBits = (int)bits;
1604 src->mSkip = channels;
1605 return 1;
1608 // Read a RIFF/RIFX WAVE data chunk, converting all elements to doubles.
1609 static int ReadWaveData(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1611 int pre, post, skip;
1612 uint i;
1614 pre = (int)(src->mSize * src->mChannel);
1615 post = (int)(src->mSize * (src->mSkip - src->mChannel - 1));
1616 skip = 0;
1617 for(i = 0;i < n;i++)
1619 skip += pre;
1620 if(skip > 0)
1621 fseek(fp, skip, SEEK_CUR);
1622 if(!ReadBinAsDouble(fp, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
1623 return 0;
1624 skip = post;
1626 if(skip > 0)
1627 fseek(fp, skip, SEEK_CUR);
1628 return 1;
1631 // Read the RIFF/RIFX WAVE list or data chunk, converting all elements to
1632 // doubles.
1633 static int ReadWaveList(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1635 uint32 fourCC, chunkSize, listSize, count;
1636 uint block, skip, offset, i;
1637 double lastSample;
1639 for (;;) {
1640 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, & fourCC) ||
1641 !ReadBin4(fp, src->mPath, order, 4, & chunkSize))
1642 return (0);
1644 if(fourCC == FOURCC_DATA)
1646 block = src->mSize * src->mSkip;
1647 count = chunkSize / block;
1648 if(count < (src->mOffset + n))
1650 fprintf(stderr, "Error: Bad read from file '%s'.\n", src->mPath);
1651 return 0;
1653 fseek(fp, (long)(src->mOffset * block), SEEK_CUR);
1654 if(!ReadWaveData(fp, src, order, n, &hrir[0]))
1655 return 0;
1656 return 1;
1658 else if(fourCC == FOURCC_LIST)
1660 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC))
1661 return 0;
1662 chunkSize -= 4;
1663 if(fourCC == FOURCC_WAVL)
1664 break;
1666 if(chunkSize > 0)
1667 fseek(fp, (long)chunkSize, SEEK_CUR);
1669 listSize = chunkSize;
1670 block = src->mSize * src->mSkip;
1671 skip = src->mOffset;
1672 offset = 0;
1673 lastSample = 0.0;
1674 while(offset < n && listSize > 8)
1676 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1677 !ReadBin4(fp, src->mPath, order, 4, &chunkSize))
1678 return 0;
1679 listSize -= 8 + chunkSize;
1680 if(fourCC == FOURCC_DATA)
1682 count = chunkSize / block;
1683 if(count > skip)
1685 fseek(fp, (long)(skip * block), SEEK_CUR);
1686 chunkSize -= skip * block;
1687 count -= skip;
1688 skip = 0;
1689 if(count > (n - offset))
1690 count = n - offset;
1691 if(!ReadWaveData(fp, src, order, count, &hrir[offset]))
1692 return 0;
1693 chunkSize -= count * block;
1694 offset += count;
1695 lastSample = hrir [offset - 1];
1697 else
1699 skip -= count;
1700 count = 0;
1703 else if(fourCC == FOURCC_SLNT)
1705 if(!ReadBin4(fp, src->mPath, order, 4, &count))
1706 return 0;
1707 chunkSize -= 4;
1708 if(count > skip)
1710 count -= skip;
1711 skip = 0;
1712 if(count > (n - offset))
1713 count = n - offset;
1714 for(i = 0; i < count; i ++)
1715 hrir[offset + i] = lastSample;
1716 offset += count;
1718 else
1720 skip -= count;
1721 count = 0;
1724 if(chunkSize > 0)
1725 fseek(fp, (long)chunkSize, SEEK_CUR);
1727 if(offset < n)
1729 fprintf(stderr, "Error: Bad read from file '%s'.\n", src->mPath);
1730 return 0;
1732 return 1;
1735 // Load a source HRIR from a RIFF/RIFX WAVE file.
1736 static int LoadWaveSource(FILE *fp, SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
1738 uint32 fourCC, dummy;
1739 ByteOrderT order;
1741 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1742 !ReadBin4(fp, src->mPath, BO_LITTLE, 4, &dummy))
1743 return 0;
1744 if(fourCC == FOURCC_RIFF)
1745 order = BO_LITTLE;
1746 else if(fourCC == FOURCC_RIFX)
1747 order = BO_BIG;
1748 else
1750 fprintf(stderr, "Error: No RIFF/RIFX chunk in file '%s'.\n", src->mPath);
1751 return 0;
1754 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC))
1755 return 0;
1756 if(fourCC != FOURCC_WAVE)
1758 fprintf(stderr, "Error: Not a RIFF/RIFX WAVE file '%s'.\n", src->mPath);
1759 return 0;
1761 if(!ReadWaveFormat(fp, order, hrirRate, src))
1762 return 0;
1763 if(!ReadWaveList(fp, src, order, n, hrir))
1764 return 0;
1765 return 1;
1768 // Load a source HRIR from a binary file.
1769 static int LoadBinarySource(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1771 uint i;
1773 fseek(fp, (long)src->mOffset, SEEK_SET);
1774 for(i = 0;i < n;i++)
1776 if(!ReadBinAsDouble(fp, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
1777 return 0;
1778 if(src->mSkip > 0)
1779 fseek(fp, (long)src->mSkip, SEEK_CUR);
1781 return 1;
1784 // Load a source HRIR from an ASCII text file containing a list of elements
1785 // separated by whitespace or common list operators (',', ';', ':', '|').
1786 static int LoadAsciiSource(FILE *fp, const SourceRefT *src, const uint n, double *hrir)
1788 TokenReaderT tr;
1789 uint i, j;
1790 double dummy;
1792 TrSetup(fp, NULL, &tr);
1793 for(i = 0;i < src->mOffset;i++)
1795 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &dummy))
1796 return (0);
1798 for(i = 0;i < n;i++)
1800 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &hrir[i]))
1801 return 0;
1802 for(j = 0;j < src->mSkip;j++)
1804 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &dummy))
1805 return 0;
1808 return 1;
1811 // Load a source HRIR from a supported file type.
1812 static int LoadSource(SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
1814 int result;
1815 FILE *fp;
1817 if (src->mFormat == SF_ASCII)
1818 fp = fopen(src->mPath, "r");
1819 else
1820 fp = fopen(src->mPath, "rb");
1821 if(fp == NULL)
1823 fprintf(stderr, "Error: Could not open source file '%s'.\n", src->mPath);
1824 return 0;
1826 if(src->mFormat == SF_WAVE)
1827 result = LoadWaveSource(fp, src, hrirRate, n, hrir);
1828 else if(src->mFormat == SF_BIN_LE)
1829 result = LoadBinarySource(fp, src, BO_LITTLE, n, hrir);
1830 else if(src->mFormat == SF_BIN_BE)
1831 result = LoadBinarySource(fp, src, BO_BIG, n, hrir);
1832 else
1833 result = LoadAsciiSource(fp, src, n, hrir);
1834 fclose(fp);
1835 return result;
1839 /***************************
1840 *** File storage output ***
1841 ***************************/
1843 // Write an ASCII string to a file.
1844 static int WriteAscii(const char *out, FILE *fp, const char *filename)
1846 size_t len;
1848 len = strlen(out);
1849 if(fwrite(out, 1, len, fp) != len)
1851 fclose(fp);
1852 fprintf(stderr, "Error: Bad write to file '%s'.\n", filename);
1853 return 0;
1855 return 1;
1858 // Write a binary value of the given byte order and byte size to a file,
1859 // loading it from a 32-bit unsigned integer.
1860 static int WriteBin4(const ByteOrderT order, const uint bytes, const uint32 in, FILE *fp, const char *filename)
1862 uint8 out[4];
1863 uint i;
1865 switch(order)
1867 case BO_LITTLE:
1868 for(i = 0;i < bytes;i++)
1869 out[i] = (in>>(i*8)) & 0x000000FF;
1870 break;
1871 case BO_BIG:
1872 for(i = 0;i < bytes;i++)
1873 out[bytes - i - 1] = (in>>(i*8)) & 0x000000FF;
1874 break;
1875 default:
1876 break;
1878 if(fwrite(out, 1, bytes, fp) != bytes)
1880 fprintf(stderr, "Error: Bad write to file '%s'.\n", filename);
1881 return 0;
1883 return 1;
1886 // Store the OpenAL Soft HRTF data set.
1887 static int StoreMhr(const HrirDataT *hData, const int experimental, const char *filename)
1889 uint e, step, end, n, j, i;
1890 uint dither_seed;
1891 FILE *fp;
1892 int v;
1894 if((fp=fopen(filename, "wb")) == NULL)
1896 fprintf(stderr, "Error: Could not open MHR file '%s'.\n", filename);
1897 return 0;
1899 if(!WriteAscii(experimental ? MHR_FORMAT_EXPERIMENTAL : MHR_FORMAT, fp, filename))
1900 return 0;
1901 if(!WriteBin4(BO_LITTLE, 4, (uint32)hData->mIrRate, fp, filename))
1902 return 0;
1903 if(experimental)
1905 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mSampleType, fp, filename))
1906 return 0;
1907 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mChannelType, fp, filename))
1908 return 0;
1910 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mIrPoints, fp, filename))
1911 return 0;
1912 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mEvCount, fp, filename))
1913 return 0;
1914 for(e = 0;e < hData->mEvCount;e++)
1916 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mAzCount[e], fp, filename))
1917 return 0;
1919 step = hData->mIrSize;
1920 end = hData->mIrCount * step;
1921 n = hData->mIrPoints;
1922 dither_seed = 22222;
1923 for(j = 0;j < end;j += step)
1925 const double scale = (!experimental || hData->mSampleType == ST_S16) ? 32767.0 :
1926 ((hData->mSampleType == ST_S24) ? 8388607.0 : 0.0);
1927 const int bps = (!experimental || hData->mSampleType == ST_S16) ? 2 :
1928 ((hData->mSampleType == ST_S24) ? 3 : 0);
1929 double out[MAX_TRUNCSIZE];
1930 for(i = 0;i < n;i++)
1931 out[i] = TpdfDither(scale * hData->mHrirs[j+i], &dither_seed);
1932 for(i = 0;i < n;i++)
1934 v = (int)Clamp(out[i], -scale-1.0, scale);
1935 if(!WriteBin4(BO_LITTLE, bps, (uint32)v, fp, filename))
1936 return 0;
1939 for(j = 0;j < hData->mIrCount;j++)
1941 v = (int)fmin(round(hData->mIrRate * hData->mHrtds[j]), MAX_HRTD);
1942 if(!WriteBin4(BO_LITTLE, 1, (uint32)v, fp, filename))
1943 return 0;
1945 fclose(fp);
1946 return 1;
1950 /***********************
1951 *** HRTF processing ***
1952 ***********************/
1954 // Calculate the onset time of an HRIR and average it with any existing
1955 // timing for its elevation and azimuth.
1956 static void AverageHrirOnset(const double *hrir, const double f, const uint ei, const uint ai, const HrirDataT *hData)
1958 double mag;
1959 uint n, i, j;
1961 mag = 0.0;
1962 n = hData->mIrPoints;
1963 for(i = 0;i < n;i++)
1964 mag = fmax(fabs(hrir[i]), mag);
1965 mag *= 0.15;
1966 for(i = 0;i < n;i++)
1968 if(fabs(hrir[i]) >= mag)
1969 break;
1971 j = hData->mEvOffset[ei] + ai;
1972 hData->mHrtds[j] = Lerp(hData->mHrtds[j], ((double)i) / hData->mIrRate, f);
1975 // Calculate the magnitude response of an HRIR and average it with any
1976 // existing responses for its elevation and azimuth.
1977 static void AverageHrirMagnitude(const double *hrir, const double f, const uint ei, const uint ai, const HrirDataT *hData)
1979 double *re, *im;
1980 uint n, m, i, j;
1982 n = hData->mFftSize;
1983 re = CreateArray(n);
1984 im = CreateArray(n);
1985 for(i = 0;i < hData->mIrPoints;i++)
1987 re[i] = hrir[i];
1988 im[i] = 0.0;
1990 for(;i < n;i++)
1992 re[i] = 0.0;
1993 im[i] = 0.0;
1995 FftForward(n, re, im, re, im);
1996 MagnitudeResponse(n, re, im, re);
1997 m = 1 + (n / 2);
1998 j = (hData->mEvOffset[ei] + ai) * hData->mIrSize;
1999 for(i = 0;i < m;i++)
2000 hData->mHrirs[j+i] = Lerp(hData->mHrirs[j+i], re[i], f);
2001 DestroyArray(im);
2002 DestroyArray(re);
2005 /* Calculate the contribution of each HRIR to the diffuse-field average based
2006 * on the area of its surface patch. All patches are centered at the HRIR
2007 * coordinates on the unit sphere and are measured by solid angle.
2009 static void CalculateDfWeights(const HrirDataT *hData, double *weights)
2011 double evs, sum, ev, up_ev, down_ev, solidAngle;
2012 uint ei;
2014 evs = 90.0 / (hData->mEvCount - 1);
2015 sum = 0.0;
2016 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2018 // For each elevation, calculate the upper and lower limits of the
2019 // patch band.
2020 ev = -90.0 + (ei * 2.0 * evs);
2021 if(ei < (hData->mEvCount - 1))
2022 up_ev = (ev + evs) * M_PI / 180.0;
2023 else
2024 up_ev = M_PI / 2.0;
2025 if(ei > 0)
2026 down_ev = (ev - evs) * M_PI / 180.0;
2027 else
2028 down_ev = -M_PI / 2.0;
2029 // Calculate the area of the patch band.
2030 solidAngle = 2.0 * M_PI * (sin(up_ev) - sin(down_ev));
2031 // Each weight is the area of one patch.
2032 weights[ei] = solidAngle / hData->mAzCount [ei];
2033 // Sum the total surface area covered by the HRIRs.
2034 sum += solidAngle;
2036 // Normalize the weights given the total surface coverage.
2037 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2038 weights[ei] /= sum;
2041 /* Calculate the diffuse-field average from the given magnitude responses of
2042 * the HRIR set. Weighting can be applied to compensate for the varying
2043 * surface area covered by each HRIR. The final average can then be limited
2044 * by the specified magnitude range (in positive dB; 0.0 to skip).
2046 static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const int weighted, const double limit, double *dfa)
2048 uint ei, ai, count, step, start, end, m, j, i;
2049 double *weights;
2051 weights = CreateArray(hData->mEvCount);
2052 if(weighted)
2054 // Use coverage weighting to calculate the average.
2055 CalculateDfWeights(hData, weights);
2057 else
2059 // If coverage weighting is not used, the weights still need to be
2060 // averaged by the number of HRIRs.
2061 count = 0;
2062 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2063 count += hData->mAzCount [ei];
2064 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2065 weights[ei] = 1.0 / count;
2067 ei = hData->mEvStart;
2068 ai = 0;
2069 step = hData->mIrSize;
2070 start = hData->mEvOffset[ei] * step;
2071 end = hData->mIrCount * step;
2072 m = 1 + (hData->mFftSize / 2);
2073 for(i = 0;i < m;i++)
2074 dfa[i] = 0.0;
2075 for(j = start;j < end;j += step)
2077 // Get the weight for this HRIR's contribution.
2078 double weight = weights[ei];
2079 // Add this HRIR's weighted power average to the total.
2080 for(i = 0;i < m;i++)
2081 dfa[i] += weight * hData->mHrirs[j+i] * hData->mHrirs[j+i];
2082 // Determine the next weight to use.
2083 ai++;
2084 if(ai >= hData->mAzCount[ei])
2086 ei++;
2087 ai = 0;
2090 // Finish the average calculation and keep it from being too small.
2091 for(i = 0;i < m;i++)
2092 dfa[i] = fmax(sqrt(dfa[i]), EPSILON);
2093 // Apply a limit to the magnitude range of the diffuse-field average if
2094 // desired.
2095 if(limit > 0.0)
2096 LimitMagnitudeResponse(hData->mFftSize, limit, dfa, dfa);
2097 DestroyArray(weights);
2100 // Perform diffuse-field equalization on the magnitude responses of the HRIR
2101 // set using the given average response.
2102 static void DiffuseFieldEqualize(const double *dfa, const HrirDataT *hData)
2104 uint step, start, end, m, j, i;
2106 step = hData->mIrSize;
2107 start = hData->mEvOffset[hData->mEvStart] * step;
2108 end = hData->mIrCount * step;
2109 m = 1 + (hData->mFftSize / 2);
2110 for(j = start;j < end;j += step)
2112 for(i = 0;i < m;i++)
2113 hData->mHrirs[j+i] /= dfa[i];
2117 // Perform minimum-phase reconstruction using the magnitude responses of the
2118 // HRIR set.
2119 static void ReconstructHrirs(const HrirDataT *hData)
2121 uint step, start, end, n, j, i;
2122 double *re, *im;
2124 step = hData->mIrSize;
2125 start = hData->mEvOffset[hData->mEvStart] * step;
2126 end = hData->mIrCount * step;
2127 n = hData->mFftSize;
2128 re = CreateArray(n);
2129 im = CreateArray(n);
2130 for(j = start;j < end;j += step)
2132 MinimumPhase(n, &hData->mHrirs[j], re, im);
2133 FftInverse(n, re, im, re, im);
2134 for(i = 0;i < hData->mIrPoints;i++)
2135 hData->mHrirs[j+i] = re[i];
2137 DestroyArray (im);
2138 DestroyArray (re);
2141 // Resamples the HRIRs for use at the given sampling rate.
2142 static void ResampleHrirs(const uint rate, HrirDataT *hData)
2144 uint n, step, start, end, j;
2145 ResamplerT rs;
2147 ResamplerSetup(&rs, hData->mIrRate, rate);
2148 n = hData->mIrPoints;
2149 step = hData->mIrSize;
2150 start = hData->mEvOffset[hData->mEvStart] * step;
2151 end = hData->mIrCount * step;
2152 for(j = start;j < end;j += step)
2153 ResamplerRun(&rs, n, &hData->mHrirs[j], n, &hData->mHrirs[j]);
2154 ResamplerClear(&rs);
2155 hData->mIrRate = rate;
2158 /* Given an elevation index and an azimuth, calculate the indices of the two
2159 * HRIRs that bound the coordinate along with a factor for calculating the
2160 * continous HRIR using interpolation.
2162 static void CalcAzIndices(const HrirDataT *hData, const uint ei, const double az, uint *j0, uint *j1, double *jf)
2164 double af;
2165 uint ai;
2167 af = ((2.0*M_PI) + az) * hData->mAzCount[ei] / (2.0*M_PI);
2168 ai = ((uint)af) % hData->mAzCount[ei];
2169 af -= floor(af);
2171 *j0 = hData->mEvOffset[ei] + ai;
2172 *j1 = hData->mEvOffset[ei] + ((ai+1) % hData->mAzCount [ei]);
2173 *jf = af;
2176 // Synthesize any missing onset timings at the bottom elevations. This just
2177 // blends between slightly exaggerated known onsets. Not an accurate model.
2178 static void SynthesizeOnsets(HrirDataT *hData)
2180 uint oi, e, a, j0, j1;
2181 double t, of, jf;
2183 oi = hData->mEvStart;
2184 t = 0.0;
2185 for(a = 0;a < hData->mAzCount[oi];a++)
2186 t += hData->mHrtds[hData->mEvOffset[oi] + a];
2187 hData->mHrtds[0] = 1.32e-4 + (t / hData->mAzCount[oi]);
2188 for(e = 1;e < hData->mEvStart;e++)
2190 of = ((double)e) / hData->mEvStart;
2191 for(a = 0;a < hData->mAzCount[e];a++)
2193 CalcAzIndices(hData, oi, a * 2.0 * M_PI / hData->mAzCount[e], &j0, &j1, &jf);
2194 hData->mHrtds[hData->mEvOffset[e] + a] = Lerp(hData->mHrtds[0], Lerp(hData->mHrtds[j0], hData->mHrtds[j1], jf), of);
2199 /* Attempt to synthesize any missing HRIRs at the bottom elevations. Right
2200 * now this just blends the lowest elevation HRIRs together and applies some
2201 * attenuation and high frequency damping. It is a simple, if inaccurate
2202 * model.
2204 static void SynthesizeHrirs (HrirDataT *hData)
2206 uint oi, a, e, step, n, i, j;
2207 double lp[4], s0, s1;
2208 double of, b;
2209 uint j0, j1;
2210 double jf;
2212 if(hData->mEvStart <= 0)
2213 return;
2214 step = hData->mIrSize;
2215 oi = hData->mEvStart;
2216 n = hData->mIrPoints;
2217 for(i = 0;i < n;i++)
2218 hData->mHrirs[i] = 0.0;
2219 for(a = 0;a < hData->mAzCount[oi];a++)
2221 j = (hData->mEvOffset[oi] + a) * step;
2222 for(i = 0;i < n;i++)
2223 hData->mHrirs[i] += hData->mHrirs[j+i] / hData->mAzCount[oi];
2225 for(e = 1;e < hData->mEvStart;e++)
2227 of = ((double)e) / hData->mEvStart;
2228 b = (1.0 - of) * (3.5e-6 * hData->mIrRate);
2229 for(a = 0;a < hData->mAzCount[e];a++)
2231 j = (hData->mEvOffset[e] + a) * step;
2232 CalcAzIndices(hData, oi, a * 2.0 * M_PI / hData->mAzCount[e], &j0, &j1, &jf);
2233 j0 *= step;
2234 j1 *= step;
2235 lp[0] = 0.0;
2236 lp[1] = 0.0;
2237 lp[2] = 0.0;
2238 lp[3] = 0.0;
2239 for(i = 0;i < n;i++)
2241 s0 = hData->mHrirs[i];
2242 s1 = Lerp(hData->mHrirs[j0+i], hData->mHrirs[j1+i], jf);
2243 s0 = Lerp(s0, s1, of);
2244 lp[0] = Lerp(s0, lp[0], b);
2245 lp[1] = Lerp(lp[0], lp[1], b);
2246 lp[2] = Lerp(lp[1], lp[2], b);
2247 lp[3] = Lerp(lp[2], lp[3], b);
2248 hData->mHrirs[j+i] = lp[3];
2252 b = 3.5e-6 * hData->mIrRate;
2253 lp[0] = 0.0;
2254 lp[1] = 0.0;
2255 lp[2] = 0.0;
2256 lp[3] = 0.0;
2257 for(i = 0;i < n;i++)
2259 s0 = hData->mHrirs[i];
2260 lp[0] = Lerp(s0, lp[0], b);
2261 lp[1] = Lerp(lp[0], lp[1], b);
2262 lp[2] = Lerp(lp[1], lp[2], b);
2263 lp[3] = Lerp(lp[2], lp[3], b);
2264 hData->mHrirs[i] = lp[3];
2266 hData->mEvStart = 0;
2269 // The following routines assume a full set of HRIRs for all elevations.
2271 // Normalize the HRIR set and slightly attenuate the result.
2272 static void NormalizeHrirs (const HrirDataT *hData)
2274 uint step, end, n, j, i;
2275 double maxLevel;
2277 step = hData->mIrSize;
2278 end = hData->mIrCount * step;
2279 n = hData->mIrPoints;
2280 maxLevel = 0.0;
2281 for(j = 0;j < end;j += step)
2283 for(i = 0;i < n;i++)
2284 maxLevel = fmax(fabs(hData->mHrirs[j+i]), maxLevel);
2286 maxLevel = 1.01 * maxLevel;
2287 for(j = 0;j < end;j += step)
2289 for(i = 0;i < n;i++)
2290 hData->mHrirs[j+i] /= maxLevel;
2294 // Calculate the left-ear time delay using a spherical head model.
2295 static double CalcLTD(const double ev, const double az, const double rad, const double dist)
2297 double azp, dlp, l, al;
2299 azp = asin(cos(ev) * sin(az));
2300 dlp = sqrt((dist*dist) + (rad*rad) + (2.0*dist*rad*sin(azp)));
2301 l = sqrt((dist*dist) - (rad*rad));
2302 al = (0.5 * M_PI) + azp;
2303 if(dlp > l)
2304 dlp = l + (rad * (al - acos(rad / dist)));
2305 return (dlp / 343.3);
2308 // Calculate the effective head-related time delays for each minimum-phase
2309 // HRIR.
2310 static void CalculateHrtds (const HeadModelT model, const double radius, HrirDataT *hData)
2312 double minHrtd, maxHrtd;
2313 uint e, a, j;
2314 double t;
2316 minHrtd = 1000.0;
2317 maxHrtd = -1000.0;
2318 for(e = 0;e < hData->mEvCount;e++)
2320 for(a = 0;a < hData->mAzCount[e];a++)
2322 j = hData->mEvOffset[e] + a;
2323 if(model == HM_DATASET)
2324 t = hData->mHrtds[j] * radius / hData->mRadius;
2325 else
2326 t = CalcLTD((-90.0 + (e * 180.0 / (hData->mEvCount - 1))) * M_PI / 180.0,
2327 (a * 360.0 / hData->mAzCount [e]) * M_PI / 180.0,
2328 radius, hData->mDistance);
2329 hData->mHrtds[j] = t;
2330 maxHrtd = fmax(t, maxHrtd);
2331 minHrtd = fmin(t, minHrtd);
2334 maxHrtd -= minHrtd;
2335 for(j = 0;j < hData->mIrCount;j++)
2336 hData->mHrtds[j] -= minHrtd;
2337 hData->mMaxHrtd = maxHrtd;
2341 // Process the data set definition to read and validate the data set metrics.
2342 static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint truncSize, HrirDataT *hData)
2344 int hasRate = 0, hasPoints = 0, hasAzimuths = 0;
2345 int hasRadius = 0, hasDistance = 0;
2346 char ident[MAX_IDENT_LEN+1];
2347 uint line, col;
2348 double fpVal;
2349 uint points;
2350 int intVal;
2352 while(!(hasRate && hasPoints && hasAzimuths && hasRadius && hasDistance))
2354 TrIndication(tr, & line, & col);
2355 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2356 return 0;
2357 if(strcasecmp(ident, "rate") == 0)
2359 if(hasRate)
2361 TrErrorAt(tr, line, col, "Redefinition of 'rate'.\n");
2362 return 0;
2364 if(!TrReadOperator(tr, "="))
2365 return 0;
2366 if(!TrReadInt(tr, MIN_RATE, MAX_RATE, &intVal))
2367 return 0;
2368 hData->mIrRate = (uint)intVal;
2369 hasRate = 1;
2371 else if(strcasecmp(ident, "points") == 0)
2373 if (hasPoints) {
2374 TrErrorAt(tr, line, col, "Redefinition of 'points'.\n");
2375 return 0;
2377 if(!TrReadOperator(tr, "="))
2378 return 0;
2379 TrIndication(tr, &line, &col);
2380 if(!TrReadInt(tr, MIN_POINTS, MAX_POINTS, &intVal))
2381 return 0;
2382 points = (uint)intVal;
2383 if(fftSize > 0 && points > fftSize)
2385 TrErrorAt(tr, line, col, "Value exceeds the overridden FFT size.\n");
2386 return 0;
2388 if(points < truncSize)
2390 TrErrorAt(tr, line, col, "Value is below the truncation size.\n");
2391 return 0;
2393 hData->mIrPoints = points;
2394 if(fftSize <= 0)
2396 hData->mFftSize = DEFAULT_FFTSIZE;
2397 hData->mIrSize = 1 + (DEFAULT_FFTSIZE / 2);
2399 else
2401 hData->mFftSize = fftSize;
2402 hData->mIrSize = 1 + (fftSize / 2);
2403 if(points > hData->mIrSize)
2404 hData->mIrSize = points;
2406 hasPoints = 1;
2408 else if(strcasecmp(ident, "azimuths") == 0)
2410 if(hasAzimuths)
2412 TrErrorAt(tr, line, col, "Redefinition of 'azimuths'.\n");
2413 return 0;
2415 if(!TrReadOperator(tr, "="))
2416 return 0;
2417 hData->mIrCount = 0;
2418 hData->mEvCount = 0;
2419 hData->mEvOffset[0] = 0;
2420 for(;;)
2422 if(!TrReadInt(tr, MIN_AZ_COUNT, MAX_AZ_COUNT, &intVal))
2423 return 0;
2424 hData->mAzCount[hData->mEvCount] = (uint)intVal;
2425 hData->mIrCount += (uint)intVal;
2426 hData->mEvCount ++;
2427 if(!TrIsOperator(tr, ","))
2428 break;
2429 if(hData->mEvCount >= MAX_EV_COUNT)
2431 TrError(tr, "Exceeded the maximum of %d elevations.\n", MAX_EV_COUNT);
2432 return 0;
2434 hData->mEvOffset[hData->mEvCount] = hData->mEvOffset[hData->mEvCount - 1] + ((uint)intVal);
2435 TrReadOperator(tr, ",");
2437 if(hData->mEvCount < MIN_EV_COUNT)
2439 TrErrorAt(tr, line, col, "Did not reach the minimum of %d azimuth counts.\n", MIN_EV_COUNT);
2440 return 0;
2442 hasAzimuths = 1;
2444 else if(strcasecmp(ident, "radius") == 0)
2446 if(hasRadius)
2448 TrErrorAt(tr, line, col, "Redefinition of 'radius'.\n");
2449 return 0;
2451 if(!TrReadOperator(tr, "="))
2452 return 0;
2453 if(!TrReadFloat(tr, MIN_RADIUS, MAX_RADIUS, &fpVal))
2454 return 0;
2455 hData->mRadius = fpVal;
2456 hasRadius = 1;
2458 else if(strcasecmp(ident, "distance") == 0)
2460 if(hasDistance)
2462 TrErrorAt(tr, line, col, "Redefinition of 'distance'.\n");
2463 return 0;
2465 if(!TrReadOperator(tr, "="))
2466 return 0;
2467 if(!TrReadFloat(tr, MIN_DISTANCE, MAX_DISTANCE, & fpVal))
2468 return 0;
2469 hData->mDistance = fpVal;
2470 hasDistance = 1;
2472 else
2474 TrErrorAt(tr, line, col, "Expected a metric name.\n");
2475 return 0;
2477 TrSkipWhitespace (tr);
2479 return 1;
2482 // Parse an index pair from the data set definition.
2483 static int ReadIndexPair(TokenReaderT *tr, const HrirDataT *hData, uint *ei, uint *ai)
2485 int intVal;
2486 if(!TrReadInt(tr, 0, (int)hData->mEvCount, &intVal))
2487 return 0;
2488 *ei = (uint)intVal;
2489 if(!TrReadOperator(tr, ","))
2490 return 0;
2491 if(!TrReadInt(tr, 0, (int)hData->mAzCount[*ei], &intVal))
2492 return 0;
2493 *ai = (uint)intVal;
2494 return 1;
2497 // Match the source format from a given identifier.
2498 static SourceFormatT MatchSourceFormat(const char *ident)
2500 if(strcasecmp(ident, "wave") == 0)
2501 return SF_WAVE;
2502 if(strcasecmp(ident, "bin_le") == 0)
2503 return SF_BIN_LE;
2504 if(strcasecmp(ident, "bin_be") == 0)
2505 return SF_BIN_BE;
2506 if(strcasecmp(ident, "ascii") == 0)
2507 return SF_ASCII;
2508 return SF_NONE;
2511 // Match the source element type from a given identifier.
2512 static ElementTypeT MatchElementType(const char *ident)
2514 if(strcasecmp(ident, "int") == 0)
2515 return ET_INT;
2516 if(strcasecmp(ident, "fp") == 0)
2517 return ET_FP;
2518 return ET_NONE;
2521 // Parse and validate a source reference from the data set definition.
2522 static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src)
2524 char ident[MAX_IDENT_LEN+1];
2525 uint line, col;
2526 int intVal;
2528 TrIndication(tr, &line, &col);
2529 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2530 return 0;
2531 src->mFormat = MatchSourceFormat(ident);
2532 if(src->mFormat == SF_NONE)
2534 TrErrorAt(tr, line, col, "Expected a source format.\n");
2535 return 0;
2537 if(!TrReadOperator(tr, "("))
2538 return 0;
2539 if(src->mFormat == SF_WAVE)
2541 if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal))
2542 return 0;
2543 src->mType = ET_NONE;
2544 src->mSize = 0;
2545 src->mBits = 0;
2546 src->mChannel = (uint)intVal;
2547 src->mSkip = 0;
2549 else
2551 TrIndication(tr, &line, &col);
2552 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2553 return 0;
2554 src->mType = MatchElementType(ident);
2555 if(src->mType == ET_NONE)
2557 TrErrorAt(tr, line, col, "Expected a source element type.\n");
2558 return 0;
2560 if(src->mFormat == SF_BIN_LE || src->mFormat == SF_BIN_BE)
2562 if(!TrReadOperator(tr, ","))
2563 return 0;
2564 if(src->mType == ET_INT)
2566 if(!TrReadInt(tr, MIN_BIN_SIZE, MAX_BIN_SIZE, &intVal))
2567 return 0;
2568 src->mSize = (uint)intVal;
2569 if(!TrIsOperator(tr, ","))
2570 src->mBits = (int)(8*src->mSize);
2571 else
2573 TrReadOperator(tr, ",");
2574 TrIndication(tr, &line, &col);
2575 if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
2576 return 0;
2577 if(abs(intVal) < MIN_BIN_BITS || ((uint)abs(intVal)) > (8*src->mSize))
2579 TrErrorAt(tr, line, col, "Expected a value of (+/-) %d to %d.\n", MIN_BIN_BITS, 8*src->mSize);
2580 return 0;
2582 src->mBits = intVal;
2585 else
2587 TrIndication(tr, &line, &col);
2588 if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
2589 return 0;
2590 if(intVal != 4 && intVal != 8)
2592 TrErrorAt(tr, line, col, "Expected a value of 4 or 8.\n");
2593 return 0;
2595 src->mSize = (uint)intVal;
2596 src->mBits = 0;
2599 else if(src->mFormat == SF_ASCII && src->mType == ET_INT)
2601 if(!TrReadOperator(tr, ","))
2602 return 0;
2603 if(!TrReadInt(tr, MIN_ASCII_BITS, MAX_ASCII_BITS, &intVal))
2604 return 0;
2605 src->mSize = 0;
2606 src->mBits = intVal;
2608 else
2610 src->mSize = 0;
2611 src->mBits = 0;
2614 if(!TrIsOperator(tr, ";"))
2615 src->mSkip = 0;
2616 else
2618 TrReadOperator(tr, ";");
2619 if(!TrReadInt (tr, 0, 0x7FFFFFFF, &intVal))
2620 return 0;
2621 src->mSkip = (uint)intVal;
2624 if(!TrReadOperator(tr, ")"))
2625 return 0;
2626 if(TrIsOperator(tr, "@"))
2628 TrReadOperator(tr, "@");
2629 if(!TrReadInt(tr, 0, 0x7FFFFFFF, &intVal))
2630 return 0;
2631 src->mOffset = (uint)intVal;
2633 else
2634 src->mOffset = 0;
2635 if(!TrReadOperator(tr, ":"))
2636 return 0;
2637 if(!TrReadString(tr, MAX_PATH_LEN, src->mPath))
2638 return 0;
2639 return 1;
2642 // Process the list of sources in the data set definition.
2643 static int ProcessSources(const HeadModelT model, TokenReaderT *tr, HrirDataT *hData)
2645 uint *setCount, *setFlag;
2646 uint line, col, ei, ai;
2647 SourceRefT src;
2648 double factor;
2649 double *hrir;
2651 setCount = (uint*)calloc(hData->mEvCount, sizeof(uint));
2652 setFlag = (uint*)calloc(hData->mIrCount, sizeof(uint));
2653 hrir = CreateArray(hData->mIrPoints);
2654 while(TrIsOperator(tr, "["))
2656 TrIndication(tr, & line, & col);
2657 TrReadOperator(tr, "[");
2658 if(!ReadIndexPair(tr, hData, &ei, &ai))
2659 goto error;
2660 if(!TrReadOperator(tr, "]"))
2661 goto error;
2662 if(setFlag[hData->mEvOffset[ei] + ai])
2664 TrErrorAt(tr, line, col, "Redefinition of source.\n");
2665 goto error;
2667 if(!TrReadOperator(tr, "="))
2668 goto error;
2670 factor = 1.0;
2671 for(;;)
2673 if(!ReadSourceRef(tr, &src))
2674 goto error;
2675 if(!LoadSource(&src, hData->mIrRate, hData->mIrPoints, hrir))
2676 goto error;
2678 if(model == HM_DATASET)
2679 AverageHrirOnset(hrir, 1.0 / factor, ei, ai, hData);
2680 AverageHrirMagnitude(hrir, 1.0 / factor, ei, ai, hData);
2681 factor += 1.0;
2682 if(!TrIsOperator(tr, "+"))
2683 break;
2684 TrReadOperator(tr, "+");
2686 setFlag[hData->mEvOffset[ei] + ai] = 1;
2687 setCount[ei]++;
2690 ei = 0;
2691 while(ei < hData->mEvCount && setCount[ei] < 1)
2692 ei++;
2693 if(ei < hData->mEvCount)
2695 hData->mEvStart = ei;
2696 while(ei < hData->mEvCount && setCount[ei] == hData->mAzCount[ei])
2697 ei++;
2698 if(ei >= hData->mEvCount)
2700 if(!TrLoad(tr))
2702 DestroyArray(hrir);
2703 free(setFlag);
2704 free(setCount);
2705 return 1;
2707 TrError(tr, "Errant data at end of source list.\n");
2709 else
2710 TrError(tr, "Missing sources for elevation index %d.\n", ei);
2712 else
2713 TrError(tr, "Missing source references.\n");
2715 error:
2716 DestroyArray(hrir);
2717 free(setFlag);
2718 free(setCount);
2719 return 0;
2722 /* Parse the data set definition and process the source data, storing the
2723 * resulting data set as desired. If the input name is NULL it will read
2724 * from standard input.
2726 static int ProcessDefinition(const char *inName, const uint outRate, const uint fftSize, const int equalize, const int surface, const double limit, const uint truncSize, const HeadModelT model, const double radius, const OutputFormatT outFormat, const int experimental, const char *outName)
2728 char rateStr[8+1], expName[MAX_PATH_LEN];
2729 TokenReaderT tr;
2730 HrirDataT hData;
2731 double *dfa;
2732 FILE *fp;
2734 hData.mIrRate = 0;
2735 hData.mSampleType = ST_S24;
2736 hData.mChannelType = CT_LEFTONLY;
2737 hData.mIrPoints = 0;
2738 hData.mFftSize = 0;
2739 hData.mIrSize = 0;
2740 hData.mIrCount = 0;
2741 hData.mEvCount = 0;
2742 hData.mRadius = 0;
2743 hData.mDistance = 0;
2744 fprintf(stdout, "Reading HRIR definition...\n");
2745 if(inName != NULL)
2747 fp = fopen(inName, "r");
2748 if(fp == NULL)
2750 fprintf(stderr, "Error: Could not open definition file '%s'\n", inName);
2751 return 0;
2753 TrSetup(fp, inName, &tr);
2755 else
2757 fp = stdin;
2758 TrSetup(fp, "<stdin>", &tr);
2760 if(!ProcessMetrics(&tr, fftSize, truncSize, &hData))
2762 if(inName != NULL)
2763 fclose(fp);
2764 return 0;
2766 hData.mHrirs = CreateArray(hData.mIrCount * hData.mIrSize);
2767 hData.mHrtds = CreateArray(hData.mIrCount);
2768 if(!ProcessSources(model, &tr, &hData))
2770 DestroyArray(hData.mHrtds);
2771 DestroyArray(hData.mHrirs);
2772 if(inName != NULL)
2773 fclose(fp);
2774 return 0;
2776 if(inName != NULL)
2777 fclose(fp);
2778 if(equalize)
2780 dfa = CreateArray(1 + (hData.mFftSize/2));
2781 fprintf(stdout, "Calculating diffuse-field average...\n");
2782 CalculateDiffuseFieldAverage(&hData, surface, limit, dfa);
2783 fprintf(stdout, "Performing diffuse-field equalization...\n");
2784 DiffuseFieldEqualize(dfa, &hData);
2785 DestroyArray(dfa);
2787 fprintf(stdout, "Performing minimum phase reconstruction...\n");
2788 ReconstructHrirs(&hData);
2789 if(outRate != 0 && outRate != hData.mIrRate)
2791 fprintf(stdout, "Resampling HRIRs...\n");
2792 ResampleHrirs(outRate, &hData);
2794 fprintf(stdout, "Truncating minimum-phase HRIRs...\n");
2795 hData.mIrPoints = truncSize;
2796 fprintf(stdout, "Synthesizing missing elevations...\n");
2797 if(model == HM_DATASET)
2798 SynthesizeOnsets(&hData);
2799 SynthesizeHrirs(&hData);
2800 fprintf(stdout, "Normalizing final HRIRs...\n");
2801 NormalizeHrirs(&hData);
2802 fprintf(stdout, "Calculating impulse delays...\n");
2803 CalculateHrtds(model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData.mRadius, &hData);
2804 snprintf(rateStr, 8, "%u", hData.mIrRate);
2805 StrSubst(outName, "%r", rateStr, MAX_PATH_LEN, expName);
2806 switch(outFormat)
2808 case OF_MHR:
2809 fprintf(stdout, "Creating MHR data set file...\n");
2810 if(!StoreMhr(&hData, experimental, expName))
2812 DestroyArray(hData.mHrtds);
2813 DestroyArray(hData.mHrirs);
2814 return 0;
2816 break;
2817 default:
2818 break;
2820 DestroyArray(hData.mHrtds);
2821 DestroyArray(hData.mHrirs);
2822 return 1;
2825 static void PrintHelp(const char *argv0, FILE *ofile)
2827 fprintf(ofile, "Usage: %s <command> [<option>...]\n\n", argv0);
2828 fprintf(ofile, "Commands:\n");
2829 fprintf(ofile, " -m, --make-mhr Makes an OpenAL Soft compatible HRTF data set.\n");
2830 fprintf(ofile, " Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
2831 fprintf(ofile, " -h, --help Displays this help information.\n\n");
2832 fprintf(ofile, "Options:\n");
2833 fprintf(ofile, " -r=<rate> Change the data set sample rate to the specified value and\n");
2834 fprintf(ofile, " resample the HRIRs accordingly.\n");
2835 fprintf(ofile, " -f=<points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
2836 fprintf(ofile, " -e={on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
2837 fprintf(ofile, " -s={on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
2838 fprintf(ofile, " -l={<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
2839 fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT);
2840 fprintf(ofile, " -w=<points> Specify the size of the truncation window that's applied\n");
2841 fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
2842 fprintf(ofile, " -d={dataset| Specify the model used for calculating the head-delay timing\n");
2843 fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
2844 fprintf(ofile, " -c=<size> Use a customized head radius measured ear-to-ear in meters.\n");
2845 fprintf(ofile, " -i=<filename> Specify an HRIR definition file to use (defaults to stdin).\n");
2846 fprintf(ofile, " -o=<filename> Specify an output file. Overrides command-selected default.\n");
2847 fprintf(ofile, " Use of '%%r' will be substituted with the data set sample rate.\n");
2850 // Standard command line dispatch.
2851 int main(const int argc, const char *argv[])
2853 const char *inName = NULL, *outName = NULL;
2854 OutputFormatT outFormat;
2855 uint outRate, fftSize;
2856 int equalize, surface;
2857 int experimental;
2858 char *end = NULL;
2859 HeadModelT model;
2860 uint truncSize;
2861 double radius;
2862 double limit;
2863 int argi;
2865 if(argc < 2 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)
2867 fprintf(stdout, "HRTF Processing and Composition Utility\n\n");
2868 PrintHelp(argv[0], stdout);
2869 return 0;
2872 if(strcmp(argv[1], "--make-mhr") == 0 || strcmp(argv[1], "-m") == 0)
2874 outName = "./oalsoft_hrtf_%r.mhr";
2875 outFormat = OF_MHR;
2877 else
2879 fprintf(stderr, "Error: Invalid command '%s'.\n\n", argv[1]);
2880 PrintHelp(argv[0], stderr);
2881 return -1;
2884 outRate = 0;
2885 fftSize = 0;
2886 equalize = DEFAULT_EQUALIZE;
2887 surface = DEFAULT_SURFACE;
2888 limit = DEFAULT_LIMIT;
2889 truncSize = DEFAULT_TRUNCSIZE;
2890 model = DEFAULT_HEAD_MODEL;
2891 radius = DEFAULT_CUSTOM_RADIUS;
2892 experimental = 0;
2894 argi = 2;
2895 while(argi < argc)
2897 if(strncmp(argv[argi], "-r=", 3) == 0)
2899 outRate = strtoul(&argv[argi][3], &end, 10);
2900 if(end[0] != '\0' || outRate < MIN_RATE || outRate > MAX_RATE)
2902 fprintf(stderr, "Error: Expected a value from %u to %u for '-r'.\n", MIN_RATE, MAX_RATE);
2903 return -1;
2906 else if(strncmp(argv[argi], "-f=", 3) == 0)
2908 fftSize = strtoul(&argv[argi][3], &end, 10);
2909 if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE)
2911 fprintf(stderr, "Error: Expected a power-of-two value from %u to %u for '-f'.\n", MIN_FFTSIZE, MAX_FFTSIZE);
2912 return -1;
2915 else if(strncmp(argv[argi], "-e=", 3) == 0)
2917 if(strcmp(&argv[argi][3], "on") == 0)
2918 equalize = 1;
2919 else if(strcmp(&argv[argi][3], "off") == 0)
2920 equalize = 0;
2921 else
2923 fprintf(stderr, "Error: Expected 'on' or 'off' for '-e'.\n");
2924 return -1;
2927 else if(strncmp(argv[argi], "-s=", 3) == 0)
2929 if(strcmp(&argv[argi][3], "on") == 0)
2930 surface = 1;
2931 else if(strcmp(&argv[argi][3], "off") == 0)
2932 surface = 0;
2933 else
2935 fprintf(stderr, "Error: Expected 'on' or 'off' for '-s'.\n");
2936 return -1;
2939 else if(strncmp(argv[argi], "-l=", 3) == 0)
2941 if(strcmp(&argv[argi][3], "none") == 0)
2942 limit = 0.0;
2943 else
2945 limit = strtod(&argv[argi] [3], &end);
2946 if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT)
2948 fprintf(stderr, "Error: Expected 'none' or a value from %.2f to %.2f for '-l'.\n", MIN_LIMIT, MAX_LIMIT);
2949 return -1;
2953 else if(strncmp(argv[argi], "-w=", 3) == 0)
2955 truncSize = strtoul(&argv[argi][3], &end, 10);
2956 if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE || (truncSize%MOD_TRUNCSIZE))
2958 fprintf(stderr, "Error: Expected a value from %u to %u in multiples of %u for '-w'.\n", MIN_TRUNCSIZE, MAX_TRUNCSIZE, MOD_TRUNCSIZE);
2959 return -1;
2962 else if(strncmp(argv[argi], "-d=", 3) == 0)
2964 if(strcmp(&argv[argi][3], "dataset") == 0)
2965 model = HM_DATASET;
2966 else if(strcmp(&argv[argi][3], "sphere") == 0)
2967 model = HM_SPHERE;
2968 else
2970 fprintf(stderr, "Error: Expected 'dataset' or 'sphere' for '-d'.\n");
2971 return -1;
2974 else if(strncmp(argv[argi], "-c=", 3) == 0)
2976 radius = strtod(&argv[argi][3], &end);
2977 if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS)
2979 fprintf(stderr, "Error: Expected a value from %.2f to %.2f for '-c'.\n", MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
2980 return -1;
2983 else if(strncmp(argv[argi], "-i=", 3) == 0)
2984 inName = &argv[argi][3];
2985 else if(strncmp(argv[argi], "-o=", 3) == 0)
2986 outName = &argv[argi][3];
2987 else if(strcmp(argv[argi], "--experimental") == 0)
2988 experimental = 1;
2989 else
2991 fprintf(stderr, "Error: Invalid option '%s'.\n", argv[argi]);
2992 return -1;
2994 argi++;
2996 if(!ProcessDefinition(inName, outRate, fftSize, equalize, surface, limit,
2997 truncSize, model, radius, outFormat, experimental,
2998 outName))
2999 return -1;
3000 fprintf(stdout, "Operation completed.\n");
3001 return 0;