@@ -48,12 +48,12 @@ static const double p23[19] = { -0.67, 0.142, 3404., -0.91, -0.67, -1.21, -1.76,
48
48
static const double p33 [19 ] = { 0.174 , -0.11 , -1699. , 0.437 , 0.658 , 2.02 , 6.815 , 0.614 , 589.3 , 16818. , -9.39 , -44.1 , -23.6 , -92.3 , -1.81 , 10.54 , 0.532 , 0.285 , -2.08 };
49
49
static const double q13 [19 ] = { -1.75 , -0.01 , 7354. , -2.18 , -1.2 , -1.59 , -1.23 , -0.89 , 29.23 , 1945. , -0.06 , 5.635 , 3.308 , 13.88 , -0.88 , -2.23 , -0.96 , -0.9 , -0.57 };
50
50
static const double q23 [19 ] = { 0.699 , -0.35 , -5350. , 1.188 , 0.256 , 0.816 , 1.166 , 0.76 , 59.51 , 1707. , -1.12 , -6.18 , -3.39 , -12.7 , -0.19 , 1.295 , -0.02 , -0.08 , -0.4 };
51
-
52
51
static const int numAz_table = sizeof (q23 );
53
- //static const float a_0 = 0.0875f; /**< Reference head size, 8.75 centimeters, used in the generation of the coeff lookup table. */
54
- //static const float a_head = 0.09096f; /**< This head size, See note for head_radius in binauraliser_nf. */
55
- static const float headDim = SAF_PI * (0.0875f /*a_0*/ / 0.09096f /*a_head*/ );
56
- static const float sosDiv2PiA = 343.0f / (2.0f * SAF_PI * 0.09096f /*a_head*/ );
52
+
53
+ /* a_0 = 0.0875f; Reference head size, 8.75 centimeters, used in the generation of the coeff lookup table. */
54
+ /* a_head = 0.09096f; This head size, see note for head_radius in binauraliser_nf. */
55
+ static const float headDim = SAF_PI * (0.0875f / 0.09096f ); /* pi * (a_0 / a_head) */
56
+ static const float sosDiv2PiA = 343.0f / (2.0f * SAF_PI * 0.09096f ); /* c / (2pi * a_head) */
57
57
58
58
/** Linear interpolation between two values */
59
59
static float interpolate_lin
@@ -78,18 +78,18 @@ static float db2mag
78
78
/*
79
79
* Calculate high-shelf parameters, g0, gInf, fc, from the lookup table coefficients (10 degree steps).
80
80
* Called twice per update as the returned values are subsequently interpolated to exact azimuth. */
81
- void calcHighShelfParams
81
+ void calcDVFShelfParams
82
82
(
83
- int i , /* index into the coefficient table, dictated by azimuth */
84
- float rhoIn , /* normalized source distance */
85
- float * g0 , /* high shelf gain at DC */
86
- float * gInf , /* high shelf gain at inf */
87
- float * fc /* high shelf cutoff frequency */
83
+ int i , /* Index into the coefficient table, dictated by azimuth. */
84
+ float rhoIn , /* Normalized source distance. */
85
+ float * g0 , /* High shelf gain at DC. */
86
+ float * gInf , /* High shelf gain at inf. */
87
+ float * fc /* High shelf cutoff frequency. */
88
88
)
89
89
{
90
90
float fc_tmp ;
91
91
double rho = (double )rhoIn ;
92
- double rhoSq = rho * rho ;
92
+ double rhoSq = rho * rho ;
93
93
94
94
/* Eq (8), (13) and (14) */
95
95
* g0 = (float )((p11 [i ] * rho + p21 [i ]) / (rhoSq + q11 [i ] * rho + q21 [i ]));
@@ -101,69 +101,65 @@ void calcHighShelfParams
101
101
}
102
102
103
103
/*
104
- * Interpolate (linear ) the high shelf parameters generated by calcHighShelfParams()
105
- * which is called twice to generate the high shelf parameters for the nearest thetas
106
- * in the lookup table. */
107
- void interpHighShelfParams
104
+ * Interpolate (linearly ) the high shelf parameters generated by
105
+ * calcDVFShelfParams() which is called twice to generate the high shelf
106
+ * parameters for the nearest thetas in the lookup table. */
107
+ void interpDVFShelfParams
108
108
(
109
- float theta , /* ipsilateral azimuth, on the inter-aural axis [0, 180] (deg) */
110
- float rho , /* distance , normalized to head radius, >= 1 */
109
+ float theta , /* Ipsilateral azimuth, on the inter-aural axis [0, 180] (deg). */
110
+ float rho , /* Distance , normalized to head radius, >= 1. */
111
111
/* output */
112
112
float * iG0 ,
113
113
float * iGInf ,
114
114
float * iFc
115
115
)
116
116
{
117
117
int theta_idx_lower , theta_idx_upper ;
118
- float ifac ;
119
- float thetaDiv10 ;
118
+ float ifac , thetaDiv10 ;
120
119
float g0_1 , g0_2 ; /* high shelf gain at DC */
121
120
float gInf_1 , gInf_2 ; /* high shelf gain at inf */
122
121
float fc_1 , fc_2 ; /* high shelf cutoff frequency */
123
122
124
- // TBD: add range checking? - clip theta and rho to valid range
123
+ // TBD: could add range checking, clipping theta and rho to valid range
125
124
126
- /* linearly interpolate DC gain, HF gain, center freq at theta */
125
+ /* Linearly interpolate DC gain, HF gain, center freq at theta.
126
+ * Table is in 10 degree steps, floor(x/10) gets lower index. */
127
127
thetaDiv10 = theta / 10.f ;
128
- theta_idx_lower = (int )thetaDiv10 ; /* Table is in 10 degree steps, floor(x/10) gets lower index */
128
+ theta_idx_lower = (int )thetaDiv10 ;
129
129
theta_idx_upper = theta_idx_lower + 1 ;
130
- if (theta_idx_upper == numAz_table ) { // alternatively, instead check theta_idx_upper => numAz_table, could clip the value > 180 here
130
+ if (theta_idx_upper == numAz_table ) { // could alternatively check theta_idx_upper => numAz_table, clip the value > 180 here
131
131
theta_idx_upper = theta_idx_lower ;
132
132
theta_idx_lower = theta_idx_lower - 1 ;
133
133
}
134
134
135
- calcHighShelfParams (theta_idx_lower , rho , & g0_1 , & gInf_1 , & fc_1 );
136
- calcHighShelfParams (theta_idx_upper , rho , & g0_2 , & gInf_2 , & fc_2 );
135
+ calcDVFShelfParams (theta_idx_lower , rho , & g0_1 , & gInf_1 , & fc_1 );
136
+ calcDVFShelfParams (theta_idx_upper , rho , & g0_2 , & gInf_2 , & fc_2 );
137
137
138
- ifac = thetaDiv10 - theta_idx_lower ; /* interpolation factor between table steps */
138
+ /* interpolation factor between table steps */
139
+ ifac = thetaDiv10 - theta_idx_lower ;
139
140
* iG0 = interpolate_lin (g0_1 , g0_2 , ifac );
140
141
* iGInf = interpolate_lin (gInf_1 , gInf_2 , ifac );
141
142
* iFc = interpolate_lin (fc_1 , fc_2 , ifac );
142
143
}
143
144
144
145
/*
145
- * Generate IIR coefficients from the shelf parameters generated by calcHighShelfParams() and
146
- * interpHighShelfParams(). * /
147
- void calcIIRCoeffs
146
+ * Calculate the DVF filter coefficients from shelving filter parameters.
147
+ */
148
+ void dvfShelfCoeffs
148
149
(
149
150
/* Input */
150
- float g0 , /* high shelf dc gain */
151
- float gInf , /* high shelf high gain */
152
- float fc , /* high shelf center freq */
153
- float fs , /* sample rate */
151
+ float g0 , /* High shelf dc gain */
152
+ float gInf , /* High shelf high gain */
153
+ float fc , /* High shelf center freq */
154
+ float fs , /* Sample rate */
154
155
/* Output */
155
156
float * b0 , /* IIR coeffs */
156
157
float * b1 ,
157
158
float * a1
158
159
)
159
160
{
160
- float v0 ;
161
- float g0_mag ;
162
- float tanF ;
163
- float v0tanF ;
164
- float a_c ;
165
- float v ;
166
- float va_c ;
161
+ float v0 , g0_mag , tanF , v0tanF ;
162
+ float a_c , v , va_c ;
167
163
168
164
v0 = db2mag (gInf ); /* Eq. (12), (10), and (11) */
169
165
g0_mag = db2mag (g0 ); // optim TBD: revisit; does g0, gInf need to be in dB?
@@ -178,40 +174,56 @@ void calcIIRCoeffs
178
174
* a1 = a_c ;
179
175
}
180
176
181
- void applyDVF
177
+ void calcDVFCoeffs
182
178
(
183
- float theta , /* ipsilateral azimuth, on the inter-aural axis [0, 180] (deg) */
184
- float rho , /* distance, normalized to head radius, >= 1 */
185
- float * in_signal ,
186
- int nSamples , /* Number of samples to process */
187
- float fs , /* Sample rate */
188
- float * wz , /* (&) Filter coefficients to be passed to the next block */
189
- float * out_signal
179
+ float alpha , /* Lateral angle, on the inter-aural axis [0, 180] (deg) */
180
+ float rho , /* Distance, normalized to head radius, >= 1 */
181
+ float fs , /* Sample rate */
182
+ float * b ,
183
+ float * a
190
184
)
191
185
{
192
- float b [2 ] = {0.f , 0.f };
193
- float a [2 ] = {1.f , 0.f };
194
186
float iG0 , iGInf , iFc ;
195
-
196
- interpHighShelfParams (theta , rho , & iG0 , & iGInf , & iFc );
197
- calcIIRCoeffs (iG0 , iGInf , iFc , fs , & b [0 ], & b [1 ], & a [1 ]);
198
- applyIIR (in_signal , nSamples , 2 , & b [0 ], & a [0 ], wz , out_signal );
187
+ interpDVFShelfParams (alpha , rho , & iG0 , & iGInf , & iFc );
188
+ dvfShelfCoeffs (iG0 , iGInf , iFc , fs , & b [0 ], & b [1 ], & a [1 ]);
199
189
}
200
190
201
- void convertFrontalDoAToIpsilateral
191
+ void doaToIpsiInteraural
202
192
(
203
- float thetaFront , /* DOA wrt 0˚ forward-facing [deg, (-180, 180)] */
204
- float * ipsiDoaLR /* pointer to 2-element array of left and right ear DoAs wrt interaural axis */
193
+ float azimuth , /* azimuth wrt 0˚ forward-facing (deg, [-360, 360]) */
194
+ float elevation , /* elevation from the horizontal plane (deg, [-180, 180]) */
195
+ float * alphaLR , /* (&) 2-element array of lateral angle alpha for left and right ear (deg, [0,180]) */
196
+ float * betaLR /* (&) 2-element array of vertical angle beta for left and right ear (deg, [0,90]) */
205
197
)
206
198
{
207
- float thetaL ;
199
+ float az_rad , el_rad , alpha_ipsi , beta_ipsi , alpha_ipsi_deg , beta_ipsi_deg ;
200
+ float sinaz , sinel , cosaz , cosel ;
208
201
209
- thetaFront = SAF_CLAMP (thetaFront , -180.f , 180.f );
210
- thetaL = fabsf (90.f - thetaFront );
211
- if (thetaL > 180.f ) {
212
- thetaL = 360.f - thetaL ;
202
+ az_rad = DEG2RAD (azimuth );
203
+ el_rad = DEG2RAD (elevation );
204
+ sinaz = sinf (az_rad );
205
+ sinel = sinf (el_rad );
206
+ cosaz = cosf (az_rad );
207
+ cosel = cosf (el_rad );
208
+ alpha_ipsi = SAF_PI /2.f - acosf (sinaz * cosel );
209
+ beta_ipsi = asinf (sinel / sqrtf (powf (sinel ,2.f ) + (powf (cosaz ,2.f ) * powf (cosel ,2.f ))));
210
+
211
+ /* Convert interaural-polar coordinates back to spherical _ranges_. */
212
+ if (beta_ipsi > SAF_PI /2.f ) {
213
+ alpha_ipsi = SAF_PI - alpha_ipsi ; /* [0,pi] */
214
+ beta_ipsi = SAF_PI - beta_ipsi ; /* [0,pi/2] */
213
215
}
216
+
217
+ /* Convert to ipsilateral offset from the left ear: [-360, 360]->[0, 180] */
218
+ alpha_ipsi = fabsf (SAF_PI /2.f - alpha_ipsi );
219
+ if (alpha_ipsi > SAF_PI )
220
+ alpha_ipsi = 2 * SAF_PI - alpha_ipsi ;
214
221
215
- ipsiDoaLR [0 ] = thetaL ;
216
- ipsiDoaLR [1 ] = 180.f - thetaL ; // thetaR
222
+ alphaLR [0 ] = alpha_ipsi_deg = RAD2DEG (alpha_ipsi );
223
+ alphaLR [1 ] = 180.f - alpha_ipsi_deg ;
224
+
225
+ if (betaLR != NULL ) {
226
+ betaLR [0 ] = beta_ipsi_deg = RAD2DEG (beta_ipsi );
227
+ betaLR [1 ] = 180.f - beta_ipsi_deg ;
228
+ }
217
229
}
0 commit comments