我正在用 C 语言编写相位声码器,用于时间拉伸音频信号。当前唯一不起作用的是相位传播。
- 我从输入信号中获取重叠帧,应用窗口函数并执行 FFT。
- 然后我计算相位传播(我坚持的那个)
- 最后,我执行 iFFT 并重叠添加具有不同跳数大小的输出帧。
如果我跳过第 2 步,即相位传播,则输出声音会正确地进行时间拉伸,但我可以听到移相器效果。我的假设是缺失的部分将纠正这一点。但是,当我应用当前的实现时,声音会严重失真。
如果有人可以就如何实现相位校正提供一些好的指导,我将不胜感激。
问的可能太多了,但如果你看到一些奇怪的东西,这是我目前的实现。
// _prevPhaseX[] = FFT phases from previous frame (n-1) (propagation input)
// _prevPhaseY[] = FFT phases from previous frame (n-1) (propagation output)
// _phase[] has the FFT phase information from current frame
static int first = 1;
if (first)
{
first = 0;
for (int k=0; k<half; k++) // half = window length/2 = number of bins
{
_prevPhaseX[k] = _phase[k];
_prevPhaseY[k] = _phase[k];
}
}
else
{
// int length = window length - e.g. 1024
// float Ra = analysis hop size - e.g. 256
// float Rs = synthesis hop size - e.g. 512
// float PI = PI
// float DPI = 2*PI
for (int k=1; k<half; k++)
{
// compute Delta Phi(k)
float phase = _phase[k];
float omega = DPI*(float)k/(float)length; // length vs length/2?
float phasediff = phase - _prevPhaseX[k] - Ra*omega;
_prevPhaseX[k] = phase; // Save value for next frame
// get principal argument
while (phasediff>PI) phasediff -=DPI;
while (phasediff<-PI) phasediff +=DPI;
float freq = omega + (phasediff)/Ra;
_phase[k] = _prevPhaseY[k] + Rs*freq;
_prevPhaseY[k] = _phase[k]; // Save value for next frame
}
}
// the _phase[] vector (and magnitude[]) goes to IFFT (after conv. to rectangluar)
谢谢!