基于python的DTMF编解码
DTMF编码
def dtmf_encoder(number):
m = 0.5 #length of each tone
s = 0.5 #space between tones
dtmf_mapping = {
'1': (697, 1209),
'2': (697, 1336),
'3': (697, 1477),
'A': (697, 1633),
'4': (770, 1209),
'5': (770, 1336),
'6': (770, 1477),
'B': (770, 1633),
'7': (852, 1209),
'8': (852, 1336),
'9': (852, 1477),
'C': (852, 1633),
'*': (941, 1209),
'0': (941, 1336),
'#': (941, 1477),
'D': (941, 1633), }
if (len(number) == 1):
s = 0
x = np.array([])
x = np.zeros(int(s * Fs))
n = np.arange(0, int(m * Fs))
for num in number:
p = np.sin(2 * np.pi * (dtmf_mapping[num][0] / Fs) * n) + np.sin(2 * np.pi * (dtmf_mapping[num][1] / Fs) * n)
space = np.zeros(int(s * Fs))
x = np.concatenate((x, p, space))
return x
写入文件
def wave_write(wave_file, wave_data, framerate, sampwidth=2, channels=1):
f = wave.open(wave_file, "wb")
# 配置声道数、量化位数和取样频率
f.setnchannels(channels)
f.setsampwidth(sampwidth)
f.setframerate(framerate)
# 将wav_data转换为二进制数据写入文件
wave_data = wave_data * int(20000 / max(abs(wave_data)))
wave_data = np.int16(wave_data)
f.writeframes(wave_data.tobytes())
f.close()
DTMF解码
def signal_energy(signal, win=80, framerate=8000):
print("signal length:", len(signal))
w = np.reshape(signal[:int(len(signal) / win) * win], (-1, win))
#print(w)
print(w.shape)
#this is a 10ms interval..
#compute energy of the tone
w_energy = np.sum(w * w, axis=1)
#plot it
time = np.arange(0, len(w_energy)) * (len(signal) / len(w_energy) / framerate)
plt.figure(figsize=(20, 4))
plt.plot(time, w_energy)
#from the plot, a threshold of 200 is enough to separate sound and silence
#based on that we can define a function that returns the start and stop indices of the tones
def split_dtmf(x, th=5, win=80):
edges = []
w = np.reshape(x[:int(len(x) / win) * win], (-1, win))
w_e = np.sum(w * w, axis=1)
L = len(w_e)
idx = 0
while idx < L:
while idx < L and w_e[idx] < th:
idx = idx + 1
if idx >= L:
break
i = idx
while i < L and w_e[i] > th:
i = i + 1
edges.append((idx * win, i * win))
idx = i
return edges
def decode_dtmf(x, th=5, edges=None):
L_Freqs = np.array([697.0, 770.0, 852.0, 941.0])
H_Freqs = np.array([1209.0, 1336.0, 1477.0, 1633.0])
KEYS = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['*', '0', '#', 'D']]
L_RANGE = (680.0, 960.0)
H_RANGE = (1180.0, 1700.0)
number = []
if edges is None:
edges = split_dtmf(x, th)
for edge in edges:
#compute dft of tone segment
X = np.abs(np.fft.fft(x[edge[0]:edge[1]]))
N = len(X)
res = float(Fs) / N #resolution of each DFT bin
#look for peak in low frequency range
a = int(L_RANGE[0] / res)
b = int(L_RANGE[1] / res)
lo = a + np.argmax(X[a:b])
#look for peak in high frequency range
a = int(H_RANGE[0] / res)
b = int(H_RANGE[1] / res)
hi = a + np.argmax(X[a:b])
row = np.argmin(abs(L_Freqs - lo * res))
col = np.argmin(abs(H_Freqs - hi * res))
number.append(KEYS[row][col])
return number
读取文件
file_name = 'pai.wav'
#%%
f = wave.open(file_name, 'rb')
params = f.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
# print('nchannels:',nchannels)
# print('sampwidth:',sampwidth)
# print('framerate:',framerate)
# print('nframes:',nframes)
strData = f.readframes(nframes) #读取音频,字符串格式
if sampwidth == 1:
waveData = np.frombuffer(strData, dtype=np.int8)
elif sampwidth == 2:
waveData = np.frombuffer(strData, dtype=np.int16)
elif sampwidth == 3:
waveData = np.frombuffer(strData, dtype=np.int24)
elif sampwidth == 4:
waveData = np.frombuffer(strData, dtype=np.int32)
waveData = waveData * 1.0 / (max(abs(waveData))) #wave幅值归一化
waveData = np.reshape(waveData, [nframes, nchannels])
waveData = waveData[:, 0]
f.close()
time = np.arange(0, nframes) * (1.0 / framerate)
plt.figure()
plt.plot(time, waveData)
plt.xlabel("Time(s)")
plt.ylabel("Amplitude")
plt.title("Wavedata")
#plt.grid('on')#标尺,on:有,off:无。
plt.show()
waveData = waveData.reshape(len(waveData), )
signal_energy(waveData)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)