HRTF学习笔记

HRTF学习笔记

最近在研究HRTF的相关知识,在这里做个笔记记录一下

    HRTF(Head Related Transfer Function):头相关变换函数,是一种音效定位算法,
    对应时域的HRIR(Head Related Inpulse Response),头相关冲击响应。

由上定义可以知道,HRTF是一种关于音效定位的算法。其实,说是算法,不如说是一种人体物理现象的数学表达。为什么说是人体的物理现象呢,因为这跟人体的生物体型构造有关,音效定位又是一种物理现象,所以说是人体的物理现象(强行一波瞎说)。

好,言归正传,有关HRTF研究很多,首先我来说下HRTF的现象(百度就行),以下来自百度(勿喷):

===============================================

人有两个耳朵,却能定位来自三维空间的声音,这得力于人耳对声音信号的分析系统。HRTF可以分解为三部分,Interaural Time Difference,Interaural Level Difference及Spectral Cues。从空间任意一点传到人耳(鼓膜前)的信号都可以用一个滤波系统来描述,音源+滤波器得到的就是两耳鼓膜前的声音信号。这个传输系统是一个黑盒子,我们不必关心声音是如何传递到双耳的,而只需关心音源和双耳信号的差别。如果我们得到这组描述空间信息的滤波器(传递函数),即HRTF,就能还原来自空间这个方位的声音信号(如通过双声道耳机)。如果我们有空间所有方位到双耳的滤波器组,就能得到一个滤波矩阵,从而还原来自整个空间方位的声音信号。但是一个严峻的问题是,HRTF是高度个人化的,在实验室测得每个人的函数组是不现实的。因此,HRTF技术就致力于研究如何方便的真实还原个人化的空间函数。这也是virtual reality(虚拟现实技术)希望达到的目标。
简单说这就是个头部反应传送函数(Head-Response Transfer Function)。要具体点呢,可以分成几个主要的步骤来描述其功用。 第一步:制作一个头部模型并安装一支麦克风到耳膜的位置; 第二步:从固定的位置发出一些声音; 第三步:分析从麦克风中得到声音并得出被模型所改变的具体数据; 第四步:设计一个音频过滤器来模仿那个效果; 第五步:当你需要模仿某个位置所发出的声音的时候就使用上述过滤器来模仿即可。 过滤器的回应就被认为是一个HRTF,你需要为每个可能存在声源的地方来设置一个HRTF。其实我们并不需要无限多个HRTF。这里的原因也很简单,我们的大脑并不能如此精确。对于从我们的头部为原点的半球形表面上大约分布1000个这样的函数就足够了,而另一半应该是对称的。至于距离感应该由回响、响度等数据变化来实现。
·HRTF英文全名为Head Related Transfer Function,这是一种声音定位的处理技术,其原理非常复杂,由于声音会从耳廓、或肩膀反射到人耳内部,于是当我们用两个音箱模拟声音定位时,可以利用HD ITD的运算方式,来计算不同方向或位置声音所产生的大小和音调等,进而制造出立体空间声音定位的效果。另外HRTF除了使用HD ITD两种技术之外,还利用制作假人头拾音的技术,以推算出立体声音环绕模型,于是可以取得比HD ITD更好的声音效果。
====================================================
说了一大堆,是不是觉得有点头大,其实简而言之,就是:声音从声源发出到被我们听到,中间经过了一系列的动作比如反射声波重叠等等,而这些,可以通过各种数学函数合成变换来模拟。但是,单纯用函数来做,太难太难以至于几乎不可能。比较简单的函数比如时差和声波能量衰减还是可以实现的,但是更多的关于人耳构造的这些,就很难去模拟了。
于是乎,万能的科学家们另辟蹊径,不去模拟,而是通过人头模型在实验室测试收集各个声源点到人耳的数据,比较出名的测试数据有CIPIC和MIT数据集,合成数据即是HRIR(不知道我的说法对不对),然后直接把音频数据通过HRIR滤波得到我们想要的效果。
上面我说的很简略,如果大家有兴趣可以在网上找找相关论文,有很详细的解释。

下面我们来说说比较关键的,大家比较关心的部分:编程怎么实现?

首先,我们要有音频数据,这个应该没问题。假设我们现在有10000帧的PCM数据,备用。

然后,我们要获取到一组HRIR数据,这个大家可以去下载CIPIC或者MIT,我用的是CIPIC,它是把数据以三维数组的形式保存在mat文件中的。

接着关键部分来了;CIPIC的数据是25*50*200的,为什么会这样呢,它的测试方位角点总共有25*50个,每个点的数据是200帧,这下明白了吧,不清楚的可以查查资料,很多

我们先选一个方位点,就取【0,0】吧,然后我们可以去到200帧的测试数据,我们用数组A[200]表示

然后,我们要把前面的10000帧音频数据和这200帧的HRIR数据做卷积运算。what?卷积是什么鬼?不明白的可以上网查

考虑到数据量比较大,我们可以用分段卷积的方式来处理。分段卷积又是什么鬼?百度百度

卷积完了之后呢,输出的数据就是我们要的了,完事。

完事了?感觉啥也没做就完事了?对,你没看错,最简单的HRTF程序,到此就可以完成了,就是这么简单,网上很多论文洋洋洒洒几十页,看的你晕头转向却依然无处下手,在我这儿就这么简单的解决了,当然,我说的只是最简单的一个程序了,如果需要用到环绕移动的效果,肯定还要额外的工作来完成;还有一些性能优化的问题,需要用到FFT这些的,我这里也没有作介绍。

本文目的,主要是记录一下自己的研究工作,并向大家捋一捋编程思路,看论文的话大家容易迷糊,而且有些论文里的废话也不少,毕竟有些要凑字数。


作者:lll_123123
来源:CSDN
原文:https://blog.csdn.net/lwsas1/article/details/54575668
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一段简单的C代码实现,用于模拟耳机虚拟环绕声的效果: ```c #define PI 3.14159265358979323846 // 定义音频缓冲区和参数 float audioBuffer[BUFFER_SIZE]; float leftDelayBuffer[DELAY_BUFFER_SIZE]; float rightDelayBuffer[DELAY_BUFFER_SIZE]; float delayTime = 0.002f; float feedback = 0.5f; // 定义HRTF函数,需要传入声源方位和音频数据 void HRTF(float azimuth, float* audioData) { float left, right; float leftEar, rightEar; float gain, delay; int delaySamples; // 计算声源到左右耳的传输函数 leftEar = sin(azimuth * PI / 180); rightEar = cos(azimuth * PI / 180); // 左耳处理 delay = leftEar * delayTime; delaySamples = (int)(delay * SAMPLE_RATE); gain = pow(feedback, delaySamples); left = audioData[i] + gain * leftDelayBuffer[DELAY_BUFFER_SIZE - delaySamples]; leftDelayBuffer[i % DELAY_BUFFER_SIZE] = left; // 右耳处理 delay = rightEar * delayTime; delaySamples = (int)(delay * SAMPLE_RATE); gain = pow(feedback, delaySamples); right = audioData[i] + gain * rightDelayBuffer[DELAY_BUFFER_SIZE - delaySamples]; rightDelayBuffer[i % DELAY_BUFFER_SIZE] = right; // 输出到耳机 audioData[i * 2] = left; audioData[i * 2 + 1] = right; } // 主函数 int main() { // 读取音频数据 readAudioData(audioBuffer, BUFFER_SIZE); // 处理音频数据 for(int i = 0; i < BUFFER_SIZE; i++) { HRTF(30, &audioBuffer[i]); } // 输出音频数据 playAudioData(audioBuffer, BUFFER_SIZE); return 0; } ``` 以上代码实现了一个简单的耳机虚拟环绕声算法,使用了HRTF函数模拟了声源到左右耳的传输函数,并利用了延迟反馈的方式实现了声场的延迟和混响效果。需要注意的是,以上代码仅供参考,实际应用中可能需要更加复杂的算法和参数调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值