三个数字的声纹密码
录制不同发音的三个字,如数字1、2、3,对语音信号做频谱分析,画出采样后的语音信号的时域波形和频域图。录制不同发音的三个字,如数字1、2、3,对语音信号做频谱分析,画出采样后的语音信号的时域波形和频域图。用手机或麦克风录下自己清晰念出的"1"、"2"、"3",保存为.wav文件。最后放个挑衅:拿这个方案去区分"4"和"10",保证翻车——所以啊,特征工程才是真·技术活。对比三个数字的波形,会发现"
数字信号处理 录制不同发音的三个字,如数字1、2、3,对语音信号做频谱分析,画出采样后的语音信号的时域波形和频域图 分析这三个字的发音频率差异,根据频率不同,区分一个未知发音。 文档,Matlab文件、gui
最近在折腾语音信号分析,发现不同数字的发音在频谱上藏着不少好玩的信息。就拿最简单的1、2、3来说,虽然都是单音节,但它们的频率特征差异明显到可以当密码用。先剧透结论:基频(F0)和共振峰(Formant)是区分它们的关键。
第一步:录个音先
用手机或麦克风录下自己清晰念出的"1"、"2"、"3",保存为.wav文件。Matlab里直接用audioread加载:
[y, fs] = audioread('number1.wav');
采样率fs通常选16kHz就够了,毕竟人声主要能量在8kHz以下。
看波形先别慌
时域波形直接暴露发音的振幅变化。比如"3"的尾音拖得比较长,波形衰减更慢:
t = (0:length(y)-1)/fs;
plot(t, y);
xlabel('时间(s)');
ylabel('振幅');
title('"3"的时域波形');
对比三个数字的波形,会发现"1"的起振更突然,而"2"的振幅包络像个小山包。
频域才是重头戏
数字信号处理 录制不同发音的三个字,如数字1、2、3,对语音信号做频谱分析,画出采样后的语音信号的时域波形和频域图 分析这三个字的发音频率差异,根据频率不同,区分一个未知发音。 文档,Matlab文件、gui
FFT一上场,真相就藏不住了。加个汉明窗防止频谱泄漏:
N = 2^nextpow2(length(y));
Y = fft(y.*hamming(length(y)), N);
f = fs/2*linspace(0,1,N/2+1);
plot(f, 20*log10(abs(Y(1:N/2+1))));
xlabel('频率(Hz)');
ylabel('幅度(dB)');
重点看两个区域:
- 基频:男声约80-150Hz,女声约150-300Hz
- 第一共振峰:300-1000Hz,决定元音特性
实测发现:"1"的基频集中在250Hz附近,共振峰在800Hz有个尖峰;"2"的基频略低(200Hz),但共振峰在500Hz和1500Hz双峰结构;"3"的基频飘忽不定(可能受尾音影响),但1200Hz附近必有能量堆积。
写个分类器试试
粗暴版规则:用峰值检测锁定主要频率成分:
[pks, locs] = findpeaks(abs(Y(1:N/2+1)), 'MinPeakHeight', max(abs(Y))*0.3);
main_freqs = f(locs(1:2)); % 取前两个显著峰值
判断逻辑:
- 若main_freqs(1) > 230Hz → 可能是"1"
- 若main_freqs(2)在400-600Hz → 大概率是"2"
- 若main_freqs(2) > 1000Hz → 认作"3"
附赠GUI操作指南
懒得写代码?Matlab的App Designer拖个按钮搞定:
- 导入音频按钮 →
uigetfile - 分析按钮 → 调用上述FFT代码
- 结果显示区 → 用
uiaxes画频谱+文本判决
完整工程文件(含测试语音)已扔GitHub,需要自取:
github.com/xxx/voicedspdemo (注:链接需替换为实际地址)
避坑提示
- 环境噪声太大?加个预加重滤波器
filter([1 -0.97],1,y) - 基频检测翻车?试试
pitch(y,fs)函数,比手动找峰值稳 - 共振峰跟踪玄学?用LPC系数逆推更准,但计算量飙升
最后放个挑衅:拿这个方案去区分"4"和"10",保证翻车——所以啊,特征工程才是真·技术活。

更多推荐



所有评论(0)