1 /*
2 
3  Copyright 2016 Christian Hoene, Symonics GmbH
4 
5  */
6 
7 #ifndef MYSOFA_H_INCLUDED
8 #define MYSOFA_H_INCLUDED
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 #include <stdbool.h>
14 #include <stdint.h>
15 
16 #define MYSOFA_DEFAULT_NEIGH_STEP_ANGLE 0.5f
17 #define MYSOFA_DEFAULT_NEIGH_STEP_RADIUS 0.01f
18 
19 /** debugging output */
20 #ifdef VDEBUG
21 #include <stdio.h>
22 #define mylog(...)                                                             \
23   {                                                                            \
24     fprintf(stderr, "%s:%d: ", __FILE__, __LINE__);                            \
25     fprintf(stderr, __VA_ARGS__);                                              \
26   }
27 #else
28 #define mylog(...)
29 #endif
30 
31 /** attributes */
32 struct MYSOFA_ATTRIBUTE {
33   struct MYSOFA_ATTRIBUTE *next;
34   char *name;
35   char *value;
36 };
37 
38 struct MYSOFA_ARRAY {
39   float *values;
40   unsigned int elements;
41   struct MYSOFA_ATTRIBUTE *attributes;
42 };
43 
44 /** additional variable */
45 struct MYSOFA_VARIABLE {
46   struct MYSOFA_VARIABLE *next;
47   char *name;
48   struct MYSOFA_ARRAY *value;
49 };
50 
51 /*
52  * The HRTF structure data types
53  */
54 struct MYSOFA_HRTF {
55 
56   /* Dimensions defined in AES69
57    M Number of measurements; must be integer greater than zero.
58    R Number of receivers; must be integer greater than zero.
59    E Number of emitters; must be integer greater than zero.
60    N Number of data samples describing one measurement; must be integer greater
61    than zero. S Number of characters in a string; must be integer greater than
62    zero. I 1 Singleton dimension, defines a scalar value. C 3 Coordinate
63    triplet, always three; the coordinate type defines the meaning of this
64    dimension.
65    */
66   unsigned I, C, R, E, N, M;
67 
68   struct MYSOFA_ARRAY ListenerPosition;
69 
70   struct MYSOFA_ARRAY ReceiverPosition;
71 
72   struct MYSOFA_ARRAY SourcePosition;
73 
74   struct MYSOFA_ARRAY EmitterPosition;
75 
76   struct MYSOFA_ARRAY ListenerUp;
77 
78   struct MYSOFA_ARRAY ListenerView;
79 
80   /** array of filter coefficients. Sizes are filters*filter_length. */
81   struct MYSOFA_ARRAY DataIR;
82 
83   /** the sampling rate used in this structure */
84   struct MYSOFA_ARRAY DataSamplingRate;
85 
86   /** array of min-phase delays. Sizes are filters */
87   struct MYSOFA_ARRAY DataDelay;
88 
89   /** general file attributes */
90   struct MYSOFA_ATTRIBUTE *attributes;
91 
92   /** additional variables that might be present in a SOFA file */
93   struct MYSOFA_VARIABLE *variables;
94 };
95 
96 /* structure for lookup HRTF filters */
97 struct MYSOFA_LOOKUP {
98   void *kdtree;
99   float radius_min, radius_max;
100   float theta_min, theta_max;
101   float phi_min, phi_max;
102 };
103 
104 struct MYSOFA_NEIGHBORHOOD {
105   int elements;
106   int *index;
107 };
108 
109 enum {
110   MYSOFA_OK = 0,
111   MYSOFA_INTERNAL_ERROR = -1,
112   MYSOFA_INVALID_FORMAT = 10000,
113   MYSOFA_UNSUPPORTED_FORMAT,
114   MYSOFA_NO_MEMORY,
115   MYSOFA_READ_ERROR,
116   MYSOFA_INVALID_ATTRIBUTES,
117   MYSOFA_INVALID_DIMENSIONS,
118   MYSOFA_INVALID_DIMENSION_LIST,
119   MYSOFA_INVALID_COORDINATE_TYPE,
120   MYSOFA_ONLY_EMITTER_WITH_ECI_SUPPORTED,
121   MYSOFA_ONLY_DELAYS_WITH_IR_OR_MR_SUPPORTED,
122   MYSOFA_ONLY_THE_SAME_SAMPLING_RATE_SUPPORTED,
123   MYSOFA_RECEIVERS_WITH_RCI_SUPPORTED,
124   MYSOFA_RECEIVERS_WITH_CARTESIAN_SUPPORTED,
125   MYSOFA_INVALID_RECEIVER_POSITIONS,
126   MYSOFA_ONLY_SOURCES_WITH_MC_SUPPORTED
127 };
128 
129 struct MYSOFA_HRTF *mysofa_load(const char *filename, int *err);
130 
131 int mysofa_check(struct MYSOFA_HRTF *hrtf);
132 char *mysofa_getAttribute(struct MYSOFA_ATTRIBUTE *attr, char *name);
133 void mysofa_tospherical(struct MYSOFA_HRTF *hrtf);
134 void mysofa_tocartesian(struct MYSOFA_HRTF *hrtf);
135 void mysofa_free(struct MYSOFA_HRTF *hrtf);
136 
137 struct MYSOFA_LOOKUP *mysofa_lookup_init(struct MYSOFA_HRTF *hrtf);
138 int mysofa_lookup(struct MYSOFA_LOOKUP *lookup, float *coordinate);
139 void mysofa_lookup_free(struct MYSOFA_LOOKUP *lookup);
140 
141 struct MYSOFA_NEIGHBORHOOD *
142 mysofa_neighborhood_init(struct MYSOFA_HRTF *hrtf,
143                          struct MYSOFA_LOOKUP *lookup);
144 struct MYSOFA_NEIGHBORHOOD *mysofa_neighborhood_init_withstepdefine(
145     struct MYSOFA_HRTF *hrtf, struct MYSOFA_LOOKUP *lookup,
146     float neighbor_angle_step, float neighbor_radius_step);
147 int *mysofa_neighborhood(struct MYSOFA_NEIGHBORHOOD *neighborhood, int pos);
148 void mysofa_neighborhood_free(struct MYSOFA_NEIGHBORHOOD *neighborhood);
149 
150 float *mysofa_interpolate(struct MYSOFA_HRTF *hrtf, float *cordinate,
151                           int nearest, int *neighborhood, float *fir,
152                           float *delays);
153 
154 int mysofa_resample(struct MYSOFA_HRTF *hrtf, float samplerate);
155 float mysofa_loudness(struct MYSOFA_HRTF *hrtf);
156 int mysofa_minphase(struct MYSOFA_HRTF *hrtf, float threshold);
157 
158 struct MYSOFA_EASY *mysofa_cache_lookup(const char *filename, float samplerate);
159 struct MYSOFA_EASY *mysofa_cache_store(struct MYSOFA_EASY *,
160                                        const char *filename, float samplerate);
161 void mysofa_cache_release(struct MYSOFA_EASY *);
162 void mysofa_cache_release_all(void);
163 
164 void mysofa_c2s(float *values);
165 void mysofa_s2c(float *values);
166 
167 struct MYSOFA_EASY {
168   struct MYSOFA_HRTF *hrtf;
169   struct MYSOFA_LOOKUP *lookup;
170   struct MYSOFA_NEIGHBORHOOD *neighborhood;
171   float *fir;
172 };
173 
174 struct MYSOFA_EASY *mysofa_open(const char *filename, float samplerate,
175                                 int *filterlength, int *err);
176 struct MYSOFA_EASY *mysofa_open_no_norm(const char *filename, float samplerate,
177                                         int *filterlength, int *err);
178 struct MYSOFA_EASY *mysofa_open_advanced(const char *filename, float samplerate,
179                                          int *filterlength, int *err, bool norm,
180                                          float neighbor_angle_step,
181                                          float neighbor_radius_step);
182 struct MYSOFA_EASY *mysofa_open_cached(const char *filename, float samplerate,
183                                        int *filterlength, int *err);
184 void mysofa_getfilter_short(struct MYSOFA_EASY *easy, float x, float y, float z,
185                             short *IRleft, short *IRright, int *delayLeft,
186                             int *delayRight);
187 void mysofa_getfilter_float(struct MYSOFA_EASY *easy, float x, float y, float z,
188                             float *IRleft, float *IRright, float *delayLeft,
189                             float *delayRight);
190 void mysofa_getfilter_float_nointerp(struct MYSOFA_EASY *easy, float x, float y,
191                                      float z, float *IRleft, float *IRright,
192                                      float *delayLeft, float *delayRight);
193 void mysofa_close(struct MYSOFA_EASY *easy);
194 void mysofa_close_cached(struct MYSOFA_EASY *easy);
195 
196 void mysofa_getversion(int *major, int *minor, int *patch);
197 
198 #ifdef __cplusplus
199 }
200 #endif
201 #endif
202