49 int i, n, j, k, maxIdx, xcorr_len;
50 float maxVal, itd_bounds, fc, Q, K, KK, D, wn, Wz1[2], Wz2[2], b[3], a[3];
51 float* xcorr_LR, *ir_L, *ir_R, *hrir_lpf;
56 K = tanf(
SAF_PI * fc/(
float)fs);
59 b[0] = (KK * Q) / D; b[1] = (2.0f * KK * Q) / D; b[2] = (KK * Q) / D;
60 a[0] = 1.0f; a[1] = (2.0f * Q * (KK - 1.0f)) / D; a[2] = (KK * Q - K + Q) / D;
63 xcorr_len = 2*(hrir_len)-1;
64 itd_bounds = sqrtf(2.0f)/2e3f;
65 xcorr_LR = (
float*)
malloc1d(xcorr_len*
sizeof(
float));
66 ir_L = (
float*)
malloc1d(hrir_len*
sizeof(
float));
67 ir_R = (
float*)
malloc1d(hrir_len*
sizeof(
float));
68 hrir_lpf = (
float*)
malloc1d(hrir_len*2*
sizeof(
float));
69 for(i=0; i<N_dirs; i++){
71 memset(Wz1, 0, 2*
sizeof(
float));
72 memset(Wz2, 0, 2*
sizeof(
float));
73 for (n=0; n<hrir_len; n++){
76 wn = hrirs[i*
NUM_EARS*hrir_len + j*hrir_len + n] - a[1] * Wz1[j] - a[2] * Wz2[j];
77 hrir_lpf[n*2+j] = b[0] * wn + b[1]*Wz1[j] + b[2]*Wz2[j];
86 for(k=0; k<hrir_len; k++){
87 ir_L[k] = hrir_lpf[k*2+0];
88 ir_R[k] = hrir_lpf[k*2+1];
90 cxcorr(ir_L, ir_R, xcorr_LR, hrir_len, hrir_len);
93 for(j=0; j<xcorr_len; j++){
94 if(xcorr_LR[j] > maxVal){
99 itds_s[i] = ((float)hrir_len-(
float)maxIdx-1.0f)/(
float)fs;
100 itds_s[i] = itds_s[i] > itd_bounds ? itd_bounds : itds_s[i];
101 itds_s[i] = itds_s[i] < -itd_bounds ? -itd_bounds : itds_s[i];
118 float_complex* hrtf_fb
132 float_complex* hrtf_fb
155 nBins = fftSize/2 + 1;
157 hrir_pad =
calloc1d(fftSize,
sizeof(
float));
158 hrtf =
malloc1d(nBins*
sizeof(float_complex));
159 for(i=0; i<N_dirs; i++){
161 memcpy(hrir_pad, &hrirs[i*
NUM_EARS*hrir_len+j*hrir_len],
SAF_MIN(fftSize, hrir_len)*
sizeof(
float));
163 for(k=0; k<nBins; k++)
164 hrtfs[k*
NUM_EARS*N_dirs + j*N_dirs + i] = hrtf[k];
186 if(applyEQ + applyPhase)
189 float* ipd, *hrtf_diff, *_weights;
195 _weights =
malloc1d(N_dirs*
sizeof(
float));
196 for(
int idx=0; idx < N_dirs; idx++)
197 _weights[idx] = 4.f*
SAF_PI / (
float)N_dirs;
201 for(band=0; band<N_bands; band++)
203 for(j=0; j<N_dirs; j++)
204 hrtf_diff[band*
NUM_EARS + i] += _weights[j]/(4.f*
SAF_PI) * powf(cabsf(hrtfs[band*
NUM_EARS*N_dirs + i*N_dirs + j]), 2.0f);
205 for(band=0; band<N_bands; band++)
208 for(band=0; band<N_bands; band++)
210 for(nd=0; nd<N_dirs; nd++)
211 hrtfs[band*
NUM_EARS*N_dirs + i*N_dirs + nd] = ccdivf(hrtfs[band*
NUM_EARS*N_dirs + i*N_dirs + nd], cmplxf(hrtf_diff[band*
NUM_EARS + i] + 2.23e-8f, 0.0f));
221 ipd =
malloc1d(N_bands*N_dirs*
sizeof(
float));
222 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, N_bands, N_dirs, 1, 1.0,
226 for(i=0; i<N_bands; i++)
227 for(j=0; j<N_dirs; j++)
230 for(band=0; band<N_bands; band++){
231 for(nd=0; nd<N_dirs; nd++){
232 hrtfs[band*
NUM_EARS*N_dirs + 0*N_dirs + nd] = crmulf( cexpf(cmplxf(0.0f, ipd[band*N_dirs + nd])), cabsf(hrtfs[band*
NUM_EARS*N_dirs + 0*N_dirs + nd]) );
233 hrtfs[band*
NUM_EARS*N_dirs + 1*N_dirs + nd] = crmulf( cexpf(cmplxf(0.0f,-ipd[band*N_dirs + nd])), cabsf(hrtfs[band*
NUM_EARS*N_dirs + 1*N_dirs + nd]) );
243 float_complex* hrtfs,
250 float_complex* hrtfs_interp
254 float* itd_interp, *mags_interp, *ipd_interp;
256 float_complex* interp_table_cmplx;
257 const float_complex calpha = cmplxf(1.0f, 0.0f), cbeta = cmplxf(0.0f, 0.0f);
259 if(itds==NULL || freqVector==NULL){
261 interp_table_cmplx =
calloc1d(N_interp_dirs*N_hrtf_dirs,
sizeof(float_complex));
262 cblas_scopy(N_interp_dirs*N_hrtf_dirs, interp_table, 1, (
float*)interp_table_cmplx, 2);
265 for(band=0; band<N_bands; band++){
266 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasTrans,
NUM_EARS, N_interp_dirs, N_hrtf_dirs, &calpha,
267 &hrtfs[band*
NUM_EARS*N_hrtf_dirs], N_hrtf_dirs,
268 interp_table_cmplx, N_hrtf_dirs, &cbeta,
269 &hrtfs_interp[band*
NUM_EARS*N_interp_dirs], N_interp_dirs);
273 free(interp_table_cmplx);
277 mags = (
float**)
malloc1d(N_bands*
sizeof(
float*));
278 itd_interp =
malloc1d(N_interp_dirs*
sizeof(
float));
280 ipd_interp =
malloc1d(N_interp_dirs*
sizeof(
float));
283 for(band=0; band<N_bands; band++){
285 for(i=0; i<
NUM_EARS * N_hrtf_dirs ; i++)
286 mags[band][i] = cabsf(hrtfs[band*
NUM_EARS * N_hrtf_dirs + i]);
290 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, N_interp_dirs, 1, N_hrtf_dirs, 1.0f,
291 interp_table, N_hrtf_dirs,
294 for(band=0; band<N_bands; band++){
296 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, N_interp_dirs,
NUM_EARS, N_hrtf_dirs, 1.0f,
297 interp_table, N_hrtf_dirs,
298 mags[band], N_hrtf_dirs, 0.0f,
302 for(i=0; i<N_interp_dirs; i++)
306 for(i=0; i<N_interp_dirs; i++){
307 hrtfs_interp[band*
NUM_EARS*N_interp_dirs + 0* N_interp_dirs +i] = ccmulf( cmplxf(mags_interp[i*
NUM_EARS+0],0.0f), cexpf(cmplxf(0.0f, ipd_interp[i])) );
308 hrtfs_interp[band*
NUM_EARS*N_interp_dirs + 1* N_interp_dirs +i] = ccmulf( cmplxf(mags_interp[i*
NUM_EARS+1],0.0f), cexpf(cmplxf(0.0f,-ipd_interp[i])) );
314 for(band=0; band<N_bands; band++)
324 float_complex* hrtfs,
334 float_complex *hrtf_ipd_lr;
337 ipd =
malloc1d(N_bands*N_hrtf_dirs*
sizeof(
float));
338 cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, N_bands, N_hrtf_dirs, 1, 1.0,
342 for(i=0; i<N_bands; i++)
343 for(j=0; j<N_hrtf_dirs; j++)
347 hrtf_ipd_lr =
calloc1d(N_bands,
sizeof(float_complex));
348 for(i=0; i<N_bands; i++){
349 for(j=0; j<N_hrtf_dirs; j++)
350 hrtf_ipd_lr[i] = ccaddf(hrtf_ipd_lr[i], crmulf(cexpf(crmulf(cmplxf(0.0f, 1.0f), ipd[i*N_hrtf_dirs+j])),
351 cabsf(hrtfs[i*
NUM_EARS*N_hrtf_dirs + 0*N_hrtf_dirs + j])*
352 cabsf(hrtfs[i*
NUM_EARS*N_hrtf_dirs + 1*N_hrtf_dirs + j])));
353 hrtf_ipd_lr[i] = ccdivf(hrtf_ipd_lr[i], cmplxf((
float)N_hrtf_dirs, 0.0f));
357 for(i=0; i<N_bands; i++)
358 HRTFcoh[i] = crealf(hrtf_ipd_lr[i]) < 0.0f ? 0.0f : crealf(hrtf_ipd_lr[i]);
377 int ch, hrirs_out_ld;
378 float resample_factor;
379#if defined(SAF_USE_INTEL_IPP) && 0
381 const int history = 128;
382 float *inBuffer, *outBuffer;
383 int filterLength, pSize, numFilters, outL;
386 unsigned int in_length, out_length;
387 int ERROR_VAL, out_latency, nsample_proc;
389 SpeexResamplerState *pRS;
393 resample_factor = (float)hrirs_out_fs / (
float)hrirs_in_fs;
394 (*hrirs_out_len) = (int)ceilf((
float)hrirs_in_len * resample_factor);
395 hrirs_out_ld = padToNextPow2 ? (int)pow(2.0, ceil(log((
double)(*hrirs_out_len))/log(2.0))) : (*hrirs_out_len);
397#if defined(SAF_USE_INTEL_IPP) && 0
399 error = ippsResamplePolyphaseFixedGetSize_32f(hrirs_in_fs, hrirs_out_fs, 2*(history-1), &pSize, &filterLength, &numFilters, ippAlgHintFast);
401 IppsResamplingPolyphaseFixed_32f* spec;
402 spec = (IppsResamplingPolyphaseFixed_32f*)ippsMalloc_8u(pSize);
403 error = ippsResamplePolyphaseFixedInit_32f(hrirs_in_fs, hrirs_out_fs, 2*(history-1), 0.98f, 12.0f, spec, ippAlgHintFast);
405 inBuffer = ippsMalloc_32f(hrirs_in_len + history * 2 + 2);
406 outBuffer = ippsMalloc_32f(hrirs_out_ld + 2);
407 ippsZero_32f(inBuffer, hrirs_in_len + history * 2 + 2);
410 (*hrirs_out) =
calloc1d(hrirs_N_dirs*
NUM_EARS*(hrirs_out_ld),
sizeof(
float));
411 for(ch=0; ch<hrirs_N_dirs*
NUM_EARS; ch++){
416 ippsCopy_32f(hrirs_in + ch * hrirs_in_len, inBuffer + history, hrirs_in_len);
417 saf_assert(!ippsResamplePolyphaseFixed_32f(inBuffer, hrirs_in_len, outBuffer, 1.0f, &pTime, &outL, spec),
"IPP error");
418 saf_assert(hrirs_out_ld==outL,
"Not all samples were processed!");
419 ippsCopy_32f(outBuffer, (*hrirs_out) + ch * (hrirs_out_ld), hrirs_out_ld);
422 (*hrirs_out_len) = hrirs_out_ld;
431 pRS = speex__resampler_init(1 , hrirs_in_fs, hrirs_out_fs, SPEEX_RESAMPLER_QUALITY_MAX, &ERROR_VAL);
432 out_latency = speex__resampler_get_output_latency(pRS);
433 zeros =
calloc1d(out_latency,
sizeof(
float));
436 (*hrirs_out) =
calloc1d(hrirs_N_dirs*
NUM_EARS*(hrirs_out_ld),
sizeof(
float));
437 for(ch=0; ch<hrirs_N_dirs*
NUM_EARS; ch++){
438 speex__resampler_reset_mem(pRS);
439 speex__resampler_skip_zeros(pRS);
443 in_length = hrirs_in_len;
444 out_length = hrirs_out_ld;
445 ERROR_VAL = speex__resampler_process_float((pRS), 0, hrirs_in + ch * hrirs_in_len, &in_length,
446 (*hrirs_out) + ch * (hrirs_out_ld), &out_length);
447 nsample_proc += out_length;
450 while(nsample_proc<(hrirs_out_ld)){
451 in_length = out_latency;
452 out_length = (hrirs_out_ld)-nsample_proc;
453 ERROR_VAL = speex__resampler_process_float((pRS), 0, zeros, &in_length,
454 (*hrirs_out) + ch * (hrirs_out_ld) + nsample_proc, &out_length);
455 nsample_proc += out_length;
457 saf_assert(nsample_proc==(hrirs_out_ld),
"Not all samples were processed!");
460 (*hrirs_out_len) = hrirs_out_ld;
463 speex__resampler_destroy(pRS);
void afSTFT_FIRtoFilterbankCoeffs(float *hIR, int N_dirs, int nCH, int ir_len, int hopSize, int LDmode, int hybridmode, float_complex *hFB)
Converts FIR filters into Filterbank Coefficients by passing them through the afSTFT filterbank.
void HRIRs2HRTFs(float *hrirs, int N_dirs, int hrir_len, int fftSize, float_complex *hrtfs)
Converts HRIRs to HRTFs for a given FFT size.
void diffuseFieldEqualiseHRTFs(int N_dirs, float *itds_s, float *centreFreq, int N_bands, float *weights, int applyEQ, int applyPhase, float_complex *hrtfs)
Applies pre-processing to a set of HRTFs, which can either be diffuse-field EQ of an (optionally weig...
void resampleHRIRs(float *hrirs_in, int hrirs_N_dirs, int hrirs_in_len, int hrirs_in_fs, int hrirs_out_fs, int padToNextPow2, float **hrirs_out, int *hrirs_out_len)
Resamples a set of HRIRs from its original samplerate to a new samplerate.
void interpHRTFs(float_complex *hrtfs, float *itds, float *freqVector, float *interp_table, int N_hrtf_dirs, int N_bands, int N_interp_dirs, float_complex *hrtfs_interp)
Interpolates a set of HRTFs based on a specified interpolation table.
void binauralDiffuseCoherence(float_complex *hrtfs, float *itds, float *freqVector, int N_hrtf_dirs, int N_bands, float *HRTFcoh)
Computes the binaural diffuse coherence per frequency for a given HRTF set, as described in [1].
void HRIRs2HRTFs_qmf(float *hrirs, int N_dirs, int hrir_len, int hopsize, int hybridmode, float_complex *hrtf_fb)
Passes zero padded HRIRs through the qmf filterbank.
void estimateITDs(float *hrirs, int N_dirs, int hrir_len, int fs, float *itds_s)
Estimates the interaural time-differences (ITDs) for each HRIR based on the cross-correlation between...
void HRIRs2HRTFs_afSTFT(float *hrirs, int N_dirs, int hrir_len, int hopsize, int LDmode, int hybridmode, float_complex *hrtf_fb)
Passes zero padded HRIRs through the afSTFT filterbank.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
#define SAF_PI
pi constant (single precision)
void qmf_FIRtoFilterbankCoeffs(float *hIR, int N_dirs, int nCH, int ir_len, int hopSize, int hybridmode, float_complex *hFB)
Converts FIR filters into Filterbank Coefficients by passing them through the QMF filterbank.
#define SAF_MAX(a, b)
Returns the maximum of the two values.
#define NUM_EARS
2 (true for most humans)
float matlab_fmodf(float x, float y)
C fmodf function, except it behaves like 'mod' in Matlab (i.e.
void cxcorr(float *a, float *b, float *x_ab, size_t la, size_t lb)
Calculates the cross correlation between two vectors.
void saf_rfft_create(void **const phFFT, int N)
Creates an instance of saf_rfft; real<->half-complex (conjugate-symmetric) FFT.
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void saf_rfft_forward(void *const hFFT, float *inputTD, float_complex *outputFD)
Performs the forward-FFT operation; use for real to complex (conjugate symmetric) transformations.
void saf_rfft_destroy(void **const phFFT)
Destroys an instance of saf_rfft.
void * malloc1d(size_t dim1_data_size)
1-D malloc (same as malloc, but with error checking)
void * calloc1d(size_t dim1, size_t data_size)
1-D calloc (same as calloc, but with error checking)
Include header for SAF externals.
Main header for the HRIR/HRTF processing module (SAF_HRIR_MODULE)
Main header for the utilities module (SAF_UTILITIES_MODULE)