41#ifdef SAF_ENABLE_HADES_MODULE
89 for(band=0; band<e->
nBands; band++){
92 azi = azi < 0.0f ? azi+360.0f : azi;
93 edit_idx =
SAF_CLAMP((
int)(azi + 0.5f), 0, 359);
96 gain_lin = powf(10.0f,
SAF_CLAMP(dirGain_dB[edit_idx], -60.0f, 12.0f)/20.0f);
123 const float_complex calpha = cmplxf(1.0f, 0.0f);
const float_complex cbeta = cmplxf(0.0f, 0.0f);
135 for(band = 0; band<a->
nBands; band++){
153 memcpy(s->
W, a->
W, s->
nGrid*(s->
nGrid)*
sizeof(float_complex));
187 for(band=0; band<s->
nBands; band++){
189 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
NUM_EARS, a->
nGrid, a->
nGrid, &calpha,
321 int i, j, ch, nMics, band, doa_idx, gain_idx;
322 float a, b, diffuseness, synAvgCoeff, streamBalance, eq, gain_dir, gain_diff, trace_M, reg_M, sum_As, targetEnergy;
323 float_complex g_l, g_r, h_dir[
NUM_EARS], AsH_invCx_As;
325 const float_complex calpha = cmplxf(1.0f, 0.0f);
const float_complex cbeta = cmplxf(0.0f, 0.0f);
331 for (band = 0; band < s->
nBands; band++) {
334 saf_assert(diffuseness>-0.0001f && diffuseness < 1.00001f,
"Erroneous parameter analysis");
343 if(streamBalance<1.0f){
349 b = 2.0f - streamBalance;
355 for(i=0; i<nMics; i++)
359 for(i=0; i<nMics; i++){
369 if(cabsf(g_l)>4.0f || cabsf(g_r)>4.0f)
370 g_l = g_r = cmplxf(1.0f, 0.0f);
386 cblas_cscal(nMics, &g_l, s->
Q_dir, 1);
387 cblas_cscal(nMics, &g_r, s->
Q_dir + nMics, 1);
392 cblas_ccopy(nMics*nMics, scon->
Cx[band].Cx, 1, Cx, 1);
394 for(i=0; i<nMics; i++)
395 trace_M += crealf(Cx[i*nMics+i]);
396 sum_As = cblas_scasum(nMics, s->
As, 1);
399 if( trace_M < 0.0001f || sum_As < 0.0001f)
403 reg_M = (trace_M/(float)nMics) * 10.0f + 0.0001f;
404 for(i=0; i<nMics; i++)
405 Cx[i*nMics+i] = craddf(Cx[i*nMics+i], reg_M);
415 AsH_invCx_As = craddf(AsH_invCx_As, 0.00001f);
418 AsH_invCx_As = ccdivf(cmplxf(1.0f, 0.0f), AsH_invCx_As);
419 cblas_cscal(nMics, &AsH_invCx_As, AsH_invCx, 1);
420 cblas_ccopy(nMics, AsH_invCx, 1, s->
Q_dir + j*nMics, 1);
424 cblas_cscal(nMics, &g_l, s->
Q_dir, 1);
425 cblas_cscal(nMics, &g_r, s->
Q_dir + nMics, 1);
433 memset(s->
Q, 0,
NUM_EARS*nMics*
sizeof(float_complex));
434 s->
Q[0*nMics+s->
refIndices[0]] = cmplxf(1.0f, 0.0f);
435 s->
Q[1*nMics+s->
refIndices[1]] = cmplxf(1.0f, 0.0f);
442 cblas_sscal(2*
NUM_EARS*nMics, eq*a*(1.0f-diffuseness), (
float*)s->
Q, 1);
443 cblas_saxpy(2*
NUM_EARS*nMics, eq*b*diffuseness, (
float*)s->
Q_diff, 1, (
float*)s->
Q, 1);
448 for(i=0; i<nMics; i++)
449 targetEnergy += crealf(scon->
Cx[band].Cx[i*nMics+i]);
450 targetEnergy = eq*0.25f*targetEnergy * s->
diffEQ[band];
453 if(s->
enableCM && targetEnergy>0.0001f){
455 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasConjTrans,
NUM_EARS,
NUM_EARS, 1, &calpha,
459 cblas_sscal(2*
NUM_EARS*
NUM_EARS, eq*a*(1.0f-diffuseness)*targetEnergy, (
float*)s->
Cy, 1);
474 cblas_sscal(2*
NUM_EARS*nMics, synAvgCoeff, (
float*)s->
M[band], 1);
475 cblas_saxpy(2*
NUM_EARS*nMics, 1.0f-synAvgCoeff, (
float*)s->
new_M, 1, (
float*)s->
M[band], 1);
479 for(band=0; band<s->
nBands; band++){
480 cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
NUM_EARS, s->
timeSlots, nMics, &calpha,
494 memcpy(output[ch], s->
outTD[ch], blocksize*
sizeof(
float));
495 for(; ch<nChannels; ch++)
496 memset(output[ch], 0, blocksize*
sizeof(
float));
void afSTFT_clearBuffers(void *const hSTFT)
Flushes time-domain buffers with zeros.
void afSTFT_create(void **const phSTFT, int nCHin, int nCHout, int hopsize, int lowDelayMode, int hybridmode, AFSTFT_FDDATA_FORMAT format)
Creates an instance of afSTFT.
void afSTFT_backward_knownDimensions(void *const hSTFT, float_complex ***dataFD, int framesize, int dataFD_nCH, int dataFD_nHops, float **dataTD)
Performs backward afSTFT transform (dataFD dimensions are known)
void afSTFT_destroy(void **const phSTFT)
Destroys an instance of afSTFT.
@ AFSTFT_BANDS_CH_TIME
nBands x nChannels x nTimeHops
void formulate_M_and_Cr_cmplx(void *const hCdf, float_complex *Cx, float_complex *Cy, float_complex *Q, int useEnergyFLAG, float reg, float_complex *M, float_complex *Cr)
Computes the optimal mixing matrices.
void cdf4sap_cmplx_destroy(void **const phCdf)
Destroys an instance of the Covariance Domain Framework.
void cdf4sap_cmplx_create(void **const phCdf, int nXcols, int nYcols)
Creates an instance of the Covariance Domain Framework.
#define saf_assert(x, message)
Macro to make an assertion, along with a string explaining its purpose.
void utility_cpinv_create(void **const phWork, int maxDim1, int maxDim2)
(Optional) Pre-allocate the working struct used by utility_cpinv()
#define SAF_CLAMP(a, min, max)
Ensures value "a" is clamped between the "min" and "max" values.
void utility_cglslv_destroy(void **const phWork)
De-allocate the working struct used by utility_cglslv()
void utility_cglslv(void *const hWork, const float_complex *A, const int dim, float_complex *B, int nCol, float_complex *X)
General linear solver: single precision complex, i.e.
#define NUM_EARS
2 (true for most humans)
void utility_cpinv(void *const hWork, const float_complex *inM, const int dim1, const int dim2, float_complex *outM)
General matrix pseudo-inverse (the svd way): single precision complex, i.e.
void utility_cpinv_destroy(void **const phWork)
De-allocate the working struct used by utility_cpinv()
#define SAF_MIN(a, b)
Returns the minimum of the two values.
void utility_cvvdot(const float_complex *a, const float_complex *b, const int len, CONJ_FLAG flag, float_complex *c)
Single-precision, complex, vector-vector dot product, i.e.
void utility_cglslv_create(void **const phWork, int maxDim, int maxNCol)
(Optional) Pre-allocate the working struct used by utility_cglslv()
void utility_cvconj(const float_complex *a, const int len, float_complex *c)
Single-precision, complex, vector-conjugate, i.e.
@ NO_CONJ
Do not take the conjugate.
void ** malloc2d(size_t dim1, size_t dim2, size_t data_size)
2-D malloc (contiguously allocated, so use free() as usual to deallocate)
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)
void *** malloc3d(size_t dim1, size_t dim2, size_t dim3, size_t data_size)
3-D malloc (contiguously allocated, so use free() as usual to deallocate)
#define FLATTEN2D(A)
Use this macro when passing a 2-D dynamic multi-dimensional array to memset, memcpy or any other func...
#define HADES_MAX_NMICS
Maximum number of microphones.
struct _hades_analysis_data * hades_analysis_handle
Handle for the hades analysis data.
struct _hades_param_container_data * hades_param_container_handle
Handle for the hades parameter container data.
struct _hades_signal_container_data * hades_signal_container_handle
Handle for the hades signal container data.
@ HADES_USE_AFSTFT
Alias-free STFT filterbank.
@ HADES_USE_AFSTFT_LD
Alias-free STFT filterbank (low delay)
void hades_getInterpolatedHRTFs(hades_analysis_handle const hAna, HADES_HRTF_INTERP_OPTIONS interpOption, hades_binaural_config *binConfig, float *target_dirs_deg, int nTargetDirs, float_complex *hrtf_interp)
Binaural filter interpolator.
Internal header for the HADES module (SAF_HADES_MODULE)
void hades_radial_editor_destroy(hades_radial_editor_handle *const phREd)
Destroys an instance of a hades radial editor object.
int hades_synthesis_getProcDelay(hades_synthesis_handle const hSyn)
Returns the synthesiser processing delay, in samples.
void hades_radial_editor_apply(hades_radial_editor_handle const hREd, hades_param_container_handle const hPCon, float dirGain_dB[360])
Applies the radial (360 degree) parameter editing.
void hades_radial_editor_create(hades_radial_editor_handle *const phREd, hades_analysis_handle const hAna)
Creates and returns a handle to an instance of a hades radial editor object, which allows for directi...
float * hades_synthesis_getEqPtr(hades_synthesis_handle const hSyn, int *nBands)
Returns a pointer to the eq vector, which can be changed at run-time.
float * hades_synthesis_getSynthesisAveragingCoeffPtr(hades_synthesis_handle const hSyn)
Returns a pointer to the synthesis averaging coefficient scalar [0..1], which can be changed at run-t...
void hades_synthesis_apply(hades_synthesis_handle const hSyn, hades_param_container_handle const hPCon, hades_signal_container_handle const hSCon, int nChannels, int blocksize, float **output)
Performs hades synthesis.
void hades_synthesis_create(hades_synthesis_handle *const phSyn, hades_analysis_handle const hAna, HADES_BEAMFORMER_TYPE beamOption, int enableCM, int refIndices[2], hades_binaural_config *binConfig, HADES_HRTF_INTERP_OPTIONS interpOption)
Creates and returns a handle to an instance of a hades synthesis object.
float * hades_synthesis_getStreamBalancePtr(hades_synthesis_handle const hSyn, int *nBands)
Returns a pointer to the stream balance vector [0..2], which can be changed at run-time.
void hades_synthesis_reset(hades_synthesis_handle const hSyn)
Flushes run-time buffers with zeros.
void hades_synthesis_destroy(hades_synthesis_handle *const phSyn)
Destroys an instance of hades synthesis.
Header for the HADES synthesis (SAF_HADES_MODULE)
struct _hades_radial_editor_data * hades_radial_editor_handle
Handle for the hades radial editor data.
struct _hades_synthesis_data * hades_synthesis_handle
Handle for the hades synthesis data.
HADES_BEAMFORMER_TYPE
Beamforming options for hades_synthesis.
@ HADES_BEAMFORMER_FILTER_AND_SUM
Filter-and-sum beamforming.
@ HADES_BEAMFORMER_BMVDR
Binaural minimum-variance distortion- less response (MVDR) beamforming.
@ HADES_BEAMFORMER_NONE
No beamforming (ref sensors only)
HADES_HRTF_INTERP_OPTIONS
HRTF interpolation options for hades_synthesis.
Main structure for hades analysis.
int nMics
Number of microphones.
int blocksize
Number of samples to process at a time (note that 1 doa and diffuseness estimate is made per block)
int hybridmode
Optionally, the lowest TF bands may be subdivided to improve low-freq resolution.
float_complex * DCM_array
Diffuse covariance matrix (computed over all grid directions and weighted); FLAT: nBands x nMics x nM...
float * grid_dirs_xyz
Scanning grid coordinates (unit vectors and only used by grid-based estimators); FLAT: nGrid x 3.
float * freqVector
Centre frequencies; nBands x 1.
float * grid_dirs_deg
Array grid dirs in degrees; FLAT: nGrid x 2.
int hopsize
Filterbank hop size (blocksize must be divisable by this.
HADES_FILTERBANKS fbOpt
see HADES_FILTERBANKS
float_complex * W
Diffuse integration weighting matrix; FLAT: nGrid x nGrid.
float_complex * H_array
Array IRs in the frequency domain; FLAT: nBands x nMics x nDirs.
int nBands
Number of frequency bands.
int timeSlots
Number of time slots.
int nGrid
Number of grid/scanning directions.
Binaural configuration struct.
int nHRIR
Number of HRIRs.
int hrir_fs
HRIR sample rate.
int lHRIR
Length of HRIRs in samples.
float * hrir_dirs_deg
HRTF directions in [azimuth elevation] format, in degrees; FLAT: nHRIR x 2.
float * hrirs
Matrix of HRIR data; FLAT: nHRIR x NUM_EARS x lHRIR.
Parameter container to store the data from an analyser for one blocksize of audio.
int * gains_idx
Reproduction direction index per band; nBands x 1.
int * doa_idx
Beamforming direction index per band; nBands x 1.
float * diffuseness
Diffuseness value per band; nBands x 1.
float * gains_diff
Extra diffuse reproduction gain per band (default=1.0f); nBands x 1
float * gains_dir
Extra direct reproduction gain per band (default=1.0f); nBands x 1
Main structure for hades radial (360degree) gain and direct-to-diffuse ratio editor.
float * pGrid_dirs_deg
Pointer to grid dirs in degrees; FLAT: nGrid x 2.
float * pGrid_dirs_xyz
Pointer to grid dirs as Cartesian coordinates of unit length; FLAT: nGrid x 3.
int nGrid
Number of grid/scanning directions.
int nBands
Number of bands.
Signal container to store one block of TF-domain audio data.
CxMic * Cx
NON-time-averaged covariance matrix per band; nBands x .Cx(nMics x nMics)
float_complex *** inTF
Input frame in TF-domain; nBands x nMics x timeSlots.
Main structure for hades synthesis.
float ** outTD
output time-domain buffer; NUM_EARS x blocksize
void * hLinSolve
Handle for solving linear equations (Ax=b)
int blocksize
blocksize in samples
void * hCDF
Handle for solving the covariance matching problem.
float_complex ** M
Mixing matrix per band; nBands x FLAT: (NUM_EARS x nMics)
float synAvgCoeff
Mixing matrix averaging coefficent [0..1].
HADES_FILTERBANKS fbOpt
Filterbank option, see HADES_FILTERBANKS.
float_complex * new_M
New mixing matrix (not yet temporally averaged); FLAT: NUM_EARS x nMics.
int nBands
Number of bands in the time-frequency transform domain.
float_complex * H_array
Array IRs in the frequency domain; FLAT: nBands x nMics x nGrid.
float_complex * As
Array steering vector for DoA; FLAT: nMics x 1.
float * eq
Gain factor per band; nBands x 1.
int timeSlots
Number of time frames in the time-frequency transform domain.
float_complex * H_bin
To spatialise the source beamformers; FLAT: nBands x NUM_EARS x nGrid.
HADES_BEAMFORMER_TYPE beamOption
see HADES_BEAMFORMER_TYPE
int enableCM
Flag: whether the spatial covariance matching is enabled (1) or disabled (0)
hades_binaural_config * binConfig
Internal copy of user configuration.
float * freqVector
Frequency vector (band centre frequencies); nBands x 1.
float * grid_dirs_deg
Array grid dirs in degrees; FLAT: nGrid x 2.
int nGrid
Number of grid/scanning directions.
float_complex * Q
Mixing matrix for the direct and diffuse streams combined (based on the diffuseness value); FLAT: NUM...
float_complex * As_r
Array steering vector relative to right reference sensor; FLAT: nMics x 1.
float * diffEQ
EQ curve to bring the overall diffuse-field magnitude response of the array to that of the HRTFs inst...
void * hPinv
Handle for computing the Moore-Penrose pseudo inverse.
float_complex * DCM_array
Diffuse coherence matrix for the array; FLAT: nBands x nMics x nMics.
int hopsize
hopsize in samples
float_complex * Cy
Target binaural spatial covariance matrix; FLAT: NUM_EARS x NUM_EARS.
float_complex *** outTF
nBands x NUM_EARS x timeSlots
float ** grid_dirs_xyz
Grid dirs as Cartesian coordinates of unit length; nGrid x 3.
float_complex * Q_dir
Mixing matrix for the direct stream; FLAT: NUM_EARS x nMics.
float_complex * DCM_bin_norm
Diffuse coherence matrix for the HRTF set, normalised with 1/trace(DCM_bin); FLAT: nBands x nMics x n...
float_complex * W
Diffuse integration weighting matrix; FLAT: nGrid x nGrid.
float_complex * Q_diff
Mixing matrix for the diffuse stream; FLAT: NUM_EARS x nMics.
HADES_HRTF_INTERP_OPTIONS interpOption
HRIR interpolation option, see HADES_HRTF_INTERP_OPTIONS.
float_complex * As_l
Array steering vector relative to left reference sensor; FLAT: nMics x 1.
int refIndices[2]
Indices into [0 nMics-1], defining the reference sensors.
void * hFB_dec
Filterbank handle.
int nMics
Number of microphones.
float * streamBalance
Stream balance per band (0:fully diffuse, 1:balanced, 2:fully direct); nBands x 1.