libmysofa

repository·main·Indexed 41 days ago

https://github.com/hoene/libmysofa

A C library for reading and processing AES SOFA files containing Head-Related Transfer Functions (HRTFs) according to the AES69-2015 standard. It provides functionality to open SOFA files from disk or memory, retrieve HRTF filters for Cartesian coordinates with optional linear interpolation, and convert between spherical and Cartesian coordinate systems.

Tokens
1.9K
Snippets
7
Records
7
Agent score
2%

What's inside libmysofa

  1. Use cached SOFA files to save memory

    main

    If you need to open the same SOFA file multiple times or use multiple filters, use the cached API. This ensures that HRTFs with the same filename and sampling rate are stored only once in memory.

    Note: If your program is multi-threaded, you must use synchronization mechanisms to ensure only a single thread accesses mysofa_open_cached and mysofa_close_cached at a time.

    To release all cached memory, call mysofa_cache_release_all().

    // Open files using the cache
    hrtf1 = mysofa_open_cached("file.sofa", 48000, &filter_length, &err);
    hrtf2 = mysofa_open_cached("file.sofa", 48000, &filter_length, &err);
    
    // Close using the cache
    mysofa_close_cached(hrtf1);
    mysofa_close_cached(hrtf2);
    
    // Release everything
    mysofa_cache_release_all();
  2. Install libmysofa to a specific directory

    main

    To install the libraries and header files to a non-system location, provide a prefix path during the CMake configuration step, then run the install command:

    cd build
    cmake -DCMAKE_BUILD_TYPE=Debug .. -DCMAKE_INSTALL_PREFIX=<CMAKE_INSTALL_PREFIX>
    make all test
    cmake install .
  3. Integrate libmysofa in CMake projects

    main

    You can use libmysofa as a CMake target. In your CMakeLists.txt, use find_package and link against the desired variant.

    1. Find the package

    find_package( mysofa CONFIG REQUIRED )

    Link against the shared variant:

    target_link_libraries( <target> PRIVATE mysofa::mysofa-shared )

    Or the static variant:

    target_link_libraries( <target> PRIVATE mysofa::mysofa-static )

    3. Locating libmysofa

    • System Install: If installed to a system location, CMake finds it automatically.
    • Custom Prefix: If installed to a non-system location, add -DCMAKE_PREFIX_PATH=<CMAKE_INSTALL_PREFIX> to your CMake configure command.
    • Build Tree: To use the build tree directly, add -Dmysofa_DIR=<MYSOFA_BUILD_DIRECTORY> (where the build directory is the build folder in the libmysofa source).
    # Example CMakeLists.txt snippet
    find_package( mysofa CONFIG REQUIRED )
    target_link_libraries( my_app PRIVATE mysofa::mysofa-shared )
  4. Install libmysofa on Ubuntu

    main

    To compile libmysofa on Ubuntu, first install the required dependencies:

    sudo apt install zlib1g-dev libcunit1-dev libcunit1-dev git build-essential cmake nodejs

    Then, follow the standard CMake build process:

    cd build
    cmake -DCMAKE_BUILD_TYPE=Debug ..
    make -j8 all
    ctest -j8
    sudo apt install zlib1g-dev libcunit1-dev libcunit1-dev git build-essential cmake nodejs
    
    cd build
    cmake -DCMAKE_BUILD_TYPE=Debug ..
    make -j8 all
    ctest -j8
  5. Convert between Spherical and Cartesian coordinates

    main

    Libmysofa provides utilities to convert between spherical and Cartesian coordinate systems. The coordinate system follows the SOFA specification: typically, the X axis (1, 0, 0) is the listening direction, Y (0, 1, 0) is the left side, and Z (0, 0, 1) is upwards.

    • mysofa_s2c(float values[3]): Converts Spherical to Cartesian. Input values contains phi (azimuth in degrees, counterclockwise from X), theta (elevation in degrees, up from X-Y plane), and r (distance). Output values contains x, y, z.
    • mysofa_c2s(float values[3]): Converts Cartesian to Spherical.
    // Spherical to Cartesian
    float values[3] = {phi, theta, r};
    mysofa_s2c(values);
    // values now contains {x, y, z}
    
    // Cartesian to Spherical
    float values2[3] = {x, y, z};
    mysofa_c2s(values2);
    // values2 now contains {phi, theta, r}
  6. Open SOFA files with libmysofa

    main

    Libmysofa provides several ways to open AES SOFA files containing HRTFs. The functions return a struct MYSOFA_EASY * and use an int *err to report errors.

    Standard Opening (with normalization)

    mysofa_open normalizes the HRTF data upon opening.

    Opening without normalization

    Use mysofa_open_no_norm if you do not want the data normalized.

    Advanced Opening

    Use mysofa_open_advanced for fine-grained control over the neighbor search algorithm parameters (angle step and radius step). Higher step values increase speed but may skip true nearest neighbors.

    Opening from memory

    If the file is already loaded into a buffer, use mysofa_open_data.

    #include <mysofa.h>
    
    int filter_length;
    int err;
    struct MYSOFA_EASY *hrtf = NULL;
    
    // Standard open
    hrtf = mysofa_open("file.sofa", 48000, &filter_length, &err);
    if(hrtf==NULL)
    	return err;
    
    // Advanced open
    bool norm = true;
    float neighbor_angle_step = 5;
    float neighbor_radius_step = 0.01;
    hrtf = mysofa_open_advanced("file.sofa", 48000, &filter_length, &err, norm, neighbor_angle_step, neighbor_radius_step);
    
    // Open from memory buffer
    char buffer[9] = "TESTDATA";
    hrtf = mysofa_open_data(buffer, 9, 48000, &filter_length, &err);
  7. Retrieve HRTF filters for coordinates

    main

    Once a SOFA file is open, you can retrieve filters for specific Cartesian [x, y, z] coordinates.

    Using Short (Integer) Filters

    mysofa_getfilter_short returns filters as short values and provides delays in samples.

    Using Float Filters

    mysofa_getfilter_float returns filters as float values (range [-1. to 1.]) and provides delays in seconds. This method applies linear interpolation (weighted sum of nearest neighbors).

    Bypassing Interpolation

    Use mysofa_getfilter_float_nointerp to get the exact filter stored in the SOFA file nearest to the requested position, bypassing linear interpolation.

    // Using short filters (delays in samples)
    short leftIR[filter_length];
    short rightIR[filter_length];
    int leftDelay;
    int rightDelay;
    mysofa_getfilter_short(hrtf, x, y, z, leftIR, rightIR, &leftDelay, &rightDelay);
    
    // Using float filters (delays in seconds)
    float leftIR[filter_length];
    float rightIR[filter_length];
    float leftDelay;
    float rightDelay;
    mysofa_getfilter_float(hrtf, x, y, z, leftIR, rightIR, &leftDelay, &rightDelay);
    
    // Using float filters without interpolation
    mysofa_getfilter_float_nointerp(hrtf, x, y, z, leftIR, rightIR, &leftDelay, &rightDelay);