Бинауральная визуализация аудио с использованием отслеживания головы

Отслеживайте ориентацию головы путем сплавления данных, полученных от БИНС, и затем управляйте направлением прибытия источника звука путем применения связанных с головой передаточных функций (HRTF).

При типичной настройке виртуальной реальности датчик БИНС крепится к наушникам или VR-гарнитуре пользователя так, чтобы воспринимаемое положение источника звука было относительно визуальной подсказки, независимой от движений головы. Например, если звук воспринимается как исходящий от монитора, он остается таким, даже если пользователь поворачивает голову в сторону.

Необходимое оборудование

  • Arduino

  • Функции Invensense MPU-9250

Аппаратное подключение

Сначала подключите MPU-9250 Invensense к плате Arduino. Для получения дополнительной информации см. «Оценка ориентации с помощью синтеза инерционного датчика и MPU-9250».

Создайте объект датчика и фильтр IMU

Создайте arduino объект.

a = arduino;

Создайте объект датчика MPU-9250 Invensense.

imu = mpu9250(a);

Создайте и установите частоту дискретизации фильтра Калмана.

Fs = imu.SampleRate;
imufilt = imufilter('SampleRate',Fs);

Загрузка набора данных HRTF ARI

Когда звук перемещается от точки в пространстве к ушам, можно локализовать его на основе интеравральных различий во времени и уровне (ITD и ILD). Эти частотно-зависимые ITD и ILD могут быть измерены и представлены в виде пары импульсных характеристик для любого заданного повышения и азимута источника. Набор данных HRTF ARI содержит 1550 пар импульсных характеристик, которые охватывают азимуты более 360 степени и повышения от -30 до 80 степеней. Вы используете эти импульсные характеристики, чтобы фильтровать источник звука так, чтобы он воспринимался как исходящий из положения, определенного ориентацией датчика. Если датчик прикреплен к устройству на голове пользователя, звук воспринимается как исходящий из одного фиксированного места, несмотря на движения головы.

Сначала загрузите набор данных HRTF.

ARIDataset = load('ReferenceHRTF.mat');

Затем получите соответствующие данные HRTF из набора данных и поместите их в полезный формат для нашей обработки.

hrtfData = double(ARIDataset.hrtfData);
hrtfData = permute(hrtfData,[2,3,1]);

Получите соответствующие исходные позиции. Углы должны находиться в той же области значений, что и датчик. Преобразуйте азимуты из [0,360] в [-180,180].

sourcePosition = ARIDataset.sourcePosition(:,[1,2]);
sourcePosition(:,1) = sourcePosition(:,1) - 180;

Загрузка Монавральной Записи

Загрузите амбизоническую запись вертолета. Сохраните только первый канал, который соответствует всенаправленной записи. Повторно отобразите его на 48 кГц для совместимости с набором данных HRTF.

[heli,originalSampleRate] = audioread('Heli_16ch_ACN_SN3D.wav');
heli = 12*heli(:,1); % keep only one channel

sampleRate = 48e3;
heli = resample(heli,sampleRate,originalSampleRate);

Загрузите аудио данных в SignalSource объект. Установите SamplesPerFrame на 0.1 секунд.

sigsrc = dsp.SignalSource(heli, ...
    'SamplesPerFrame',sampleRate/10, ...
    'SignalEndAction','Cyclic repetition');

Настройка Аудио устройства

Создайте audioDeviceWriter с той же частотой дискретизации, что и аудиосигнал.

deviceWriter = audioDeviceWriter('SampleRate',sampleRate);

Создайте конечная импульсная характеристика для коэффициентов HRTF

Создайте пару конечных импульсных характеристик для выполнения бинауральной фильтрации HRTF.

FIR = cell(1,2);
FIR{1} = dsp.FIRFilter('NumeratorSource','Input port');
FIR{2} = dsp.FIRFilter('NumeratorSource','Input port');

Инициализация средства просмотра ориентации

Создайте объект, чтобы выполнить визуализацию в реальном времени для ориентации датчика IMU. Один раз вызовите фильтр БИНС и отобразите начальную ориентацию.

orientationScope = HelperOrientationViewer;
data = read(imu);

qimu = imufilt(data.Acceleration,data.AngularVelocity);
orientationScope(qimu);

Цикл обработки аудио

Выполните цикл обработки в течение 30 секунд. Этот цикл выполняет следующие шаги:

  1. Считайте данные с датчика БИНС.

  2. Для оценки ориентации датчика используйте данные БИНС. Визуализация текущей ориентации.

  3. Преобразуйте ориентацию из представления кватерниона в тангаж и рыскание в углах Эйлера.

  4. Использование interpolateHRTF для получения пары HRTF в желаемом положении.

  5. Считайте систему координат аудио от источника сигнала.

  6. Применить HRTF к монорегистрации и воспроизвести стереосигнал. Это лучше всего испытать, используя наушники.

imuOverruns = 0;
audioUnderruns = 0;
audioFiltered = zeros(sigsrc.SamplesPerFrame,2);
tic
while toc < 30

    % Read from the IMU sensor.
    [data,overrun] = read(imu);
    if overrun > 0
        imuOverruns = imuOverruns + overrun;
    end
    
    % Fuse IMU sensor data to estimate the orientation of the sensor.
    qimu = imufilt(data.Acceleration,data.AngularVelocity); 
    orientationScope(qimu);
    
    % Convert the orientation from a quaternion representation to pitch and yaw in Euler angles.
    ypr = eulerd(qimu,'zyx','frame');
    yaw = ypr(end,1);
    pitch = ypr(end,2);
    desiredPosition = [yaw,pitch];
    
    % Obtain a pair of HRTFs at the desired position.
    interpolatedIR = squeeze(interpolateHRTF(hrtfData,sourcePosition,desiredPosition));
    
    % Read audio from file   
    audioIn = sigsrc();
             
    % Apply HRTFs
    audioFiltered(:,1) = FIR{1}(audioIn, interpolatedIR(1,:)); % Left
    audioFiltered(:,2) = FIR{2}(audioIn, interpolatedIR(2,:)); % Right    
    audioUnderruns = audioUnderruns + deviceWriter(squeeze(audioFiltered)); 
end

Очистка

Отпустите ресурсы, включая звуковое устройство.

release(sigsrc)
release(deviceWriter)
clear imu a