基于倒谱变换法的语音信号基频与共振峰计算matlab仿真

本文详细介绍了倒谱变换在语音信号分析中的作用,包括计算方法,以及如何通过倒谱估计基频(F0)和共振峰(Formants)。还提供了MATLAB程序示例,展示了如何计算平均基频和共振峰,并讨论了实际应用中可能遇到的挑战和优化策略。
摘要由CSDN通过智能技术生成

目录

1.倒谱的计算

2.基频估计(F0 Estimation)

3. 共振峰估计(Formant Estimation)

4. matlab程序

5.仿真结果


       倒谱变换是一种广泛应用于语音信号分析的技术,主要用于估计语音信号的基频(Fundamental Frequency, F0)和共振峰(Formants)。倒谱变换是傅立叶变换的逆过程,即从频域信号反推至时域上的信号。对于语音信号而言,它通过分析信号功率谱的对数倒数来揭示信号的谐波结构。语音信号主要由一系列以基频整数倍频率出现的谐波构成,而倒谱能够凸显这些谐波成分。

1.倒谱的计算

       倒谱(Cepstrum)是一种信号处理工具,最初由 Bogert, Healy 和 Tukey 在 1963 年提出,主要用于分析具有周期性或准周期性的信号。在语音信号处理领域,倒谱被广泛应用在基频(Fundamental Frequency, F0)估计、共振峰(Formants)分析及其它相关任务上。

       给定一段离散语音信号x[n],先对其进行短时傅立叶变换(Short-Time Fourier Transform, STFT),得到短时功率谱P(ω,n):

其中,X(ω,n) 是信号x[n] 的 STFT,ω 是频率,n 是帧索引。

接下来计算对数功率谱L(ω,n):

这里引入了很小的正值ϵ 来避免零功率导致的对数运算问题。

再对L(ω,n) 进行倒谱变换(cepstral analysis),得到倒谱系数C(m,n):

这里 F−1 表示逆傅立叶变换,m 是倒谱系数的索引。

2.基频估计(F0 Estimation)

      基频(Fundamental Frequency, F0)是指语音信号中振动最频繁的主要频率成分,尤其在声带振动产生的语音信号中最为显著。基频通常与语音的音调高低紧密相关,是人耳感知语音声调变化的主要依据。

       在倒谱序列中,第一项(或经过适当的平滑处理后的第一项)与语音信号的基频密切相关。可以通过搜索倒谱序列中相邻峰值间的最小距离来估计基频:

       其中Δmn​ 是倒谱序列中第 n 个局部最小值与下一个局部峰值之间的倒谱系数索引差,fs​ 是采样频率。

3. 共振峰估计(Formant Estimation)

       共振峰(Formant)是在声音频谱中能量相对集中的特定频率区域,特别是在语音信号分析中,它指的是声音经过声道(即人体的口腔、鼻腔和喉部形成的复杂共振腔)时,某些特定频率的声波得到了增强的现象。这些被增强的频率区域对应着声道内各共振腔体(例如喉、咽、口、鼻腔)的自然谐振频率,形成了声谱包络曲线上的尖峰,即共振峰。

       在语音学中,共振峰对语音的音质有着决定性的作用,特别是对于区分不同的元音至关重要。通常,人类语言中的元音音素可以由一连串共振峰的位置来表征,比如第一共振峰(F1)、第二共振峰(F2)和第三共振峰(F3)等。其中,前两个共振峰尤为关键,它们与发音时舌头在口腔内的位置(舌位)密切相关,从而决定了元音的前后高低特征。

      共振峰反映的是语音声腔的几何特性,通常出现在倒谱序列的后续几项中。为了确定共振峰的位置,通常需要对倒谱序列进行希尔伯特变换(Hilbert transform)或峰值检测,找到峰值对应的频率位置。例如,第k 个共振峰Fk​ 可以通过以下步骤获得:

其中C′(m,n) 是倒谱序列C(m,n) 的一阶导数,argmax 表示寻找使目标函数取得最大值的频率 ω。

4. matlab程序

.......................................................

% 计算平均基频与共振峰
Fpitch_mean  = 0;
Fgz1_m = 0;
Fgz2_m = 0;
Fgz3_m = 0;
Fgz4_m = 0;
cnt1 = 0;
cnt2 = 0;
cnt3 = 0;
cnt4 = 0;
count_pitch = 0;

% 忽略能量低于最大能量一半的帧
for i=1:Nframe
    if Fengy(i) > Emax/2
        if Fpitch(i) > 0
            Fpitch_mean = Fpitch_mean + Fpitch(i);  % 计算有效基频平均值
            count_pitch = count_pitch + 1;
        end
        if Fgz(1,i) > 0
           Fgz1_m = Fgz1_m + Fgz(1,i);% 计算F1共振峰平均值
           cnt1 = cnt1 + 1;
        end
        if Fgz(2,i) > 0
           Fgz2_m = Fgz2_m + Fgz(2,i); % 计算F2共振峰平均值
           cnt2 = cnt2 + 1;
        end
        if Fgz(3,i) > 0
           Fgz3_m = Fgz3_m + Fgz(3,i); % 计算F3共振峰平均值
           cnt3 = cnt3 + 1;
        end
        if Fgz(4,i) > 0
           Fgz4_m = Fgz4_m + Fgz(4,i);% 计算F4共振峰平均值
           cnt4 = cnt4 + 1;
        end
    end
end
% 计算最终的平均基频与共振峰
Fpitch_mean = Fpitch_mean/count_pitch; % 最终基频结果
Fgz1_m = Fgz1_m / cnt1; % 平均共振峰1,2,3,4
Fgz2_m = Fgz2_m / cnt2;
Fgz3_m = Fgz3_m / cnt3;
Fgz4_m = Fgz4_m / cnt4;

% 绘制基频与共振峰图形
figure
plot(Fpitch); 
title('基频');
 
figure
hold on
plot(Fgz(1,:),'r');
plot(Fgz(2,:),'g');
plot(Fgz(3,:),'b');
plot(Fgz(4,:),'c');
title('共振峰');

% 输出最终结果
fprintf("Results: \n 基频频率 %f \n", Fpitch_mean);
fprintf(" 共振峰: F1= %f, F2= %f, F3= %f, F4= %f \n", Fgz1_m, Fgz2_m, Fgz3_m, Fgz4_m)
up4075

5.仿真结果

      实际应用中,基频和共振峰的估计可能会受到噪声、非平稳性等因素的影响,因此常常会结合其他技术,如噪声抑制、峰值跟踪、平滑滤波等方法,来优化估计结果的准确性。

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
倒谱是一种常用的基音周期检测方,可以借助MATLAB实现。下面提供一个简单的基音周期检测和共振检测的MATLAB代码示例,供参考。 ```matlab % 基音周期检测和共振检测 % 首先读取音频文件,使用matlab自带的audioread函数 [x, fs] = audioread('voice.wav'); % 设置分析参数 winlen = 512; % 窗口长度 overlap = 256; % 帧重叠长度 nfft = 1024; % FFT点数 preemph = 0.97; % 预加重系数 minf0 = 80; % 最小基频 maxf0 = 300; % 最大基频 voicedthresh = 0.4; % 有声门限 unvoicedthresh = 0.1; % 无声门限 % 对每一帧进行处理 frames = enframe(x, winlen, overlap); % 分帧 nframes = size(frames, 1); % 帧数 f0 = zeros(nframes, 1); % 存储基频 formants = zeros(nframes, 4); % 存储共振 for i = 1:nframes frame = frames(i, :); % 取出一帧 frame = filter([1 -preemph], 1, frame); % 预加重 spec = abs(fft(frame, nfft)); % 傅里叶变换 spec = spec(1:nfft/2); % 取一半 logspec = log(spec); % 取对数 cepstrum = ifft(logspec); % 倒谱 cepstrum = cepstrum(1:nfft/2); % 取一半 cepstrum(1:minf0/fs*nfft) = 0; % 去掉基频以下的分量 cepstrum(maxf0/fs*nfft:end) = 0; % 去掉基频以上的分量 [~, locs] = findpeaks(cepstrum); % 找值 if ~isempty(locs) f0(i) = fs/locs(1); % 基频为第一个的频率倒数 formants(i, :) = locs(2:5)*fs/nfft; % 共振为2~5个的频率 end end % 判断有声无声 voiced = f0 > voicedthresh*fs/winlen & f0 < maxf0; unvoiced = f0 < unvoicedthresh*fs/winlen; f0(unvoiced) = 0; % 无声部分基频设为0 % 绘制频谱、倒谱基频共振等 t = (0:nframes-1)*overlap/fs; f = (0:nfft/2-1)/nfft*fs; figure; subplot(2, 2, 1); imagesc(t, f, 20*log10(abs(spec))); axis xy; xlabel('Time (s)'); ylabel('Frequency (Hz)'); title('Spectrogram'); subplot(2, 2, 2); imagesc(t, f, 20*log10(abs(cepstrum))); axis xy; xlabel('Time (s)'); ylabel('Quefrency'); title('Cepstrum'); subplot(2, 2, 3); plot(t, f0, 'r'); axis([0 max(t) 0 maxf0]); xlabel('Time (s)'); ylabel('Frequency (Hz)'); title('Pitch'); subplot(2, 2, 4); plot(t, formants); axis([0 max(t) 0 maxf0]); xlabel('Time (s)'); ylabel('Frequency (Hz)'); title('Formants'); legend('F1', 'F2', 'F3', 'F4'); ``` 该代码读取声音文件`voice.wav`,对每一帧进行基音周期检测和共振检测,并将结果绘制成图形。其中,`enframe`是分帧函数,`findpeaks`是寻找值函数。可以根据需要自行调整参数,例如窗口长度、帧重叠长度、FFT点数等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fpga和matlab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值