2019年12月23日

praat

praat 是一款跨平台的多功能語音學專業軟體,主要用於對數位化的語音信號進行分析、標註、處理及合成等實驗,同時生成各種語圖和文字報表。

Praat的主要功能是對自然語言的語音信號進行採集、分析和標註,並執行包括變換和濾波等在內的多種處理任務。作為分析結果的文字報表和語圖,不但可以輸出到 PC 檔案中和終端顯示器上,更能夠輸出為精緻的向量圖或位圖,供寫作和印刷學術論文與專著使用。此外,Praat還可用於合成語音或聲音、統計分析語言學數據、輔助語音教學測試。

基本功能

錄音

在 Praat Objects -> 上面的選單 New -> Record mono sound -> (預設 sample rate 為 44100 Hz) -> Record -> (Play 可播放剛剛路的聲音 ) -> Save to list

View & Edit

  • 上面是 wav 的波形,中間是聲譜 (spectrum),代表聲音在每一個頻率的能量大小,越黑代表越強。在上面選單 Spectrum -> Show spectrum 可選擇要不要顯示 spectrum
  • 藍色線條就是 Pitch 音高 (代表聲帶震動的快慢,震動越快,音高會越高。) 在上面 Pitch -> Show pitch 可以將 pitch 關掉
  • Intensity 強度、音量,在選單 Intensity -> Show intensity 可顯示黃色線條 intensity
  • Formant 共振峰 是用來描述聲學共振現象的一種概念,在語音科學及語音學中,描述的是人類聲道中的共振情形。

note:

  • 音量(Volume):代表聲音的大小,可由聲音訊號的震幅來類比,震幅越大,代表此聲音波形的音量越大。音量又稱為能量(Energy)或強度(Intensity)等。
  • 音高(Pitch):代表聲音的高低,可由基本頻率(Fundamental Frequency)來類比,這是基本週期(Fundamental Period)的倒數。聲音的基本頻率越高,代表音高越高;反之,聲音的基本頻率越低,代表音高越低。
  • 音色(Timbre):代表聲音的內容(例如英文的母音),可由每一個波形在一個基本週期的變化來類比。不同的音色即代表不同的音訊內容,例如不同的字母有不同的發音,都是由於音色不同而產生。

如果是用人聲來說明,這些語音特徵的物理意義如下:

  • 音量:代表肺部壓縮力量的大小,力量越大,音量越大。
  • 音高:代表聲帶震動的快慢,震動越快,音高會越高。
  • 音色:代表嘴唇和舌頭的位置和形狀,不同的位置和形狀,就會產生不同的語音內容。

選取後,點中間灰色區塊的秒數長度的部分,就可以播放聲音。點 "Visible part" 或 "Total duration" 可播放整個音檔。

在 Edit -> Set selection to zero,可以將選取起來的雜音部分都設定為 0,也就是刪除那一部分的聲音的意思。

Edit -> Reverse selection,可將聲音倒過來。就等於將聲音倒著播放。

音檔標注

  1. Open -> Read from file 讀取語音 wav 檔

  2. Annotate -> To TextGrid 產生一個空白的標註文件。要先規劃好對這個聲音文件要標註幾層訊息,通常會標註音素 (phone)、音節 (syllable)、字詞。在 All tier names: 填上 phon syllable。

  3. 目前先在 All tier names 填上 sentence,清除 "wichi of these are point tiers?"

  4. 同時選取聲音文件跟 TextGrid,點 View & Edit 進行標注。標注時,聽辨邊界,並查閱語圖資訊,確定音素與音節的邊界

  5. 點擊剛剛聽到的單字的起點,點中間 sentence 裡面的圓圈,設定單字起點。同樣標記出終點 boundary。

  1. 可在 Tier -> add interval tier ,增加一層標記

    1. 有另一種 Point tier,可用來標記 事件

    1. File -> Save TextGrid as text file 可將標記存成文字檔

    2. 在 Praat Obejcts 畫面,選語音,Save -> Save as WAV file 可將剛剛修改過的 wav 存成另一個 wav file

  2. 把 Parrat 關掉時,會將選取的 wav, TextGrid 都清除。Open -> Open from file 可將剛剛存的 wav, TextGrid 選取回來

Drawing

可將 wav & textgrid 同時選取,並點 Praat Objects 右邊的 Draw,就會在 Praat Picture 出現圖檔。點擊 Draw 之前,可先在 Praat Picture 重新把藍色框框範圍改為 9x6,再 Draw,就可得到比較大的圖檔。

畫圖時,有個 "Garnish" 選項,如果有打勾,畫圖時就會增加座標的資訊。如果沒有,就只會畫出線條。

Combine

如果已經有 150 個單字 wav以及 TextGrid,可同時將 150 個 wav 讀取進來,然後用 Combine -> Concatenate recoverably 將 150 個單字及 TextGrid 合併為一個檔案以及一個 TextGrid。

共振峰

ref:

共振峰 wiki

什麼是共振峰?

12-1 共振峰

共振峰(formant)是用來描述聲學共振現象的一種概念,在語音學中,描述的是人類聲道中的共振情形。常用的量測方法是由頻譜分析或聲譜圖(spectrogram)中,尋找頻譜中的峰值。

人類說話或唱歌產生的聲音包含許多不同的頻率,共振峰是這些頻率中較有意義的部分。定義上,人類若想分辨幾個不同的元音,我們所需要的資訊是完全可以被量化的。共振峰是使聽者能夠區分元音的關鍵泛音。大部份的這些共振峰是由管內或腔體的共振產生,但是有些哨音是由文丘裡效應中的低壓區域週期性回縮產生。

頻率最低的共振峰頻率稱為 f1,第二低的是 f2,而第三低的是 f3(基頻一般以 f0 標示)。絕大多部分的情形是,前兩個共振峰,f1 和 f2 就足以劃分不同元音。這兩個共振峰可以描述元音的開/閉、前/後兩個維度(過去傳統上把這和舌頭的位置聯結在一起,不過這並不完全精確)。因此開元音如 [a] 有比較高的第一共振峰頻率f1,而閉元音如 [i u] 的則比較低;前元音如 [i] 的第二共振峰頻率 f2 較高,後元音如 [u] 的則比較低。元音幾乎都有四個以上的共振峰,有時還會超過六個。然而,前兩個共振峰還是最關鍵的。通常我們會用第一共振峰對第二共振峰的 關係圖描述不同元音的性質。但這不足以描述某些元音的性質,例如圓唇與否。圓唇會降低 f3,該效果對高前元音最明顯。


"音高比較低的共振峰是第一共振峰,另一個就是第二共振峰"

元音,或稱母音,是音素的一種,與輔音相對。元音是在發音過程中由氣流通過口腔而不受阻礙發出的音。

輔音,或稱子音,在調音語音學中是語音的一類,與元音相對,發音的調音環節中氣流在調音器官某一部分受到完全或部分阻礙。

英語的「元音」和「輔音」分別相當於漢語拼音裡的「韻母」和「聲母」。單元音可比對單韻母、雙元音相當於複韻母。


聲音可分為 periodic 與 aperiodic ,就是有沒有週期性的差異

人類語言,不管是元音還是輔音,都要有一個音源(source)。

元音的音源來自聲帶,一班是 almost periodic,輔音的音源一半來自 constriction (ex: s ),由此產生 aperiodic 的 noise

periodic 的音分為兩種:簡單(ex: 正弦波)、複雜

元音的音源一般都是複雜的,也就是可以分解成好幾個簡單的波

有好幾個 components 組成的波,經過數學分解後,可產生多個 harmonic 諧波 (spectrum)

在很多 harmonics 諧波中,第一個稱為基頻,也就是 F0 (0號共振峰、1號諧波),其他的都是基頻的整數倍 (H1,H2,H3)

ex: F0/H1=100Hz, F2/H1=200Hz, F3/H1=300Hz


語音學中,要強調一件事情,可以在兩件事情中間,加上一小段停頓。


頻譜圖(Spectrum) 就是描述在某一時間點上,各個頻率的聲音分佈情況。頻譜圖只能描述某一時間點,不能表達一段時間的情況,所以把頻譜連續的畫到一張圖裡,就有了聲譜圖 (Spectrogram)。

Pitch listing and plotting in Excel

  1. 選取一個音檔,只顯示 Spectrum, Pitch,把 Intensity, Formant 關掉。畫面上是 spectrum 跟藍色線條 Pitch
  2. 選取某一個聲音區塊,點下面的 "sel" 放大該區塊的畫面

  1. 如果發現突然有一個點特別高,還有最前面,沒有聲音,但是卻有 pitch 點,都可能是 praat 誤判。最後輸出時,可將該點刪除,改用前後兩點的平均作為該點的值(內插法)。
  2. 選取畫面上需要的聲音區塊,點 Pitch -> Pitch listing,會列出每10ms 的 F0_Hz

  1. 將兩段語音的 pitching listing,複製到 excel 畫出折線圖


另一種方法是,在 Praat Objects 右邊 "Analyse periodicity" -> "to pitch",(這邊如果已經知道該語音的)pitch 上下界限,可以調整設定。然後 OK 產生 pitch object。然後就先標記一塊 draw area(藍色框框),就能 Draw 到 picture。

Duration Manipulation

在不影響前後的聲音的條件下,先決定想要調整的 duration 聲音區塊,然後在前後一點點時間點,設定一塊處理語音的限制區間,修改 duration。

  1. 在 Praat Objects 右邊的 Manipulate -> To Manipulate,用預設值,點 OK

  2. 先選取要處理 duration 的聲音區塊

  3. 首先放大到聲音區間的開始點。將 cursor 點到想要處理的起點。在選單 Dur -> Add duration point at cursor,畫面上就會產生一個紅點。然後再 Add duration point at...,將 小數點第三位由 3 改為 2。畫面上會出現另一個綠色點

  1. 用相同的步驟,到聲音區塊的終點。增加兩個 duration point

  2. 回到 Praat Objects 畫面,點 Extract duration tier,就會出現一個新的 duration tier object

  3. Save -> Save as text file,存成一個 text file

  4. 用 text editor 打開該檔案 (test2.DurationTier),可看到四個點。第 1,4 兩點不動,

    File type = "ooTextFile"
    Object class = "DurationTier"
    
    xmin = 0 
    xmax = 1.8870625 
    points: size = 4 
    points [1]:
        number = 0.38218997211642386 
        value = 1 
    points [2]:
        number = 0.38318997211642386 
        value = 0.9999999999999996 
    points [3]:
        number = 0.49353125000000003 
        value = 0.9999999999999996 
    points [4]:
        number = 0.49453125000000003 
        value = 1 
    

    把中間兩點的 value 改為 1.5 倍,修改時必須放大為一樣的倍數

    File type = "ooTextFile"
    Object class = "DurationTier"
    
    xmin = 0 
    xmax = 1.8870625 
    points: size = 4 
    points [1]:
        number = 0.38218997211642386 
        value = 1 
    points [2]:
        number = 0.38318997211642386 
        value = 1.5
    points [3]:
        number = 0.49353125000000003 
        value = 1.5
    points [4]:
        number = 0.49453125000000003 
        value = 1 
    

    存檔後

  5. 回到 Parrat Objects,刪除舊的 DurationTier, Open -> Open from file,載入修改後的 duration tier

  6. 選取 "Manupulation" 及 "Duration Tier",右邊會出現 "Replace duration tier" 按鈕

  7. View & Edit Manupulation,可看到被拉高的 duration

  1. 可實際聽聽看聲音是不是被拉長了。在 File -> Publish resynthesis。回到 Praat Object 會出現一個 "Sound fromManipulationEditor" 的聲音檔。在 Save -> Save as wav file 可存成另一個 wav file

Pitch Manipulation

  1. 在 Praat Objects 右邊的 Manipulate -> To Manipulate,用預設值,點 OK。會出現一個 Manipulation object。可先 View & Edit
  2. 可以直接拉動 pitch 的點去做調整。也可以匯出到一個 text file,直接用 text editor 修改
  3. 回到 Praat Object,點右邊的 "Extract pitch tier",會出現 PitchTier object。點上面的 Save -> Save as PitchTier spreadsheet file

  4. 用 text editor 打開會是這樣

    "ooTextFile"
    "PitchTier"
    0 1.8870625 143
    0.24353125  405.36076816599967
    0.25353124999999999 384.58128094973438
    0.26353124999999999 371.21591458911877
    0.27353125  367.63791485651495
    0.28353125000000001 368.6819886604992
    0.29353125000000002 368.89100487289591
    0.30353125000000003 367.44155207316203
    0.31353124999999998 365.30946486949387
    0.32353124999999999 362.17120060758612
    0.33353125  360.9426395082146
    0.34353125000000001 361.86527201551934
    0.35353125000000002 363.25320207521213
  5. 可直接修改後面 pitch 數值,再載入修改後的 PitchTier,然後回到 Praat Object,選取 "Manipulation" 及新的 PitchTier,"Replace pitch tier" 後,可得到修改後的 sound file

Scripting

ref:

Mietta's Scripts

praat scripts

This is a collection of Praat scripts, written, modified, or used by Will Styler

執行 praat script 就是在 praat 最上面的選單中,有個 Open praat script 的功能,選取該 script,然後上面的選單最後一個,Run 執行即可

會將 labels.txt 文字檔,填寫到 TextGrid object 的 intervals 的 label 裡面

# This script reads lines from a text file (called labels.txt and saved in the home directory)
# and adds them line by line as labels for intervals in a selected TextTier in the selected TextGrid object.
#
# You should check that the boundaries are correct before running the script.
# The script will jump over intervals labeled as "xxx". Use this marking if there are intervals that
# you will remove later.
# Hint: This tool is useful if you use the mark_pauses script before it! It is easy to check that the
# pause boundaries are in correct places, if you know what kind of content should be in the sound
# segments - e.g., read sentences.
#
# This script is distributed under the GNU General Public License.
# Mietta Lennes 25.1.2002
#
soundname$ = selected$ ("TextGrid", 1)
select TextGrid 'soundname$'
stringlength = 0
filelength = 0
firstnewline = 0
oldlabel$ = ""
newlabel$ = ""
form Label intervals in an IntervalTier from text file
comment Give the path of the text file containing the label lines:
sentence Filename /Users/zqi/Dropbox/BILD/MMN/psychopy/labels.txt
comment Which IntervalTier in the selected TextGrid do you want to label?
integer Tier_(index) 1 (= the first IntervalTier)
comment Which interval do we start labeling from?
integer Starting_interval_(index) 1 (= the first interval)
comment Do you want to overwrite old labels?
comment (Intervals previously marked with 'xxx' will be skipped despite this!)
boolean Overwrite 1
endform

if fileReadable (filename$)
numberOfIntervals = Get number of intervals... tier
if starting_interval > numberOfIntervals
exit There are not that many intervals in the IntervalTier!
endif
leftoverlength = 0
# Read the text file and put it to the string file$
file$ < 'filename$'
if file$ = ""
    exit The text file is empty.
endif
filelength = length (file$)
leftover$ = file$
# Loop through intervals from the selected interval on:
for interval from starting_interval to numberOfIntervals
oldlabel$ = Get label of interval... tier interval
if oldlabel$ <> "xxx"
# Here we read a line from the text file and put it to newlabel$:
firstnewline = index (leftover$, newline$)
newlabel$ = left$ (leftover$, (firstnewline - 1))
leftoverlength = length (leftover$)
leftover$ = right$ (leftover$, (leftoverlength - firstnewline))
# Then we check if the interval label is empty. If it is or if we decided to overwrite, 
# we add the new label we collected from the text file:
    if overwrite = 1
                Set interval text... tier interval 'newlabel$'
            elsif oldlabel$ = ""
              Set interval text... tier interval 'newlabel$'
            else 
                    exit Stopped labeling, will not overwrite old labels!
   endif
endif
endfor
else 
    exit The label text file 'filename$' does not exist where it should!
endif

限制要處理 long sound file (Open -> Open long sound file)

處理一個已經有 interval labels 的 sound file,將每個 textgrid 作為檔名,分割成多個 wav,可加上檔名的 prefix/suffix。通常如果是有多個人講的同一段文字,在存檔時,會將每個人的 id number 放在檔名 suffix,這樣就可以針對同一個單字,同時聽多個人的 wav,做分析判斷。

# This script saves each interval in the selected IntervalTier of a TextGrid to a separate WAV sound file.
# The source sound must be a LongSound object, and both the TextGrid and 
# the LongSound must have identical names and they have to be selected 
# before running the script.
# Files are named with the corresponding interval labels (plus a running index number when necessary).
#
# NOTE: You have to take care yourself that the interval labels do not contain forbidden characters!!!!
# 
# This script is distributed under the GNU General Public License.
# 8.3.2002 Mietta Lennes
#

form Save intervals to small WAV sound files
    comment Which IntervalTier in this TextGrid would you like to process?
    integer Tier 1
    comment Starting and ending at which interval? 
    integer Start_from 1
    integer End_at_(0=last) 0
    boolean Exclude_empty_labels 1
    boolean Exclude_intervals_labeled_as_xxx 1
    boolean Exclude_intervals_starting_with_dot_(.) 1
    comment Give a small margin for the files if you like:
    positive Margin_(seconds) 0.01
    comment Give the folder where to save the sound files:
    sentence Folder /Users/lennes/Demo/save_labeled_intervals/exported/
    comment Give an optional prefix for all filenames:
    sentence Prefix Test_
    comment Give an optional suffix for all filenames (.wav will be added anyway):
    sentence Suffix 
endform

gridname$ = selected$ ("TextGrid", 1)
soundname$ = selected$ ("LongSound", 1)
select TextGrid 'gridname$'
numberOfIntervals = Get number of intervals... tier
if start_from > numberOfIntervals
    exit There are not that many intervals in the IntervalTier!
endif
if end_at > numberOfIntervals
    end_at = numberOfIntervals
endif
if end_at = 0
    end_at = numberOfIntervals
endif

# Default values for variables
files = 0
intervalstart = 0
intervalend = 0
interval = 1
intname$ = ""
intervalfile$ = ""
endoffile = Get finishing time

# ask if the user wants to go through with saving all the files:
for interval from start_from to end_at
    xxx$ = Get label of interval... tier interval
    check = 0
    if xxx$ = "xxx" and exclude_intervals_labeled_as_xxx = 1
        check = 1
    endif
    if xxx$ = "" and exclude_empty_labels = 1
        check = 1
    endif
    if left$ (xxx$,1) = "." and exclude_intervals_starting_with_dot = 1
        check = 1
    endif
    if check = 0
       files = files + 1
    endif
endfor
interval = 1
pause 'files' sound files will be saved. Continue?

# Loop through all intervals in the selected tier of the TextGrid
for interval from start_from to end_at
    select TextGrid 'gridname$'
    intname$ = ""
    intname$ = Get label of interval... tier interval
    check = 0
    if intname$ = "xxx" and exclude_intervals_labeled_as_xxx = 1
        check = 1
    endif
    if intname$ = "" and exclude_empty_labels = 1
        check = 1
    endif
    if left$ (intname$,1) = "." and exclude_intervals_starting_with_dot = 1
        check = 1
    endif
    if check = 0
        intervalstart = Get starting point... tier interval
            if intervalstart > margin
                intervalstart = intervalstart - margin
            else
                intervalstart = 0
            endif
    
        intervalend = Get end point... tier interval
            if intervalend < endoffile - margin
                intervalend = intervalend + margin
            else
                intervalend = endoffile
            endif
    
        select LongSound 'soundname$'
        Extract part... intervalstart intervalend no
        filename$ = intname$
        intervalfile$ = "'folder$'" + "'prefix$'" + "'filename$'" + "'suffix$'" + ".wav"
        indexnumber = 0
        while fileReadable (intervalfile$)
            indexnumber = indexnumber + 1
            intervalfile$ = "'folder$'" + "'prefix$'" + "'filename$'" + "'suffix$''indexnumber'" + ".wav"
        endwhile
        Write to WAV file... 'intervalfile$'
        Remove
    endif
endfor
  • VOT (Voice onset time) tier

發聲起始時間(英語:Voice onset time,簡稱VOT),或譯為嗓音起始時間、濁音起始時間、聲帶震動起始時間、濁聲初起時、初濁。VOT的具體含義不完全與字面吻合,實際指某一輔音從除阻的一刻到聲帶開始震動,中間所經過的時間。

從 release -> 到 onset 所經過的時間

calculatesegmentdurations.praat

# This script will calculate the durations of all labeled segments in a TextGrid object.
# The results will be save in a text file, each line containing the label text and the 
# duration of the corresponding segment..
# A TextGrid object needs to be selected in the Object list.
#
# This script is distributed under the GNU General Public License.
# 12.3.2002 Mietta Lennes

# ask the user for the tier number
form Calculate durations of labeled segments
    comment Which tier of the TextGrid object would you like to analyse?
    integer Tier 1
    comment Where do you want to save the results?
    text textfile durations.txt
endform

# check how many intervals there are in the selected tier:
numberOfIntervals = Get number of intervals... tier

# loop through all the intervals
for interval from 1 to numberOfIntervals
    label$ = Get label of interval... tier interval
    # if the interval has some text as a label, then calculate the duration.
    if label$ <> ""
        start = Get starting point... tier interval
        end = Get end point... tier interval
        duration = end - start
        # append the label and the duration to the end of the text file, separated with a tab:      
        resultline$ = "'label$' 'duration''newline$'"
        fileappend "'textfile$'" 'resultline$'
    endif
endfor

Automatically open each .wav file in a folder, manually label intervals and rectify vocal pulse markings

References

PRAAT 使用手冊

praat wiki

結合Praat進行語音實驗的步驟

以Praat 語言分析軟體應用於華語語音教學法初探

[Phonetics] Praat的下載、教學、plug-in、script

熊子瑜「XIONG Ziyu」語音與言語科學重點實驗室

praat 語音軟體操作手冊

Lec15 Praat ─ 進階版

NCTU OCW 外國語文學系 賴郁雯老師 發音概論 The art of articulation

音色與聲譜圖

沒有留言:

張貼留言