(2011 年の GW 頃の記事です)
巷ではゴールデンウィーク真っ最中ですが、こちとら仕事です。てーかさ、「連休明けに使いますから」 とか、俺に GW 休むなって話なのよね。こうなると、誰かにイタ電 (嫌がらせともいう) をしたくなってしまうのが心情というものです。
さて、黒 DEKO さんは先日、Nifty-Serve のログを整理中に面白い投稿を見つけました。それは "FDELPHI MES( 6):入門者のための Pascal文法とDelphi-IDE" の
[36383] スピーカー音で電話をかけたい
でした (Nifty-Serve ログをお持ちの方は内容をご確認下さい)。結局スレッド中で解決はしていないのですが、「コレは面白そうだ」と思って仕組みを調べた事がありました。
具体的な情報はというと…
- "DTMF (Dual-Tone Multi-Frequency)" で実現可能らしい。
- 特定の周波数の高音と低音をそれぞれ 4 種類組み合わせて 16 通りの信号音を生成する。
- これを受話器で流せば自動ダイアルできる。
- 信号音は 50ms 以上でなくてはならない。
- 信号音間は 30ms 以上でなくてはならない (ミニマムポーズ)。
- 信号音とミニマムポーズの和は 120ms 以上でなくてはならない。
WikiPedia に全部書いてありました。信号音 100ms とミニマムポーズ 50ms で仕様に一致しますわね。
さて、どうやって信号音を生成するかですけど、そこは仕事の合間の暇潰し。コスト (時間) を掛けていたらシャチョサンに怒られてしまいます…ここは一つ、ローテクで行く事にしましょう。
1.信号音は Wikipedia にある (パブリックドメイン) のを使う。 2.音声ファイルは ogg なので、まず wav に変換。 3.長さ制御が面倒なので、100ms にトリミング。 4.これをリソースファイルにブチ込む。 5.MMSystem.PlaySound() を SND_SYNC (再生終了まで処理が戻らない) で連続再生。
概略はこんな所です。周波数と ms を指定できる Windows.Beep() で信号音を生成する事も考えましたが、あくまで単音なので今回の用途には使えません。
そして、なんだかんだしているうちに出来上がったのが以下のソースです。
unit dtmf;
interface
uses Classes, SysUtils, MMSystem;
type { TDTMF } TDTMF = record public class procedure Play(const aPhoneNumber: string; aMinimumPause: Integer = 0); static; end;
implementation
{ TDTMF }
class procedure TDTMF.Play(const aPhoneNumber: string; aMinimumPause: Integer = 0); var C: Char; {PlayWav Begin} procedure PlayWav(aC: Char; aMinimumPause: Integer); var RS: TResourceStream; ResName: String; dC: Char; begin // Generate Resource Name case C of '#': dC := 'N'; // Number '*': dC := 'S'; // Asterisk else dC := aC; end; ResName := Format('DTMF_%s', [dC]); // Play DTMF 100ms RS := TResourceStream.Create(hInstance, ResName, 'WAV'); try PlaySound(RS.Memory, 0, SND_MEMORY or SND_SYNC); finally RS.Free; end; // Sleep <aMinimumPause>ms (Minimum Pause) Sleep(aMinimumPause); end; {PlayWav End} begin // Play Null { PlayWav('_', 0); } // Play DTMF for C in aPhoneNumber do if CharInSet(C, ['#', '*', '0'..'9', 'A'..'D']) then PlayWav(C, aMinimumPause); end; end.
短いですね。え?何故関数じゃないのかって?最初はもっと機能が要るかなと思って用意してたら、結局使わなかったってだけです。他意はありません (w
使い方は以下のようになります。
uses ..., dtmf;
procedure TForm1.Button1Click(Sender: TObject); begin TDTMF.Play(Edit1.Text, 10); end;
これまた短いですね。Button1 を押すと Edit1 に入力された電話番号を再生しますので、PC のスピーカーに受話器を近づけて下さい。本気 (と書いてマジと読む) で使う気なら、二重再生防止の機構をちゃんと実装して下さいね。
2 番目の引数はミニマムポーズですが、PlaySound() の再生オーバーヘッドがあるので、0 ms (= 引数省略) でもイケると思います。最初に無音の wav を再生しようとしているのは、PlaySound() が等間隔で鳴らない事があったからですが、この処理はあってもなくてもあまり変化はありませんでした。
リソーススクリプトファイル (dtmf.rc) はこんな感じです。
DTMF_0 WAV "WAV\Dtmf0.wav" DTMF_1 WAV "WAV\Dtmf1.wav" DTMF_2 WAV "WAV\Dtmf2.wav" DTMF_3 WAV "WAV\Dtmf3.wav" DTMF_4 WAV "WAV\Dtmf4.wav" DTMF_5 WAV "WAV\Dtmf5.wav" DTMF_6 WAV "WAV\Dtmf6.wav" DTMF_7 WAV "WAV\Dtmf7.wav" DTMF_8 WAV "WAV\Dtmf8.wav" DTMF_9 WAV "WAV\Dtmf9.wav" DTMF_A WAV "WAV\DtmfA.wav" DTMF_B WAV "WAV\DtmfB.wav" DTMF_C WAV "WAV\DtmfC.wav" DTMF_D WAV "WAV\DtmfD.wav" DTMF_N WAV "WAV\Dtmf-.wav" // Number (#) DTMF_S WAV "WAV\DtmfStar.wav" // Asterisk (*) DTMF__ WAV "WAV\DtmfNull.wav" // Null
wav ファイルをご自分で用意されるのが一番ですが、面倒臭がり屋さんのために リソース付きソース を用意しておきました。
それでは、皆さんご一緒に Let's イタ電!!…すんなよ? (^^;A
See Also:
[dtmf100.zip]
https://ht-deko.com/software/dtmf100.zip
[DTMF (Dual-Tone Multi-Frequency)]
https://ja.wikipedia.org/wiki/DTMF
|