一、设计思路
电话拨号音合成与识别的项目可以分为两个主要部分:拨号音的合成(生成)和拨号音的识别。
1. 拨号音合成思路
理解DTMF(双音多频)信号:电话拨号音使用的是一种称为双音多频(DTMF)的信号。每个按键按下时会生成两个特定的频率。了解这些频率对应的按键是生成拨号音的基础。
生成DTMF信号:使用MATLAB的信号处理工具箱,为每个数字(0-9)和特殊字符(#,*)生成对应的DTMF信号。这通常涉及到生成两个正弦波的叠加,每个波的频率对应于DTMF标准中指定的频率,然后将它们合成一个信号。
保存或播放信号:生成的信号可以保存为音频文件或直接在MATLAB中播放,以验证其正确性。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
2. 拨号音识别思路
录制或获取DTMF信号:这一步涉及到获取或录制包含DTMF拨号音的音频。这可以通过录制实际电话信号或使用之前步骤生成的音频文件来完成。
预处理音频信号:在识别拨号音之前,可能需要对音频信号进行预处理,比如去噪、归一化等,以提高识别准确率。
信号分析:使用MATLAB的信号处理功能来分析音频信号。这通常涉及到频谱分析,比如使用快速傅里叶变换(FFT)来识别信号中存在的频率分量。
识别DTMF频率:根据FFT分析的结果,识别出信号中的频率分量,并将它们与DTMF标准中定义的频率进行匹配,以确定被按下的按键。
输出结果:最后,将识别出的按键以文本或其他形式输出,完成识别过程。
3. 实现思路
- 使用MATLAB的audioread和audiowrite函数来读取和保存音频文件。
- 使用fft函数进行频谱分析。
- 使用sin函数生成正弦波。
- 使用MATLAB的filter函数进行信号预处理。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
二、具体实现
1. 拨号音合成
在定义DTMF频率表时,使用了结构体 dtmfFreqs 来存储DTMF信号的频率信息。每个按键对应一个字段,字段名采用字符代替数字,例如 ‘n1’ 代替了数字 1。这样的修改是为了提高代码的可读性和可维护性,因为字符可以更直观地表示按键的含义,而不必记住数字与按键的对
应关系。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
根据输入的键值,函数需要确定对应的字段名。键值表示的是电话键盘上的按键,包括数字键 0 到 9,以及 ‘*’ 和 ‘#’。
% 部分代码如下: fs = 8000; % 采样频率 duration = 1; % 信号持续时间,单位为秒 t = 0:1/fs:duration-1/fs; if key == '*' fieldName = 'star'; elseif key == '#' fieldName = 'hash'; else fieldName = ['n' key]; end
利用获取到的频率信息,函数生成对应的DTMF信号。采用了两个正弦波的叠加来表示DTMF信号,每个正弦波对应一个频率成分。根据正弦波的频率公式,使用正弦函数生成每个频率成分对应的波形。
% 部分代码如下: sinWave1 = sin(2 * pi * dtmfFreqs.(fieldName)(1) * t); sinWave2 = sin(2 * pi * dtmfFreqs.(fieldName)(2) * t); % 1. 生成的DTMF信号波形图 figure; plot(t, signal); title('生成的DTMF信号波形'); xlabel('时间 (s)'); ylabel('振幅');
生成两个正弦波形的意义在于模拟DTMF信号的频率成分。DTMF信号是由两个频率成分叠加而成的,分别对应电话按键上的两个按钮。通过生成两个正弦波形,可以模拟这两个频率成分,从而生成符合电话按键的DTMF信号,使信号更接近实际的通信信号。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
通过FFT变换将DTMF信号转换到频域,并对频谱进行归一化和对称处理。生成的频谱图展示了信号在频域上的幅值分布,帮助分析和理解信号的频域特性。这为信号的频谱分析提供了有力的工具。生成的DTMF信号频谱如下:
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
在DTMF信号的生成过程中,采用了两个频率成分的叠加来表示一个按键,其中每个频率成分对应电话按键上的一个按钮。
可以通过观察频谱图来确认每个正弦波的频率成分是否准确。频谱图显示的频率信息应该与预期的频率相符,这有助于验证生成的正弦波的频率设置是否正确。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
可以通过绘制两个正弦波的频谱来验证它们的叠加效果。由于DTMF信号是两个频率成分的叠加,因此期望在频谱上能够观察到这两个频率处的峰值。通过验证叠加效果,可以确保生成的DTMF信号在频域上与预期一致。
% 部分代码如下: subplot(2,1,1); plot(f(1:length(sinWave1)/2+1),P1_1) title('第一个正弦波的频谱') xlabel('频率 (Hz)') ylabel('|P1(f)|') subplot(2,1,2); plot(f(1:length(sinWave2)/2+1),P1_2) title('第二个正弦波的频谱') xlabel('频率 (Hz)') ylabel('|P1(f)|')
播放保存音频文件
播放信号:使用 sound(signal, fs) 函数可以播放生成的信号。signal 是生成的DTMF信号,fs 是采样频率。通过这个函数,可以听到生成的信号的声音效果。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
保存为音频文件:使用函数将生成的信号保存为音频文件。这个函数需要三个参数:文件名、信号数据和采样频率。文件名基于输入的键值,这样每个按键对应的DTMF信号都可以保存为一个单独的音频文件。保存为 .wav 格式的文件是为了保持音频的无损质量。
拨号音识别
1)读取音频文件并显示原始波形图
audioread(‘6.wav’)是一个Matlab函数调用,用于读取名为"6.wav"的音频文件。
返回的keySignal是一个包含了音频信号的数组,fs是音频文件的采样频率。
figure函数创建一个新的图形窗口,使得后续的绘图操作在这个窗口中进行。
plot函数用于绘制图形,绘制波形图。
(1:length(keySignal))/fs创建了一个时间轴,用于表示音频信号的时间。
keySignal是音频信号的振幅值。
将时间轴和振幅值作为参数传递给plot函数,以绘制原始音频信号的波形图。
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
2)信号预处理
以上代码对音频信号进行了预处理,包括归一化和带通滤波器的应用。首先,通过归一化确保了音频信号的振幅范围统一在[-1, 1]之间,这样的处理提高了后续处理的稳定性和一致性。
% 部分代码如下: keySignal = keySignal / max(abs(keySignal)); bpFilt = designfilt('bandpassfir', 'FilterOrder', 20, ... 'CutoffFrequency1', 697-25, 'CutoffFrequency2', 1477+25, ... 'SampleRate', fs); filteredSignal = filter(bpFilt, keySignal);
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇
3)按键识别
识别音频中的DTMF信号并将其转换为相应的按键。使用了findpeaks函数来寻找频谱中的峰值,通过按降序排列找到前两个最高峰值,即主要频率成分。这一步骤确保了我们捕获了音频中最明显的频率特征。接下来,在第五部分中,我们定义了DTMF信号可能的频率和相应的按键映射关系。通过遍历找到的主要频率成分,并与预定义的DTMF频率表进行匹配,确定了对应的按键。在匹配过程中,设置了容差范围为25Hz,确保了频率匹配的准确性。一旦成功匹配到按键,即更新recognizedKey并结束循环。这段代码的执行流程清晰,通过频率的匹配实现了从音频信号到按键的准确识别。
最终的识别结果:
频谱如下:
👇👇👇 关注公众号,回复 “拨号音合成与识别” 获取源码👇👇👇