音频信息
时域音频信息就是一个点随着时间在振膜垂直方向振动的情况,可表示为一个2D点集,采样率越高,就越接近连续曲线。
sample rate 采样率 = 对这个点所在位置测量的频率,通常就是44100Hz。
bit rate 比特率 = 采样率 * 量化精度 * 声道数,是指单位时间内处理的数据量。
buffer size = window size = 每次分析步骤所需的sample数。通常是1024或2048。
hop size = 两个相邻窗口之间错开的sample数,越小,则说明时序解析度越高,计算成本也越高。通常为buffer size的一半或四分之一。
frame size = 帧长,媒体帧的长度。
fps = 帧率。一个帧可能包含多个采样。音频基本都是这样,视频帧则一般一帧一采样。因此fps这个概念通常用于视频和游戏领域。
bit depth = 位深度,每次采样sample里包含的信息的bit数。
channels = 声道数,双声道文件大小是单声道两倍。
<---- buf_size ---->
[.....step 0.......]
<-- hop -><---- buf_size ---->
[.....step 1.......]
<-- hop -><- hop --><----buf_size ---->
[.....step 2.......]
|-------------------|------------------------>
t t+buf_size (samples)
音频的表示
根据傅立叶理论,任何波形的周期函数都是不同振幅、不同相位的正弦波cost(wt)的叠加。无穷多个的正弦波甚至会叠加成标准矩形波(如果以时间为x轴,振幅为y轴)。下图是不同频率振幅的正弦波叠加的直观表现。
频谱就是各频率的振幅图,即下图中的侧视图,频域为x轴,振幅为y轴。可以看到偶数参数的频率相当于cos(0t),是振幅为0的直线,不影响波形,只影响。
除了正面看的时域角度的波形图,侧面看的频域角度的频谱,还有第三个角度,从上往下看的,以频率为x轴,相位(与周期和初相相关)为y轴。
各种傅立叶变换
傅立叶级数在时域是一个周期且连续的函数,在频域则是一个非周期离散的函数。如下图。
傅立叶变换就是将一个时域非周期(也可以理解为周期无限大)的连续信号转换为在频域非周期的连续信号。连续信号,就相当于粒度无限细的从0到无穷大所有离散频率的组合,比如下图。
很多时候在时域很难处理的事情,放到频域就很简单。比如sin3x+sin5x的时域曲线很难画出来,但频域图很容易画,两条竖线搞定。因此很多时候需要用傅立叶变换把时域表示转换成频域表示。又比如微分方程,在时域是微分和积分的操作,到频域变成乘除法。
频谱分析一般包括幅频谱和相频谱,不过常用的是幅频谱。
模拟信号(1)通过FT变换到连续的频域信号(2),于是有了模拟信号的频谱。
计算机只能处理数字信号,需要将原模拟信号在时域离散化,即在时域对其进行采样,采样脉冲序列如(3)所示,就是均匀地采样。(1)×(3)=(5),得到离散时间信号x[n],时域离散,但FT变换后频谱依旧连续。
连续的频谱仍然不能被计算机处理,需要再进行采样,得到(10)DFT(离散傅立叶变换)结果。著名的FFT就是快速计算DFT的方法,本质并非速算FT,而是速算DFT。
(10)进行逆DFT运算,得到IDFT结果,即为时域信号,它与(5)的x[n]不同,是它的周期性拓延。
DFS(离散傅立叶级数)是针对离散周期信号提出的,本质和DFT一样(截取主值空间做输入)。对(9)这种离散时域信号进行DFS即可得到(10)。
STFT(短时距傅立叶变换)是FT的变形,用于决定随时间变化的信号局部部分的正弦频率和相位。计算STFT的过程往往是将长时间信号切割成数个较短的等长信号没然后分别再计算短程的傅立叶变换,从而描绘频域与时域上的变化(相比之下,FT不能给出任何信号频率随时间改变的信息)。
能量谱(power spectrum)又叫能量谱密度,描述了信号或时间序列的能量如何随频率分布,是原信号FT之后的平方。
倒频谱(cepstrum),或者说倒谱是log(spectrum)进行IFT(傅立叶逆变换)的结果。存在complex cepstrum,power cepstrum,phase cepstrum,real cepstrum这几种。其中power cepstrum对人类语音分析很有用。原频谱上肉眼难识别的周期性信号(指的是重复出现的边频带),或者说成族的边频带谱线简化为单根谱线。所谓边频带就是以高频信号特质频率为中心,对称分布两侧的一对分量。
Essentia
Essentia是一个C++音频数据分析库,既适用于研究人员在交互式环境下进行实验和迅速迭代开发(python接口),又支持优化的提取器在生产集群和大数据集上高效运转(C++接口)。
Essentia还支持标准和流式两种接口,前者提供完整控制权限但代码复杂,后者相反,能轻松把多个算法串起来形成提取器,但不够灵活。
Essentia音频算法
Envelop/SFX:
SFX是sound effects或special effects的简写。
- AfterMaxToBeforeMaxEnergyRatio::输入pitch数组,输出最大pitch后的值与最大pitch前的值的比值。
- DerivativeSFX:输入singal envelope,输出最大振幅后导数的加权平均值,以及最大振幅前最大导数。(导数是singal envelope的导数)
- Envelope:输入signal,输出非对称lowpass filter(低通滤波器)后的signal,signal envelope译作信号包络。
- FlatnessSFX:输入singal envelope,输出flatness coefficient。
- LogAttackTime:所谓attack time就是指声音达到对人耳可以听得到,到最高强度之间的时间。输入signal envelope,输出logAttackTime,attackStart,attackStop。
Filters
滤波器的输入都是signal,输出也都是过滤后的signal。
- AllPass:bandwidth,cutoffFrequency,order,sampleRate。基于1阶或2阶IIR(Infinite Impulse Response)。
- BandPass:基于2阶IIR。
- DCRemoval:基于1阶IIR。移除DC offset。
- Equaloudness:人耳对相同loudness不能感知所有频段,为此,信号需要做处理。
- HighPass:参数cutoffFrequency,sampleRate。基于1阶IIR。
- MaxFilter:参数causal(bool,true时window再当前值之后,false时则以当前值为中心),width(窗口大小,中心模式下必须为奇数)。
有两种滤波器:FIR & IIR。FIR适合对相位敏感的图像处理和数据传输,IIR适合量相对小且幅频特性精度高的语音信号。
Input/Output
- AudioLoader:输入audio stream,filename,输出audio,sampleRate,nrChannels,md5,bitRate,codec。支持所有FFmpeg支持的格式:wav,aiff,flac,ogg,mp3。
- EasyLoader:输入audio stream,filename,downmix,endTime,replayGain,sampleRate,startTime,输出audio(real vector)。先读出音频文件的raw data,downmix到mono,并用replayGain做normalization,最后如果给定的采样率与输入不符,则以给定的采样率重新采样。
- MonoLoader:输入audio stream,downmix(对立体声的选项,可选左,右,混),filename,sampleRate,输出audio。先读取raw data,再downmix(所谓downmix就是将左声右声道、中声道、左环绕、右环绕这些声道以一种合理的方式合并到单声道mono或立体声stereo) to moto(单声道),最后如果给定的采样率与输入不符,则以给定的采样率重新采样。
- AudioWriter:输入audio信号(stereosample vector),bitrate,filename,format,sampleRate。将立体声信号编码形成音频文件。
Standard
- AutoCorrelation:输入real vec,输出自相关vec。所谓自相关指的是同一个序列中有一定间隔的两段数据之间的相关性。
- BPF:实现一个断点函数(break point function),在离散的x、y轴坐标系的点集之间进行linear interpolation(线性插值,一种curve fitting方法,用linear polynomials,即线性多项式表达式,在已知点集的范围内构造新的点),使之连续。
- BinaryOperator:对两个数组进行基本的binary算术运算。
-
Clipper:将输入信号clip,剪掉过大和过小的值。
- ConstantQ:用FFT将一个数据序列转化到频域frequency domain。CrossCorrelation:两个信号的互相关性,即相似度。计算方法是sliding点乘,或sliding inner-product,用表示。(fg)[n]就是将f函数的复共轭(complex conjugate)与g函数横坐标偏移n后的值乘起来,然后横坐标从负无穷到正无穷所有这些乘积加起来的值,度量了n这个offset上二者的相似度,毫无疑问重合时达到峰值。这个函数本质上和两个函数的卷积很像。Autocorrelation本质上就是自己与自己的cross-correlation。
-
DCT:计算Discrete Cosine Transform离散余弦变换,用于将信号压缩,将空域信号转换到频域上,具有良好的去相关性性能,是无损的,对称的。
其中,f(i)为原始信号,N为点数,c(u)是一个补偿系数。
二维DCT就是在一维基础上再做一次DCT。 FFT:实际上是计算positive complex short-term Fourier transform,即STFT。
FrameCutter:将input buffer裁剪到各个帧中。最后不满的帧用0填满,也可以直接舍弃。输入frameSize,hopSize,是否startFromTimeZero,丢弃过小的帧的阈值。输出frame(real vec)。
MonoMixer:将信号downmix为单声道。
Multiplexer:输入number of values或frames,输出一个vector。
NSGConstantQ:输入frame(real vec),输出constq,constqdc(DC band transform),constqnf(Nyquist band transform)。用非静态Gabor frame计算constant Q transform。
NoiseAdder:给输入信号里添加噪声,可设置分贝dB等级与随机种子。
PeakDetection:探测数组的局部峰值(可设置阈值,必须大于它的才算peak),返回所有peak位置。
RealAccumulator:输入信号,输出一个累加后的结果,存在单个vector里(单frame)。
Resample:重新采样,转变为想要的采样率,不过必须保证essentia在编译时选了Real=float,否则会报错。
Scale:按比例缩放声音,同时加上clipping机制。
Slicer:给出几个起止时间,将音频信号分成若干个segments。
-
Spline:数学上,spline指的是多项式表达式分段定义出的特殊函数,常用于插值,因为spline interpolation可以用很低degree的多项式拟合出大体上近似的结果。
StereoMuxer:输入左、右声道的信号,输出立体声信号。
StereoTrimmer:从立体声信号里截取一段。
Welch:用Welch方法估算power spectral density(即前文里的能量谱,或能量谱密度)。
Windowing:window函数又称tapering function或apodization function,将某个选定区间之外的部分归零。通常就是选定接近max的地方,以之为中心。数学上,任何函数与window函数相乘,结果都会导致选定区域之外归零,选定区域内则变成"view through the window"。
ZeroCrossingRate:计算一个音频信号的zero-crossing rate,指的是正负符号变化的频率。可以用来给percussive sounds(打击乐)分类。
Special
Power Spectrum:计算能量谱。
Panning:比较左右声道的频谱,刻画panorama(全景) distribution。主要用于音乐种类分类。
MelBands:施加一个由根据mel scale分布的若干等面积三角过滤器组成的频域上的filterbank。
MaxMagFreq:计算频谱中最大magnitude的频率。频谱中至少又2个频率。
MFCC:输入频谱,输出mfcc(mel frequency cepstrum coefficients)与mel bands的能量。
LogSpectrum:用log分布的frequency bins计算频谱。
LPC:计算Linear Predictive Coefficients & associated reflection coefficients。它是最强大的语音分析技术之一,能以低bit rate提供高度准确的speech parameter estimates,广泛应用于语音编码与语音合成。
-
HFC:计算频谱的High Frequency Content。高频内容度量是一种简单的度量。
GFCC:计算频谱的Gammatone-frequency cepstral coefficients,与MFCC等价,但用了一个在Equivalent Rectangular Bandwidth上scale的gammatone filterbank。
FrequencyBands:计算频谱的矩形频带(Frequency band,频谱中的一个区间,由低频下限与高频上限界定)的能量。
Flux:计算频谱通量。频谱(幅度谱)的通量被定义为两个连续帧之间差别的L2-norm或L1-norm。
FlatnessDB:计算一个数组的flatness,即geometric mean与arithmetic mean的比值。
EnergyBandRatio:计算[startFreq, endFreq]区间内频谱能量占总能量的比例。
EnergyBand:计算一个给定的频带[startHz,endHz]内能量。
ERBBands:计算一个频谱的各个ERB频带的能量。ERB即Equivalent Rectangular Bandwidth,给出一个近似人类听觉的滤波器带宽组。
-
BarkBands:计算一个频谱的Bark频带的能量。Barkhausen是历史上最初提出对音量进行主观度量的人,他提出了一种频带scale,没有mel scale流行。
BFCC:计算一个频谱的Bark Frequency cepstrum coefficients。
Spectrum:计算一个frame的频谱(幅频谱)。
-
SpectralWhitening:让信号的频谱更一致、统一,让autocorrelation更窄。
在音频领域,可以集中音效,减少SNR(signal-to-noise ratio),倾向于让频率变高,可能用于pop music中的complex mixture,主要还是用于提高onset(音符或声音的开端、端点) detection函数的性能。
StrongPeak:计算一个频谱的Strong Peak,即max peak的magnitude与该peak高于一定阈值的频带宽的比值。很窄的频率带宽上的peak才足够"pronounced",足够强。
Rhythm
- BeatTrackerDegara:估计节拍位置。
- Beatogram:通过BeatsLoudness算法得到loudness矩阵,根据它过滤,留下最显著的节拍频带。
- Danceability:估计一个音频信号的danceability,算法基于DFA(Detrended Fluctuation Analysis)。
- BpmHistogram:BPM是beats per minute。估算pulse BPM值与时间位置。
Essentia标准模式
如果想要处理下面这个流程:
Audio → FrameCutter → Windowing → Spectrum → MFCC → Aggregate(mean/var) → Output.
Essentia的调用步骤如下:
- 初始化,essentia::init()。
- 定义一些变量:pool(用于存放最终结果),sampleRate(采样率,单位一般用Hz),frameSize,hopSize。
- 用AlgorithmFactory创建一些算法:audio=MonoLoader(filename,sampleRate), fc=FrameCreator(frameSize,hopSize),w=Windowing(type=blackmanharris63),spec=Spectrum,mfcc=MFCC。
- 创建vector
audioBuffer作为容器,作为Audio → FrameCutter过程中Audio的输出和FrameCreator的输入。同理创建其他步骤间的临时容器,以及最后一部的输出容器,都是Real型vector。 - 先audio->compute(),开始不断加载音频数据。
- 然后在一个while(true)循环里,先调用fc->compute,FrameCutter的输出容器如果非空则说明音频未结束,继续处理,后面依次调用w、spec、mfcc的compute,并在最后在pool中添加这个循环里算出来的最终产物。
- 新建一个aggrPool,新建PoolAggregator(mean,var,min,max)算法,以原来的pool为输入,aggrPool为输出,compute,算出mean,var,min,max等度量值。
- 新建YamlOutput(filename)算法,将输入设为pool,compute。
- 善后,delete各种算法,最后essentia::shutdown。