今回はあのDTMF音を
プログラムで作ってみました

解説動画はこちら



DTMFとは


DTMFというのは
Dual-Tone Multi-Frequencyの略で
プッシュホン方式の電話機で
ボタンを押すたびに発せられる音のことです

要はプッシュ音のことです
この音で電話をかける事が出来るらしいです

これをプログラムで作ってみましょう



DTMF音を作るコード

こちらのコードで音声ファイルを作成できます
import math
import wave

# 定数の定義
FRAME_RATE = 44100  # サンプリング周波数
DURATION = 0.2  # 音の継続時間

# DTMF信号の周波数を定義
DTMF_FREQS = {
    '1': (697, 1209), '2': (697, 1336), '3': (697, 1477),
    '4': (770, 1209), '5': (770, 1336), '6': (770, 1477),
    '7': (852, 1209), '8': (852, 1336), '9': (852, 1477),
    '*': (941, 1209), '0': (941, 1336), '#': (941, 1477)
}

# 音声を生成する関数
def generate_dtmf_signal(number):
    freq1, freq2 = DTMF_FREQS.get(number, (0, 0))
    if freq1 == 0 or freq2 == 0:
        raise ValueError("Invalid DTMF number: {}".format(number))

    # DTMF信号を生成
    num_samples = int(DURATION * FRAME_RATE)
    signal = [0] * num_samples
    for i in range(num_samples):
        t = float(i) / FRAME_RATE
        signal[i] = math.sin(2.0 * math.pi * freq1 * t) + math.sin(2.0 * math.pi * freq2 * t)

    # サンプルを符号なし16bit整数に変換
    signal = [int((x + 32768) * 65535 / 65535) for x in signal]
    return signal

# 音声をファイル化する関数
def write_wave_file(filename, signal):
    with wave.open(filename, 'w') as wav_file:
        wav_file.setparams((1, 2, FRAME_RATE, len(signal), 'NONE', 'not compressed'))
        for sample in signal:
            wav_file.writeframesraw(sample.to_bytes(2, 'little', signed=False))

# DTMF音のファイルを生成
for i in [str(n) for n in range(10)]+['*','#']:
  dtmf_signal = generate_dtmf_signal(i)
  write_wave_file('dtmf_{0}.wav'.format(i) , dtmf_signal)

実行すると配下に
12個の音声ファイルが作成されます

音声ファイルを確認するには
from IPython.display import Audio
Audio("ファイル名" , autoplay=True)
で確認する事ができます


まとめて確認したいならコレで
from IPython.display import Audio
import ipywidgets as widgets

def on_button_click(button,file):
    display(Audio(file , autoplay=True))

buttons = []
for i in [str(n) for n in range(10)]+['*','#']:
    button = widgets.Button(description=str(i))
    button.on_click(lambda b, i=i: on_button_click(b,'dtmf_{0}.wav'.format(i)))
    buttons.append(button)

display(*buttons)

さて、音声ファイルは出来ても
あまり使い道はないですねえ

これで電話をかけてみましょうか
・・・

なーんか悪用されそうな気がしてきたので
今回はここでおしまいです

それでは