kazumori
@kazumori

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

プログラムでDTMF音声を番号から生成しスピーカーで再生したがIP電話をダイアルできない

解決したいこと

会社のIP電話ACD08-0359001をPCの画面を見ながらダイアルを押すのが面倒であったため、
こちらをC#に書き直したコードにてDTMF信号生成し通話しようとした。

しかし、正しい手順であるはずにもかかわらず通話開始ができない。

コールは下記の手順で行った。

  1. 受話器を本体から離す
  2. PCのスピーカーを受話器のマイクに直接押し当てる
  3. 番号を入力シエンターを押す
  4. DTMF信号を流す
  5. (スピーカーから音がループバックして聞こえる。妥当な音っぽいのが聞こえる。)

他の既知のプログラムを調査したが、適当なものが見つからなかったため自作コードを使用している。
既存のがあれば紹介いただければと思う。
探したが無かった。ただし根気が足りないだけの可能性は十二分にある。

発生している問題・エラー

通話開始ができない。
ソフト的な間違いはなさそうに見えるが、
物理側の手順が間違っている可能性がある。

該当するソースコード

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NAudio.Wave; // NAudioライブラリを使用して音声信号を扱う
using System.Text.Json;

using TONE = System.Collections.Generic.Dictionary<string, (int low, int high)>;


namespace DTMFSignalGenerator {
	class Program {
		// 設定を変更するには設定ファイルから読み込む
		static int SAMPLING_RATE;
		static double SIGNAL_DURATION;
		static double PAUSE_DURATION;

		// ダイヤル番号の周波数テーブル
		static readonly TONE TONE_TABLE = new TONE(){
			{ "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) }
		};

		static void Main(string[] args) {
			LoadSettings();

			if (args.Length > 0) {
				ProcessDial(args[0]);
			}
			else {
				while (true) {
					Console.Write("電話番号入力: ");
					string dialNumber = Console.ReadLine();
					ProcessDial(dialNumber);
				}
			}
		}

		static void ProcessDial(string dialNumber) {

			// 「+」を「010-」に置換
			if (dialNumber.Contains("+")) {
				dialNumber = dialNumber.Replace("+", "010-");
			}

			dialNumber = "0" + dialNumber;

			// DTMF信号の生成
			var data = GenerateDTMFWave(dialNumber);

			// 信号の再生
			PlayAudio(data);
		}

		static void LoadSettings() {
			try {
				using (var stream = File.OpenRead("settings.json")) {
					Settings settings = JsonSerializer.Deserialize<Settings>(new StreamReader(stream).ReadToEnd());
					SAMPLING_RATE	= settings.SamplingRate;
					SIGNAL_DURATION	= settings.SignalDuration;
					PAUSE_DURATION	= settings.PauseDuration;
				}
			}
			catch (Exception ex) {
				Console.WriteLine($"設定ファイルの読み込みに失敗しました: {ex.Message}");
				SAMPLING_RATE	= 48000;
				SIGNAL_DURATION	= 0.1;
				PAUSE_DURATION	= 0.1;
			}
		}

		static float[] GenerateDTMFWave(string numbers) {
			Console.WriteLine(numbers);
			var data = new List<float>();
			var t = Enumerable.Range(0, (int)(SAMPLING_RATE * SIGNAL_DURATION)).Select(i => i / (double)SAMPLING_RATE).ToArray();
			var u = Enumerable.Range(0, (int)(SAMPLING_RATE * PAUSE_DURATION)).Select(i => 0f).ToArray();

			foreach (char n in numbers) {
				if (TONE_TABLE.ContainsKey(n.ToString())) {
					var (lowFreq, highFreq) = TONE_TABLE[n.ToString()];
					var lowTone		= t.Select(time => (float)Math.Sin(2 * Math.PI * lowFreq * time)).ToArray();
					var highTone	= t.Select(time => (float)Math.Sin(2 * Math.PI * highFreq * time)).ToArray();
					var combinedTone = lowTone.Zip(highTone, (low, high) => low + high).ToArray();
					data.AddRange(combinedTone);
					data.AddRange(u);
				}
			}

			return data.ToArray();
		}

		static void PlayAudio(float[] data) {
			using (var waveOut = new WaveOutEvent()) {
				var waveProvider = new BufferedWaveProvider(new WaveFormat(SAMPLING_RATE, 1));
				waveProvider.AddSamples(data.SelectMany(BitConverter.GetBytes).ToArray(), 0, data.Length * sizeof(float));
				waveOut.Init(waveProvider);
				waveOut.Play();

				while (waveOut.PlaybackState == PlaybackState.Playing && waveProvider.BufferedBytes > 0) {
					System.Threading.Thread.Sleep(100);
				}

			}
		}

		class Settings {
			public int SamplingRate { get; set; }
			public double SignalDuration { get; set; }
			public double PauseDuration { get; set; }
		}
	}
}

追記
なんか音声が元コードに比べキーが低くなっていたような…??

0

2Answer

スマホでDTMF音を出せるダイヤルアプリがあるので、それを使ってIP電話をダイヤルできるかを試してみてはどうか?
ダイヤルアプリでダイヤルできなければ、IP電話側の問題。
(あり得ないと思うが、DPしか対応していないとか?)

1Like

Your answer might help someone💌