2021/4/26

Acoustic Echo Cancellation (AEC)

回音就是發話端發出的聲音,在經過一陣子以後,自己又聽到自己發出的聲音,通常音量會變比較小一點,但還是能識別出來是自己發出的聲音。

回音通常分為兩種:線路回音、聲學回音。

線路回音是因為傳送語音的實體線路造成的,通常是因為電信局之間是使用四線,而電信局到用戶端是兩芯線,中間會有四線、二線的轉換混合器,如果阻抗不匹配(使用不同型號的電線,或是沒有使用負載線圈),就會導致混合器接收線路的語音訊號,外溢流到發送線路上,因此產生了回音。

聲學回音,就是發話端發出的聲音,傳送到接收端後,接收端以 speaker 播放出來,在麥克風收音時,同時又把 speaker 播放的聲音收錄進去,傳送回到發話端,通常造成這樣的回音的終端,並不會知道自己造成了回音,讓另一端聽到回音。

聲學回音又分為直接回音和間接回音。直接回音是指 speaker 播放出來的聲音未經任何反射直接進入麥克風,這種回音延遲最短。間接回音是指 speaker 播放的聲音經不同的路徑一次或多次反射後進入麥克風所產生的回音集合,有可能是房間的牆壁反射造成的。

回音消除主要包含兩個步驟:線性自適應濾波和非線性處理。

線性自適應濾波就是對 fe=f(fs) 求解,建立遠端回聲的語音模型,進行第一輪回音消除。

非線性處理又分為兩個步驟:殘留回音處理和非線性剪切處理。殘留回音處理進行第二輪回音消除,處理殘留回音;非線性剪切處理就是對衰減量達到閾值的語音信號進行比較激進的剪切處理。

自適應濾波演算法

有兩個系列:LMS 與 RLS

LMS 比較穩定,運算量小,比較容易建置與實作。RLS 執行時收斂速度較快,缺點是運算量大。

LMS: Least Mean Square Algorithm

LMS 是最廣泛使用的濾波器演算法,計算過程只有加法與乘法。做法是讓輸出的誤差訊號的均方值最小化。

LMS 的 adaptation step size 是用來調整加權參數的修正速度,數值太小會讓收斂速度變慢,太大會造成發散。

NLMS: Normalized LMS

重新定義 LMS 中的 𝜇 (adaptation step size),讓 𝜇 會隨輸入訊號的 normalization 而改變,提升收斂的穩定性。

RLS: Recursive Least Squares Algorithm

RLS 演算法目標是將輸出誤差信號平方值總和最小化

open source AEC

目前 open source 的 AEC 演算法有 speex 與 webrtc,兩種都是使用自適應濾波 NLMS。

speex 是使用 MDF 雙濾波結構,用前綠波跟本次濾波的結果來調整濾波器的參數,濾波器的長度很長。

webrtc AEC 比較複雜,包含了 delay 估計, NLMS 及 NLP,舒適噪音。NLMS 的部分只用了 12 block。

目前 speex AEC 用在嵌入式系統,硬體不需要延時模組,速度比較快。webrtc AEC 用在軟體。

References

聲學回聲消除(Acoustic Echo Cancellation)原理與實現

回聲消除基本介紹

音視頻社交中回聲消除技術是如何實現的

AEC 原理

Echo Cancellation

VoIP Echo Cancellation

Understanding the Echo "Phenomenon" Causes and Solutions

可適性濾波器演算法用於聲學回聲消除.pdf

speex AEC

Speex Acoustic Echo Cancellation (AEC) 回聲消除模塊的使用 2013

音訊演算法speex中的aec分析以及解析 2019

speexdsp回聲消除模塊在android中封裝及使用例子 2020

webetc AEC

單獨編譯和使用webrtc音訊回聲消除模組(附完整原始碼+測試音訊檔案)

WebRTC AudioProcessing 3A: AEC AGC ANC 初探

webrtc sample

WebRTC AudioProcessing 3A: AEC AGC ANC 初探

speex aec 與webrtc 回聲消除的比較優化

2021/4/19

Caller ID

Caller ID 來話號碼顯示的功能,是透過交換機做信號傳遞,傳送資料訊息送到使用者的終端設備上(話機),也就是把撥打電話這端的電話號碼,送到接聽電話的那一端。接聽電話端,可以根據電話號碼,選擇要不要接聽電話。

最早提供 Caller ID 服務是由美國及加拿大,Bellcore (Bellcore Client Company) 定義了Type I, Type I, Type III 三種不同類別。

Type Services Supported
Type 1 Calling Number Delivery
Calling Name Delivery
Visual Message Waiting Indicator
Type 2 Type 1 Services +
Calling Identity Delivery on Call Waiting
Type 3 Type 2 Services +
ADSI: both server Display control and Feature Download
ADSI: base visual features such as:
- Visual Screening List Editing
- Calling Waiting Deluxe
- Visual access to information services such as directory, home banking, etc...

ON/OFF Hook

on hook 是電話掛機狀態,off hook 是通話中的狀態。

在 on hook 狀態中,A Party 打電話給 B Party,B Party 能夠顯示來電時間、電話號碼、人名,就是 Caller ID Type I 服務。

在 off hook 狀態中,當 A, B 在通話中,如果 C 打電話給 B,B 能夠在通話中得知 C 的來電時間、電話號碼、人名,B可利用 Call Waiting 決定要不要允許插撥,接聽 C 的來電,這是 Type 2 的服務。

DTMF/FSK

來電號碼顯示目前有兩種信號,一種是簡易的雙音複頻 DTMF: Dual Tone Multi-Frequency,另一種是速度較快,傳輸較複雜的 FSK: Frequency Shift Keying。

DTMF 是由矩陣式 Hi/Lo 頻率編碼組成數字及英文字,只能表示 1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #, A, B, C, D 這些字元。所以目前只能提供用來顯示來電號碼而已。

頻率 Hz H1 1209 H2 1336 H3 1477 H4 1633
L1 697 1 2 3 A
L2 770 4 5 6 B
L3 852 7 8 9 C
L4 941 * 0 # D

  

FSK 是用兩個頻率 FH, FL 來代表 0 與 1,接收到訊號後,要解碼比對 ASCII Code 成為數位訊號,故可以處理來電號碼、姓名、時間、語音留言訊息。

DTMF 目前只有瑞典、荷蘭、大陸使用,但已經慢慢改為 FSK。台灣先開通使用 DTMF,因交換機逐漸汰換,逐步開通 FSK,故兩種都有可能。

除了 DTMF, FSK 的差異外,各國傳輸協定是不同的,有的是第一聲鈴響後,傳遞訊號,有的是在極性反轉下傳遞資料,有的是先送自己的號碼,再送對方的號碼,因此 Caller ID 必須考慮不同國家地區使用,才能符合當地的規範。

FSK Bell 202A 與 V.23 規格

Bell 202A 是美國使用,V.23 是英國使用,差異在於頻率跟位準大小

Bell 202A
Link type Simplex
Modulation Phase coherent frequency shift keying
Logical 1 1200 +- 12 Hz
Logical 0 2200 +- 12 Hz
Transmission rate 1200 bite per second
Data Serial, Binary, Asynchronous
Transmission level -13.5 +- 1 dBm into 900 ohm
V.23
Link type Simplex
Modulation FSK
Logical 1 1300 +- 1.5 %
Logical 0 2100 +- 1.5 %
Transmission rate 1200 baud +- 1%
Received signal level for mark: -8 dBV to -40 dBV
Received signal level for space differ by up to 6 dB for mark and space
Unwant signals Total power of extraneous signals in the voice band 300~3400 Hz are at least 20 dB below the signal level
Data Format Serial binary asynchronous ( 1 start bit first, then 8 data bits with least significant bits first, followed by 1 stop bit minimum, up to 10 stop bits maximum) Start bit = 0, Stop bit = 1

美規 Caller ID

有 Type I, II 兩種。

Type I 是 Off Hook 的來電號碼資料,使用 FSK 訊號,資料跟著第一次鈴聲後面進來。

  1. 第一次鈴聲長度約為 0.2~3 seconds

  2. 鈴響後會有一段大約 0.5~1.5 seconds 的靜止狀態

  3. 然後是資料傳輸,會傳入 Caller ID,大約 2.9~3.7 seconds

  4. 資料傳送後,有 >=200ms 的靜止狀態

  5. 然後是第二次鈴聲 1.8 ~ 3 seconds

  6. 然後是第三、第四次 ... 鈴聲

還有一種 Type I 訊號,沒有跟著鈴聲進來,用在 Message Waiting 狀態,也就是有人留言在 Voice Mail 時,交換機會發送訊號過來,通知有人留言。

這一種不跟隨鈴聲的方式,會有一個 OSI (Open Switching Interval) 訊號來讓終端偵測,但根據 Bellcore 規範,這個 OSI 訊號可有可無。 OSI 訊號是一種一段時間,電話線中斷的訊號,由於 OSI 訊號不一定會發生,因此不能當作可偵測的訊號。

  1. OSI 150~350 ms
  2. Silent Interval 300 ms
  3. Data transmission

Type II 除了 Type I 以外,還增加了 OFF Hook,也就是 Call Waiting 狀態,當使用者收到訊息後,可以利用 Flash Key 切換通話對象。

因為沒有鈴聲,所以傳送方式為

CPE Alerting Signal - CPE Sends ACK - FSK Data Transmission - CPE unmutes - OSI - W - SAS X - X1 - CAS Y - t1 - Q - FSK data Z - OSI - S

  1. 一開始會有 0 ~ 300 ms OSI 訊號
  2. 交換機會暫時靜止遠端的聲音,送入 0 ~ 60 ms (W),並送出一個插撥聲音 SAS (X) 250ms ~ 1 sec
  3. 經過 0 ~ 50ms 間斷 X1
  4. 交換機送出 CAS 2130 + 2750 Hz 約 80 ~ 85ms 的複頻 Tone Y
  5. 一般的終端必須要偵測 CAS Tone,用來準備接收 Caller ID 訊號
  6. 終端要先作並機測試,查看是否有並聯的分機佔線,如果沒有,就發出 "D" Tone (941 + 1633 Hz) 給交換機,也就是 ACK 訊號
  7. 交換機會等待 ACK,約等待 160 +- 5ms 的時間 t1
  8. 交換機收到 ACK 後,會等待 50 ~ 500ms 的間隔 Q,然後送出資料 Z
  9. 接著是 OSI 與 間隔 S 0~320ms
  10. 最後回到通話狀態

OSI 不一定會發生

美規 Caller ID 資料格式

分為單筆資料 Single Data 與多筆資料 Multiple Data 兩類,目前大部分是 Multiple Data

SDMF - Single Data Message Format 只能傳送日期時間、電話號碼與 message waiting

MDMF - Multiple Data Message Format 還可以傳送人名,特殊的訊息。在 Call Waiting 的訊號只有 Multiple DAta 的格式。

Single Data 會先出線一連串 250 ms 的 1, 0 交替的捕捉訊號 (Channel Seizure),然後會有 150ms 連續的 1,後面開始才是真正的資料,這些資料包含,訊息種類、長度、訊息字元,然後是校正位元。

訊息種類分為電話號碼及 message waiting 兩種,訊息字元會送出月份、日期、小時、分鐘,及電話號碼,資料送完後,會送出校正字元。

Channel Seizure Signal - Mark Signal - Message Type Word - Mark bits(0~20) - Messge Length Word - Mark bits(0~20) - Message Words - Mark bits(0~20) - Checksum Word

Multiple Data 會在資料種類後面出現多個 Parameter 參數位元組,裡面包含參數種類、參數長度、參數字元。Off Hook Call Waiting 的 Multiple Data 資料開頭沒有 1010... 的捕捉訊號。

台灣 DTMF Caller ID

台灣的 Caller ID 根據 ETSI 修改而來,分為 DTMF, FSK 兩種,目前大部分是用 DTMF。DTMF 用來傳送發話者的電話號碼。

DTMF 台灣規格,在電話機鈴響前,傳送資料,開始碼 Start Bit 是 D,結束 Stop Bit 是 C,在資料傳送狀態下 (NIT: Number Information Transfer State),介於電話線路兩端之間的直流阻抗必須大於 9 M ohm,在資料訊息傳送完成後,終端設備要脫離資料接收狀態,隨電話鈴聲回到靜止狀態,電話號碼顯示的 DTMF 有一定的時序與時間。

Ta 為 DTMF 送訊息結束到第一聲鈴響之間的中段時間,長度約為 150 ~ 700ms。Tb 為傳送結束時,會到靜止狀態的時間,長度要小於等於 150ms。DTMF 資料傳送時間長度要 <= 3 秒。DTMF 每一碼的長度與間隔都會 >= 50ms,在 D 之前會有一個間隔時間 50 ~ 400 ms。

CID 傳送時機 電話號碼 時間日期 發話者名字
DTMF 振鈴前 有 無 無
FSK V.23 極性反轉後振鈴前 有 有 SDMF 無, MDMF 有
FSK Bell 202 振鈴中第一個長停歇 有 有 SDMF 無, MDMF 有

FSK 用 V.23,但使用 Dual Tone Alerting Signal (DTAS) 取代極性反轉。

DTAS (2130 + 2750 Hz 100±10 ms) → 45 ~ 500 ms → FSK 訊息 → 200 ~ 500 ms → 振鈴

FSK 是採用美規 On Hook 資料傳送格式,但採用 Before Ringer 的傳送方法。

  1. 首先會發送 TAS (Tone Alerting Signal),時間長度 100 +- 10ms,頻率為 2130 Hz + 2750 Hz,誤差 +- 5%。信號位準是每一個音頻 -4 ~ -40 dBm,頻率位準差距最大為 6bB

  2. TAS 後面是靜止 T1,約 45~500ms

  3. T1 結束後,傳送 FSK Data。資料包含日期、時間、電話號碼,因為中文編碼定義問題,目前無法處理姓名

    FSK Data 如下

  1. 後面是一個中斷時間 T2,長度 200 ~ 500ms,然後是振鈴訊號

  2. 從準備接收 FSK Data 到接收結束,起始動作時間長度 T3 <=45ms,結束動作時間長度 T4 <= 150ms。

ADSI

Analog Display Service Interface

ADSI 是 1992 年 12 月 Bellcore Client Company 定義,可用在電話終端與交換機之間的語音與資料傳送,也就是利用 PSTN 進行文字及語音的傳送,進而提供多項加值服務。

這就是 Type III ADSI

ADSI 話機是由 Voice, 警示音 CAS Tone, DTMF, FSK 四種訊號架構的通訊方式

References

FSK CID Format

Caller ID

Caller ID wiki

Caller ID晶片分析 2001年

Caller ID未來市場百家爭鳴 2001年

Frequency-shift keying (FSK) wiki

數位資料與類比訊號 FSK, ASK, PSK

電力線通訊系統

frequency shifting

來電顯示器

Caller ID/SMS

2021/4/12

mongodb 帳號驗證權限

資料庫的權限有四種

  1. readAnyDatabase 任何資料庫的唯讀權限
  2. userAdminAnyDatabase 任何資料庫的讀寫權限
  3. userAdminAnyDatabase 任何資料庫用戶的管理權限
  4. dbAdminAnyDatabase 任何資料庫的管理權限

以往在啟動 mongodb 時,就直接指定 mongod.conf

mongod -f $MONGODB_HOME/conf/mongod.conf

這時候可用 mongo client 連接資料庫

./mongo

查看有沒有 users

db.system.users.find()

查看 user

show users

建立 admin 資料庫的管理者帳號

use admin

db.createUser({
  user : "root",
  pwd : "password",
  roles : [
    "clusterAdmin",
    "dbAdminAnyDatabase",
    "userAdminAnyDatabase",
    "readWriteAnyDatabase"
  ]
})

重新啟動 mognodb (加上 --auth 參數)

mongod --auth -f $MONGODB_HOME/conf/mongod.conf

再次查看 users

> use admin
> db.system.users.find()
Error: error: {
    "ok" : 0,
    "errmsg" : "command find requires authentication",
    "code" : 13,
    "codeName" : "Unauthorized"
}
> show users
2020-09-02T11:36:48.994+0800 E QUERY    [js] Error: command usersInfo requires authentication :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.getUsers@src/mongo/shell/db.js:1763:1
shellHelper.show@src/mongo/shell/utils.js:859:9
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1

驗證後,就可以查看 users

> use admin
switched to db admin
> db.auth("root", "password")
1
> show users
{
    "_id" : "admin.root",
    "user" : "root",
    "db" : "admin",
    "roles" : [
        {
            "role" : "clusterAdmin",
            "db" : "admin"
        },
        {
            "role" : "dbAdminAnyDatabase",
            "db" : "admin"
        },
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        },
        {
            "role" : "readWriteAnyDatabase",
            "db" : "admin"
        }
    ],
    "mechanisms" : [
        "SCRAM-SHA-1",
        "SCRAM-SHA-256"
    ]
}

針對資料庫,建立管理者

use admin

db.createUser({
  user : "maxkit",
  pwd : "password",
  roles : [
    {role:"readWrite", db:"larzio"}
  ]
})

針對資料庫,建立一般使用者

use larzio

db.createUser({
  user : "maxkit",
  pwd : "max168kit",
  roles : [
    {role:"readWrite", db:"larzio"}
  ]
})

刪除帳號

use admin

db.dropUser("maxkit")

關閉 mognodb

mongo 127.0.0.1:27017 -u root -p 'password' --authenticationDatabase 'admin' --eval "db.getSiblingDB('admin').shutdownServer()"

References

Mongodb 創建管理員帳號與普通帳號

2021/3/29

DSP 應用

數位音樂合成 digital music synthesis、數位語音合成 digital speech synthesis、數位語音辨識 digital speech recognition

數位音樂合成 digital music synthesis

使用訊號產生技術,包含週期性訊號及非週期性訊號,並透過數位訊號的排列組合,產生數位音樂

音樂的基本概念

音樂的基本構成要素:音高 pitch、節拍 beats、節奏 tempo

聲音的高低稱為音高 pitch,唱名:Do, Re, Mi, Fa, So, La, Si,對應的英語音名:C, D, E, F, G, A, B

鋼琴鍵盤的排列方式,是依照音高的順序,以中央 C 為基準向左右延伸,兩個相同音名鍵盤之間,有 8 個鍵盤,因此稱為八度音 octave。相鄰白鍵是相差一個全音,相鄰的白鍵與黑鍵,相差一個半音。

音高、音頻對照表:頻率,單位為赫茲。括號內為距離中央C(261.63赫茲)的半音距離。

0 1 2 3 4 5 6 7 8 9
C 16.352 (−48) 32.703 (−36) 65.406 (−24) 130.81 (−12) 261.63 (0) 523.25 (+12) 1046.5 (+24) 2093.0 (+36) 4186.0 (+48) 8372.0 (+60)
C♯/D♭ 17.324 (−47) 34.648 (−35) 69.296 (−23) 138.59 (−11) 277.18 (+1) 554.37 (+13) 1108.7 (+25) 2217.5 (+37) 4434.9 (+49) 8869.8 (+61)
D 18.354 (−46) 36.708 (−34) 73.416 (−22) 146.83 (−10) 293.66 (+2) 587.33 (+14) 1174.7 (+26) 2349.3 (+38) 4698.6 (+50) 9397.3 (+62)
D♯/E♭ 19.445 (−45) 38.891 (−33) 77.782 (−21) 155.56 (−9) 311.13 (+3) 622.25 (+15) 1244.5 (+27) 2489.0 (+39) 4978.0 (+51) 9956.1 (+63)
E 20.602 (−44) 41.203 (−32) 82.407 (−20) 164.81 (−8) 329.63 (+4) 659.26 (+16) 1318.5 (+28) 2637.0 (+40) 5274.0 (+52) 10548 (+64)
F 21.827 (−43) 43.654 (−31) 87.307 (−19) 174.61 (−7) 349.23 (+5) 698.46 (+17) 1396.9 (+29) 2793.8 (+41) 5587.7 (+53) 11175 (+65)
F♯/G♭ 23.125 (−42) 46.249 (−30) 92.499 (−18) 185.00 (−6) 369.99 (+6) 739.99 (+18) 1480.0 (+30) 2960.0 (+42) 5919.9 (+54) 11840 (+66)
G 24.500 (−41) 48.999 (−29) 97.999 (−17) 196.00 (−5) 392.00 (+7) 783.99 (+19) 1568.0 (+31) 3136.0 (+43) 6271.9 (+55) 12544 (+67)
G♯/A♭ 25.957 (−40) 51.913 (−28) 103.83 (−16) 207.65 (−4) 415.30 (+8) 830.61 (+20) 1661.2 (+32) 3322.4 (+44) 6644.9 (+56) 13290 (+68)
A 27.500 (−39) 55.000 (−27) 110.00 (−15) 220.00 (−3) 440.00 (+9) 880.00 (+21) 1760.0 (+33) 3520.0 (+45) 7040.0 (+57) 14080 (+69)
A♯/B♭ 29.135 (−38) 58.270 (−26) 116.54 (−14) 233.08 (−2) 466.16 (+10) 932.33 (+22) 1864.7 (+34) 3729.3 (+46) 7458.6 (+58) 14917 (+70)
B 30.868 (−37) 61.735 (−25) 123.47 (−13) 246.94 (−1) 493.88 (+11) 987.77 (+23) 1975.5 (+35) 3951.1 (+47) 7902.1 (+59) 15804 (+71)

樂曲中,每一個音都有自己的節拍 beats,代表這個音的時間長短,在五線譜中,節拍是用 音符 notes 表示,包含:全音符、二分音符、四分音符等等。ex: 五線譜中的拍號為 C 或 4/4,代表每一個小節有 4 拍,全音符代表這個音佔滿整個小節,因此為 4 拍,二分音符是全音符的一半,是 2 拍

另一個元素是節奏 tempo,就是音樂的快慢或速度。目前節奏通常是以每分鐘的節拍數 beats per minutes 決定。音樂的節奏包含:慢板、行板、中板、快板,與音樂要表達的情感有關。

小蜜蜂

import numpy as np
import wave
import struct

# 音符:音高 pitch + 節拍 beat
def note( pitch, beat ):
    fs = 44000
    amplitude = 30000
    # C, D, E, F, G, A, B 的頻率
    frequency = np.array( [ 261.6, 293.7, 329.6, 349.2, 392.0, 440.0, 493.9 ] )
    num_samples = beat * fs

    t = np.linspace( 0, beat, num_samples, endpoint = False )
    # 淡出效果
    a = np.linspace( 0, 1, num_samples, endpoint = False )

    # 弦波
    x = amplitude * a * np.cos( 2 * np.pi * frequency[ pitch - 1 ] * t )
    return x

def main():
    file = "little_bee.wav" # 檔案名稱

    # 音高 pitch
    pitches = np.array( [ 5, 3, 3, 4, 2, 2, 1, 2, 3, 4, 5, 5, 5,    \
                          5, 3, 3, 4, 2, 2, 1, 3, 5, 5, 3,          \
                          2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 3, 3, 4, 5, \
                          5, 3, 3, 4, 2, 2, 1, 3, 5, 5, 1 ] )

    # 節拍 beat
    beats = np.array( [ 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2,    \
                        1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4,          \
                        1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, \
                        1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 4 ] )

    tempo = 0.5                 # 節奏(每拍0.5秒)
    fs = 44000

    # 時間總長度 = 節拍總和 * 節奏
    duration = sum( beats ) * tempo
    # 總樣本數 = 時間總長度 * 頻率
    num_samples = int( duration * fs )

    num_channels = 1            # 通道數
    samwidth = 2                # 樣本寬度
    num_frames = num_samples    # 音框數 = 樣本數
    comptype = "NONE"           # 壓縮型態
    compname = "not compressed" # 無壓縮

    num_notes = np.size( pitches )

    y = np.array( [ ] )
    for i in range( num_notes ):
        x = note( pitches[i], beats[i] * tempo )
        y = np.append( y, x )

    wav_file = wave.open( file, 'w' )
    wav_file.setparams(( num_channels, samwidth, fs, num_frames, comptype, compname ))

    for s in y:
        wav_file.writeframes( struct.pack( 'h', int( s ) ) )

    wav_file.close( )

main()

數位語音合成 digital speech synthesis

也就是 TTS, Text to Speech 的技術。

python 套件

  • Pyttsx Text to Speech
  • gTTS Text to Speech
  • eSpeak

數位語音辨識 digital speech recognition

Speech To Text

發展的技術:隱藏式馬可夫模型(Hidden Markov Models)、動態時間扭曲(Dynamic Time Warping, DTW)、人工神經網路(Artificial Neural Networks)、深度學習 (Deep Learning)、點對點自動語音辨識 (End-to-End Automatic Speech Recognition)。語音辨識率的準確度受到許多因素影響:雜訊、男生/女生、成人/兒童、口音、語意

新的人工智慧技術:遞迴神經網路 (Recurrent Neural Network, RNN),同時結合長短期記憶 (Long-Short Term Memory, LSTM)的技術最具代表性。AI 技術將成為語音辨識的主流

python 語音辨識 library: SpeechRecognition,支援許多 engines/apis

  • CMU Sphinx
  • Google Speech Recognition
  • Google Cloud Speech API
  • Wit.ai
  • Microsoft Bing Voice Recognition
  • Houndify API
  • IBM Speech to Txt
  • Snowboy Hotword Detection

References

數位訊號處理:Python程式實作(附範例光碟)(第二版)

2021/3/22

時頻分析

時間-頻率分析 Time-Frequency Analysis,首先介紹時頻分析的概念及數學工具 短時間傅立葉轉換 (Short-Time Fourier Transform, STFT),最後介紹範例與結果,用時頻圖 (spectrogram) 表示。

基本概念

通常輸入訊號是 non-stationary 訊號,會跟著時間改變。也就是頻率分量通常會隨著時間改變,因此無法在單一的頻譜分析非靜態(non-stationary)的訊號

例如一首歌曲,在不同時間點的頻率,會隨著時間改變,進而組成一首歌曲。人類發出的語音訊號,說話時每個字的音頻不同,進而組成一個句子。

為了分析或特性化 non-stationary 訊號,需要使用時間頻率分析技術,簡稱時頻分析技術

時頻分析 Time-Frequency Analysis:是訊號分析技術,同時包含時間域與頻率域,以時頻表示法Time-Frequency Representations 呈現。

因為時頻分析包含時間域與頻率域,可表示成二維訊號,稱為時頻表示法 Time-Frequency Representations ,通常是以二維圖形呈現

短時間傅立葉轉換

Short-Time Fourier Transform, STFT

STFT 定義:

\(STFT\{x(t)\}(τ, ω) = X(τ, ω) = \int_{-∞}^{∞}x(t)w(t-τ)e^{-jωt} {\rm d}t\)

其中 \(w(t)\) 為窗函數,通常是以原點為中心,包含 rectangular, hanning, gaussian window function 等等

注意 \(w, ω\) 代表不同的意義


離散短時間傅立葉轉換 Discrete STFT

定義:

\(STFT\{x[n]\}(m, ω) = X(m, ω) = \sum_{-∞}^{∞}x[n]w(n-m)e^{-jωn}\)

其中 \(w[n]\) 為窗函數

雖然 \(ω\) 是連續的,但因為 DSP 是用 快速傅立葉轉換 FFT 進行運算,因此頻率 \(ω\) 也會是離散的資料


時頻分析示意圖:

先將輸入訊號分成不同時間的區塊,通常是短暫且固定的時間,透過窗函數的運算,取得訊號區塊,每個訊號區塊,在經過傅立葉轉換,運算結果為複數,構成二維矩陣。最後,組合不同時間點訊號區塊的頻譜分析結果。

時頻圖 Spectrogram

定義:\(|X(m, ω)|^2\),其中 \(X(m, ω)\) 是 STFT 的結果

將 \(X(m, ω)\) 的二維複數矩陣結果,取強度 (magnitude) 平方,則形成二維的時數矩陣,就可以用二維的圖形呈現,稱為 spectrogram

STFT 主要缺點是解析度問題,由於窗函數的寬度固定,取得訊號區塊大小不同,使得時間域與頻率域的解析度也有所不同。

如訊號區塊的寬度較窄,則時間域解析度較佳,但在頻率域的解析度較差 (左圖)。

ex: 若數位訊號由弦波組成,時間長度為 10s,第一秒頻率 20Hz,第二秒頻率 40Hz,第三秒頻率 60Hz,遞增至 200Hz,取樣頻率為 1000Hz。假設窗函數為 rectangular window function,區塊長度為 100, 200, 500, 1000,求訊號的 STFT,以 spectrogram 表示。

import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt

print( "Short-Time Fourier Transform" )
# n = eval( input( "Enter the length of segment: " ) )

def plot(x, fs, n, plotpos):
    f, t, Zxx = signal.stft( x, fs, window = 'boxcar', nperseg = n )

    plt.subplot(plotpos)
    plt.pcolormesh( t, f, abs(Zxx) )
    plt.xlabel( 'Time(Second)'+' (n='+str(n)+')' )
    plt.ylabel( 'Frequency(Hz)' )

fs = 1000
t = np.linspace( 0, 1, fs )

x = np.array( [ ] )
for i in range( 10 ):
    segment = np.cos( 2 * np.pi * ( ( i + 1 ) * 20 ) * t )
    x = np.append( x, segment )

# n: the length of segment
n = 100
plot(x, fs, n, '221')

n = 200
plot(x, fs, n, '222')

n = 500
plot(x, fs, n, '223')

n = 1000
plot(x, fs, n, '224')

plt.show( )

當弦波頻率增加,由於區塊長度不同,讓時間域與頻率域的解析度結果不同。當區塊長度增加,時間域的解析度越來越差,但頻率域的解析度越來越好。

時頻圖通常用 colormap 色彩圖呈現,亮度較高代表強度越大。

目前有一種 wavelet transform,可克服 STFT 的解析度問題。在高頻範圍,時間解析度較好,在低頻範圍,頻率解析度較好。


f, t, Zxx = signal.stft( x, fs, window = 'boxcar', nperseg = n ) 的部分可改用 SciPy 的 spectrogram 函式

f, t, Zxx = signal.spectrogram( x, fs )

import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt

print( "Short-Time Fourier Transform" )
# n = eval( input( "Enter the length of segment: " ) )

def plot(x, fs):
    f, t, Zxx = signal.spectrogram( x, fs )

    plt.pcolormesh( t, f, abs(Zxx) )
    plt.xlabel( 'Time(Second)' )
    plt.ylabel( 'Frequency(Hz)' )

fs = 1000
t = np.linspace( 0, 1, fs )

x = np.array( [ ] )
for i in range( 10 ):
    segment = np.cos( 2 * np.pi * ( ( i + 1 ) * 20 ) * t )
    x = np.append( x, segment )

plot(x, fs)

plt.show( )

結果為

wav 的時頻分析

STFT 時頻圖

wav file 的 STFT 時頻圖

import numpy as np
import wave
from scipy.io import wavfile
import struct
import scipy.signal as signal
import matplotlib.pyplot as plt

infile  = input( "Input File: " )
fs, x = wavfile.read( infile )

# nperseg: 區塊長度 1000
f, t, Zxx = signal.stft( x, fs, nperseg = 1000 )

plt.pcolormesh( t, f, abs( Zxx ) )
plt.xlabel( 'Time(Second)' )
plt.ylabel( 'Frequency(Hz)' )

plt.show( )

sample rate: 11025Hz 的 wav file

SciPy 時頻圖(spectrogram)

import numpy as np
import wave
from scipy.io import wavfile
import struct
import scipy.signal as signal
import matplotlib.pyplot as plt

infile  = input( "Input File: " )   
fs, x = wavfile.read( infile )  
f, t, Zxx = signal.spectrogram( x, fs )

plt.pcolormesh( t, f, abs( Zxx ) )
plt.xlabel( 'Time(Second)' )
plt.ylabel( 'Frequency(Hz)' )

plt.show( )

跟上面的例子一樣的語音檔

References

數位訊號處理:Python程式實作(附範例光碟)(第二版)