第一次实验:短时时域分析

摘要
语音信号处理第一次实验
仅供参考

一、 实验内容概述:

本次实验实验前语音数据准备以及语音实验内容两个部分。
实验前语音数据准备要求录制并加载语音数据文件WHUT_10k,绘制完整波形图找出并移除前后噪声段,确保录音数据质量。
语音实验内容围绕语音信号处理基础,涵盖了绘制分帧加窗图、计算语音短时能量、语音短时幅度、语音短时过零率以及计算语音短时自相关。

二、 编程思路及步骤

实验前语音数据准备部分,利用Lectrue1_Demo_speech_recorder.m代码加载语音数据文件,通过绘制完整波形图找出前后噪声段,进行处理,使用代码截取无噪声段区间以获得纯净音频,并保存处理后的语音数据及对应图像。
语音实验内容中的分帧加窗图绘制,先读取语音文件,确定帧长20ms和帧移50%,进行分帧操作,确保列存储。提取第 45 帧后,分别生成矩形窗和 Hamming 窗函数,对第 45 帧数据加窗处理。最后绘制原始信号与加窗后信号的对比图。
计算每帧信号的平方和,得到短时能量。逐帧计算信号的绝对值之和,绘制短时幅度随时间的变化曲线。按照公式$ZCR(t)=\frac{1}{N}\sum_{n=0}^{N-1}\frac{1}{2}|\mathrm{sign}(x(t+n))-\mathrm{sign}(x(t+n-1))|$统计每帧内信号符号变化的次数。逐帧计算信号的自相关函数,绘制短时自相关随延迟时间的变化曲线。

三、 指定内容的输出结果

一、 实验前语音数据准备

利用Lectrue1_Demo_speech_recorder.m文件代码录制音频“武汉理工大学”,并截取无噪声段区间,获得纯净音频。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
fs = 10000;                            % set sampling rate
r = audiorecorder(fs, 24, 1); % creat a recoreder object
record(r); % speak into microphone...
pause(4); % set recording time
stop(r); % stop recording
data0 = getaudiodata(r); % get audio data
sound(data0, fs) % listen to complete recording
plot(data0)
data = data0(3706: 18181);
sound(data, fs)
figure
t = (1:length(data))/fs;
plot(t, data)
sound(data, fs)
xlabel('时间/ s')
ylabel('振幅')
axis tight
title({'电信2206 赵连政 0122209360431''武汉理工大学'})
fileName = 'WHUT10K2025';
saveDataDir = './data2025/';
saveDataName = strcat(saveDataDir, fileName);
if ~exist(saveDataDir, 'dir')
mkdir(saveDataDir)
end
save(saveDataName, 'data', 'fs') % save audio data as mat format
%save('A12345')
saveFigureDir = './figure2025/';
if ~exist(saveFigureDir, 'dir')
mkdir(saveFigureDir)
end
saveFigureName = strcat(saveFigureDir, fileName);
title('png')
print(saveFigureName, '-dpng')
title('emf')
print(saveFigureName, '-dmeta')

图 1 武汉理工大学fs=10k

1
上述图像前后各有一段近似为0的波形,该区域即为不含语音信息的噪声。3706-18181为有效音频段,以外为噪声段。波形在-1~+1之间,幅度合适。

图 2武汉理工大学fs=10k

1
上述图像前后不含噪声波形,已经截取为含有“武汉理工大学”语音信号波形,图像更加紧凑。

二、语音实验内容:

首先画出Ah 第20帧时域波形图,10k采样,与实验要求给出的图像进行对比:
图 3  Ah语音第20帧加窗,10k采样
图 4 Ah 第20帧时域波形图,10k采样(给出)
1. 分帧加窗图:画出oh语音第45帧单帧语音时域图,同时加矩形窗和hamming窗(oh语音,第45帧)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
%% 分帧加窗对比图(oh语音第45帧)
clc; clear; close all;
name = '赵连政';
class = '电信2206';
id = '0122209360431';
% 读取语音文件(文件名为'oh.wav',采样率10kHz)
[y, fs] = audioread('oh.wav');
frame_duration = 0.02; % 帧长20ms
frame_length = round(frame_duration * fs);
frame_shift = frame_length/2; % 50%帧移
% 分帧操作(确保列存储)
frames = buffer(y, frame_length, frame_length - frame_shift, 'nodelay');
frame45 = frames(:,45); % 提取第45帧(列向量)
% 生成窗函数(列向量)
rect_win = ones(size(frame45));
hamm_win = hamming(length(frame45));
% 加窗操作
frame_rect = frame45 .* rect_win;
frame_hamm = frame45 .* hamm_win;
% 矩形窗对比
figure('Color','white');
hold on;
plot(frame45, 'b', 'LineWidth', 1.2);
plot(frame_rect, 'r', 'LineWidth', 1);
hold off;
legend('原始信号', '矩形窗处理');
title({[name ' ' class ' ' id] 'Oh语音第45帧加窗对比 (矩形窗)'});
xlabel('采样点');
ylabel('幅度');
grid on;
% Hamming窗对比
figure('Color','white');
hold on;
plot(frame45, 'b', 'LineWidth', 1.2);
plot(frame_hamm, 'm--', 'LineWidth', 1);
hold off;
legend('原始信号', 'Hamming窗处理');
title({[name ' ' class ' ' id] 'Oh语音第45帧加窗对比 (Hamming窗)'});
xlabel('采样点');
ylabel('幅度');
grid on;
% 添加公共标注
annotation('textbox',...
[0.3 0.001 0.4 0.05],...
'String',['语音内容: oh语音第45帧 | 采样率: ' num2str(fs/1000) 'kHz'],...
'FitBoxToText','on',...
'EdgeColor','none',...
'HorizontalAlignment','center');

图 5 Oh语音第45帧加窗对比 (矩形窗) 采样率10k

1
2
蓝色曲线是原始信号,粉色曲线是经过 Hamming 窗处理后的信号。对于 Hamming 窗处理后的信号,其波形在帧的起始和结束处被衰减。
这是因为 Hamming 窗是一种升余弦窗,窗函数在两端趋近于 0,中间部分接近 1。在采样点 0 和 200 附近,信号幅度被明显压低,相比原始信号,其起始和结束部分的波动幅度变小。

图 6 Oh语音第45帧加窗对比 (Hamming窗)

1
蓝色曲线是原始信号,红色曲线是经过矩形窗处理后的信号。矩形窗处理后的信号与原始信号在时域波形上基本一致。因为矩形窗函数在整个窗口范围内值都为 1,相当于没有对信号进行加权处理,只是简单地截取了一段信号作为一帧。

2. 语音短时能量(武汉理工大学语音)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
% 1. 加载语音文件
load('WHUT10K2025.mat');
% 信号变量名为'data',采样率为'fs'
% 2. 设置帧参数
frame_duration = 0.02; % 帧长20ms
frame_length = round(frame_duration * fs);
frame_shift = round(frame_length/2); % 50%帧移
% 3. 分帧操作 - 处理所有帧
frames = buffer(data, frame_length, frame_length - frame_shift, 'nodelay');
num_frames = size(frames, 2); % 获取总帧数
% 4. 应用Hamming窗到所有帧
hamm_win = hamming(frame_length); % 创建Hamming窗
% 对每一帧应用窗函数
for i = 1:num_frames
frames(:, i) = frames(:, i) .* hamm_win;
end
% 5. 计算短时特征
% 短时能量 (加窗后)
short_time_energy = sum(frames.^2, 1);
% 6. 创建时间轴
time_signal = (0:length(data)-1)/fs; % 原始信号时间轴
frame_time = ((0:num_frames-1)*frame_shift + frame_length/2)/fs; % 帧中心时间轴
% 短时能量
figure()
plot(frame_time, short_time_energy, 'r', 'LineWidth', 1.5);
title('短时能量 (Hamming窗, 帧长20ms, 帧移50%)', 'FontSize', 12);
xlabel('时间 (s)', 'FontSize', 10);
ylabel('能量', 'FontSize', 10);
xlim([0 max(time_signal)]);
grid on;

图 7 语音内容:武汉理工大学 采样率:10k

1
短时能量曲线呈现出两个明显的高能量峰值区段,分别位于大约 0.25-0.5 秒和 0.95-1.2 秒附近,表明在这两个时间段内语音能量较强,对应着语音中的较强发音或音节。根据图中标注的语音内容为“武汉理工大学”,可以推测这两个高能量区段分别对应着“武汉”和“理工大学”这两个主要的词汇部分。

3. 语音短时幅度 (武汉理工大学语音)

1
2
3
4
5
6
7
8
9
10
% 短时幅度 (加窗后)
short_time_magnitude = sum(abs(frames), 1);
% 短时幅度
figure()
plot(frame_time, short_time_magnitude, 'm', 'LineWidth', 1.5);
title('短时幅度 (Hamming窗, 帧长20ms, 帧移50%)', 'FontSize', 12);
xlabel('时间 (s)', 'FontSize', 10);
ylabel('幅度', 'FontSize', 10);
xlim([0 max(time_signal)]);
grid on;

图 8 语音内容:武汉理工大学 采样率:10k

1
曲线中有两个主要的高幅度区段,分别位于大约 0.25-0.5 秒 和 0.95-1.2 秒,这两个区段的幅度显著高于其他部分。0-0.25 秒幅度较低,变化较为平缓,可能对应语音的起始部分或弱音。0.5-0.95 秒幅度较低且变化较小,可能对应语音中的停顿或静音段。1.2-1.4 秒幅度再次上升后逐渐下降,可能对应语音的结束部分。

4. 语音短时过零率 (武汉理工大学语音)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
% 短时过零率 (加窗后)
zero_crossing_rate = zeros(1, num_frames);
for i = 1:num_frames
frame = frames(:, i);
signs = sign(frame);
% 计算符号变化次数(过零次数)
cross_points = find(diff(signs) ~= 0);
zero_crossing_rate(i) = length(cross_points);
end
% 短时过零率
figure()
plot(frame_time, zero_crossing_rate, 'g', 'LineWidth', 1.5);
title('短时过零率 (Hamming窗, 帧长20ms, 帧移50%)', 'FontSize', 12);
xlabel('时间 (s)', 'FontSize', 10);
ylabel('过零次数', 'FontSize', 10);
xlim([0 max(time_signal)]);
grid on;

图 9 语音内容:武汉理工大学 采样率:10k

1
曲线中有多个高峰和低谷,表明语音信号在某些时间段内过零次数较高,而在其他时间段内过零次数较低。0.2秒到0.4秒之间:过零率出现多个高峰,过零次数在60到80之间波动。这表明在这一时间段内,语音信号的过零次数较高,可能对应清音部分。1.0秒到1.2秒之间:过零率出现一个显著的高峰,过零次数超过120。这是图中过零率最高的区域,表明这一时间段内的语音信号变化非常剧烈,可能是连续的清音或语音的突变部分。

5. 语音短时自相关 (oh语音,第45帧)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
%% 短时自相关分析(第45帧)
% 计算加Hamming窗后的自相关函数
N = length(frame_hamm); % 帧长
max_lag = N - 1; % 最大延迟

% 计算自相关函数
autocorr = zeros(2*max_lag+1, 1);
for lag = -max_lag:max_lag
n_start = max(1, 1+lag);
n_end = min(N, N+lag);
autocorr(lag+max_lag+1) = sum(frame_hamm(n_start:n_end) .* ...
frame_hamm(n_start-lag:n_end-lag));
end

% 归一化自相关函数
autocorr = autocorr / max(autocorr);

% 提取正延迟部分(0到max_lag)
positive_lags = 0:max_lag;
positive_autocorr = autocorr(max_lag+1:end);

% 查找基音周期(最大峰值位置,排除0延迟)
[~, max_idx] = max(positive_autocorr(21:end)); % 跳过前20个样本(避免基音倍频错误)
pitch_period = max_idx + 20; % 基音周期(样本数)
pitch_freq = fs / pitch_period; % 基音频率(Hz)

% 创建自相关图
lags = -max_lag:max_lag;
figure('Color','white', 'Position', [100, 100, 1200, 500]);

% 完整自相关函数
subplot(1,2,1);
plot(lags, autocorr, 'b', 'LineWidth', 1.5);
hold on;
plot([0, 0], ylim, 'k--', 'LineWidth', 1); % 零延迟线
title({[name ' ' class ' ' id] 'Oh语音第45帧短时自相关函数 (Hamming窗)'});
xlabel('延迟 (样本)');
ylabel('归一化自相关值');
xlim([-max_lag, max_lag]);
grid on;
text(0.05*max_lag, 0.9, ['基音周期: ' num2str(pitch_period) ' 样本'], 'FontSize', 10);
text(0.05*max_lag, 0.8, ['基音频率: ' num2str(round(pitch_freq)) ' Hz'], 'FontSize', 10);

% 局部放大图(重点显示基音周期)
subplot(1,2,2);
plot(positive_lags, positive_autocorr, 'b', 'LineWidth', 1.5);
hold on;
plot([pitch_period, pitch_period], ylim, 'r--', 'LineWidth', 1.5); % 基音周期线
title('自相关函数局部放大 (0-300样本)');
xlabel('延迟 (样本)');
ylabel('归一化自相关值');
xlim([0, 300]);
grid on;
text(pitch_period+5, 0.9, ['基音周期: ' num2str(pitch_period) ' 样本'], 'FontSize', 10, 'Color', 'r');

% 添加公共标注
annotation('textbox',...
[0.3 0.001 0.4 0.05],...
'String',['帧长: ' num2str(frame_length) ' 样本 | 基音频率: ' num2str(round(pitch_freq)) ' Hz'],...
'FitBoxToText','on',...
'EdgeColor','none',...
'HorizontalAlignment','center');

图 10 语音内容:oh语音,第45帧 采样率:10k

1
在延迟为0的位置,自相关值达到最大值1,这是自相关函数的典型特征,因为信号与自身的完全重合时相关性最强。随着延迟的增加或减少,自相关值呈现出周期性的波动。在延迟约为±50样本的位置,自相关值形成了明显的峰值。右图中在延迟为0的位置,自相关值为1。随着延迟的增加,自相关值呈现出周期性的波动。在延迟约为50样本的位置,自相关值形成了一个明显的峰值,这与左图中标注的基音周期一致。

四、 编程中遇到的问题、解决方法及存在的疑问

  1. 在计算语音信号的短时能量、短时幅度、短时过零率和短时自相关等特征时,因为公式的理解不准确、计算过程中的数值精度问题或边界处理不当等原因,导致计算结果与预期不符。
    解决方法:
    仔细研读相关公式,确保对每个特征的定义和计算方法有准确的理解。例如,在计算短时过零率时,要注意符号变化的判断条件以及如何处理连续的零值等情况。
    在编程实现特征计算时,要注意数值精度的问题。可以采用合适的数值类型(如双精度浮点数)来存储和计算数据,以减少舍入误差等对结果的影响。
    对于分帧后的语音信号,在计算每帧的特征值时,要注意边界处理。例如,在计算最后一帧时,可能会出现数据不足的情况,可以通过补零或舍弃不完整的帧等方法来解决。
    编写代码后,可以使用一些已知结果的测试数据来验证所编写代码的正确性。例如,可以构造一个简单的正弦信号,计算其短时能量和短时自相关等特征,并与理论结果进行比较,以检查代码是否存在错误。
1
2
声明
本文档部分内容由人工智能生成,不保证准确性,仅作参考使用。

参考文章:
参考链接

Author

Zelazia

Posted on

2025-12-19

Updated on

2025-12-23

Licensed under

Comments

:D 一言句子获取中...

Loading...Wait a Minute!