栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

拨号声音识别 非实时

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

拨号声音识别 非实时

拨号声音识别 非实时

电话拨号时的“嘟嘟”声由两组单频信号叠加而成。

按键1209Hz1336Hz1447Hz1663Hz
697Hz123A
770Hz456B
852Hz789C
941Hz*0#D
用 Matlab 读取音频文件
[waveData,Fs] = audioread(".m4a")	
% waveData 是读取到的音频数据 常常是双通道的
% Fs 是该音频文件的采样速率
waveDataHalf = waveData(:,1) %此次只使用 waveData 的一个通道的数据
save  -ascii waveDataHalf
% 保存数据
用 Python 处理数据

刚插入耳机时会有一段强度很大的信号,所以需要截断时域信号的开始部分
线性搜索截断出每一个拨号声音的区间
独立的对每一个拨号音频做FFT即可获得单个拨号音频的频谱
对8个频率附近分别做理想带通滤波器
低频组的4个和高频组的4个频率各选出一个强度最高的频率组合出键值

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft

freqLow1 =  697     #Hz
freqLow2 =  770
freqLow3 =  852
freqLow4 =  941
freqHigh1 = 1209
freqHigh2 = 1336
freqHigh3 = 1447
freqHigh4 = 1633

threshold  = 25     #Hz     使用了8个理想带通滤波器,这个是带通滤波器的门限
sampleFreq = 48000  #Hz     采样频率

searchThreshold = 0.03      #信号强度高于0.03,认为不是噪声
detectSpace = 4800          
avgParm = 200               

def get_key_val(data):

    dataFFT = abs(fft(data))

    sPointNum = len(data)   #样点数目
    k = np.array(range(1,sPointNum+1))
    f = k*sampleFreq/sPointNum

    window = np.zeros((len(data)))      #设置理想带通滤波器
    for i in range(0,len(f)):
        if f[i] > freqLow1-threshold and f[i] < freqLow1+threshold:
            window[i] = 1
        if f[i] > freqLow2-threshold and f[i] < freqLow2+threshold:
            window[i] = 1
        if f[i] > freqLow3-threshold and f[i] < freqLow3+threshold:
            window[i] = 1
        if f[i] > freqLow4-threshold and f[i] < freqLow4+threshold:
            window[i] = 1
        if f[i] > freqHigh1-threshold and f[i] < freqHigh1+threshold:
            window[i] = 1
        if f[i] > freqHigh2-threshold and f[i] < freqHigh2+threshold:
            window[i] = 1
        if f[i] > freqHigh3-threshold and f[i] < freqHigh3+threshold:
            window[i] = 1
        if f[i] > freqHigh4-threshold and f[i] < freqHigh4+threshold:
            window[i] = 1

    dataFFT = dataFFT*window
    max_vals = [0,0,0,0,0,0,0,0]        #分别找8个频带内信号的最大值

    max_vals[0] = max(dataFFT[int((freqLow1-threshold)*sPointNum/sampleFreq-1):int((freqLow1+threshold)*sPointNum/sampleFreq+1)])     #k=f*sampleFreq/sPointNum
    max_vals[1] = max(dataFFT[int((freqLow2-threshold)*sPointNum/sampleFreq-1):int((freqLow2+threshold)*sPointNum/sampleFreq+1)])
    max_vals[2] = max(dataFFT[int((freqLow3-threshold)*sPointNum/sampleFreq-1):int((freqLow3+threshold)*sPointNum/sampleFreq+1)])
    max_vals[3] = max(dataFFT[int((freqLow4-threshold)*sPointNum/sampleFreq-1):int((freqLow4+threshold)*sPointNum/sampleFreq+1)])
    max_vals[4] = max(dataFFT[int((freqHigh1-threshold)*sPointNum/sampleFreq-1):int((freqHigh1+threshold)*sPointNum/sampleFreq+1)])
    max_vals[5] = max(dataFFT[int((freqHigh2-threshold)*sPointNum/sampleFreq-1):int((freqHigh2+threshold)*sPointNum/sampleFreq+1)])
    max_vals[6] = max(dataFFT[int((freqHigh3-threshold)*sPointNum/sampleFreq-1):int((freqHigh3+threshold)*sPointNum/sampleFreq+1)])
    max_vals[7] = max(dataFFT[int((freqHigh4-threshold)*sPointNum/sampleFreq-1):int((freqHigh4+threshold)*sPointNum/sampleFreq+1)])


    max1 = max2 = max1Index = max2Index = 0     #低频组和高频组各找一个强度最大的信号所在的频率
    for i in range(4):
        if max_vals[i] > max1:
            max1 = max_vals[i]
            max1Index = i
    for i in range(4,8):
        if max_vals[i] > max2:
            max2 = max_vals[i]
            max2Index = i
    keyVal = max1Index + 4*(max2Index-4)        #换算出相应键值
    keyName = "147*2580369#ABCD"                #键值换算出按键
    return keyName[keyVal]                      #返回键值





def find_boarder(pos, data):                    #在data[pos]附近寻找该拨号信号的左右边界,结果以数组返回
    L = R = pos
    while(max(data[L-avgParm:L]) > searchThreshold):
        L -= avgParm
    while (max(data[R:R+avgParm]) > searchThreshold):
        R += avgParm
    return [L,R]



# main
ans = []

F = open(r"")
data = F.read()
data = np.array(data.split())
data = np.delete(data,[range(0,20000)])		#截断前20000个采样点
data = [float(i) for i in data]

plt.plot(range(len(data)),data)
#plt.show()             #读入音频信号显示

print("截断区间")
print("下限 上限 区间间隔")
i = 0
while i < len(data):
    if max(data[i:i+avgParm]) > searchThreshold:
        tmp = find_boarder(i,data)
        print(tmp[0], tmp[1], tmp[1]-tmp[0])
        plt.plot(range(tmp[1] - tmp[0]), data[tmp[0]:tmp[1]])
        #plt.show()      #手机号截断效果显示
        i = tmp[1]
        if tmp[1]-tmp[0] > 0:
            ans.append(get_key_val(data[tmp[0]:tmp[1]]))
    i += detectSpace

F.close()

print(ans)          #输出手机号
print(len(ans))     #输出结果长度
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/960817.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号