Отследите главную ориентацию путем объединения данных, полученных от IMU, и затем управляйте направлением прибытия источника звука путем применения функций моделирования восприятия звука (HRTF).
В типичной настройке виртуальной реальности датчик IMU присоединен к наушникам пользователя или гарнитуре VR так, чтобы воспринятое положение источника звука было относительно визуальной подсказки, независимой от главных перемещений. Например, если звук воспринят как прибывающий из монитора, это остается тот путь, даже если пользователь поворачивает голову стороне.
Uno Arduino
Invensense MPU-9250
Во-первых, соедините Invensense MPU-9250 с платой Arduino. Для получения дополнительной информации смотрите, что Оценка Ориентации Использует Инерционное Cочетание датчиков и MPU-9250.
Создайте arduino
объект.
a = arduino;
Создайте объект датчика Invensense MPU-9250.
imu = mpu9250(a);
Создайте и установите частоту дискретизации Фильтра Калмана.
Fs = imu.SampleRate;
imufilt = imufilter('SampleRate',Fs);
Когда звук перемещается от точки в пространстве до ваших ушей, можно локализовать его на основе межслухового времени и различий в уровне (ITD и ILD). Они зависимый частотой ITD и ILD's могут быть измерены и представлены как пара импульсных характеристик для любого данного исходного вертикального изменения и азимута. Набор данных АРИ HRTF содержит 1 550 пар импульсных характеристик, которые охватывают азимуты более чем 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;
Загрузите запись ambisonic вертолета. Сохраните только первый канал, который соответствует всенаправленной записи. Передискретизируйте его к 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.
FIR = cell(1,2); FIR{1} = dsp.FIRFilter('NumeratorSource','Input port'); FIR{2} = dsp.FIRFilter('NumeratorSource','Input port');
Создайте объект выполнить визуализацию в реальном времени для ориентации датчика IMU. Вызовите фильтр IMU однажды и отобразите начальную ориентацию.
orientationScope = HelperOrientationViewer; data = read(imu); qimu = imufilt(data.Acceleration,data.AngularVelocity); orientationScope(qimu);
Выполните цикл обработки в течение 30 секунд. Этот цикл выполняет следующие шаги:
Считайте данные из датчика IMU.
Объедините данные о датчике IMU, чтобы оценить ориентацию датчика. Визуализируйте текущую ориентацию.
Преобразуйте ориентацию от представления кватерниона до тангажа и рыскания в Углах Эйлера.
Используйте interpolateHRTF
получить пару HRTFs в желаемом положении.
Считайте систему координат аудио из источника сигнала.
Примените HRTFs к моно записи и проигрывайте сигнал стерео. Это лучше всего испытано с помощью наушников.
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