フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1]
トピック: イタ電 (DTMF)
DEKO
管理者
投稿数: 2644
イタ電 (DTMF)
on: 2013/04/09 23:40 Tue

(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]
http://ht-deko.minim.ne.jp/software/dtmf100.zip

[DTMF (Dual-Tone Multi-Frequency)]
http://ja.wikipedia.org/wiki/DTMF

ページ: [1]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.026 sec.