DTMF采用RFC2833进行带内传输的实现

摘要:    本文主要说明采用RFC2833标准进行DTMF传送的方法和格式。

关键字:RFC2833,RTPDTMF

 

一.IP电话传送DTMF的方式

       DTMF就是双音多频,我们日常生活中拨打电话的过程中经常会用到,如拨打用户的分机号码,输入帐号和密码等。而随着IP电话的大量使用如何实现传送DTMF成为IP电话中的一个技术问题。

目前传送DTMF信号普遍有两种方式:带内传送和带外传送。

其中带外传送主要通过将DTMF消息封装到协议中进行传送,如H323协议中可以通过Q931H245进行传送DTMF

而带内传输主要有两种:透明传送和RFC2833方式。所谓透明传送就是将DTMF音作为语音一起打包到RTP中进行发送。由于网络丢包的影响,有时会造成DTMF信号丢失,而且DTMF音混合在语音包中,容易产生偏差,造成信号失真。所以目前普遍采用的是RFC2833方式,就是将DTMF数字按照一个的规则和格式组成一个数据包,然后封装到RTP中发送。接收端接收后进行解析,再还原成相应的DTMF信号,这种方式的优点是对丢包的容错性强以及识别差错率低。

 

.RTP

       在介绍RFC2833前,先来了解一下RTPReal Time Protocal),该协议可参见RFC1889RTP协议是IP电话中以及NGN中最经典的协议。无论采用H323H248MGCP还是SIP,这些都属于信令层的协议,他们之间进行互通、交换其最终目的是为了实现媒体流的收发。而所有的媒体流都是采用RTP协议,无论是视频,语音还是图象,包括本文所提到的DTMF都是建立在RTP的基础上的。

RTP协议用以传送实时数据。RTP协议通常运行在UDP层之上,二者共同完成运输层的功能。UDP提供复用及校验和服务,也就是通过分配不同的端口号传送多个RTP流。协议规定,RTP流使用偶数(2n)端口号,相应的RTCP流使用相邻的奇数(2n+1)端口号。因此,应用进程应在一对端口上接收RTP数据和RTCP控制数据,同时向另一对端口上接收RTP数据和RTCP控制数据。

 

       RTP分组由RTP头部和净荷数据组成;RTP分组由UDP包来进行传输,通常一个UDP包仅含一个RTP分组,若采用一定的封装方法,也可以包含多个RTP分组;其中的RTP净荷就是RTP传送的语音数据。RTP分组的头部的格式如表1

 

0-1

2

3

4-7

8

9-15

16-31

V

P

X

CC

M

PT

序号

时戳

同步源(SSRC)标识

分信源(CSRC)标识(0~15个)

 

1 RTP分组头部格式

 

       RTP分组头部的各字段含义为:

 

1VRTP版本号。为“10”。

2P:填充指示位。

       P为“1”时表示分组结尾含有1个或多个填充字节。

3X:扩展指示位。

       X为“1”时,则表示固定头部后还有一个扩展头部,这种情况较复杂,很少使用。

4CCCSRC计数。

       指示固定头部后的CSRC的个数

5M

       由应用文档解释,通常不用。

6PT:净荷类型

       表示RTP分组的净荷类型。我们常用的有:

¨          0”:    G.711μ

¨          8”:    G.711A

¨          4”:    G.723.1

¨          18”:  G.729

¨          96”:RFC2833

7.序号:

       序号顾名思义就是表示RTP分组的次序。初值为随机数,每发送一个增加1。可供接收方检测分组丢失和恢复分组次序。

8.时戳:

       表示RTP分组第一个字节的取样时刻。其初值为随机数,每个采用周期加1。如果每次传送20ms的数据,由于音频的采样频率为8000Hz,即每20ms160次采样,则每传送20ms的数据,时戳增加160

9SSRC:同步源标识(Synchronous Source

       表示信号的同步源,其值应随机选择,以保证同一个RTP会话中任意两个同步源的SSRC标识不同。

10CSRC:分信源标识(Contributing Source

       CSRC标识由混合器插入,其值就是组成复合信号的各个分信号的SSRC标识,用以标识各个组成分信号的信源。RTP分组的头部最多可以包含15CSRC标识,其数目由CC字段指明。

 

三.RFC2833

1.标准格式

RFC2833(RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals)IETF制定的,它规定了传送DTMF数字以及其他电话音和信号的标准。

0-7

8

9

10-15

16-31

event 

E

R

volume

 duration

 

2 RFC2833 净荷格式

2给出RFC2833的标准格式

events: 事件号,8位,用于说明本数据包的事件。RFC2833除了传送DTMF信号外还能传送传真,调制解调器,MF信号等。本文只关注DTMF信号,有关DTMF的事件看见表2

Event

encoding (十进制)

0—9

0--9

10

11

A—D

12—15

Flash

16

2DTMF的事件

volume: 音量,6位,用于说明DTMF信号的音频功率级,范围从(0~ -63dbm)。有效的DTMF范围是从0 -36 dBm0;低于-55 dBm0则必须丢弃。

duration:数字信号的宽度,16位,以时戳单元表示。这样,事件从RTP时间戳表示的瞬间开始,并一直持续到该参数表示的长度。事件可以已经结束也可以没有结束。以8000赫兹

取样来说,本字段最长可以表示8秒。

E:结束位,1位,若设置为1表明数据包中含有事件的结束。因此上述的duration参数即测定了事件的完整宽度。

R:本字段为以后使用而保留。发送方必须将它设为0,接收端则应忽略它。

 

2.举例

 

3 Sniffer抓包截图

3是采用Sniffer软件所捕获的数据包,从上面可以看到RTP数据为:80 60 03 8e 7d 8b 6a d5 5a 12 02 80 05 f0。我们将该报数据按照格式还原如表3

 

0-1

2

3

4-7

8

9-15

16-31

V

P

X

CC

M

PT

序号

2

0

0

0

0

96=0x60

910  (03 8e)

时戳

2106288853 (7d 8b 6a d5)

同步源(SSRC)标识

5a 12 02 80

Event 

E

R

Volume

 Duration

05

1

1

0

 












3 DTMF ‘5’的数据格式

在表3中净荷类型为96,这是RFC2833中规定的,在实际情况下可以自己定义类型,只要通信双方能够确认即可。

对于同一个DTMF信号,其时戳是相同的,这样接收方可以通过判断时戳来剔除冗余信息。

 

3. 安全性

 

参考资料:

 

1.  RFC1889 RTP: A Transport Protocol for Real-Time Applications

2.  RFC2833 RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 下面是一个用MATLAB实现DTMF信号检测的示例代码: ``` % 采样率为8000Hz fs = 8000; % DTMF的频率 freq1 = 697; freq2 = 1209; % 生成DTMF信号 key = '1'; % 待检测的按键 dtmf = dtmfGen(key, fs, freq1, freq2); % 添加白噪声 dtmf = dtmf + 0.1*randn(size(dtmf)); % 播放DTMF信号 sound(dtmf, fs); % 设定带通滤波器的频率范围 f_low1 = freq1 - 10; f_high1 = freq1 + 10; f_low2 = freq2 - 10; f_high2 = freq2 + 10; % 创建带通滤波器 [b1, a1] = butter(2, [f_low1, f_high1]/(fs/2), 'bandpass'); [b2, a2] = butter(2, [f_low2, f_high2]/(fs/2), 'bandpass'); % 滤波 output1 = filter(b1, a1, dtmf); output2 = filter(b2, a2, dtmf); % 求均方根(RMS)值 rms1 = sqrt(mean(output1.^2)); rms2 = sqrt(mean(output2.^2)); % 检测信号 if rms1 > 0.1 && rms2 > 0.1 disp(['按键', key, '被检测到']); else disp('未检测到信号'); end % 生成DTMF信号的函数 function dtmf = dtmfGen(key, fs, freq1, freq2) t = 0:1/fs:0.2; % 时长为0.2秒 switch key case '1' f1 = freq1; f2 = freq2; case '2' f1 = freq1; f2 = freq2+300; case '3' f1 = freq1; f2 = freq2-300; case '4' f1 = freq1+300; f2 = freq2; case '5' f1 = freq1+300; f2 = freq2+300; case '6' f1 = freq1+300; f2 = freq2-300; case '7' f1 = freq1-300; f2 = freq2; case '8' f1 = freq1-300; f2 = freq2+300; case '9' f1 = freq1-300; f2 = freq2-300; case '0' f1 = freq1; f2 = freq2; end dtmf = sin(2*pi*f1*t) + sin(2*pi*f2*t); end ``` 这段代码中,首先定义了采样率、DTMF信号的频率,然后通过调用`dtmfGen`函数生成待检测的DTMF信号,再给信号添加白噪声并播放出来。接着,根据DTMF信号的特好的,下面是一个简单的 MATLAB 代码实现 DTMF 信号检测的方法: ```matlab % 采样率 fs = 8000; % DTMF 频率表 freqs = [697 770 852 941 1209 1336 1477 1633]; % 窗口长度 window_size = round(0.02 * fs); % 加载音频文件 [x, fs] = audioread('dtmf_signal.wav'); % 预处理,去除直流分量 x = x - mean(x); % 分帧,取相邻两帧之间的重叠长度为一半 frames = buffer(x, window_size, window_size/2); % 加汉明窗 win = hamming(window_size); frames = frames .* win; % FFT N = 2^nextpow2(window_size); fft_frames = abs(fft(frames, N)); % 提取 DTMF 信号 dtmf_tones = zeros(size(frames,2), 2); for i = 1:size(frames,2) % 对每一帧,找到最大的两个频率分量,即为 DTMF 信号频率 [~, idx] = sort(fft_frames(1:N/2,i), 'descend'); f1_idx = find(freqs == round(idx(1)/N*fs)); f2_idx = find(freqs == round(idx(2)/N*fs)); dtmf_tones(i,:) = [f1_idx f2_idx]; end % 输出 DTMF 信号 disp('DTMF 信号频率为:'); disp(dtmf_tones); ``` 这个代码实现DTMF 信号的检测,输入一个包含 DTMF 信号的音频文件,输出每个时间窗口内的 DTMF 信号频率。具体实现方法为:首先将音频信号预处理,去除直流分量;然后将音频信号分帧,并加窗(这里使用汉明窗);接着对每一帧进行 FFT 变换,并找到最大的两个频率分量,即为 DTMF 信号频率;最后输出每个时间窗口内的 DTMF 信号频率。 ### 回答2: DTMF(双音多频)信号是由两个频率相加而成的信号,DTMF信号检测可以应用在电话系统、安防系统等领域。MATLAB是计算机辅助工程领域应用广泛的软件,它可以实现信号的分析和处理,包括DFT、滤波等。下面介绍MATLAB实现DTMF信号检测的代码。 首先,需要生成DTMF信号。MATLAB可以使用下面的函数生成DTMF信号: ```matlab t = linspace(0, 1, 8000); f1 = 697; f2 = 1336; y = sin(2 * pi * f1 * t) + sin(2 * pi * f2 * t); ``` 此处,时间域采样频率为8000Hz,f1和f2为两个不同的频率。 在使用DTMF信号之前,需要对其进行数字信号处理。对于DTMF信号的检测,可以使用Goertzel算法进行处理。Goertzel算法是一种能够快速计算单个频率的DFT(离散傅立叶变换)的算法,计算公式如下: $Q_k = 2\cos(\frac{2\pi \frac{k}{N}}{N-1})Q_{k-1}-Q_{k-2}+x(n)$ 其中,$Q_k$为中间结果,$x(n)$为输入的信号,$N$为信号长度。 下面是MATLAB实现Goertzel算法的代码: ```matlab function Q = goertzel(x, k) N = length(x); Q1 = 0; Q2 = 0; w = 2*pi*k/N; for n = 1:N Q0 = x(n) + 2*cos(w)*Q1 - Q2; Q2 = Q1; Q1 = Q0; end Q = Q1 - exp(-1i*w)*Q2; end ``` 使用Goertzel算法,MATLAB可以检测DTMF信号的频率。为检测DTMF信号,可以将Goertzel算法应用于DTMF信号的每个频率,并通过幅度比较判断DTMF信号是否存在。下面是MATLAB实现DTMF信号检测的代码: ```matlab D = [697, 770, 852, 941]; S = [1209, 1336, 1477]; D_len = length(D); S_len = length(S); Y = zeros(D_len, S_len); for ii = 1:D_len for jj = 1:S_len Y(ii, jj) = abs(goertzel(y, D(ii))+goertzel(y, S(jj))); end end idx = find(Y == max(Y(:))); [row, col] = ind2sub(size(Y), idx); disp(['DTMF signal detected: ', num2str(D(row)), ' & ', num2str(S(col))]); ``` 此处,我们定义了许多DTMF信号的频率,包括D(低频)和S(高频),然后通过遍历D和S数组,检测每个DTMF信号的频率,并计算每个DTMF信号的幅度。最后,返回幅度比较大的DTMF信号的频率。将此代码放入MATLAB命令窗口中并运行,即可进行DTMF信号检测。 ### 回答3: DTMF(Dual Tone Multi-Frequency)信号是由两个频率的正弦波信号组成的,用于电话通信中传输数字信息。以下是MATLAB实现DTMF信号检测的代码: ```matlab % DTMF信号检测代码 Fs = 8000; % 采样率 f1 = [697, 770, 852, 941]; % 第一个频率的四个选项 f2 = [1209, 1336, 1477, 1633]; % 第二个频率的四个选项 frameSize = 250; % 帧的大小,单位为毫秒 frameShift = 50; % 帧移,单位为毫秒 frameLen = frameSize * Fs / 1000; % 帧的样本数 sigLen = length(signal); % 信号长度 numFrames = floor((sigLen-frameLen)/frameShift)+1; % 帧的数量 count = 1; % 计数器 for m = 1:numFrames frame = signal((m-1)*frameShift+1:(m-1)*frameShift+frameLen); % 提取当前帧的信号 Y = fft(frame); % 对帧进行FFT Pyy = Y.*conj(Y)/frameLen; % 计算功率谱密度 f = Fs*(0:(frameLen/2))/frameLen; % 创建频率向量 Pyy = Pyy(1:frameLen/2+1); % 找到最强的两个频率 [max1, idx1] = max(Pyy); Pyy(idx1) = 0; [max2, idx2] = max(Pyy); % 判断是否为DTMF信号 if (f(idx1) < 1209 && f(idx2) < 1633 && f(idx2) >= 1209 && abs(f(idx1)-f(idx2)) >= 300) || ... (f(idx1) >= 1209 && f(idx1) < 1633 && f(idx2) >= 697 && f(idx2) < 941 && abs(f(idx1)-f(idx2)) >= 300) % 判断第一个频率 if f(idx1) >= 697 && f(idx1) < 725 col = 1; elseif f(idx1) >= 725 && f(idx1) < 763 col = 2; elseif f(idx1) >= 763 && f(idx1) < 809 col = 3; elseif f(idx1) >= 809 && f(idx1) < 871 col = 4; end % 判断第二个频率 if f(idx2) >= 1209 && f(idx2) < 1275 row = 1; elseif f(idx2) >= 1275 && f(idx2) < 1350 row = 2; elseif f(idx2) >= 1350 && f(idx2) < 1429 row = 3; elseif f(idx2) >= 1429 && f(idx2) < 1521 row = 4; end % 输出DTMF信号 disp(['Frame ', num2str(count), ': DTMF signal detected! Row = ', num2str(row), ', Column = ', num2str(col)]); count = count + 1; end end ``` 上述代码中,我们首先定义了采样率`Fs`,以及第一个频率选项`f1`和第二个频率选项`f2`。同时,我们还定义了每个帧的大小`frameSize`和帧移`frameShift`,并通过这两个参数计算了实际的帧长度`frameLen`和信号长度`sigLen`以及帧的数量`numFrames`。 接下来的循环中,我们逐帧地对信号进行处理。对于每一帧,我们先计算其功率谱密度,并保存频率向量`f`及对应的功率谱密度`Pyy`。然后,我们找到音频中最强的两个频率(即功率谱密度最大的两个频率),并计算它们之间的差距。 如果这两个频率满足DTMF信号的条件,则在第一个选项中找到第一个频率所处的行号`row`,在第二个选项中找到第二个频率所处的列号`col`,并输出DTMF信号的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上海老李

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值