openal-soft icon indicating copy to clipboard operation
openal-soft copied to clipboard

A bit of documentation around MHR and SOFA support please?

Open SDX-LV opened this issue 1 year ago • 4 comments

hi,

While ThreeDeeJay supposedly got the SOFA to MHR conversion working, I did not get convincing results at the moment.

Could you please explain a bit on a Wiki what does "MHR" file contain, what limitations are there (maximum number of Impulse Responses per file, per degree or something; max length of IRs; etc.) and most importantly:

What is the Ideal input data for MHR?

The thing is, Mesh2HRTF allows to simulate any evaluation grid so we can specify any number of speaker locations, distances and other parameters in order to skip any interpolation or other avoidable processing during MHR conversion.

I would like to test OpenAL-SOFT with my custom SOFA file, but the current black-mystery-box conversion is not very approachable :)

Thanks!

SDX-LV avatar Jan 19 '23 22:01 SDX-LV

Some info I could find from:

  • https://github.com/kcat/openal-soft/blob/master/utils/sofa-support.cpp
  • https://github.com/kcat/openal-soft/blob/master/utils/makemhr/loadsofa.cpp
  • https://github.com/kcat/openal-soft/blob/master/utils/makemhr/makemhr.h

Are:

  1. the only supported sampling grid is "Equal angle" (or "globe-type") sphere https://pyfar.readthedocs.io/en/latest/modules/pyfar.samplings.html#pyfar.samplings.sph_equal_angle
  2. the coordinates along azimuth and elevation are required to be equally spaced (constant step in degrees from one coordinate to another).
  3. Some Elevation points can be missing, but then "Missing elevations can be synthesized" (not ideal!)
  4. "The limit to the number of 'distances' listed in the data set definition" = 16 (theoretically up to 256)
  5. "The limits to the number of 'elevations' listed in the data set definition" = 181 (theoretically up to 256)
  6. "The limits for each of the 'azimuths' listed in the data set definition." = 255 (theoretically up to 256)
  7. "The limits for the 'distance' from source to listener for each field in the definition file." min = 0.05 ; max = 2.50
  8. "The limits for the sample 'rate' metric in the data set definition and for resampling." min = 32000 ; max = 96000
  9. "The limits for the HRIR 'points' metric in the data set definition." min = 16 ; max = 8192 (note, given 4 "distances" it allows for example 128x16 or 120x17 or 72x28 sources for azimuth-x-elevation)
  10. head radius should be correctly read from SOFA file? otherwise it is set to 9cm (quite big) mRadius = 0.09;
  11. "The maximum number of channels that can be addressed for a WAVE file source listed in the data set definition." = 65535 (note, also applies to SOFA file)
  12. "AverageHrirMagnitude" function "Calculate the magnitude response of an HRIR and average it with any existing responses for its field, elevation, azimuth, and ear."
  13. ...

Still wondering

  • how many coordinates will MHR file contain if it is given for example more than 8192 points?
  • Is it possible to avoid averaging of data by "AverageHrirMagnitude" function?
  • Where is diffuse equalization code?
  • Can MHR file use impulse responses from SOFA HRIR file directly? What processing is done to the SOFA data and how to minimize it?

SDX-LV avatar Jan 19 '23 23:01 SDX-LV

The limits for the mhr file are largely listed in the file format docs. There can be 1 to 16 fields or distances (which can be between 5cm and 2.5m), each field can have between 5 to 128 elevations (starting at -90 degrees, with even steps up to +90 degrees), and each elevation can have between 1 to 128 azimuths (which start at 0 degrees, and are evenly spaced to create a circle on that elevation).

Each HRIR can be between 8 and 128 samples. These HRIRs are minimum phase, so the delay is held separately from the actual response; the maximum delay can be up to 63 samples (~1.3ms at 48khz).

A given SOFA file doesn't need to adhere to these limits, though. The makemhr utility will work out a compatible layout largely automatically; if the elevations or azimuths aren't evenly spaced, or if there's too many, it'll try to find a set of evenly spaced points that fit within the limit. The HRIRs are processed to get the minimum phase response and extract the delays, so the SOFA's HRIR length can be as large as you want[1], and it'll be clipped down as appropriate for the mhr file[2].

[1] If the length is really large (>32k samples), you may want to increase the FFT window size with the -f switch, else the quality may suffer. Not that such large IR sizes are expected for sane data sets. [2] By default makemhr creates mhr files using a HRIR length of 32 currently. You can use the -w switch to increase that up to 128.

how many coordinates will MHR file contain if it is given for example more than 8192 points?

Depends on the placement of the points. The number of points themselves isn't relevant, it's the number of fields/distances, elevations per distance, and azimuths per elevation it can use that matters.

Is it possible to avoid averaging of data by "AverageHrirMagnitude" function?

Don't supply multiple data sets that use the same distance, elevation, and azimuths. If there's only one HRIR at a given point, there's nothing for it to average with so it'll just be the one response.

Where is diffuse equalization code?

https://github.com/kcat/openal-soft/blob/f80470bb/utils/makemhr/makemhr.cpp#L602 is where it applies the diffuse field averages to equalize the responses.

https://github.com/kcat/openal-soft/blob/f80470bb/utils/makemhr/makemhr.cpp#L537 is where it calculates the diffuse field averages (which may or may not be weighted by coverage, depending on the -s option, and may or may not be limited in magnitude, depending on the -l option) to equalize with.

Can MHR file use impulse responses from SOFA HRIR file directly? What processing is done to the SOFA data and how to minimize it?

Disable diffuse field equalization with -e off, and make sure the SOFA file covers the full range from -90 degree elevation to +90 so it doesn't have to synthesize missing elevations. The impulse responses will be minimum phase reduced and have the delay extracted from it, which is unavoidable since that's how OpenAL Soft handles HRTF processing (if the SOFA is already minimum phase reduced, this should result in the same responses; just be aware of the output HRIR length with the -w option). But with diffuse field equalization off and no synthesized elevations, the only other processing done is an overall gain adjustment (to help ensure the filtered sounds are about as loud as any direct sounds).

kcat avatar Jan 20 '23 02:01 kcat

OK, thanks, I prepared some custom SOFA evaluation grids now for testing OpenAL-Soft optimized simulation in Mesh2HRTF - https://sourceforge.net/p/mesh2hrtf-tools/code/ci/master/tree/extra_Evaluation_Grids/

@ThreeDeeJay - you may be interested to simulate something using "greater_circle_5_5_x4" for the multi-field SOFA https://github.com/kcat/openal-soft/issues/775 . Simulation should work, but haven't tested if post-processing to SOFA file will work as well.

evaluation_grid

more testing needed

SDX-LV avatar Jan 22 '23 01:01 SDX-LV

@SDX-LV Nice, that's exactly what I've been wanting, it's just unfortunate that I don't have the proper hardware to generate it myself yet, but I'll definitely give it a try when I get a chance. In the meantime, I asked someone who might give it a shot 👍

While ThreeDeeJay supposedly got the SOFA to MHR conversion working, I did not get convincing results at the moment.

yeah, I managed to converted Mesh2HRTF SOFAs to MHR, tho I haven't tested its multi-field exports so let me know if you have something to test with 👌 I managed to convert the SCUT KEMAR SOFAs (multi-field, multi-SOFAs, single-field) and compared them to the built-in (single-field, I assume) MIT KEMAR as well which you can test here:

Built-in HRTF vs Single-Field vs Multi-field vs Multi-SOFAs.zip

There's a subtle but audible difference in simulated distance when moving the sound source closer or farther away in a straight line with the multi- import methods, unlike the single-field ones which just seem to remain at a fixed point and only volume changes with distance. nfc=false in alsoft.ini so this isn't OpenAL Soft's NFC, which leads me to believe that the multiple fields are working, tho @kcat might wanna confirm this cuz I'm not 100% sure 👀

ThreeDeeJay avatar Jan 22 '23 11:01 ThreeDeeJay