这里提一个(i)STFT的细节。做短时傅里叶分析的时候,通常会选取窗函数,缓解频谱泄露。把频域的谱通过OLA(overlap add)转换到时域上时,我以前的做法是选取相同的窗函数。这么做会带来一个问题,如果直接把OLA的结果写入磁盘,特别容易出现clipping,所以我通常会在OLA之后对samples做一个renorm/rescale操作,避免数值超出wav的采样单元,但是这么一做,往往就丢失了原先音频的能量信息。理想情况下,在频域不做任何处理,变换到时域,应该存在条件,使得时域结果完美重构的。
后来逐渐的在一些文献中看到了一些资料。发现这个窗函数的选取,不是那么随意,要想达到最佳重构,正逆过程的窗需要满足一个约束条件,有些文献中也称为双正交。正过程的窗称为分析(analysis)窗,逆过程的窗(synthesis)称为合成窗。下面导出这个约束条件。
令$t$表示帧索引,$S$表示帧移,$w, v$分别表示analysis和synthesis window。$s, \hat{s}$表示原始信号和合成信号。
基于以上定义,分帧过程可以表示为:
OLA过程表示为:
将式$(1)$重写为:
带入$(2)$式
因此达到完美重构条件(完全相等),analysis和synthesis窗需要满足条件
此式即为所谓的双正交约束。
另外在做短时傅里叶分析的时候,主流工具喜欢对wave进行padding,以期望达到更好的重构效果,这里这么理解,如果不进行padding的话,第一帧和最后一帧必然存在某些samples,无法通过叠加得到(即仅仅只做了加窗),因此,这些点难以达到完美重构条件,padding的目的是对这些点位置进行shift,尽可能的使它们可能达到完美重构条件(这里理解未必正确,看官需小心)。
其次,librosa和fgnt的实现版本也不完全一样,前者是对合成的samples最后做了normalize,后者则是根据analysis窗,构建synthesis窗,之后进行OLA,我参考后者,在kaldi-enhan上的实现如下:
1 | void ShortTimeFTComputer::CacheSynthesisWindow(const ShortTimeFTOptions &opts) { |
关于这里提的问题,在”Springer Handbook of Speech Processing”的12.1节 The Short-Time Fourier Transform中有详细论述,想要继续深入的可以做一下参考。