解释这段代码:% 实验要求三:倒谱法基音周期检测 clc; close all; clear all; wlen=3200; inc=800; % 分帧的帧长和帧移 T1=0.05; % 设置基音端点检测的参数 [x,fs]=audioread('E:/qq.下载/3245.wav'); % 读入wav文件 x=x-mean(x); % 消去直流分量 x=x/max(abs(x)); % 幅值归一化 [voiceseg,vosl,SF,Ef,period]=pitch_Ceps(x,wlen,inc,T1,fs); %基于倒谱法的基音周期检测 fn=length(SF); time = (0 : length(x)-1)/fs; % 计算时间坐标 frameTime = FrameTimeC(fn, wlen, inc, fs); % 计算各帧对应的时间坐标 % 作图 subplot 211, plot(time,x,'k'); title('语音信号') axis([0 max(time) -1 1]); ylabel('幅值'); subplot 212; plot(frameTime,period,'k'); xlim([0 max(time)]); title('倒谱法基音周期检测'); xlabel('时间/s'); ylabel('样点数'); for k=1 : vosl % 标出有话段 nx1=voiceseg(k).begin; nx2=voiceseg(k).end; nxl=voiceseg(k).duration; fprintf('%4d %4d %4d %4d\n',k,nx1,nx2,nxl); subplot 211 line([frameTime(nx1) frameTime(nx1)],[-1 1],'color','r','linestyle','-'); line([frameTime(nx2) frameTime(nx2)],[-1 1],'color','b','linestyle','--'); subplot 212 line([frameTime(nx1) frameTime(nx1)],[0 150],'color','r','linestyle','-'); line([frameTime(nx2) frameTime(nx2)],[0 150],'color','b','linestyle','--'); end
时间: 2023-11-18 10:04:46 浏览: 37
这段代码实现了基于倒谱法的基音周期检测,并通过作图展示了语音信号和检测结果。具体实现步骤如下:
1. 设置分帧的帧长和帧移,以及基音端点检测的参数。
2. 读入wav文件,并进行直流分量的消去和幅值归一化处理。
3. 调用pitch_Ceps函数进行基音周期检测,返回基音周期、有话段数以及每个有话段的起始、结束样点和持续时间。
4. 计算时间坐标和各帧对应的时间坐标,并作图展示语音信号和基音周期检测结果。
5. 标出有话段,并在作图上用红色实线和蓝色虚线表示。
其中,pitch_Ceps函数是用来进行基于倒谱法的基音周期检测的核心函数。
相关问题
倒谱法基音周期检测、共振峰检测代码matlab
倒谱法是一种常用的基音周期检测方法,可以借助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点数等。
帮我在这段代码中增加求基音频率的代码“% 实验要求三:倒谱法基音周期检测 clc; close all; clear all; wlen=3200; inc=800; % 分帧的帧长和帧移 T1=0.05; % 设置基音端点检测的参数 [x,fs]=audioread('C:\Users\DELL\Desktop\C4_2_y.wav'); % 读入wav文件 x=x-mean(x); % 消去直流分量 x=x/max(abs(x)); % 幅值归一化 [voiceseg,vosl,SF,Ef,period]=pitch_Ceps(x,wlen,inc,T1,fs); %基于倒谱法的基音周期检测 fn=length(SF); time = (0 : length(x)-1)/fs; % 计算时间坐标 frameTime = FrameTimeC(fn, wlen, inc, fs); % 计算各帧对应的时间坐标 % 作图 subplot 211, plot(time,x,'k'); title('语音信号') axis([0 max(time) -1 1]); ylabel('幅值'); subplot 212; plot(frameTime,period,'k'); xlim([0 max(time)]); title('倒谱法基音周期检测'); xlabel('时间/s'); ylabel('样点数'); for k=1 : vosl % 标出有话段 nx1=voiceseg(k).begin; nx2=voiceseg(k).end; nxl=voiceseg(k).duration; fprintf('%4d %4d %4d %4d\n',k,nx1,nx2,nxl); subplot 211 line([frameTime(nx1) frameTime(nx1)],[-1 1],'color','r','linestyle','-'); line([frameTime(nx2) frameTime(nx2)],[-1 1],'color','b','linestyle','--'); subplot 212 line([frameTime(nx1) frameTime(nx1)],[0 150],'color','r','linestyle','-'); line([frameTime(nx2) frameTime(nx2)],[0 150],'color','b','linestyle','--'); end”
在代码的最后一个 for 循环内部,可以增加以下代码来求取基音频率:
```matlab
% 求基音频率
for k = 1 : vosl
nx1 = voiceseg(k).begin;
nx2 = voiceseg(k).end;
x_seg = x((nx1-1)*inc+1 : (nx2-1)*inc+wlen); % 取出当前帧对应的语音信号
[r, ~] = xcorr(x_seg); % 自相关函数
r = r(wlen : end); % 取出正半轴部分
[pks, locs] = findpeaks(r); % 找到所有极大值点
[~, max_idx] = max(pks); % 取最大极大值点
p = locs(max_idx); % 基音周期
f0 = fs/p; % 基音频率
fprintf('第 %d 个音段的基音频率为 %f Hz\n', k, f0);
% 在图上显示基音周期
subplot(212)
hold on
line([frameTime(nx1) frameTime(nx1)], [0 150], 'color', 'r', 'linestyle', '-');
line([frameTime(nx2) frameTime(nx2)], [0 150], 'color', 'b', 'linestyle', '--');
plot(frameTime(nx1) + wlen/fs*p, f0, 'r*');
hold off
end
```
注意,在添加这段代码之前,需要在代码开头加上 `findpeaks` 函数所在的 Matlab 工具箱路径,即:
```matlab
addpath('C:\Program Files\MATLAB\R2021a\toolbox\signal\signal');
```
其中,`C:\Program Files\MATLAB\R2021a` 是 Matlab 的安装路径,根据自己的实际情况进行修改。