hoene / libmysofa

Reader for AES SOFA files to get better HRTFs
Other
131 stars 70 forks source link

EAC SOFAs are detected as invalid #195

Closed ThreeDeeJay closed 1 year ago

ThreeDeeJay commented 1 year ago

SOFA files generated in EAC Individualized HRTF aren't valid according to OpenAL Soft's makemhr (where mysofa_load returns null) and SOFAlizer in ffmpeg, where I get this error:

[Parsed_sofalizer_0 @ 000001b92955f440] Can't find SOFA-file 'EAC_Default_CustomGrid_-90_90_5_0_360_5_48kHz_UniqueCartesianCoordinates.sofa'
[Parsed_sofalizer_0 @ 000001b92955f440] Error while loading SOFA file: 'EAC_Default_CustomGrid_-90_90_5_0_360_5_48kHz_UniqueCartesianCoordinates.sofa'
[Parsed_sofalizer_0 @ 000001b92955f440] No valid SOFA file could be loaded. Please specify valid SOFA file.
[AVFilterGraph @ 000001b929515180] Error initializing filter 'sofalizer' with args 'sofa=EAC_Default_CustomGrid_-90_90_5_0_360_5_48kHz_UniqueCartesianCoordinates.sofa:normalize=disabled:rotation=30'
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:0

I'm not sure if this is an issue on EAC or libmysofa's end, but hopefully the file in question here can offer some clues https://www.dropbox.com/s/ow1f3t46tw4tuvr/makemhr-f176484%2BEAC.SOFA-05ac8cc_InvalidFormat.7z?dl=1

richardpl commented 1 year ago

Happens here too.

petibub commented 1 year ago

Could you provide the SOFA file?

ThreeDeeJay commented 1 year ago

@petibub EAC_Default_CustomGrid_-90_90_5_0_360_5_48kHz_UniqueCartesianCoordinates.sofa? It's included in https://www.dropbox.com/s/ow1f3t46tw4tuvr/makemhr-f176484%2BEAC.SOFA-05ac8cc_InvalidFormat.7z?dl=1

Also, here's the script I used to replicate the error above (you'll need ffmpeg.exe in Resources\Tool\ffmpeg and of course the SOFA from the 7z file above). [HeSuVi] SOFA to WAV.zip

hoene commented 1 year ago

issue confirmed. Branch created.

hoene commented 1 year ago

Actually, the file is a denial of service attack. The issue can be fixed with the following patch

diff --git a/src/hdf/btree.c b/src/hdf/btree.c
index 824e115..6487efa 100644
--- a/src/hdf/btree.c
+++ b/src/hdf/btree.c
@@ -266,7 +266,7 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) {

   mylog("elements %d size %d\n", elements, size);

-  if (elements <= 0 || size <= 0 || elements >= 0x100000 || size > 0x10)
+  if (elements <= 0 || size <= 0 || elements > 2004800 || size > 0x10)
     return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE
   if (!(output = malloc(elements * size))) {
     return MYSOFA_NO_MEMORY; // LCOV_EXCL_LINE

However, I will not push this change as libmysofa works as expected. It limits the maximum file size to a reasonable maximum. Also, github does not allow me to upload the test files because they are too large.

davircarvalho commented 1 year ago

Hello @hoene

Would you please clarify what you mean by the file is a denial of service attack?

I'm the maintainer of the EAC hrtfs, if there's anything you have identified in the file that I could do to optimize them, please let me know :)

richardpl commented 1 year ago

Just use .wav files directly - no limitations.

ThreeDeeJay commented 1 year ago

@hoene I can confirm, the issue seems filesize-related: I was able to convert the files by increasing the azimuth/elevation degree steps (decreasing grid resolution and thus lowering the filesize), though I also noticed that increasing resolution to 1 degree (>2GB SOFA) results in a new error: Unknown in addition to Invalid format. Perhaps we're hitting a different limit here? πŸ€”

explorer_LceHBLufWm

I know that >2GB SOFA pushes the definition of a reasonable file size, but wouldn't it be more flexible to make it print a filesize warning and let the user decide if they want to continue or stop the process in case it's a memory leak or something? πŸ˜…

Generating "1- EAC_DefaultCustomGrid-90_90_15_0_360_15_48kHz-48000.mhr" Using 2 threads. Reading HRTF data from 1- EAC_DefaultCustomGrid-90_90_15_0_360_15_48kHz.sofa... Unexpected delay attribute: _Netcdf4Coordinates = Unexpected IR attribute: _Netcdf4Coordinates = Detecting compatible layout... Using 266 of 266 IRs. Loading HRIRs... 266 of 266 Calculating HRIR onsets... 532 of 532 Calculating HRIR magnitudes... 532 of 532 Calculating diffuse-field average... Performing diffuse-field equalization... Synthesizing missing elevations... Performing minimum phase reconstruction... 100% done (532 of 532) Truncating minimum-phase HRIRs... Normalizing final HRIRs... Calculating impulse delays... Creating MHR data set Output\1- EAC_DefaultCustomGrid-90_90_15_0_360_15_48kHz\1- EAC_DefaultCustomGrid-90_90_15_0_360_15_48kHz-48000.mhr... Operation completed.

Generating "2- EAC_DefaultCustomGrid-90_90_10_0_360_10_48kHz-48000.mhr" Using 2 threads. Reading HRTF data from 2- EAC_DefaultCustomGrid-90_90_10_0_360_10_48kHz.sofa... Unexpected delay attribute: _Netcdf4Coordinates = Unexpected IR attribute: _Netcdf4Coordinates = Detecting compatible layout... Using 614 of 614 IRs. Loading HRIRs... 614 of 614 Calculating HRIR onsets... 1228 of 1228 Calculating HRIR magnitudes... 1228 of 1228 Calculating diffuse-field average... Performing diffuse-field equalization... Synthesizing missing elevations... Performing minimum phase reconstruction... 100% done (1228 of 1228) Truncating minimum-phase HRIRs... Normalizing final HRIRs... Calculating impulse delays... Creating MHR data set Output\2- EAC_DefaultCustomGrid-90_90_10_0_360_10_48kHz\2- EAC_DefaultCustomGrid-90_90_10_0_360_10_48kHz-48000.mhr... Operation completed.

Generating "3- EAC_DefaultCustomGrid-90_90_5_0_360_5_48kHz-48000.mhr" Using 2 threads. Reading HRTF data from 3- EAC_DefaultCustomGrid-90_90_5_0_360_5_48kHz.sofa... Error: Could not load 3- EAC_DefaultCustomGrid-90_90_5_0_360_5_48kHz.sofa: Invalid format

Generating "4- EAC_DefaultCustomGrid-90_90_1_0_360_1_48kHz-48000.mhr" Using 2 threads. Reading HRTF data from 4- EAC_DefaultCustomGrid-90_90_1_0_360_1_48kHz.sofa... Error: Could not load 4- EAC_DefaultCustomGrid-90_90_1_0_360_1_48kHz.sofa: Unknown

ThreeDeeJay commented 1 year ago

I'm the maintainer of the EAC hrtfs, if there's anything you have identified in the file that I could do to optimize them, please let me know :)

@davircarvalho Does SOFA support mirroring? Like, just storing the left hemisphere impulse responses so the SOFA parsers would just flip the left and right channels on the fly to use as the right hemisphere IRs. That alone would, in theory, cut the filesize in half. HeSuVi can do that, so if you remove channels 8-14 (right virtual speakers), it will reuse channels 1-7 (left virtual speakers) and swap left and right ear channels to virtualize right virtual speakers. That, just like syncing virtual speakers which EAC already does, also reduces virtualization artifacts, particularly when using stereo upmix. image So if Input left ear only is checked, SOFAs should only include left hemisphere IRs (if supported) and HeSuVi WAV file should only have 7 channels since the other 7 would be identical, so this would reduce redundancy and possibly improve virtualization, two birds with one stoneπŸ‘

petibub commented 1 year ago

@petibub EAC_DefaultCustomGrid-90_90_5_0_360_5_48kHz_UniqueCartesianCoordinates.sofa? It's included in https://www.dropbox.com/s/ow1f3t46tw4tuvr/makemhr-f176484%2BEAC.SOFA-05ac8cc_InvalidFormat.7z?dl=1

I tested this file in the SOFA Toolbox for Matlab: Nothing wrong. I can load it, plot the amplitude spectra, and use it for spatialization. The HRTF set is rather small (122 MB when loaded to the memory), but the file seems to be not fully compressed because when I re-save it with compression of 9, it gets reduced from 125 MB to 102 MB. HRTF sets of hundreds of MBs are not a problem for SOFA.

So guess, the problem is somewhere else.

I know that >2GB SOFA pushes the definition of a reasonable file size...

For SOFA, there is no such a limit. Whatever size goes with your operating system, it (more or less) will go with SOFA. See https://docs.unidata.ucar.edu/nug/current/file_structure_and_performance.html#large_file_support. Datasets in the range GBs are not unusual, see https://sofacoustics.org/data/database/tuburo/ or https://sofacoustics.org/data/database/room%20transition%20dataset/. Most probably your RAM is your limit.

Does SOFA support mirroring?

Yes, but probably not the way you think: When you save your HRTFs for a single channel (e.g., left ear) only, your software will need to do the mirroring. If you can do that, than SOFA supports mirroring :-). Note that while per AES standard, the SimpleFreeFieldHRIR convention (as used by libmysofa) supports two ears (number of receivers: 2) only, you could, if you want to reduce the size of a SOFA file, just fill the second receiver channel with zeros and save the matrix with compression. I just did it for the file from above and the size reduced from 102 MB to 51 MB. Note that your software will still need to support the mirroring when doing the spatialization!

Hope that helps a bit... Piotr

ThreeDeeJay commented 1 year ago

I tested this file in the SOFA Toolbox for Matlab: Nothing wrong. I can load it, plot the amplitude spectra, and use it for spatialization. The HRTF set is rather small (122 MB when loaded to the memory), but the file seems to be not fully compressed because when I re-save it with compression of 9, it gets reduced from 125 MB to 102 MB. HRTF sets of hundreds of MBs are not a problem for SOFA.

So guess, the problem is somewhere else.

For SOFA, there is no such a limit. Whatever size goes with your operating system, it (more or less) will go with SOFA. See https://docs.unidata.ucar.edu/nug/current/file_structure_and_performance.html#large_file_support. Datasets in the range GBs are not unusual, see https://sofacoustics.org/data/database/tuburo/ or https://sofacoustics.org/data/database/room%20transition%20dataset/. Most probably your RAM is your limit.

@petibub I thought we had already figured out that it's not a problem with the SOFA file/format/specification, but rather a limit in libmysofa which I assume is like a sanity check of sorts:

libmysofa works as expected. It limits the maximum file size to a reasonable maximum.

I removed the filesize limit then compiled a new makemhr.exe (OpenAL Soft's SOFA importer/converter) and copied it over the old one in the Resources folder of makemhr-f176484+EAC.SOFA-05ac8cc_InvalidFormat.7z and now it works: image

So the issue can be manually fixed but I'm still curious: @hoene is there a particular reason why the limit is this low if SOFAs that are GBs in size aren't unusual like @petibub mentioned? πŸ€”

Yes, but probably not the way you think: When you save your HRTFs for a single channel (e.g., left ear) only, your software will need to do the mirroring. If you can do that, than SOFA supports mirroring :-). Note that while per AES standard, the SimpleFreeFieldHRIR convention (as used by libmysofa) supports two ears (number of receivers: 2) only, you could, if you want to reduce the size of a SOFA file, just fill the second receiver channel with zeros and save the matrix with compression. I just did it for the file from above and the size reduced from 102 MB to 51 MB. Note that your software will still need to support the mirroring when doing the spatialization!

@petibub That's pretty clever. and I don't know about other applications, but makemhr has just the right parameter for it:

-m Change the data set to mono, mirroring the left ear for the right ear. https://github.com/kcat/openal-soft/blob/e11cae32067a7ab84b51e5483470020251c943d5/utils/makemhr/makemhr.cpp#L1308

@davircarvalho so with this in mind, I think EAC should default to generating both left and right IRs (if it's not doing that already), and if it's set to generate only the left ear, it should probably give the option to

ThreeDeeJay commented 1 year ago

@petibub my b, scratch that. Just realized you were talking about the other (Unknown) error after noticing it still happens even with the patch. Like, even though the 5 degree resolution SOFA now works, I still get errors when I lower degree steps (increasing resolution and filesize):

15 degrees    13MB βœ… Operation completed.
10 degrees    30MB βœ… Operation completed.
5 degrees    122MB βœ… Operation completed.
4 degrees   4.43MB ❌ No usable elevations on field distance 1.000000.
3 degrees    332MB ❌ Invalid format
2 degrees    718MB ❌ Invalid format
1 degree    2.54GB ❌ Unknown

Here are all those SOFA files with a script to replicate conversion attempt and the patched makemhr (using libmysofa without file limitations) to see if it happens on your end, too. https://mega.nz/file/zOZTSIyT#TLnY4CeqVzwgH2_w3mrqAaT6NUgNYN_x57EXHJE4anM

@davircarvalho Does 4 degree elevations and azimuths on your end? Following the file size trend, it should be somewhere between 122MB and 332MB, but instead it's just ~4MB and conversion results in an error so it seems to be corrupted. πŸ€”