主要内容

使用头部跟踪的双耳音频渲染

通过融合从IMU接收的数据来跟踪头部方向,然后通过应用头部相关传递函数(HRTF)来控制声源的到达方向。

在典型的虚拟现实设置中,IMU传感器连接到用户的耳机或VR耳机上,以便声源的感知位置相对于独立于头部运动的视觉线索。例如,如果声音被感知到来自显示器,即使用户把头转向一侧,它也会保持这种方式。

所需的硬件

  • Arduino Uno

  • Invensense微处理器- 9250

硬件连接

首先,将Invensense mcu -9250连接到Arduino板。详情请参见基于惯性传感器融合和MPU-9250的方向估计

创建传感器对象和IMU过滤器

创建一个arduino对象。

A = arduino;

创建Invensense mcu -9250传感器对象。

Imu = mpu9250(a);

创建并设置卡尔曼滤波器的采样率。

Fs = imu.SampleRate;Imufilt = imufilter(“SampleRate”Fs);

加载ARI HRTF数据集

当声音从空间中的一点传播到你的耳朵时,你可以根据耳间时间和声级差(ITD和ILD)来定位它。这些频率相关的过渡段和间质间隙可以被测量并表示为一对脉冲响应,对于任何给定的源仰角和方位角。ARI HRTF数据集包含1550对脉冲响应,它们的方位跨度超过360度,海拔高度从-30度到80度。您使用这些脉冲响应来过滤声源,以便它被感知为来自由传感器方向决定的位置。如果将传感器连接到用户头上的设备上,尽管头部移动,声音仍被感知到来自一个固定的地方。

首先,加载HRTF数据集。

aridatset = load(“ReferenceHRTF.mat”);

然后,从数据集中获取相关的HRTF数据,并将其转换为便于我们处理的有用格式。

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

获取相关的源位置。角度应与传感器在同一范围内。将方位角从[0,360]转换为[-180,180]。

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

加载单声录音

装上一架直升机的双音速录像。只保留第一个通道,它对应于全向录音。为了与HRTF数据集兼容,将其重新采样到48 kHz。

[heli,originalSampleRate] = audioread(“Heli_16ch_ACN_SN3D.wav”);直升机= 12*直升机(:,1);只保留一个频道sampleRate = 48e3;heli = resample(heli,sampleRate,originalSampleRate);

加载音频数据到SignalSource对象。设置SamplesPerFrame0.1秒。

Sigsrc = dsp。SignalSource(heli,...“SamplesPerFrame”sampleRate / 10...“SignalEndAction”循环重复的);

设置音频设备

创建一个audioDeviceWriter用与音频信号相同的采样率。

deviceWriter = audioDeviceWriter(“SampleRate”, sampleRate);

为HRTF系数创建FIR滤波器

创建一对FIR滤波器来执行双耳HRTF滤波。

FIR = cell(1,2);FIR{1} = dsp。FIRFilter (“NumeratorSource”输入端口的);FIR{2} = dsp。FIRFilter (“NumeratorSource”输入端口的);

初始化方向查看器

创建一个对象以执行IMU传感器方向的实时可视化。调用一次IMU过滤器并显示初始方向。

orientationScope = HelperOrientationViewer;数据=读取(imu);qimu = imufilt(data.Acceleration,data.AngularVelocity);orientationScope (qimu);

音频处理回路

执行处理循环30秒。这个循环执行以下步骤:

  1. 从IMU传感器读取数据。

  2. 融合IMU传感器数据,估计传感器方向。可视化当前的方向。

  3. 将方向从四元数表示转换为欧拉角的俯仰和偏航。

  4. 使用interpolateHRTF以获得一对在所需位置的hrtf。

  5. 从信号源读取一帧音频。

  6. 应用hrtf到单声道录音并播放立体声信号。使用耳机是最好的体验。

imuOverruns = 0;audioUnderruns = 0;audioFiltered = 0 (sigsrc.SamplesPerFrame,2);抽搐Toc < 30%从IMU传感器读取。[data, overflow] = read(imu);如果imuOverruns = imuOverruns +溢出;结束融合IMU传感器数据,估计传感器方向。qimu = imufilt(data.Acceleration,data.AngularVelocity);orientationScope (qimu);将方向从四元数表示转换为欧拉角的俯仰和偏航。Ypr =欧拉(齐木,“zyx股票”“帧”);偏航= ypr(end,1);Pitch = ypr(end,2);desiredPosition =[偏航,俯仰];在需要的位置获得一对hrtf。interpolatedIR = squeeze(interpolateHRTF(hrtfData,sourcePosition,desiredPosition));从文件中读取音频audioIn = sigsrc();应用hrtfaudioFiltered(:,1) = FIR{1}(audioIn, interpolatedIR(1,:));%左audioFiltered(:,2) = FIR{2}(audioIn, interpolatedIR(2,:));%对吧audioUnderruns = audioUnderruns + deviceWriter(squeeze(audioFiltered));结束

清理

释放资源,包括声音设备。

释放(sigsrc)释放(deviceWriter)清除imu一个