先理解几个名词和概念:
声音:一种波动,通过空气分子有节奏的震动进行传递。
声音频率Hz:声音每秒种震动的次数,以赫兹Hz 表示。频率越高,音高越高。
分贝dB:量度两个相同单位之数量比例的单位,可表示声音的强度单位。
人耳可听到的声波频率:每秒振动20次到20000次的范围内,既20赫兹至20000赫兹之间,。
采样Sampling:在信号处理程序中,将连续信号(例如声波)降低成离散信号(一系列样本数据)。
采样率Sampling Rate:每秒从连续信号中提取并组成离散信号的采样个数,单位也是赫兹。
快速傅里叶变换FFT:一种算法,可用来转换信号。
窗函数Window Function:在信号处理之中,用来降低信噪比的一种算法。
信噪比:
—噪讯比越高的话,声音的大音量和小音量的音量差会越大(音质猛爆)。
—噪讯比越低的话,声音的大音量和小音量的音量差会越小(音质柔和)。
然后我们看一下Unity内置的这条命令:
AudioSource.GetSpectrumData
—public void GetSpectrumData(float[] samples, int channel, FFTWindow window);
samples:将音频样本数据传送至samples数组,数组大小必须为2的n次方,最小64,最大8192。
channel:一般设置为0。
window:转换信号所用的窗函数,算法越复杂,声音越柔和,但速度更慢。
因此我们先声明一个浮点数组:
public float[] spectrumData=new float[8192];
- 1
在Update方法里面使用方法:
thisAudioSource.GetSpectrumData(spectrumData,0,FFTWindow.BlackmanHarris);
- 1
那么这个方法传送到浮点数组里的数据是什么呢?
已知了开始部分的概念,我们可以定义几个变量:
一系列采样数据样本: N
采样频率: fs
时间:T
T=Nfs
df=1T=fsN
频率分辨率越高,转换出来的数据越精确。(下图,同样情况下,低频率分辨率与高频率分辨率的比较)
而我们声明的浮点数数组的大小既是GetSpectrumData这个方法的窗函数转换数据时所用的频率分辨率,而数组中每个浮点数的值既是谱密度,每单位频率波携带的功率,我们知道了频率分辨率df=8196,那么每个浮点数,既谱密度dB表示的的是哪个频率范围,既音高范围的功率呢?
目前数字音乐领域的采样率通常为44100Hz,但通过分析音频文件[MV] FIESTAR(피에스타) _ Mirror.mp3的频谱,可能是因为通过视频转音频的缘故,基本上16000Hz以上的谱密度都非常低了。
而在Unity内通过分析spectrumData的数值,spectrumData[5500]左右以后的浮点数值与前面有一个断崖似的减少,因此可推断出,GetSpectrumData的采样的最高频率是在20000~23000赫兹之间,既音频文件23000赫兹以上频率的数据都被忽略掉了。
如果继续深入,可研究声波频率与音高的关系,将spectrumData特定范围的浮点数相加即可体现乐曲中各个音高的谱密度,由于人的听觉系统对音高最为敏感,其视觉效果应该会更加理想。
视频