基于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)
posted @   Enep  阅读(105)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示