Cheaptrick算法

Cheaptrick,a spectral envelope estimator for high-qualityspeech synthesis

转载请注明出处!

2015年Morise发表在SPEECH COMMUNICATION期刊上的一篇文章。

该算法目的是获得一个准确的、时间稳定的谱包络,采用基频(F0),由F0自适应加窗、功率谱平滑和频率域频谱恢复三部分组成。

引言

一些估计算法,如倒谱(Noll, 1964;Oppenheim, 1969)和线性预测编码(LPC) (Atal和Hanauer, 1969)及许多改进的算法,如离散全极建模(El-Jaroudi和Makhoul,1991),加权最大似然自回归和移动平均建模(Badeau和David, 2009),以及惩罚似然方法(Campedel-Oudot等人,2001)。但是这些算法合成的语音音质比使用PSOLA等基于波形的合成方法要差,很难实现高质量的语音转换。
STRAIGHT (Kawahara et al.1999)被认为是一种有效的高质量语音合成框架。为了在保持音质的同时减少计算成本,提出了TANDEM_STRAIGHT,在庞大的数据库可实现实时应用(Morise et al., 2009)和统计分析。

待解决问题

根据STRAIGHT的思想,浊音包含F0、谱包络和非周期性信息。为了简化讨论,我们只处理固定的F0和谱包络,而忽略非周期性。要求从语音波形中获得精确的频谱包络,而不考虑加窗的时间位置。
在这里插入图片描述
*表示卷积,T0是基音周期,w0是基本角频率(=2Π/T0)。
谱恢复还需要补偿离散化的影响。由于加窗波形的功率谱依赖于窗函数的时间位置,因此也需要去除这种影响(本文中的时变分量)。
传统算法除了STRAIGHT算法和TANDEM-STRAIGHT,在估计性能上不能满足这两个要求,并且不能去除时变分量。本文介绍了一种算法
它在客观上和主观上都优于传统算法。CheapTrick的名字来源于它基于f0自适应窗口和倒谱方法等传统算法的cheap和trick的设计。

Cheaptrick算法

CheapTrick由三个步骤组成:f0自适应窗口,平滑功率谱,以及平滑和频谱恢复的提升处理。

第一步:计算F0自适应功率谱

第一步是在基音同步分析的理想基础上设计窗口函数(Mathews et al., 1961)。

(1)分帧加窗
分帧:语音分帧的时候不再以传统的定长帧为单位,而是以f0对应的周期为单位,以保证波形和频谱的平滑连续。(自适应)
加窗:采用长度为3T0的汉宁窗。以当前时间点为中心,左右各取1.5T0长度的语音。

在这里插入图片描述
清音没有基频,一般使用一个适当的常数。

窗口在ω0 Hz处的功率比主瓣的功率(0 Hz)低30 dB,这表明在30 dB以下谐波结构对邻近结构有影响。由于实际语音包含时间波动、非周期性和噪声,我们假设30 dB足够小。

waveform = GetWindowedWaveform(x, fs, current_f0, current_position);

function waveform = GetWindowedWaveform(x, fs, current_f0, current_position)
%  prepare internal variables
half_window_length = round(1.5 * fs / current_f0);%1169=round(1.5 * 88200 / 113.21)
base_index = (-half_window_length : half_window_length)';%2339*1 = (-1169 : 1169)'
index = round(current_position * fs + 0.001) + 1 + base_index;%2339*1 = round(0*88200+0.001)+1+2339*1(所有值全加1)
safe_index = min(length(x), max(1, round(index)));% 只取2339*1? 

%  wave segments and set of windows preparation
segment = x(safe_index);
time_axis = base_index / fs / 1.5;
window = 0.5 * cos(pi * time_axis * current_f0) + 0.5;
window = window / sqrt(sum(window .^ 2));
waveform = segment .* window - window * mean(segment .* window) / mean(window);

周期信号y(t)经过加窗w(t),计算功率谱:

在这里插入图片描述
T0是基音周期。该方程表明,一个窗内的周期信号的总功率是时间稳定的。

power_spectrum = GetPowerSpectrum(waveform, fs, fft_size, current_f0);

function power_spectrum = GetPowerSpectrum(waveform, fs, fft_size, f0)
power_spectrum = abs(fft(waveform(:), fft_size)) .^ 2;
% DC correction
frequency_axis = (0 : fft_size - 1)' / fft_size * fs;
low_frequency_axis = frequency_axis(frequency_axis <  f0 + fs / fft_size);
low_frequency_replica = interp1(f0 - low_frequency_axis,...
  power_spectrum(frequency_axis < f0 + fs / fft_size),...
  low_frequency_axis(:), 'linear', 'extrap');
power_spectrum(frequency_axis < f0) =...
  low_frequency_replica(frequency_axis < f0) +...
  power_spectrum(frequency_axis < f0);
power_spectrum(end : -1 : fft_size / 2 + 2) = power_spectrum(2 : fft_size / 2);

第二步:功率谱平滑

对于加窗以后的时域信号进行FFT获得对应的功率谱P(ω),由于后面第三步需要对功率谱取log操作,所以需要保证功率谱没有零值。

通过一个矩形窗进行简单滤波来实现平滑:
在这里插入图片描述
P(ω)是加汉宁窗的功率谱。由于矩形窗宽为2ω0/3,这一步确保了与第一步一样相邻结构之间的影响小于30db。

smoothed_spectrum = LinearSmoothing(power_spectrum, current_f0, fs, fft_size);

function smoothed_spectrum = LinearSmoothing(power_spectrum, f0, fs, fft_size)
double_frequency_axis = (0 : 2 * fft_size - 1)' / fft_size * fs - fs;
double_spectrum = [power_spectrum; power_spectrum];

double_segment = cumsum(double_spectrum * (fs / fft_size));
center_frequency = (0 : fft_size / 2)' / fft_size * fs;
low_levels = interp1H(double_frequency_axis + fs / fft_size / 2,...
  double_segment, center_frequency - f0 / 3);
high_levels = interp1H(double_frequency_axis + fs / fft_size / 2,...
  double_segment, center_frequency + f0 / 3);

smoothed_spectrum = (high_levels - low_levels) * 1.5 / f0;
smoothed_spectrum =...
  smoothed_spectrum + abs(randn(length(smoothed_spectrum), 1)) * eps;

第三步:倒频域提升

可以将功率谱看做是普通信号,求出信号的包络也就是找到信号的低频部分。

提升目的:去除离散化引起的频率波动。同时进行了光谱恢复。
时变分量是由周期脉冲卷积和加窗引起的。

时域:周期为T0的周期脉冲
频域:谱是周期为ω0的周期脉冲
倒谱:也是倒频率域内周期为T0的周期脉冲,如下图
在这里插入图片描述
为了明确计算nT0处的时变分量,信号的采样频率为65536 Hz, F0为128 Hz, FFT长度为65,536,信号长度为1 s,帧移长度为一个样本。
为了去除时变分量和提取低定量分量,采用sinc函数作为提升函数。
谱恢复基于一致采样理论(Unser, 2000)。一致采样理论是采样理论的扩展,要求AD转换后的数字信号必须等于AD/DA/AD转换后的数字信号。这种采样使线性滤波器的设计能够满足这一要求。
在一致性采样的基础上,设计了提升功能作为补偿滤波器。该函数可以补偿nω0 Hz处的误差,这些误差是由第二步和第三步平滑引起的。

TANDEM-STRAIGHT的频域上进行了基于一致采样的谱恢复(Kawahara et al., 2008):
在这里插入图片描述
本文的提升恢复谱计算方法如下:

  • 首先对上一步求出来的功率谱做反傅里叶变换
    在这里插入图片描述

  • 过滤得到信号的低频部分
    在这里插入图片描述
    sinc函数第一个作用,相当于一个低通滤波器;第二个作用,它在nT0 点对应的幅值为0,相当于清除了原始周期脉冲串δ的影响。

  • 谱恢复
    两个参数的经验值是1.18和-0.09。目的是为了消除前面平滑带来的畸变。
    在这里插入图片描述

  • 获取最后的频谱包络
    在这里插入图片描述

原文公式:
在这里插入图片描述
频域矩形窗,该窗在图2所示的quefency域的nT0处为零。
试错实验,得到q0=1.18, q1=-0.09。

在这里插入图片描述
每个处理都是在离散时频表示上进行的。Pl(k,n),其中k表示离散频率索引,n表示帧数。

spectral_envelope = SmoothingWithRecovery(...
  [smoothed_spectrum; smoothed_spectrum(end - 1 : -1 : 2)], current_f0, fs,...
  fft_size, q1);


function spectral_envelope =...
  SmoothingWithRecovery(smoothed_spectrum, f0, fs, fft_size, q1)
quefrency_axis = (0 : fft_size - 1)' / fs;
smoothing_lifter = sin(pi * f0 * quefrency_axis) ./ (pi * f0 * quefrency_axis);
smoothing_lifter(fft_size / 2 + 2 : end) =...
  smoothing_lifter(fft_size / 2 : -1 : 2);
smoothing_lifter(1) = 1;

compensation_lifter =...
  (1 - 2 * q1) + 2 * q1 * cos(2 * pi * quefrency_axis * f0);
compensation_lifter(fft_size / 2 + 2 : end) =...
  compensation_lifter(fft_size / 2 : -1 : 2);
tandem_cepstrum = fft(log(smoothed_spectrum));
tmp_spectral_envelope =...
  exp(real(ifft(tandem_cepstrum .* smoothing_lifter .* compensation_lifter)));
spectral_envelope = tmp_spectral_envelope(1 : fft_size / 2 + 1);

参考文献
[1].Spectral Envelopes in Sound Analysis and Synthesis
[2].CheapTrick, a spectral envelope estimator for high-quality speech synthesis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值