"Unfix" the filter length calculation
[openal-soft.git] / utils / makehrtf.c
blob1447e9ee49d6b3d94d7e90c84a60c2e23a6805b8
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. Round up when
1300 // calculating the left offset to avoid increasing the transition width.
1301 l = (CalcKaiserOrder(180.0, width)+1) / 2;
1302 beta = CalcKaiserBeta(180.0);
1303 rs->mM = l*2 + 1;
1304 rs->mL = l;
1305 rs->mF = CreateArray(rs->mM);
1306 for(i = 0;i < ((int)rs->mM);i++)
1307 rs->mF[i] = SincFilter((int)l, beta, rs->mP, cutoff, i);
1310 // Clean up after the resampler.
1311 static void ResamplerClear(ResamplerT *rs)
1313 DestroyArray(rs->mF);
1314 rs->mF = NULL;
1317 // Perform the upsample-filter-downsample resampling operation using a
1318 // polyphase filter implementation.
1319 static void ResamplerRun(ResamplerT *rs, const uint inN, const double *in, const uint outN, double *out)
1321 const uint p = rs->mP, q = rs->mQ, m = rs->mM, l = rs->mL;
1322 const double *f = rs->mF;
1323 uint j_f, j_s;
1324 double *work;
1325 uint i;
1327 if(outN == 0)
1328 return;
1330 // Handle in-place operation.
1331 if(in == out)
1332 work = CreateArray(outN);
1333 else
1334 work = out;
1335 // Resample the input.
1336 for(i = 0;i < outN;i++)
1338 double r = 0.0;
1339 // Input starts at l to compensate for the filter delay. This will
1340 // drop any build-up from the first half of the filter.
1341 j_f = (l + (q * i)) % p;
1342 j_s = (l + (q * i)) / p;
1343 while(j_f < m)
1345 // Only take input when 0 <= j_s < inN. This single unsigned
1346 // comparison catches both cases.
1347 if(j_s < inN)
1348 r += f[j_f] * in[j_s];
1349 j_f += p;
1350 j_s--;
1352 work[i] = r;
1354 // Clean up after in-place operation.
1355 if(in == out)
1357 for(i = 0;i < outN;i++)
1358 out[i] = work[i];
1359 DestroyArray(work);
1363 /*************************
1364 *** File source input ***
1365 *************************/
1367 // Read a binary value of the specified byte order and byte size from a file,
1368 // storing it as a 32-bit unsigned integer.
1369 static int ReadBin4(FILE *fp, const char *filename, const ByteOrderT order, const uint bytes, uint32 *out)
1371 uint8 in[4];
1372 uint32 accum;
1373 uint i;
1375 if(fread(in, 1, bytes, fp) != bytes)
1377 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1378 return 0;
1380 accum = 0;
1381 switch(order)
1383 case BO_LITTLE:
1384 for(i = 0;i < bytes;i++)
1385 accum = (accum<<8) | in[bytes - i - 1];
1386 break;
1387 case BO_BIG:
1388 for(i = 0;i < bytes;i++)
1389 accum = (accum<<8) | in[i];
1390 break;
1391 default:
1392 break;
1394 *out = accum;
1395 return 1;
1398 // Read a binary value of the specified byte order from a file, storing it as
1399 // a 64-bit unsigned integer.
1400 static int ReadBin8(FILE *fp, const char *filename, const ByteOrderT order, uint64 *out)
1402 uint8 in [8];
1403 uint64 accum;
1404 uint i;
1406 if(fread(in, 1, 8, fp) != 8)
1408 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1409 return 0;
1411 accum = 0ULL;
1412 switch(order)
1414 case BO_LITTLE:
1415 for(i = 0;i < 8;i++)
1416 accum = (accum<<8) | in[8 - i - 1];
1417 break;
1418 case BO_BIG:
1419 for(i = 0;i < 8;i++)
1420 accum = (accum<<8) | in[i];
1421 break;
1422 default:
1423 break;
1425 *out = accum;
1426 return 1;
1429 /* Read a binary value of the specified type, byte order, and byte size from
1430 * a file, converting it to a double. For integer types, the significant
1431 * bits are used to normalize the result. The sign of bits determines
1432 * whether they are padded toward the MSB (negative) or LSB (positive).
1433 * Floating-point types are not normalized.
1435 static int ReadBinAsDouble(FILE *fp, const char *filename, const ByteOrderT order, const ElementTypeT type, const uint bytes, const int bits, double *out)
1437 union {
1438 uint32 ui;
1439 int32 i;
1440 float f;
1441 } v4;
1442 union {
1443 uint64 ui;
1444 double f;
1445 } v8;
1447 *out = 0.0;
1448 if(bytes > 4)
1450 if(!ReadBin8(fp, filename, order, &v8.ui))
1451 return 0;
1452 if(type == ET_FP)
1453 *out = v8.f;
1455 else
1457 if(!ReadBin4(fp, filename, order, bytes, &v4.ui))
1458 return 0;
1459 if(type == ET_FP)
1460 *out = v4.f;
1461 else
1463 if(bits > 0)
1464 v4.ui >>= (8*bytes) - ((uint)bits);
1465 else
1466 v4.ui &= (0xFFFFFFFF >> (32+bits));
1468 if(v4.ui&(uint)(1<<(abs(bits)-1)))
1469 v4.ui |= (0xFFFFFFFF << abs (bits));
1470 *out = v4.i / (double)(1<<(abs(bits)-1));
1473 return 1;
1476 /* Read an ascii value of the specified type from a file, converting it to a
1477 * double. For integer types, the significant bits are used to normalize the
1478 * result. The sign of the bits should always be positive. This also skips
1479 * up to one separator character before the element itself.
1481 static int ReadAsciiAsDouble(TokenReaderT *tr, const char *filename, const ElementTypeT type, const uint bits, double *out)
1483 if(TrIsOperator(tr, ","))
1484 TrReadOperator(tr, ",");
1485 else if(TrIsOperator(tr, ":"))
1486 TrReadOperator(tr, ":");
1487 else if(TrIsOperator(tr, ";"))
1488 TrReadOperator(tr, ";");
1489 else if(TrIsOperator(tr, "|"))
1490 TrReadOperator(tr, "|");
1492 if(type == ET_FP)
1494 if(!TrReadFloat(tr, -HUGE_VAL, HUGE_VAL, out))
1496 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1497 return 0;
1500 else
1502 int v;
1503 if(!TrReadInt(tr, -(1<<(bits-1)), (1<<(bits-1))-1, &v))
1505 fprintf(stderr, "Error: Bad read from file '%s'.\n", filename);
1506 return 0;
1508 *out = v / (double)((1<<(bits-1))-1);
1510 return 1;
1513 // Read the RIFF/RIFX WAVE format chunk from a file, validating it against
1514 // the source parameters and data set metrics.
1515 static int ReadWaveFormat(FILE *fp, const ByteOrderT order, const uint hrirRate, SourceRefT *src)
1517 uint32 fourCC, chunkSize;
1518 uint32 format, channels, rate, dummy, block, size, bits;
1520 chunkSize = 0;
1521 do {
1522 if (chunkSize > 0)
1523 fseek (fp, (long) chunkSize, SEEK_CUR);
1524 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1525 !ReadBin4(fp, src->mPath, order, 4, &chunkSize))
1526 return 0;
1527 } while(fourCC != FOURCC_FMT);
1528 if(!ReadBin4(fp, src->mPath, order, 2, & format) ||
1529 !ReadBin4(fp, src->mPath, order, 2, & channels) ||
1530 !ReadBin4(fp, src->mPath, order, 4, & rate) ||
1531 !ReadBin4(fp, src->mPath, order, 4, & dummy) ||
1532 !ReadBin4(fp, src->mPath, order, 2, & block))
1533 return (0);
1534 block /= channels;
1535 if(chunkSize > 14)
1537 if(!ReadBin4(fp, src->mPath, order, 2, &size))
1538 return 0;
1539 size /= 8;
1540 if(block > size)
1541 size = block;
1543 else
1544 size = block;
1545 if(format == WAVE_FORMAT_EXTENSIBLE)
1547 fseek(fp, 2, SEEK_CUR);
1548 if(!ReadBin4(fp, src->mPath, order, 2, &bits))
1549 return 0;
1550 if(bits == 0)
1551 bits = 8 * size;
1552 fseek(fp, 4, SEEK_CUR);
1553 if(!ReadBin4(fp, src->mPath, order, 2, &format))
1554 return 0;
1555 fseek(fp, (long)(chunkSize - 26), SEEK_CUR);
1557 else
1559 bits = 8 * size;
1560 if(chunkSize > 14)
1561 fseek(fp, (long)(chunkSize - 16), SEEK_CUR);
1562 else
1563 fseek(fp, (long)(chunkSize - 14), SEEK_CUR);
1565 if(format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT)
1567 fprintf(stderr, "Error: Unsupported WAVE format in file '%s'.\n", src->mPath);
1568 return 0;
1570 if(src->mChannel >= channels)
1572 fprintf(stderr, "Error: Missing source channel in WAVE file '%s'.\n", src->mPath);
1573 return 0;
1575 if(rate != hrirRate)
1577 fprintf(stderr, "Error: Mismatched source sample rate in WAVE file '%s'.\n", src->mPath);
1578 return 0;
1580 if(format == WAVE_FORMAT_PCM)
1582 if(size < 2 || size > 4)
1584 fprintf(stderr, "Error: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
1585 return 0;
1587 if(bits < 16 || bits > (8*size))
1589 fprintf (stderr, "Error: Bad significant bits in WAVE file '%s'.\n", src->mPath);
1590 return 0;
1592 src->mType = ET_INT;
1594 else
1596 if(size != 4 && size != 8)
1598 fprintf(stderr, "Error: Unsupported sample size in WAVE file '%s'.\n", src->mPath);
1599 return 0;
1601 src->mType = ET_FP;
1603 src->mSize = size;
1604 src->mBits = (int)bits;
1605 src->mSkip = channels;
1606 return 1;
1609 // Read a RIFF/RIFX WAVE data chunk, converting all elements to doubles.
1610 static int ReadWaveData(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1612 int pre, post, skip;
1613 uint i;
1615 pre = (int)(src->mSize * src->mChannel);
1616 post = (int)(src->mSize * (src->mSkip - src->mChannel - 1));
1617 skip = 0;
1618 for(i = 0;i < n;i++)
1620 skip += pre;
1621 if(skip > 0)
1622 fseek(fp, skip, SEEK_CUR);
1623 if(!ReadBinAsDouble(fp, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
1624 return 0;
1625 skip = post;
1627 if(skip > 0)
1628 fseek(fp, skip, SEEK_CUR);
1629 return 1;
1632 // Read the RIFF/RIFX WAVE list or data chunk, converting all elements to
1633 // doubles.
1634 static int ReadWaveList(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1636 uint32 fourCC, chunkSize, listSize, count;
1637 uint block, skip, offset, i;
1638 double lastSample;
1640 for (;;) {
1641 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, & fourCC) ||
1642 !ReadBin4(fp, src->mPath, order, 4, & chunkSize))
1643 return (0);
1645 if(fourCC == FOURCC_DATA)
1647 block = src->mSize * src->mSkip;
1648 count = chunkSize / block;
1649 if(count < (src->mOffset + n))
1651 fprintf(stderr, "Error: Bad read from file '%s'.\n", src->mPath);
1652 return 0;
1654 fseek(fp, (long)(src->mOffset * block), SEEK_CUR);
1655 if(!ReadWaveData(fp, src, order, n, &hrir[0]))
1656 return 0;
1657 return 1;
1659 else if(fourCC == FOURCC_LIST)
1661 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC))
1662 return 0;
1663 chunkSize -= 4;
1664 if(fourCC == FOURCC_WAVL)
1665 break;
1667 if(chunkSize > 0)
1668 fseek(fp, (long)chunkSize, SEEK_CUR);
1670 listSize = chunkSize;
1671 block = src->mSize * src->mSkip;
1672 skip = src->mOffset;
1673 offset = 0;
1674 lastSample = 0.0;
1675 while(offset < n && listSize > 8)
1677 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1678 !ReadBin4(fp, src->mPath, order, 4, &chunkSize))
1679 return 0;
1680 listSize -= 8 + chunkSize;
1681 if(fourCC == FOURCC_DATA)
1683 count = chunkSize / block;
1684 if(count > skip)
1686 fseek(fp, (long)(skip * block), SEEK_CUR);
1687 chunkSize -= skip * block;
1688 count -= skip;
1689 skip = 0;
1690 if(count > (n - offset))
1691 count = n - offset;
1692 if(!ReadWaveData(fp, src, order, count, &hrir[offset]))
1693 return 0;
1694 chunkSize -= count * block;
1695 offset += count;
1696 lastSample = hrir [offset - 1];
1698 else
1700 skip -= count;
1701 count = 0;
1704 else if(fourCC == FOURCC_SLNT)
1706 if(!ReadBin4(fp, src->mPath, order, 4, &count))
1707 return 0;
1708 chunkSize -= 4;
1709 if(count > skip)
1711 count -= skip;
1712 skip = 0;
1713 if(count > (n - offset))
1714 count = n - offset;
1715 for(i = 0; i < count; i ++)
1716 hrir[offset + i] = lastSample;
1717 offset += count;
1719 else
1721 skip -= count;
1722 count = 0;
1725 if(chunkSize > 0)
1726 fseek(fp, (long)chunkSize, SEEK_CUR);
1728 if(offset < n)
1730 fprintf(stderr, "Error: Bad read from file '%s'.\n", src->mPath);
1731 return 0;
1733 return 1;
1736 // Load a source HRIR from a RIFF/RIFX WAVE file.
1737 static int LoadWaveSource(FILE *fp, SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
1739 uint32 fourCC, dummy;
1740 ByteOrderT order;
1742 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC) ||
1743 !ReadBin4(fp, src->mPath, BO_LITTLE, 4, &dummy))
1744 return 0;
1745 if(fourCC == FOURCC_RIFF)
1746 order = BO_LITTLE;
1747 else if(fourCC == FOURCC_RIFX)
1748 order = BO_BIG;
1749 else
1751 fprintf(stderr, "Error: No RIFF/RIFX chunk in file '%s'.\n", src->mPath);
1752 return 0;
1755 if(!ReadBin4(fp, src->mPath, BO_LITTLE, 4, &fourCC))
1756 return 0;
1757 if(fourCC != FOURCC_WAVE)
1759 fprintf(stderr, "Error: Not a RIFF/RIFX WAVE file '%s'.\n", src->mPath);
1760 return 0;
1762 if(!ReadWaveFormat(fp, order, hrirRate, src))
1763 return 0;
1764 if(!ReadWaveList(fp, src, order, n, hrir))
1765 return 0;
1766 return 1;
1769 // Load a source HRIR from a binary file.
1770 static int LoadBinarySource(FILE *fp, const SourceRefT *src, const ByteOrderT order, const uint n, double *hrir)
1772 uint i;
1774 fseek(fp, (long)src->mOffset, SEEK_SET);
1775 for(i = 0;i < n;i++)
1777 if(!ReadBinAsDouble(fp, src->mPath, order, src->mType, src->mSize, src->mBits, &hrir[i]))
1778 return 0;
1779 if(src->mSkip > 0)
1780 fseek(fp, (long)src->mSkip, SEEK_CUR);
1782 return 1;
1785 // Load a source HRIR from an ASCII text file containing a list of elements
1786 // separated by whitespace or common list operators (',', ';', ':', '|').
1787 static int LoadAsciiSource(FILE *fp, const SourceRefT *src, const uint n, double *hrir)
1789 TokenReaderT tr;
1790 uint i, j;
1791 double dummy;
1793 TrSetup(fp, NULL, &tr);
1794 for(i = 0;i < src->mOffset;i++)
1796 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &dummy))
1797 return (0);
1799 for(i = 0;i < n;i++)
1801 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &hrir[i]))
1802 return 0;
1803 for(j = 0;j < src->mSkip;j++)
1805 if(!ReadAsciiAsDouble(&tr, src->mPath, src->mType, (uint)src->mBits, &dummy))
1806 return 0;
1809 return 1;
1812 // Load a source HRIR from a supported file type.
1813 static int LoadSource(SourceRefT *src, const uint hrirRate, const uint n, double *hrir)
1815 int result;
1816 FILE *fp;
1818 if (src->mFormat == SF_ASCII)
1819 fp = fopen(src->mPath, "r");
1820 else
1821 fp = fopen(src->mPath, "rb");
1822 if(fp == NULL)
1824 fprintf(stderr, "Error: Could not open source file '%s'.\n", src->mPath);
1825 return 0;
1827 if(src->mFormat == SF_WAVE)
1828 result = LoadWaveSource(fp, src, hrirRate, n, hrir);
1829 else if(src->mFormat == SF_BIN_LE)
1830 result = LoadBinarySource(fp, src, BO_LITTLE, n, hrir);
1831 else if(src->mFormat == SF_BIN_BE)
1832 result = LoadBinarySource(fp, src, BO_BIG, n, hrir);
1833 else
1834 result = LoadAsciiSource(fp, src, n, hrir);
1835 fclose(fp);
1836 return result;
1840 /***************************
1841 *** File storage output ***
1842 ***************************/
1844 // Write an ASCII string to a file.
1845 static int WriteAscii(const char *out, FILE *fp, const char *filename)
1847 size_t len;
1849 len = strlen(out);
1850 if(fwrite(out, 1, len, fp) != len)
1852 fclose(fp);
1853 fprintf(stderr, "Error: Bad write to file '%s'.\n", filename);
1854 return 0;
1856 return 1;
1859 // Write a binary value of the given byte order and byte size to a file,
1860 // loading it from a 32-bit unsigned integer.
1861 static int WriteBin4(const ByteOrderT order, const uint bytes, const uint32 in, FILE *fp, const char *filename)
1863 uint8 out[4];
1864 uint i;
1866 switch(order)
1868 case BO_LITTLE:
1869 for(i = 0;i < bytes;i++)
1870 out[i] = (in>>(i*8)) & 0x000000FF;
1871 break;
1872 case BO_BIG:
1873 for(i = 0;i < bytes;i++)
1874 out[bytes - i - 1] = (in>>(i*8)) & 0x000000FF;
1875 break;
1876 default:
1877 break;
1879 if(fwrite(out, 1, bytes, fp) != bytes)
1881 fprintf(stderr, "Error: Bad write to file '%s'.\n", filename);
1882 return 0;
1884 return 1;
1887 // Store the OpenAL Soft HRTF data set.
1888 static int StoreMhr(const HrirDataT *hData, const int experimental, const char *filename)
1890 uint e, step, end, n, j, i;
1891 uint dither_seed;
1892 FILE *fp;
1893 int v;
1895 if((fp=fopen(filename, "wb")) == NULL)
1897 fprintf(stderr, "Error: Could not open MHR file '%s'.\n", filename);
1898 return 0;
1900 if(!WriteAscii(experimental ? MHR_FORMAT_EXPERIMENTAL : MHR_FORMAT, fp, filename))
1901 return 0;
1902 if(!WriteBin4(BO_LITTLE, 4, (uint32)hData->mIrRate, fp, filename))
1903 return 0;
1904 if(experimental)
1906 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mSampleType, fp, filename))
1907 return 0;
1908 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mChannelType, fp, filename))
1909 return 0;
1911 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mIrPoints, fp, filename))
1912 return 0;
1913 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mEvCount, fp, filename))
1914 return 0;
1915 for(e = 0;e < hData->mEvCount;e++)
1917 if(!WriteBin4(BO_LITTLE, 1, (uint32)hData->mAzCount[e], fp, filename))
1918 return 0;
1920 step = hData->mIrSize;
1921 end = hData->mIrCount * step;
1922 n = hData->mIrPoints;
1923 dither_seed = 22222;
1924 for(j = 0;j < end;j += step)
1926 const double scale = (!experimental || hData->mSampleType == ST_S16) ? 32767.0 :
1927 ((hData->mSampleType == ST_S24) ? 8388607.0 : 0.0);
1928 const int bps = (!experimental || hData->mSampleType == ST_S16) ? 2 :
1929 ((hData->mSampleType == ST_S24) ? 3 : 0);
1930 double out[MAX_TRUNCSIZE];
1931 for(i = 0;i < n;i++)
1932 out[i] = TpdfDither(scale * hData->mHrirs[j+i], &dither_seed);
1933 for(i = 0;i < n;i++)
1935 v = (int)Clamp(out[i], -scale-1.0, scale);
1936 if(!WriteBin4(BO_LITTLE, bps, (uint32)v, fp, filename))
1937 return 0;
1940 for(j = 0;j < hData->mIrCount;j++)
1942 v = (int)fmin(round(hData->mIrRate * hData->mHrtds[j]), MAX_HRTD);
1943 if(!WriteBin4(BO_LITTLE, 1, (uint32)v, fp, filename))
1944 return 0;
1946 fclose(fp);
1947 return 1;
1951 /***********************
1952 *** HRTF processing ***
1953 ***********************/
1955 // Calculate the onset time of an HRIR and average it with any existing
1956 // timing for its elevation and azimuth.
1957 static void AverageHrirOnset(const double *hrir, const double f, const uint ei, const uint ai, const HrirDataT *hData)
1959 double mag;
1960 uint n, i, j;
1962 mag = 0.0;
1963 n = hData->mIrPoints;
1964 for(i = 0;i < n;i++)
1965 mag = fmax(fabs(hrir[i]), mag);
1966 mag *= 0.15;
1967 for(i = 0;i < n;i++)
1969 if(fabs(hrir[i]) >= mag)
1970 break;
1972 j = hData->mEvOffset[ei] + ai;
1973 hData->mHrtds[j] = Lerp(hData->mHrtds[j], ((double)i) / hData->mIrRate, f);
1976 // Calculate the magnitude response of an HRIR and average it with any
1977 // existing responses for its elevation and azimuth.
1978 static void AverageHrirMagnitude(const double *hrir, const double f, const uint ei, const uint ai, const HrirDataT *hData)
1980 double *re, *im;
1981 uint n, m, i, j;
1983 n = hData->mFftSize;
1984 re = CreateArray(n);
1985 im = CreateArray(n);
1986 for(i = 0;i < hData->mIrPoints;i++)
1988 re[i] = hrir[i];
1989 im[i] = 0.0;
1991 for(;i < n;i++)
1993 re[i] = 0.0;
1994 im[i] = 0.0;
1996 FftForward(n, re, im, re, im);
1997 MagnitudeResponse(n, re, im, re);
1998 m = 1 + (n / 2);
1999 j = (hData->mEvOffset[ei] + ai) * hData->mIrSize;
2000 for(i = 0;i < m;i++)
2001 hData->mHrirs[j+i] = Lerp(hData->mHrirs[j+i], re[i], f);
2002 DestroyArray(im);
2003 DestroyArray(re);
2006 /* Calculate the contribution of each HRIR to the diffuse-field average based
2007 * on the area of its surface patch. All patches are centered at the HRIR
2008 * coordinates on the unit sphere and are measured by solid angle.
2010 static void CalculateDfWeights(const HrirDataT *hData, double *weights)
2012 double evs, sum, ev, up_ev, down_ev, solidAngle;
2013 uint ei;
2015 evs = 90.0 / (hData->mEvCount - 1);
2016 sum = 0.0;
2017 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2019 // For each elevation, calculate the upper and lower limits of the
2020 // patch band.
2021 ev = -90.0 + (ei * 2.0 * evs);
2022 if(ei < (hData->mEvCount - 1))
2023 up_ev = (ev + evs) * M_PI / 180.0;
2024 else
2025 up_ev = M_PI / 2.0;
2026 if(ei > 0)
2027 down_ev = (ev - evs) * M_PI / 180.0;
2028 else
2029 down_ev = -M_PI / 2.0;
2030 // Calculate the area of the patch band.
2031 solidAngle = 2.0 * M_PI * (sin(up_ev) - sin(down_ev));
2032 // Each weight is the area of one patch.
2033 weights[ei] = solidAngle / hData->mAzCount [ei];
2034 // Sum the total surface area covered by the HRIRs.
2035 sum += solidAngle;
2037 // Normalize the weights given the total surface coverage.
2038 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2039 weights[ei] /= sum;
2042 /* Calculate the diffuse-field average from the given magnitude responses of
2043 * the HRIR set. Weighting can be applied to compensate for the varying
2044 * surface area covered by each HRIR. The final average can then be limited
2045 * by the specified magnitude range (in positive dB; 0.0 to skip).
2047 static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const int weighted, const double limit, double *dfa)
2049 uint ei, ai, count, step, start, end, m, j, i;
2050 double *weights;
2052 weights = CreateArray(hData->mEvCount);
2053 if(weighted)
2055 // Use coverage weighting to calculate the average.
2056 CalculateDfWeights(hData, weights);
2058 else
2060 // If coverage weighting is not used, the weights still need to be
2061 // averaged by the number of HRIRs.
2062 count = 0;
2063 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2064 count += hData->mAzCount [ei];
2065 for(ei = hData->mEvStart;ei < hData->mEvCount;ei++)
2066 weights[ei] = 1.0 / count;
2068 ei = hData->mEvStart;
2069 ai = 0;
2070 step = hData->mIrSize;
2071 start = hData->mEvOffset[ei] * step;
2072 end = hData->mIrCount * step;
2073 m = 1 + (hData->mFftSize / 2);
2074 for(i = 0;i < m;i++)
2075 dfa[i] = 0.0;
2076 for(j = start;j < end;j += step)
2078 // Get the weight for this HRIR's contribution.
2079 double weight = weights[ei];
2080 // Add this HRIR's weighted power average to the total.
2081 for(i = 0;i < m;i++)
2082 dfa[i] += weight * hData->mHrirs[j+i] * hData->mHrirs[j+i];
2083 // Determine the next weight to use.
2084 ai++;
2085 if(ai >= hData->mAzCount[ei])
2087 ei++;
2088 ai = 0;
2091 // Finish the average calculation and keep it from being too small.
2092 for(i = 0;i < m;i++)
2093 dfa[i] = fmax(sqrt(dfa[i]), EPSILON);
2094 // Apply a limit to the magnitude range of the diffuse-field average if
2095 // desired.
2096 if(limit > 0.0)
2097 LimitMagnitudeResponse(hData->mFftSize, limit, dfa, dfa);
2098 DestroyArray(weights);
2101 // Perform diffuse-field equalization on the magnitude responses of the HRIR
2102 // set using the given average response.
2103 static void DiffuseFieldEqualize(const double *dfa, const HrirDataT *hData)
2105 uint step, start, end, m, j, i;
2107 step = hData->mIrSize;
2108 start = hData->mEvOffset[hData->mEvStart] * step;
2109 end = hData->mIrCount * step;
2110 m = 1 + (hData->mFftSize / 2);
2111 for(j = start;j < end;j += step)
2113 for(i = 0;i < m;i++)
2114 hData->mHrirs[j+i] /= dfa[i];
2118 // Perform minimum-phase reconstruction using the magnitude responses of the
2119 // HRIR set.
2120 static void ReconstructHrirs(const HrirDataT *hData)
2122 uint step, start, end, n, j, i;
2123 double *re, *im;
2125 step = hData->mIrSize;
2126 start = hData->mEvOffset[hData->mEvStart] * step;
2127 end = hData->mIrCount * step;
2128 n = hData->mFftSize;
2129 re = CreateArray(n);
2130 im = CreateArray(n);
2131 for(j = start;j < end;j += step)
2133 MinimumPhase(n, &hData->mHrirs[j], re, im);
2134 FftInverse(n, re, im, re, im);
2135 for(i = 0;i < hData->mIrPoints;i++)
2136 hData->mHrirs[j+i] = re[i];
2138 DestroyArray (im);
2139 DestroyArray (re);
2142 // Resamples the HRIRs for use at the given sampling rate.
2143 static void ResampleHrirs(const uint rate, HrirDataT *hData)
2145 uint n, step, start, end, j;
2146 ResamplerT rs;
2148 ResamplerSetup(&rs, hData->mIrRate, rate);
2149 n = hData->mIrPoints;
2150 step = hData->mIrSize;
2151 start = hData->mEvOffset[hData->mEvStart] * step;
2152 end = hData->mIrCount * step;
2153 for(j = start;j < end;j += step)
2154 ResamplerRun(&rs, n, &hData->mHrirs[j], n, &hData->mHrirs[j]);
2155 ResamplerClear(&rs);
2156 hData->mIrRate = rate;
2159 /* Given an elevation index and an azimuth, calculate the indices of the two
2160 * HRIRs that bound the coordinate along with a factor for calculating the
2161 * continous HRIR using interpolation.
2163 static void CalcAzIndices(const HrirDataT *hData, const uint ei, const double az, uint *j0, uint *j1, double *jf)
2165 double af;
2166 uint ai;
2168 af = ((2.0*M_PI) + az) * hData->mAzCount[ei] / (2.0*M_PI);
2169 ai = ((uint)af) % hData->mAzCount[ei];
2170 af -= floor(af);
2172 *j0 = hData->mEvOffset[ei] + ai;
2173 *j1 = hData->mEvOffset[ei] + ((ai+1) % hData->mAzCount [ei]);
2174 *jf = af;
2177 // Synthesize any missing onset timings at the bottom elevations. This just
2178 // blends between slightly exaggerated known onsets. Not an accurate model.
2179 static void SynthesizeOnsets(HrirDataT *hData)
2181 uint oi, e, a, j0, j1;
2182 double t, of, jf;
2184 oi = hData->mEvStart;
2185 t = 0.0;
2186 for(a = 0;a < hData->mAzCount[oi];a++)
2187 t += hData->mHrtds[hData->mEvOffset[oi] + a];
2188 hData->mHrtds[0] = 1.32e-4 + (t / hData->mAzCount[oi]);
2189 for(e = 1;e < hData->mEvStart;e++)
2191 of = ((double)e) / hData->mEvStart;
2192 for(a = 0;a < hData->mAzCount[e];a++)
2194 CalcAzIndices(hData, oi, a * 2.0 * M_PI / hData->mAzCount[e], &j0, &j1, &jf);
2195 hData->mHrtds[hData->mEvOffset[e] + a] = Lerp(hData->mHrtds[0], Lerp(hData->mHrtds[j0], hData->mHrtds[j1], jf), of);
2200 /* Attempt to synthesize any missing HRIRs at the bottom elevations. Right
2201 * now this just blends the lowest elevation HRIRs together and applies some
2202 * attenuation and high frequency damping. It is a simple, if inaccurate
2203 * model.
2205 static void SynthesizeHrirs (HrirDataT *hData)
2207 uint oi, a, e, step, n, i, j;
2208 double lp[4], s0, s1;
2209 double of, b;
2210 uint j0, j1;
2211 double jf;
2213 if(hData->mEvStart <= 0)
2214 return;
2215 step = hData->mIrSize;
2216 oi = hData->mEvStart;
2217 n = hData->mIrPoints;
2218 for(i = 0;i < n;i++)
2219 hData->mHrirs[i] = 0.0;
2220 for(a = 0;a < hData->mAzCount[oi];a++)
2222 j = (hData->mEvOffset[oi] + a) * step;
2223 for(i = 0;i < n;i++)
2224 hData->mHrirs[i] += hData->mHrirs[j+i] / hData->mAzCount[oi];
2226 for(e = 1;e < hData->mEvStart;e++)
2228 of = ((double)e) / hData->mEvStart;
2229 b = (1.0 - of) * (3.5e-6 * hData->mIrRate);
2230 for(a = 0;a < hData->mAzCount[e];a++)
2232 j = (hData->mEvOffset[e] + a) * step;
2233 CalcAzIndices(hData, oi, a * 2.0 * M_PI / hData->mAzCount[e], &j0, &j1, &jf);
2234 j0 *= step;
2235 j1 *= step;
2236 lp[0] = 0.0;
2237 lp[1] = 0.0;
2238 lp[2] = 0.0;
2239 lp[3] = 0.0;
2240 for(i = 0;i < n;i++)
2242 s0 = hData->mHrirs[i];
2243 s1 = Lerp(hData->mHrirs[j0+i], hData->mHrirs[j1+i], jf);
2244 s0 = Lerp(s0, s1, of);
2245 lp[0] = Lerp(s0, lp[0], b);
2246 lp[1] = Lerp(lp[0], lp[1], b);
2247 lp[2] = Lerp(lp[1], lp[2], b);
2248 lp[3] = Lerp(lp[2], lp[3], b);
2249 hData->mHrirs[j+i] = lp[3];
2253 b = 3.5e-6 * hData->mIrRate;
2254 lp[0] = 0.0;
2255 lp[1] = 0.0;
2256 lp[2] = 0.0;
2257 lp[3] = 0.0;
2258 for(i = 0;i < n;i++)
2260 s0 = hData->mHrirs[i];
2261 lp[0] = Lerp(s0, lp[0], b);
2262 lp[1] = Lerp(lp[0], lp[1], b);
2263 lp[2] = Lerp(lp[1], lp[2], b);
2264 lp[3] = Lerp(lp[2], lp[3], b);
2265 hData->mHrirs[i] = lp[3];
2267 hData->mEvStart = 0;
2270 // The following routines assume a full set of HRIRs for all elevations.
2272 // Normalize the HRIR set and slightly attenuate the result.
2273 static void NormalizeHrirs (const HrirDataT *hData)
2275 uint step, end, n, j, i;
2276 double maxLevel;
2278 step = hData->mIrSize;
2279 end = hData->mIrCount * step;
2280 n = hData->mIrPoints;
2281 maxLevel = 0.0;
2282 for(j = 0;j < end;j += step)
2284 for(i = 0;i < n;i++)
2285 maxLevel = fmax(fabs(hData->mHrirs[j+i]), maxLevel);
2287 maxLevel = 1.01 * maxLevel;
2288 for(j = 0;j < end;j += step)
2290 for(i = 0;i < n;i++)
2291 hData->mHrirs[j+i] /= maxLevel;
2295 // Calculate the left-ear time delay using a spherical head model.
2296 static double CalcLTD(const double ev, const double az, const double rad, const double dist)
2298 double azp, dlp, l, al;
2300 azp = asin(cos(ev) * sin(az));
2301 dlp = sqrt((dist*dist) + (rad*rad) + (2.0*dist*rad*sin(azp)));
2302 l = sqrt((dist*dist) - (rad*rad));
2303 al = (0.5 * M_PI) + azp;
2304 if(dlp > l)
2305 dlp = l + (rad * (al - acos(rad / dist)));
2306 return (dlp / 343.3);
2309 // Calculate the effective head-related time delays for each minimum-phase
2310 // HRIR.
2311 static void CalculateHrtds (const HeadModelT model, const double radius, HrirDataT *hData)
2313 double minHrtd, maxHrtd;
2314 uint e, a, j;
2315 double t;
2317 minHrtd = 1000.0;
2318 maxHrtd = -1000.0;
2319 for(e = 0;e < hData->mEvCount;e++)
2321 for(a = 0;a < hData->mAzCount[e];a++)
2323 j = hData->mEvOffset[e] + a;
2324 if(model == HM_DATASET)
2325 t = hData->mHrtds[j] * radius / hData->mRadius;
2326 else
2327 t = CalcLTD((-90.0 + (e * 180.0 / (hData->mEvCount - 1))) * M_PI / 180.0,
2328 (a * 360.0 / hData->mAzCount [e]) * M_PI / 180.0,
2329 radius, hData->mDistance);
2330 hData->mHrtds[j] = t;
2331 maxHrtd = fmax(t, maxHrtd);
2332 minHrtd = fmin(t, minHrtd);
2335 maxHrtd -= minHrtd;
2336 for(j = 0;j < hData->mIrCount;j++)
2337 hData->mHrtds[j] -= minHrtd;
2338 hData->mMaxHrtd = maxHrtd;
2342 // Process the data set definition to read and validate the data set metrics.
2343 static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint truncSize, HrirDataT *hData)
2345 int hasRate = 0, hasPoints = 0, hasAzimuths = 0;
2346 int hasRadius = 0, hasDistance = 0;
2347 char ident[MAX_IDENT_LEN+1];
2348 uint line, col;
2349 double fpVal;
2350 uint points;
2351 int intVal;
2353 while(!(hasRate && hasPoints && hasAzimuths && hasRadius && hasDistance))
2355 TrIndication(tr, & line, & col);
2356 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2357 return 0;
2358 if(strcasecmp(ident, "rate") == 0)
2360 if(hasRate)
2362 TrErrorAt(tr, line, col, "Redefinition of 'rate'.\n");
2363 return 0;
2365 if(!TrReadOperator(tr, "="))
2366 return 0;
2367 if(!TrReadInt(tr, MIN_RATE, MAX_RATE, &intVal))
2368 return 0;
2369 hData->mIrRate = (uint)intVal;
2370 hasRate = 1;
2372 else if(strcasecmp(ident, "points") == 0)
2374 if (hasPoints) {
2375 TrErrorAt(tr, line, col, "Redefinition of 'points'.\n");
2376 return 0;
2378 if(!TrReadOperator(tr, "="))
2379 return 0;
2380 TrIndication(tr, &line, &col);
2381 if(!TrReadInt(tr, MIN_POINTS, MAX_POINTS, &intVal))
2382 return 0;
2383 points = (uint)intVal;
2384 if(fftSize > 0 && points > fftSize)
2386 TrErrorAt(tr, line, col, "Value exceeds the overridden FFT size.\n");
2387 return 0;
2389 if(points < truncSize)
2391 TrErrorAt(tr, line, col, "Value is below the truncation size.\n");
2392 return 0;
2394 hData->mIrPoints = points;
2395 if(fftSize <= 0)
2397 hData->mFftSize = DEFAULT_FFTSIZE;
2398 hData->mIrSize = 1 + (DEFAULT_FFTSIZE / 2);
2400 else
2402 hData->mFftSize = fftSize;
2403 hData->mIrSize = 1 + (fftSize / 2);
2404 if(points > hData->mIrSize)
2405 hData->mIrSize = points;
2407 hasPoints = 1;
2409 else if(strcasecmp(ident, "azimuths") == 0)
2411 if(hasAzimuths)
2413 TrErrorAt(tr, line, col, "Redefinition of 'azimuths'.\n");
2414 return 0;
2416 if(!TrReadOperator(tr, "="))
2417 return 0;
2418 hData->mIrCount = 0;
2419 hData->mEvCount = 0;
2420 hData->mEvOffset[0] = 0;
2421 for(;;)
2423 if(!TrReadInt(tr, MIN_AZ_COUNT, MAX_AZ_COUNT, &intVal))
2424 return 0;
2425 hData->mAzCount[hData->mEvCount] = (uint)intVal;
2426 hData->mIrCount += (uint)intVal;
2427 hData->mEvCount ++;
2428 if(!TrIsOperator(tr, ","))
2429 break;
2430 if(hData->mEvCount >= MAX_EV_COUNT)
2432 TrError(tr, "Exceeded the maximum of %d elevations.\n", MAX_EV_COUNT);
2433 return 0;
2435 hData->mEvOffset[hData->mEvCount] = hData->mEvOffset[hData->mEvCount - 1] + ((uint)intVal);
2436 TrReadOperator(tr, ",");
2438 if(hData->mEvCount < MIN_EV_COUNT)
2440 TrErrorAt(tr, line, col, "Did not reach the minimum of %d azimuth counts.\n", MIN_EV_COUNT);
2441 return 0;
2443 hasAzimuths = 1;
2445 else if(strcasecmp(ident, "radius") == 0)
2447 if(hasRadius)
2449 TrErrorAt(tr, line, col, "Redefinition of 'radius'.\n");
2450 return 0;
2452 if(!TrReadOperator(tr, "="))
2453 return 0;
2454 if(!TrReadFloat(tr, MIN_RADIUS, MAX_RADIUS, &fpVal))
2455 return 0;
2456 hData->mRadius = fpVal;
2457 hasRadius = 1;
2459 else if(strcasecmp(ident, "distance") == 0)
2461 if(hasDistance)
2463 TrErrorAt(tr, line, col, "Redefinition of 'distance'.\n");
2464 return 0;
2466 if(!TrReadOperator(tr, "="))
2467 return 0;
2468 if(!TrReadFloat(tr, MIN_DISTANCE, MAX_DISTANCE, & fpVal))
2469 return 0;
2470 hData->mDistance = fpVal;
2471 hasDistance = 1;
2473 else
2475 TrErrorAt(tr, line, col, "Expected a metric name.\n");
2476 return 0;
2478 TrSkipWhitespace (tr);
2480 return 1;
2483 // Parse an index pair from the data set definition.
2484 static int ReadIndexPair(TokenReaderT *tr, const HrirDataT *hData, uint *ei, uint *ai)
2486 int intVal;
2487 if(!TrReadInt(tr, 0, (int)hData->mEvCount, &intVal))
2488 return 0;
2489 *ei = (uint)intVal;
2490 if(!TrReadOperator(tr, ","))
2491 return 0;
2492 if(!TrReadInt(tr, 0, (int)hData->mAzCount[*ei], &intVal))
2493 return 0;
2494 *ai = (uint)intVal;
2495 return 1;
2498 // Match the source format from a given identifier.
2499 static SourceFormatT MatchSourceFormat(const char *ident)
2501 if(strcasecmp(ident, "wave") == 0)
2502 return SF_WAVE;
2503 if(strcasecmp(ident, "bin_le") == 0)
2504 return SF_BIN_LE;
2505 if(strcasecmp(ident, "bin_be") == 0)
2506 return SF_BIN_BE;
2507 if(strcasecmp(ident, "ascii") == 0)
2508 return SF_ASCII;
2509 return SF_NONE;
2512 // Match the source element type from a given identifier.
2513 static ElementTypeT MatchElementType(const char *ident)
2515 if(strcasecmp(ident, "int") == 0)
2516 return ET_INT;
2517 if(strcasecmp(ident, "fp") == 0)
2518 return ET_FP;
2519 return ET_NONE;
2522 // Parse and validate a source reference from the data set definition.
2523 static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src)
2525 char ident[MAX_IDENT_LEN+1];
2526 uint line, col;
2527 int intVal;
2529 TrIndication(tr, &line, &col);
2530 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2531 return 0;
2532 src->mFormat = MatchSourceFormat(ident);
2533 if(src->mFormat == SF_NONE)
2535 TrErrorAt(tr, line, col, "Expected a source format.\n");
2536 return 0;
2538 if(!TrReadOperator(tr, "("))
2539 return 0;
2540 if(src->mFormat == SF_WAVE)
2542 if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal))
2543 return 0;
2544 src->mType = ET_NONE;
2545 src->mSize = 0;
2546 src->mBits = 0;
2547 src->mChannel = (uint)intVal;
2548 src->mSkip = 0;
2550 else
2552 TrIndication(tr, &line, &col);
2553 if(!TrReadIdent(tr, MAX_IDENT_LEN, ident))
2554 return 0;
2555 src->mType = MatchElementType(ident);
2556 if(src->mType == ET_NONE)
2558 TrErrorAt(tr, line, col, "Expected a source element type.\n");
2559 return 0;
2561 if(src->mFormat == SF_BIN_LE || src->mFormat == SF_BIN_BE)
2563 if(!TrReadOperator(tr, ","))
2564 return 0;
2565 if(src->mType == ET_INT)
2567 if(!TrReadInt(tr, MIN_BIN_SIZE, MAX_BIN_SIZE, &intVal))
2568 return 0;
2569 src->mSize = (uint)intVal;
2570 if(!TrIsOperator(tr, ","))
2571 src->mBits = (int)(8*src->mSize);
2572 else
2574 TrReadOperator(tr, ",");
2575 TrIndication(tr, &line, &col);
2576 if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
2577 return 0;
2578 if(abs(intVal) < MIN_BIN_BITS || ((uint)abs(intVal)) > (8*src->mSize))
2580 TrErrorAt(tr, line, col, "Expected a value of (+/-) %d to %d.\n", MIN_BIN_BITS, 8*src->mSize);
2581 return 0;
2583 src->mBits = intVal;
2586 else
2588 TrIndication(tr, &line, &col);
2589 if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal))
2590 return 0;
2591 if(intVal != 4 && intVal != 8)
2593 TrErrorAt(tr, line, col, "Expected a value of 4 or 8.\n");
2594 return 0;
2596 src->mSize = (uint)intVal;
2597 src->mBits = 0;
2600 else if(src->mFormat == SF_ASCII && src->mType == ET_INT)
2602 if(!TrReadOperator(tr, ","))
2603 return 0;
2604 if(!TrReadInt(tr, MIN_ASCII_BITS, MAX_ASCII_BITS, &intVal))
2605 return 0;
2606 src->mSize = 0;
2607 src->mBits = intVal;
2609 else
2611 src->mSize = 0;
2612 src->mBits = 0;
2615 if(!TrIsOperator(tr, ";"))
2616 src->mSkip = 0;
2617 else
2619 TrReadOperator(tr, ";");
2620 if(!TrReadInt (tr, 0, 0x7FFFFFFF, &intVal))
2621 return 0;
2622 src->mSkip = (uint)intVal;
2625 if(!TrReadOperator(tr, ")"))
2626 return 0;
2627 if(TrIsOperator(tr, "@"))
2629 TrReadOperator(tr, "@");
2630 if(!TrReadInt(tr, 0, 0x7FFFFFFF, &intVal))
2631 return 0;
2632 src->mOffset = (uint)intVal;
2634 else
2635 src->mOffset = 0;
2636 if(!TrReadOperator(tr, ":"))
2637 return 0;
2638 if(!TrReadString(tr, MAX_PATH_LEN, src->mPath))
2639 return 0;
2640 return 1;
2643 // Process the list of sources in the data set definition.
2644 static int ProcessSources(const HeadModelT model, TokenReaderT *tr, HrirDataT *hData)
2646 uint *setCount, *setFlag;
2647 uint line, col, ei, ai;
2648 SourceRefT src;
2649 double factor;
2650 double *hrir;
2652 setCount = (uint*)calloc(hData->mEvCount, sizeof(uint));
2653 setFlag = (uint*)calloc(hData->mIrCount, sizeof(uint));
2654 hrir = CreateArray(hData->mIrPoints);
2655 while(TrIsOperator(tr, "["))
2657 TrIndication(tr, & line, & col);
2658 TrReadOperator(tr, "[");
2659 if(!ReadIndexPair(tr, hData, &ei, &ai))
2660 goto error;
2661 if(!TrReadOperator(tr, "]"))
2662 goto error;
2663 if(setFlag[hData->mEvOffset[ei] + ai])
2665 TrErrorAt(tr, line, col, "Redefinition of source.\n");
2666 goto error;
2668 if(!TrReadOperator(tr, "="))
2669 goto error;
2671 factor = 1.0;
2672 for(;;)
2674 if(!ReadSourceRef(tr, &src))
2675 goto error;
2676 if(!LoadSource(&src, hData->mIrRate, hData->mIrPoints, hrir))
2677 goto error;
2679 if(model == HM_DATASET)
2680 AverageHrirOnset(hrir, 1.0 / factor, ei, ai, hData);
2681 AverageHrirMagnitude(hrir, 1.0 / factor, ei, ai, hData);
2682 factor += 1.0;
2683 if(!TrIsOperator(tr, "+"))
2684 break;
2685 TrReadOperator(tr, "+");
2687 setFlag[hData->mEvOffset[ei] + ai] = 1;
2688 setCount[ei]++;
2691 ei = 0;
2692 while(ei < hData->mEvCount && setCount[ei] < 1)
2693 ei++;
2694 if(ei < hData->mEvCount)
2696 hData->mEvStart = ei;
2697 while(ei < hData->mEvCount && setCount[ei] == hData->mAzCount[ei])
2698 ei++;
2699 if(ei >= hData->mEvCount)
2701 if(!TrLoad(tr))
2703 DestroyArray(hrir);
2704 free(setFlag);
2705 free(setCount);
2706 return 1;
2708 TrError(tr, "Errant data at end of source list.\n");
2710 else
2711 TrError(tr, "Missing sources for elevation index %d.\n", ei);
2713 else
2714 TrError(tr, "Missing source references.\n");
2716 error:
2717 DestroyArray(hrir);
2718 free(setFlag);
2719 free(setCount);
2720 return 0;
2723 /* Parse the data set definition and process the source data, storing the
2724 * resulting data set as desired. If the input name is NULL it will read
2725 * from standard input.
2727 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)
2729 char rateStr[8+1], expName[MAX_PATH_LEN];
2730 TokenReaderT tr;
2731 HrirDataT hData;
2732 double *dfa;
2733 FILE *fp;
2735 hData.mIrRate = 0;
2736 hData.mSampleType = ST_S24;
2737 hData.mChannelType = CT_LEFTONLY;
2738 hData.mIrPoints = 0;
2739 hData.mFftSize = 0;
2740 hData.mIrSize = 0;
2741 hData.mIrCount = 0;
2742 hData.mEvCount = 0;
2743 hData.mRadius = 0;
2744 hData.mDistance = 0;
2745 fprintf(stdout, "Reading HRIR definition...\n");
2746 if(inName != NULL)
2748 fp = fopen(inName, "r");
2749 if(fp == NULL)
2751 fprintf(stderr, "Error: Could not open definition file '%s'\n", inName);
2752 return 0;
2754 TrSetup(fp, inName, &tr);
2756 else
2758 fp = stdin;
2759 TrSetup(fp, "<stdin>", &tr);
2761 if(!ProcessMetrics(&tr, fftSize, truncSize, &hData))
2763 if(inName != NULL)
2764 fclose(fp);
2765 return 0;
2767 hData.mHrirs = CreateArray(hData.mIrCount * hData.mIrSize);
2768 hData.mHrtds = CreateArray(hData.mIrCount);
2769 if(!ProcessSources(model, &tr, &hData))
2771 DestroyArray(hData.mHrtds);
2772 DestroyArray(hData.mHrirs);
2773 if(inName != NULL)
2774 fclose(fp);
2775 return 0;
2777 if(inName != NULL)
2778 fclose(fp);
2779 if(equalize)
2781 dfa = CreateArray(1 + (hData.mFftSize/2));
2782 fprintf(stdout, "Calculating diffuse-field average...\n");
2783 CalculateDiffuseFieldAverage(&hData, surface, limit, dfa);
2784 fprintf(stdout, "Performing diffuse-field equalization...\n");
2785 DiffuseFieldEqualize(dfa, &hData);
2786 DestroyArray(dfa);
2788 fprintf(stdout, "Performing minimum phase reconstruction...\n");
2789 ReconstructHrirs(&hData);
2790 if(outRate != 0 && outRate != hData.mIrRate)
2792 fprintf(stdout, "Resampling HRIRs...\n");
2793 ResampleHrirs(outRate, &hData);
2795 fprintf(stdout, "Truncating minimum-phase HRIRs...\n");
2796 hData.mIrPoints = truncSize;
2797 fprintf(stdout, "Synthesizing missing elevations...\n");
2798 if(model == HM_DATASET)
2799 SynthesizeOnsets(&hData);
2800 SynthesizeHrirs(&hData);
2801 fprintf(stdout, "Normalizing final HRIRs...\n");
2802 NormalizeHrirs(&hData);
2803 fprintf(stdout, "Calculating impulse delays...\n");
2804 CalculateHrtds(model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData.mRadius, &hData);
2805 snprintf(rateStr, 8, "%u", hData.mIrRate);
2806 StrSubst(outName, "%r", rateStr, MAX_PATH_LEN, expName);
2807 switch(outFormat)
2809 case OF_MHR:
2810 fprintf(stdout, "Creating MHR data set file...\n");
2811 if(!StoreMhr(&hData, experimental, expName))
2813 DestroyArray(hData.mHrtds);
2814 DestroyArray(hData.mHrirs);
2815 return 0;
2817 break;
2818 default:
2819 break;
2821 DestroyArray(hData.mHrtds);
2822 DestroyArray(hData.mHrirs);
2823 return 1;
2826 static void PrintHelp(const char *argv0, FILE *ofile)
2828 fprintf(ofile, "Usage: %s <command> [<option>...]\n\n", argv0);
2829 fprintf(ofile, "Commands:\n");
2830 fprintf(ofile, " -m, --make-mhr Makes an OpenAL Soft compatible HRTF data set.\n");
2831 fprintf(ofile, " Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
2832 fprintf(ofile, " -h, --help Displays this help information.\n\n");
2833 fprintf(ofile, "Options:\n");
2834 fprintf(ofile, " -r=<rate> Change the data set sample rate to the specified value and\n");
2835 fprintf(ofile, " resample the HRIRs accordingly.\n");
2836 fprintf(ofile, " -f=<points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE);
2837 fprintf(ofile, " -e={on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
2838 fprintf(ofile, " -s={on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
2839 fprintf(ofile, " -l={<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n");
2840 fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT);
2841 fprintf(ofile, " -w=<points> Specify the size of the truncation window that's applied\n");
2842 fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
2843 fprintf(ofile, " -d={dataset| Specify the model used for calculating the head-delay timing\n");
2844 fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
2845 fprintf(ofile, " -c=<size> Use a customized head radius measured ear-to-ear in meters.\n");
2846 fprintf(ofile, " -i=<filename> Specify an HRIR definition file to use (defaults to stdin).\n");
2847 fprintf(ofile, " -o=<filename> Specify an output file. Overrides command-selected default.\n");
2848 fprintf(ofile, " Use of '%%r' will be substituted with the data set sample rate.\n");
2851 // Standard command line dispatch.
2852 int main(const int argc, const char *argv[])
2854 const char *inName = NULL, *outName = NULL;
2855 OutputFormatT outFormat;
2856 uint outRate, fftSize;
2857 int equalize, surface;
2858 int experimental;
2859 char *end = NULL;
2860 HeadModelT model;
2861 uint truncSize;
2862 double radius;
2863 double limit;
2864 int argi;
2866 if(argc < 2 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)
2868 fprintf(stdout, "HRTF Processing and Composition Utility\n\n");
2869 PrintHelp(argv[0], stdout);
2870 return 0;
2873 if(strcmp(argv[1], "--make-mhr") == 0 || strcmp(argv[1], "-m") == 0)
2875 outName = "./oalsoft_hrtf_%r.mhr";
2876 outFormat = OF_MHR;
2878 else
2880 fprintf(stderr, "Error: Invalid command '%s'.\n\n", argv[1]);
2881 PrintHelp(argv[0], stderr);
2882 return -1;
2885 outRate = 0;
2886 fftSize = 0;
2887 equalize = DEFAULT_EQUALIZE;
2888 surface = DEFAULT_SURFACE;
2889 limit = DEFAULT_LIMIT;
2890 truncSize = DEFAULT_TRUNCSIZE;
2891 model = DEFAULT_HEAD_MODEL;
2892 radius = DEFAULT_CUSTOM_RADIUS;
2893 experimental = 0;
2895 argi = 2;
2896 while(argi < argc)
2898 if(strncmp(argv[argi], "-r=", 3) == 0)
2900 outRate = strtoul(&argv[argi][3], &end, 10);
2901 if(end[0] != '\0' || outRate < MIN_RATE || outRate > MAX_RATE)
2903 fprintf(stderr, "Error: Expected a value from %u to %u for '-r'.\n", MIN_RATE, MAX_RATE);
2904 return -1;
2907 else if(strncmp(argv[argi], "-f=", 3) == 0)
2909 fftSize = strtoul(&argv[argi][3], &end, 10);
2910 if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE)
2912 fprintf(stderr, "Error: Expected a power-of-two value from %u to %u for '-f'.\n", MIN_FFTSIZE, MAX_FFTSIZE);
2913 return -1;
2916 else if(strncmp(argv[argi], "-e=", 3) == 0)
2918 if(strcmp(&argv[argi][3], "on") == 0)
2919 equalize = 1;
2920 else if(strcmp(&argv[argi][3], "off") == 0)
2921 equalize = 0;
2922 else
2924 fprintf(stderr, "Error: Expected 'on' or 'off' for '-e'.\n");
2925 return -1;
2928 else if(strncmp(argv[argi], "-s=", 3) == 0)
2930 if(strcmp(&argv[argi][3], "on") == 0)
2931 surface = 1;
2932 else if(strcmp(&argv[argi][3], "off") == 0)
2933 surface = 0;
2934 else
2936 fprintf(stderr, "Error: Expected 'on' or 'off' for '-s'.\n");
2937 return -1;
2940 else if(strncmp(argv[argi], "-l=", 3) == 0)
2942 if(strcmp(&argv[argi][3], "none") == 0)
2943 limit = 0.0;
2944 else
2946 limit = strtod(&argv[argi] [3], &end);
2947 if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT)
2949 fprintf(stderr, "Error: Expected 'none' or a value from %.2f to %.2f for '-l'.\n", MIN_LIMIT, MAX_LIMIT);
2950 return -1;
2954 else if(strncmp(argv[argi], "-w=", 3) == 0)
2956 truncSize = strtoul(&argv[argi][3], &end, 10);
2957 if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE || (truncSize%MOD_TRUNCSIZE))
2959 fprintf(stderr, "Error: Expected a value from %u to %u in multiples of %u for '-w'.\n", MIN_TRUNCSIZE, MAX_TRUNCSIZE, MOD_TRUNCSIZE);
2960 return -1;
2963 else if(strncmp(argv[argi], "-d=", 3) == 0)
2965 if(strcmp(&argv[argi][3], "dataset") == 0)
2966 model = HM_DATASET;
2967 else if(strcmp(&argv[argi][3], "sphere") == 0)
2968 model = HM_SPHERE;
2969 else
2971 fprintf(stderr, "Error: Expected 'dataset' or 'sphere' for '-d'.\n");
2972 return -1;
2975 else if(strncmp(argv[argi], "-c=", 3) == 0)
2977 radius = strtod(&argv[argi][3], &end);
2978 if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS)
2980 fprintf(stderr, "Error: Expected a value from %.2f to %.2f for '-c'.\n", MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
2981 return -1;
2984 else if(strncmp(argv[argi], "-i=", 3) == 0)
2985 inName = &argv[argi][3];
2986 else if(strncmp(argv[argi], "-o=", 3) == 0)
2987 outName = &argv[argi][3];
2988 else if(strcmp(argv[argi], "--experimental") == 0)
2989 experimental = 1;
2990 else
2992 fprintf(stderr, "Error: Invalid option '%s'.\n", argv[argi]);
2993 return -1;
2995 argi++;
2997 if(!ProcessDefinition(inName, outRate, fftSize, equalize, surface, limit,
2998 truncSize, model, radius, outFormat, experimental,
2999 outName))
3000 return -1;
3001 fprintf(stdout, "Operation completed.\n");
3002 return 0;