1 #include "../hrtf/mysofa.h"
2 #include "../hrtf/tools.h"
3 #include "json.h"
4 #include "tests.h"
5 #include <float.h>
6 #include <math.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #ifndef M_PI
12 #define M_PI (3.14159265358979323846)
13 #endif
14
15 /* #define VDEBUG */
16
test_easy_open()17 void test_easy_open() {
18 struct MYSOFA_EASY *easy;
19 int err = 0;
20 int filterlength;
21
22 easy = mysofa_open("tests/MIT_KEMAR_normal_pinna.old.sofa", 8000.,
23 &filterlength, &err);
24 if (!easy) {
25 CU_FAIL_FATAL("Error reading file.");
26 return;
27 }
28
29 mysofa_close(easy);
30 }
31
test_easy()32 void test_easy() {
33 struct MYSOFA_EASY *easy;
34 int err = 0;
35 int filterlength;
36 int filters = 0;
37 float theta, r;
38 float *coordinates;
39 float *ir;
40 float *delays;
41 int count = 0;
42 FILE *file;
43 float c[3];
44 float l1, l2;
45 float sdiff1, sdiff2, diff1, diff2;
46
47 easy = mysofa_open("tests/tester.sofa", 48000, &filterlength, &err);
48 if (!easy) {
49 CU_FAIL_FATAL("Error reading file.");
50 return;
51 }
52 mysofa_minphase(easy->hrtf, 0.01);
53
54 for (filters = 0; filters < easy->hrtf->M; filters++) {
55 c[0] = easy->hrtf->SourcePosition.values[filters * 3];
56 c[1] = easy->hrtf->SourcePosition.values[filters * 3 + 1];
57 c[2] = easy->hrtf->SourcePosition.values[filters * 3 + 2];
58 mysofa_c2s(c);
59
60 #ifdef VDEBUG
61 printf("in %d %f %f %f # %f %f %f\n", filters, c[0], c[1], c[2],
62 easy->hrtf->SourcePosition.values[filters * 3],
63 easy->hrtf->SourcePosition.values[filters * 3 + 1],
64 easy->hrtf->SourcePosition.values[filters * 3 + 2]);
65 #endif
66 c[0] = fmod(round(c[0] + 360), 360);
67 c[1] = fmod(round(c[1] + 361), 360);
68 l1 = round(easy->hrtf->DataDelay.values[filters * 2] * 48000 * 2);
69 l2 = round(easy->hrtf->DataDelay.values[filters * 2 + 1] * 48000 * 2);
70
71 #ifdef VDEBUG
72 /* printf("compare %d %f %f %f %f
73 * %f\n",filters,c[0],c[1],c[2],l1,l2);
74 */
75 #endif
76 CU_ASSERT(
77 !((fabs(c[0] - l1) > 2 || fabs(c[1] - l2) > 2) && !fequals(l2, 90)));
78 }
79
80 filters = 0;
81 for (theta = -90.; theta <= 90.; theta += 5.) {
82 r = round(cos(theta * M_PI / 180.) * 120.);
83 if (r == 0.)
84 r = 1;
85 filters += r;
86 }
87 #ifdef VDEBUG
88 printf("Filters %d\n", filters);
89 #endif
90
91 coordinates = malloc(filters * sizeof(float) * 3);
92 ir = malloc(filters * easy->hrtf->N * sizeof(float) * 2);
93 delays = malloc(filters * 2 * sizeof(float));
94
95 sdiff1 = sdiff2 = 0;
96 err = 0;
97 for (theta = -90.; theta <= 90.; theta += 5.) {
98 int r = round(cos(theta * M_PI / 180.) * 120.);
99 int phi;
100 if (r == 0)
101 r = 1;
102 for (phi = 0; phi < r; phi++) {
103 coordinates[count * 3 + 0] = phi * (360. / r);
104 coordinates[count * 3 + 1] = theta;
105 coordinates[count * 3 + 2] = 1;
106 mysofa_s2c(coordinates + count * 3);
107 #ifdef VDEBUG
108 printf("req %f %f %d %f %f %f\n", phi * (360. / r), theta, count,
109 coordinates[count * 3 + 0], coordinates[count * 3 + 1],
110 coordinates[count * 3 + 2]);
111 #endif
112 mysofa_getfilter_float(
113 easy, coordinates[count * 3 + 0], coordinates[count * 3 + 1],
114 coordinates[count * 3 + 2], ir + 2 * count * easy->hrtf->N,
115 ir + (2 * count + 1) * easy->hrtf->N, &delays[2 * count],
116 &delays[2 * count + 1]);
117 diff1 = fabs(phi * (360. / r) - delays[2 * count] * 48000 * 2);
118 diff2 = fabs(fmod(theta + 360, 360) - delays[2 * count + 1] * 48000 * 2);
119 if (diff1 > 5 || diff2 > 5)
120 err++;
121 else {
122 sdiff1 += diff1;
123 sdiff2 += diff2;
124 }
125
126 #ifdef VDEBUG
127 printf("diff %f %f\t", diff1, diff2);
128 printf("delays %f %f %f %f\n", phi * (360. / r), fmod(theta + 360, 360),
129 delays[2 * count] * 48000 * 2, delays[2 * count + 1] * 48000 * 2);
130 #endif
131 count++;
132 }
133 }
134 err = err * 100. / count;
135 sdiff1 = sdiff1 / (count - err);
136 sdiff2 = sdiff2 / (count - err);
137
138 #ifdef VDEBUG
139 printf("errors %f%% diffs %f %f\n", err * 100. / count,
140 sdiff1 / (count - err), sdiff2 / (count - err));
141 #endif
142 CU_ASSERT(err < 31.7);
143 CU_ASSERT(sdiff1 < 1.67);
144 CU_ASSERT(sdiff2 < 1.43);
145
146 free(easy->hrtf->DataDelay.values);
147 free(easy->hrtf->DataIR.values);
148 free(easy->hrtf->SourcePosition.values);
149 easy->hrtf->DataDelay.elements = filters * 2;
150 easy->hrtf->DataDelay.values = delays;
151 easy->hrtf->DataIR.elements = filters * 2 * easy->hrtf->N;
152 easy->hrtf->DataIR.values = ir;
153 easy->hrtf->SourcePosition.elements = filters * 3;
154 easy->hrtf->SourcePosition.values = coordinates;
155 easy->hrtf->M = filters;
156
157 file = fopen("/tmp/easy.tmp.json", "w");
158 CU_ASSERT(file != NULL);
159 printJson(file, easy->hrtf, 0);
160 fclose(file);
161
162 mysofa_close(easy);
163 }
164
test_easy_nonorm()165 void test_easy_nonorm() {
166 struct MYSOFA_EASY *easy;
167 int err = 0;
168 int filterlength;
169 int filters = 0;
170 float diff1, diff2;
171
172 /* Test raw opening (no norm) and MxR delay .sofa */
173 easy = mysofa_open_no_norm("tests/tester2.sofa", 48000., &filterlength, &err);
174 if (!easy) {
175 CU_FAIL_FATAL("Error reading file.");
176 return;
177 }
178
179 err = 0;
180
181 for (filters = 0; filters < easy->hrtf->M; filters++) {
182 // see tester2.sofa file creation in tester2.m file
183 diff1 = filters - easy->hrtf->DataDelay.values[easy->hrtf->R * filters];
184 diff2 = filters + easy->hrtf->DataDelay.values[easy->hrtf->R * filters + 1];
185 if (diff1 > 0.1 || diff2 > 0.1)
186 err++;
187 #ifdef VDEBUG
188 printf("delays: %f %f \t",
189 easy->hrtf->DataDelay.values[easy->hrtf->R * filters],
190 easy->hrtf->DataDelay.values[easy->hrtf->R * filters + 1]);
191 printf("diff: %f %f %i\n", diff1, diff2, err);
192 #endif
193 }
194 CU_ASSERT(err < 1);
195
196 mysofa_close(easy);
197 }
198