Working with Second Order Sections HRTF dataset for binauralization

13 次查看(过去 30 天)
Hey all,
I'm trying to transform a mono audio signal to a binaural one using a SOS HRTF sofa file. I have done this in the past but by using the HRIR HRTF file. I'm stuck on how to use the SOS files for the similar task, since there is not enough documentation on the dataset I'm using (BiLi). Does anyone have any experience working with SOS files. Here's the code I have so far:
clear all; clc; close all;
SOFAstart;
clear all; clc; close all;
SOFAstart;
%% Load audio
[audio, fs] = audioread('Mono audio.wav');
%% Load HRTF
HRTF = SOFAload('BiLi-IRC_1130_I_SOS36_48000.sofa');
%% Process HRTF Data
HRTF_Data = shiftdim(HRTF.Data.SOS, 2); % Shift dimensions to rearrange SOS coefficients
disp(size(HRTF.Data.SOS));
disp(HRTF.SourcePosition);
%% Define desired azimuth and elevation
az = 30;
elevation = 0;
% Convolve audio with HRTF
%for az = azimuths
pos_idx = get_pos(HRTF.SourcePosition, az, elevation);
HRTF_left = HRTF_Data(:, :, pos_idx, 1);
HRTF_right = HRTF_Data(:, :, pos_idx, 2);
conv_audio_HRTF_left_time = sosfilt(HRTF_left, audio);
conv_audio_HRTF_right_time = sosfilt(HRTF_right, audio);
conv_audio_HRTF_stereo = [conv_audio_HRTF_left_time, conv_audio_HRTF_right_time];
conv_audio_HRTF_stereo = conv_audio_HRTF_stereo / max(abs(conv_audio_HRTF_stereo(:)));
audiowrite(sprintf('convolved_HRTF_audio_%d_degrees.wav', 360 - az), conv_audio_HRTF_stereo, fs);
end }%
%% Function to get position index
function idx = get_pos(sourcePositions, azimuth, elevation)
az_diff = abs(sourcePositions(:,1) - azimuth);
el_diff = abs(sourcePositions(:,2) - elevation);
[~, idx] = min(sqrt(az_diff.^2 + el_diff.^2));
end

回答(2 个)

Shishir Reddy
Shishir Reddy 2024-9-3
Hi Shaunak
The code looks well-structured for transforming a mono audio signal into a binaural signal using a SOFA file containing Head-Related Transfer Function (HRTF) data, but I see that you are facing an issue with ‘for’ loop.
If the goal is to compute binaural audio for several azimuth angles, ‘for’ loop is required because it allows to iterate through a set of azimuth values, applying the (HRTF) for each angle to generate spatialized audio outputs.
For example, if you want to simulate sound coming from various directions around the listener, a list of azimuths can be defined, and a loop can be used like this:
azimuths = 0:30:330;
for az = azimuths
% Process the audio for each azimuth
end
However, if the binaural audio is required to be calculated for a single azimuth angle, a ‘for’ loop is unnecessary. In this case, the azimuth can be specified directly and processed.
az = 30;
% Process the audio for this azimuth
I hope this helps.

jibrahim
jibrahim 2024-10-9
Hi Shaunak,
This is possible with Audio Toolbox, which has functionality to read and write SOFA files. Here is example code.
% Read the SOFA file
s = sofaread("IRC_1130_I_SOS36_48000.sofa");
% Get the numerator and denominator coefficients
num = s.Numerator;
den = s.Denominator;
fs = s.SamplingRate;
% Get the source azimuth and elevation values
src = s.SourcePosition(:,1:2);
% Define desired azimuth and elevation
az = 30;
elevation = 0;
% Get the closest point
idx = get_pos(src, az, elevation);
% Get the coefficients
n = squeeze(num(idx,:,:,:));
d = squeeze(den(idx,:,:,:));
% Read a mono signal
x = audioread('FunkyDrums-48-stereo-25secs.mp3');
x = x(:,1);
% Create binaural signal
sos1 = [squeeze(n(1,:,:)),squeeze(d(1,:,:))];
y1 = sosfilt(sos1,x);
sos2 = [squeeze(n(2,:,:)),squeeze(d(2,:,:))];
y2 = sosfilt(sos2,x);
% Play result
sound([y1,y2],fs)
function idx = get_pos(sourcePositions, azimuth, elevation)
az_diff = abs(sourcePositions(:,1) - azimuth);
el_diff = abs(sourcePositions(:,2) - elevation);
[~, idx] = min(sqrt(az_diff.^2 + el_diff.^2));
end

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by