1. 程式人生 > >談談語音通訊中的各種tone

談談語音通訊中的各種tone

今天談的這個主題(tone)存在於我們的日常打電話過程中。先舉兩個場景:1,你拿起固話話筒準備打電話,按電話號碼前先從話筒裡聽到“嗡”的連續音,這叫dial tone(撥號音,表示你可以撥電話號碼了),你撥完號碼對方振鈴後你又聽到有規律的“嘟-嘟-”的斷續音,這叫ring back tone(回鈴音,表示對方已振鈴了)。2,你給企業服務號(比如中國移動的10086)打電話,對方叫你按鍵選擇,當你按下鍵後會聽到按鍵聲,這叫DTMF tone(雙音多頻音)。感覺到它存在於我們日常的打電話過程中了吧。現在我們就從技術的角度談談這些tone。

 

在語音通訊中tone主要分兩大類:CPT(call progress tone,呼叫過程音)tone和DTMF(dual tone multi frequency,雙音多頻音)tone。CPT tone存在於通話過程中,主要用於告訴使用者目前在什麼狀態,主要有dial tone(撥號音)/ringback tone(回鈴音)/busy tone(忙音)等。CPT tone是單頻音,即由一個頻率的正弦波形成。CPT tone沒有全球統一的標準,而是各個國家有自己的標準,比如中國的標準,歐洲的標準,美國的標準等。下表就是我們國家的標準:

還有其他型別的CPT tone,由於用的相對較少,這裡就不一一列出了。相對於CPT tone是單頻音,DTMF tone是雙頻音,即用兩個頻率(一個高頻和一個低頻)的正弦波疊加去表示某個按鍵值。與CPT tone各國有自己的標準不同的是DTMF tone全球有統一的標準,下表列出了常用的16個按鍵值是由哪些高頻音和低頻音組合而成的:

從軟體實現的角度對tone主要有兩類處理:tone generation,讓使用者聽到tone;tone detection,主要是指DTMF tone的detection,讓軟體知道哪個按鍵按下了,好進行後續的處理。我們先看tone generation,也就是生成單個頻率的正弦波(CPT tone)或者兩個頻率正弦波的疊加(DTMF tone),在訊號處理上有相應的演算法。對於單頻正弦波,各個取樣點上值的生成可通過如下的數學表示式求得:

 

其中a/y(0)/y(1)在各個頻點上的值已事先根據數學公式做成表,從而減少數學運算。對於DTMF這樣的雙頻率音來說,取樣點上的值就是兩個頻率取樣點上的值相加。Tone generation分兩個方向,local 和remote。Local是tone讓自己聽到,把生成的正弦波放到RX stream上;remote是tone讓對端聽到,把生成的正弦波放到TX stream上。對於像ring back tone等斷續音還需要timer控制放多長時間停多長時間。

 

再來看tone detection,這裡主要是指對DTMF的tone detection。有專門的演算法(Goertzel戈澤爾演算法)來detect DTMF的鍵值,把DTMF的音訊訊號(多幀的PCM訊號)作為演算法的輸入,經過一定幀數後得到的就是DTMF的鍵值。原理這裡就不詳細講了,有興趣的可以看相關文章。有時候我們需要告訴對端按下的是什麼DTMF鍵,即要把鍵值傳給對端,主要有三種方法,具體如下:

1,把DTMF音訊訊號直接編碼得到碼流放在RTP中發給對端。對端收到RTP包後解碼復原出音訊訊號,然後再通過DTMF detection演算法得到鍵值。這通常被叫做in-band方法。

 

2,在本端做DTMF detection得到鍵值,然後根據RFC2833(後來升級成RFC4733)組成RFC2833包發給對端。對端收到RFC2833包後去解析就知道是哪個鍵值了。這通常被叫做out-of-band方法。RFC2833包也是用RTP做承載,不過它的payload type是動態的(96~127之間一個值),payload共4個位元組(32個位元),具體如下:

 

 

packages/services/Telecomm/src/com/android/server/telecom/InCallTonePlayer.java,該類用於通話中提示音的播放。
case TONE_RING_BACK:
toneType = ToneGenerator.TONE_SUP_RINGTONE;
toneVolume = RELATIVE_VOLUME_HIPRI;
toneLengthMillis = Integer.MAX_VALUE -TIMEOUT_BUFFER_MILLIS;
                  break;
----------------------------------------------------------------------------------------------
Also please enable telecom log to collect the dut and ref logs. Thanks 

adb reboot  
adb wait-for-device  
adb shell setprop log.tag.TelecomFramework VERBOSE  
adb shell setprop log.tag.Telecom VERBOSE  
adb shell setprop log.tag.Telephony VERBOSE  
adb shell setprop log.tag.InCall VERBOSE  
adb shell setprop log.tag.QImsService VERBOSE  
DONOT reboot after this