トップ   新規 一覧 単語検索   ヘルプ   最終更新のRSS

Praat のバックアップ(No.2)


2015/08/28 誤記および古い記法を一部修正しました。西川賢哉 様、ご指摘ありがとうございます。*1
2015/02/10 フォルマント解析のパラメータについて検討結果を載せました。
2013/12/11 Praat 5.3.60 に合わせて内容を新しくしました。

音声解析ソフトウェア Praat*2*3

ダウンロード

  • ここから(左上「Download Praat」)

音声ファイル読み込み&視覚化

  • まず、Praatを開く。
  • Praat Objects ウインドウで、「Open」>「Read from file...」>解析したいファイルを指定
  • Praat Objects ウインドウで、右の「View & Edit」を選択 > 波形画面が表示される
    • 「View」>「Zoom in」(もしくはCtrl+I)で拡大、「View」>「Zoom out」(もしくはCtrl+O)で縮小、ある程度拡大されれば自動的にスペクトログラム、ピッチの推定値(青線)を表示してくれます
    • 「Formant」>「Show formants」でフォルマントの推定値(赤線)も表示します
praat_edit.jpg
  • 【注】音声ファイルがモノラルの場合は波形は一つ、ステレオの場合は波形は二つ表示されますが、スペクトログラムはチャンネル1のもののみ表示されるようです。ステレオ音声のチャンネルを別々に扱いたい場合は、音声ファイルを読み込む際に「Open」>「Read separate channnels from sound file...」を選択します。「Sound (ファイル名)_ch1」と「Sound (ファイル名)_ch2」オブジェクトが Praat Objects ウインドウに表示されます。
  • 【注】ここで表示されるフォルマントやピッチ曲線は、高速で視覚化するための簡略的なアルゴリズムであるようです(マニュアルには詳細な記述なし)。そのため、ウインドウをずらしたり、ズーム率を変えるなどすると解析結果は変わります。*4正確な値を知りたい場合は、以下のフォルマント解析ピッチ解析を行なって下さい。

音声ファイルの各種情報を得る

  • 音声ファイルを読み込み、読み込んだサウンドオブジェクトを選択する。
  • Query > Get ~ を選択することで各種情報が表示される。
    • 例えばサンプリング周波数が知りたい場合は、Query > Query time sampling > Get sampling frequency

変換

サンプリング周波数を変換する

  • 音声ファイルを読み込み、右のウインドウで「Convert -」>「Resample...」>「New sampling frequency [Hz]」に変換後のサンプリング周波数を指定して「OK」
  • Praatスクリプト では、例えば以下のように書きます(16kHzに変換したい場合)。
    do ("Read from file...", "(ファイルパス)/(ファイル名).wav")
    do ("Resample...", 16000, 50)
    do ("Save as WAV file...", "(ファイルパス)/(ファイル名)_16000.wav")
  • 【注】Praat右のウインドウで「Modify」>「Override sampling frequency」を選んでも、サンプリング周波数の指定が変わるだけでリサンプルは行われないので注意してください(再生速度が伸びたり縮んだりするだけ)。
  • 【注】大きなサイズの音声ファイルのサンプリング周波数を変換しようとすると、「Out of memory」エラーが出ます。メモリーオーバーエラーが出て解析が止まってしまったとき を参照して下さい。

フォルマント解析

指定したファイルのフォルマントの値を取得する

  • 音声ファイルを読み込み、できた Sound オブジェクトを選択して、ウインドウ右から「Analyse spectrum -」>「To Formant(burg)」を選択
    • パラメータを設定して「OK」
      praat_formant.jpg
      • デフォルト値で 0.0 になっているところは、Praat が適当なパラメータを指定して解析してくれます。手動で指定したい場合は フォルマント解析(burg法)のパラメータについて を参照して下さい。
      • number of formants はフォルマント解析の精度に大きく影響します。この値が4だと、自然発話音声のF1, F2の推定値に誤りが多くなりました。5にすると誤りの値は少なくなるようです。読み上げ音声では誤りの数に大きな違いはないようです。音声の種類にかかわらず5や6を推奨します。 → 2015/02/09 Number of formants = 6 は、音声の種類によらず、4や5よりも外れ値が多くなるようです。上の記述は誤りです。誠に申し訳ありません。詳しい議論はフォルマント解析(burg法)のパラメータについてを参照して下さい。
  • 解析が終わると、Praat Objects ウインドウに Formant オブジェクトが作られます。

解析したデータの書き出し(上に続いて実行)

  • タブ区切りのテキストファイルで書き出したいとき
    • Formant オブジェクトを選択して、ウインドウ右の「Tabulate -」>「Down to Table...」> パラメータを選択して(デフォルトでも可)「OK」> Tableオブジェクトができるので、そのオブジェクトを選択して「Save」 >「Save as tab-separated file...」> 書き出し
    • 書き出されたテキストファイル(例)
      time(s)	nformants	F1(Hz)	B1(Hz)	F2(Hz)	B2(Hz)	F3(Hz) ...
      0.024682	4	1080.832	693.576	1986.333	275.479	2793.186 ...
      0.034682	5	256.895	71.533	1186.697	405.533	2104.542 ...
      0.044682	5	267.422	58.941	1115.706	444.280	2105.796 ...
      0.054682	5	284.791	90.876	1045.615	1249.046	1945.385 ...
      ...
  • Praat標準の形式*6で書き出したいとき
    • Formant オブジェクトを選択して、「Save」>「Save as text file...」> 書き出し
    • 書き出されたPraat標準の形式のテキストファイル(例)
      File type = "ooTextFile"
      Object class = "Formant 2"
      
      xmin = 0 
      xmax = 1.9681875 
      nx = 981 
      dx = 0.002 
      x1 = 0.004093749999999896 
      maxnFormants = 5 
      frame []: 
          frame [1]:
              intensity = 2.467072818385887e-07 
              nFormants = 3 
              formant []: 
                  formant [1]:
                      frequency = 1709.0579979105942 
                      bandwidth = 550.5559909690334 
                  formant [2]:
                      frequency = 2757.1904024912733 
                      bandwidth = 1506.7589741423592 
                  formant [3]:
                      frequency = 3677.525893148506 
                      bandwidth = 997.3536122646018 
          frame [2]:
          ...
  • Praat標準の形式のファイルを、単純な csv 形式に変換したいとき

フォルマント解析(burg法)のパラメータについて

  • Time step (seconds)
    連続的な分析フレームの中心と中心の間の時間。もしも2秒の長さの音声で、time step が 0.01秒であるなら、分析フレームの数は約200です。フレームの端はあまりよく測定できないので、実際の数はやや少なくなります(通常は195)。あなたが time step に 0.0 (デフォルト)を指定した場合、praat は下記の window length の長さの 25% を time step として使用します。
  • Maximum number of formants
    人のスピーチの大部分を解析するためには、各フレームについて5つのフォルマントが必要です。この値と Maximum formant の値を組み合わせて設定することが、母音と互換性のあるフォルマントの結果(すなわち、母音の高さ(F1)と母音の場所(F2))を得るための唯一の方法です。そうでないなら、Maximum number of formants は 0.5 のどのような倍数でも有り得ます。あなたは 4, 4.5, 5, 5.5, 6 などを選ぶことができます。
    • 詳しくはリンク先の Algorithm 以下を参照。
    • FAQ: Formant analysis に詳細な議論があります。*7Number of formants の値はスペクトル包絡にいくつのフォルマントがあると考えるかの値(モデルパラメータ)のようです。女性音声の第一~第三フォルマントを推定したいなら、Number of formants = 5, Maximum formant = 5500 が推奨されています。
  • Maximum formant (Hz)
  • Window length (s)
    分析ウインドウの(実効的な)長さ。praatはサイドローブが -120dB 以下のガウス的な分析ウインドウを使うので、実際の長さはこの値の2倍になります。例えば、window length が 0.025 秒であるなら、実際のガウスウインドウの長さは 0.050 秒です。このウインドウでは、(フレームの)中心の0.025秒の範囲から外れる値は 4% 以下で、その周波数分解能(-3 dB point)は 1.298 / 0.025[秒] = 51.9[Hz] であり、[Sound: To Spectrogram...] で使われる計算手法と同じです。これは、0.025秒のハミング・ウインドウの帯域幅に相当します(それは 1.303 / 0.025[秒] = 52.1[Hz] です)、しかし、そのウインドウ(他の分析プログラムで最も多く使われるウインドウです)は両側に約-42dBの3つのスペクトルの極大値をもちます。
  • Pre-emphasis from (Hz)
  • 最適な Maximum number of formants の検討
    • /a/の単独発話ファイル filea.wav を使って、 Maximum number of formants の値が 4, 5, 6 のときの F1 と F2 の値を比べてみます。
    • Praatスクリプトで解析します。
      clearinfo
      
      #wavフォルダのパス
      directory$ = "E:/Users/m-kouki/Desktop"
      #wavファイル名
      wavfile$ = "a.wav"
      
      #ファイル読み込み
      Read from file: "'directory$'/'wavfile$'"
      #拡張子を除去したファイル名(オブジェクト名)を得る
      objname$ = wavfile$ - ".wav"
      
      selectObject: "Sound 'objname$'"
      To Formant (burg): 0, 4, 5500, 0.025, 50
      Down to Table... no yes 6 no 3 yes 3 yes
      Write to table file:  "'directory$'/'objname$'_NoF4.Table"
      
      selectObject: "Sound 'objname$'"
      To Formant (burg): 0, 5, 5500, 0.025, 50
      Down to Table... no yes 6 no 3 yes 3 yes
      Write to table file:  "'directory$'/'objname$'_NoF5.Table"
      
      selectObject: "Sound 'objname$'"
      To Formant (burg): 0, 6, 5500, 0.025, 50
      Down to Table... no yes 6 no 3 yes 3 yes
      Write to table file:  "'directory$'/'objname$'_NoF6.Table"
  • a_NoF4.Table, a_NoF5.Table, a_NoF6.Table が書き出されるので、Excelでグラフ化します。filea_NoF.xls
    a_NoF.png
    • Number of Formants の値は小さいほうが、推定結果の値は安定している(外れ値が少ない)ようです。
  • 続いて、日本語話し言葉コーパスの2名の話者が発声した母音 /i/, /a/, /u/ を各100個取り出して*8、各ファイルの時間的中心点のF1, F2を取り出してプロットしてみます。
    • 音声ファイル CSJ_samplevowels.zip(リンク切れ)
    • 以下のPraatスクリプトを使います。以下は Number of fotmants = 4 の解析をしています。
    clearinfo
    #フォルダのパス
    directory$ = "E:/Users/m-kouki/Desktop/CSJ_samplevowels"
    #出力ファイル名
    output$ = "E:/Users/m-kouki/Desktop/CSJ_samplevowels_NoF4.txt"
    #Number of Formants
    number_of_formants = 4
    #フォルダ内の全ての.wav形式のファイル名を取得
    Create Strings as file list...  list 'directory$'/*.wav
    number_files = Get number of strings
    #各ファイルを順番に処理
    for i from 1 to number_files
        #今回のファイルの名前を取得
        selectObject ("Strings list")
        current_token$ = Get string... 'i'
        #拡張子を除去したファイル名(オブジェクト名)を得る
        objname$ = current_token$ - ".wav"
    
        #.wavファイルを読み込む
        do ("Read from file...", "'directory$'/'current_token$'")
        
        # 開始時間・終了時間を得る
        start_time = Get start time
        end_time = Get end time
        # 時間的中心点の時間を得る
        center_time = (end_time - start_time) / 2
        
        # フォルマント解析
        do ("To Formant (burg)...", 0.01, 'number_of_formants', 5500, 0.02, 50)
        # 時間的中心点の第一・第二フォルマントを得る
        formant_one = Get value at time: 1, center_time, "Hertz", "Linear"
        formant_two = Get value at time: 2, center_time, "Hertz", "Linear"
        # 情報ウインドウに表示する
        print 'objname$','center_time','formant_one','formant_two''newline$'
        # ファイルに出力する
        fileappend 'output$' 'objname$','center_time','formant_one','formant_two''newline$'
        
        #オブジェクトを削除する
        Remove
        selectObject ("Sound 'objname$'")
        Remove
    endfor
    selectObject ("Strings list")
    Remove
  • 得られた結果をまとめたファイル fileCSJ_samplevowels_NoF.txt を、以下のRスクリプトで視覚化*9
    library(ggplot2)
    data <- read.table("E:/Users/m-kouki/Desktop/CSJ_samplevowels_NoF.txt", header = T)
    
    ggplot(data) + geom_point(aes(x=NoF4_F1, y=NoF4_F2, color=vowel)) + 
      labs(title="Number of formants = 4") + facet_wrap( ~ speaker) + 
      xlim(0, 1500) + ylim(500, 3500)
    ggplot(data) + geom_point(aes(x=NoF5_F1, y=NoF5_F2, color=vowel)) + 
      labs(title="Number of formants = 5") + facet_wrap( ~ speaker) + 
      xlim(0, 1500) + ylim(500, 3500)
    ggplot(data) + geom_point(aes(x=NoF6_F1, y=NoF6_F2, color=vowel)) + 
      labs(title="Number of formants = 6") + facet_wrap( ~ speaker) + 
      xlim(0, 1500) + ylim(500, 3500)
    CSJ_samplevowels_NoF.png
  • /i/の推定値にかなりのばらつきがあります。音声1(和歌山大河原先生)の母音の図と比べてみてください。Number of formants = 6 のとき、最も /i/ のF2方向の外れ値が多くなっているようです。
  • Number of formants, Maximum formant の値とフォルマント解析結果
    • 以下は「二番目が」と発話された音声(女性話者)を解析した結果です。例えば「pF1 4 5500」は Number of formants = 4, Maximum formant = 5500 で解析したF1を表しています。細い線がF1、太い線がF2です。
NoFandMaxF.png
  • Number of formants = 6(ピンク)では、F2をF1に間違う例が多いようです。また、Number of formants = 4, Maximum formant = 6000(黒)では、F1をF2に間違う例があるようです(?)
  • ここで検討したパラメータの中では、Number of formants = 4 or 5, Maximum formant = 5500 が良さそうです。

ピッチ(基本周波数, F0)解析

  • 音声ファイルを読み込み、できた Sound オブジェクトを選択して、ウインドウ右から「Analyse periodicity -」>「To Pitch」を選択
    • パラメータを設定して「OK」
      praat_pitch.jpg
      • デフォルト値で 0.0 になっているところは、Praat が適当なパラメータを指定して解析してくれます。
    • ピッチ解析のパラメータの詳細は To Pitch (ac)... を参照して下さい。以下は大雑把な訳です。
      • 基底ピッチ周波数(pitch floor)はデフォルトでは 75[Hz]、この値に基づいてウインドウ長(Window length)も決まるようです(基底ピッチ周波数に相当する時間長の3倍)。具体的には、「(1/(pitch floor)) * 3 [s]」がウインドウ長になるようです。
      • ウインドウシフト長(Time step)はデフォルトでは 0.75 / (pitch floor) の値に自動設定されます。例えば、もしもピッチの底値が75Hzであるなら、0.01秒です。この例では、praatは毎秒100回ピッチの値を計算します。
  • 解析が終わると、Praat Objects ウインドウに Pitch オブジェクトが作られます。
    • データをタブ区切りで書き出すには、できた Pitch オブジェクトを選択して、「Convert -」>「Down to PitchTier」> できた PitchTier オブジェクトを選択して、「Save」>「Save as headerless spreadsheet file...」

音響インテンシティ解析

MFCC解析

  • 音声ファイルを読み込み、できた Sound オブジェクトを選択して、ウインドウ右から「Analyse spectrum -」>「To MFCC」を選択
    • パラメータを設定して「OK」
      praat_mfcc.jpg
  • 解析が終わると、Praat Objects ウインドウに MFCC オブジェクトが作られます。
    • できた MFCC オブジェクトを選択して、「Save」>「Save as text file...」を選択すると、以下のようなファイルが保存されます。
      File type = "ooTextFile"
      Object class = "MFCC 1"
      
      xmin = 0 
      xmax = 18.5298125 
      nx = 3700 
      dx = 0.005 
      x1 = 0.017406250000001008 
      fmin = 100 
      fmax = 2700 
      maximumNumberOfCoefficients = 12 
      frame []: 
          frame [1]:
              numberOfCoefficients = 12 
              c0 = 24.36560329075726 
              c []: 
                  c [1] = 82.28431789991208 
                  c [2] = -16.406116271253623 
                  c [3] = 17.948883291899406 
                  c [4] = 26.182123443407328 
                  c [5] = 1.4004139248903602 
                  c [6] = -28.63868916512294 
                  c [7] = 3.456068179796329 
                  c [8] = 10.503555237099786 
                  c [9] = 12.208769119473299 
                  c [10] = -2.552543112600171 
                  c [11] = -16.38476565418306 
                  c [12] = -6.106540020839194 
          frame [2]:
              numberOfCoefficients = 12 
              c0 = 23.3904395317179 
              c []: 
                  c [1] = 98.12248910653565 
                  c [2] = -18.160192859174146 
                  c [3] = 31.530121962755366 
      (以下略)
  • データをタブ区切りで書き出すには、できた MFCC オブジェクトを選択して、「To TableOfReal...」>「OK」を選択 > できた TableOfReal オブジェクトを選択して、「Save」>「Save as headerless spreadsheet file...」
  • ファイルの長さがウインドウ長よりある程度長くないと解析に失敗し、「shorter than window length」エラーが出ます。
    • ウインドウ長 = 0.025[s] のとき、0.050[s] のファイルでエラーが出ました。
    • ファイルの持続時間がウインドウ長の2倍「より」大きい値のときは、エラーが出ませんでした。

発話区間(無音区間)推定*12

  • 音声ファイルを読み込み、ウインドウ右の「Annotate」>「To TextGrid (Silences)...」> パラメータを設定して「OK」を押します。
    • Minimum silent interval duration[s] の値は、小さすぎると破裂音などが無音区間に判定されてしまいます。日本語話し言葉コーパス等に準拠する場合は、「0.2(200ms)」が適当ですが、この値でも促音「っ」が誤って無音区間に判定される場合があります。
    • Silence threshold[dB] の値は、背景雑音の程度によって変えます。値が小さすぎると、摩擦音や長母音が誤って無音に判定されてしまいます。値が大きすぎると、背景雑音も発話区間に判定されてしまいます。
  • TextGridオブジェクトが作られるので、結果を見たければ解析に使った Sound オブジェクトとできた TextGrid オブジェクトを両方選択して、ウインドウ右の「View & Edit」を押します。
    • 結果を書き出したければ TextGrid オブジェクトを選択して、「Save」>「Save as text file...」を押します。

Praatスクリプトの書き方

  • Praat上で手動で行った分析手順を自動化したい場合(ファイル名だけ変えて実行したいなど)は、ここ で例示したように、Paste History コマンドを使えば簡単にできます。
    • 各処理を行うためのPraatの操作方法は、Praat の Helpを参照して下さい。リンク も参照して下さい。
  • もう少し複雑な操作をしたい場合はPraatスクリプトを直接編集します。以下の説明は、全て Praat script ウインドウ(Praat Objectsウインドウで「Praat」>「New Praat script」> untitled script)での操作です。
  • 参考:Scripting (Praat 公式マニュアル)
    • 特にPraatスクリプトで使える関数については、Formulas を参照

メッセージ表示&変数操作&型変換&予約語&文字列操作

  • 2015/08/28 【注】以下で説明している、シングルクオートで囲む変数展開法は古いため、動かないかもしれません。Praatスクリプト:文字列を数値に変換、数値を文字列に変換(西川様)を参照して下さい。
  • メッセージを表示するには、untitled script ウインドウに以下を貼り付けて「Run」 > 「Run」
    print Hello World!
    • 「Praat Info」ウインドウが立ち上がり「Hello World!」と表示される。
  • 変数を操作してみる
    clearinfo
    num = 1 + 2
    print num
    print 'newline$'
    print 'num'
    • %%シングルクオートで囲まないと変数扱いにならない。
    • 改行は 'newline$'
    • 「Praat Info」ウインドウを空白にするには clearinfo を実行する
  • 文字列型と数値型*13
    • 名前の最後に「$」がついた変数は文字列として扱われます。
      clearinfo
      num1$ = "1" + "2"
      num2 = 1 + 2
      print 'num1$''newline$''num2'
    • 文字列型を数値型に変更するには、「num = 'num$'」のように書きます。
    • 数値型を文字列型に変更するには、「num$ = "'num'"」のように書きます。
  • 予約語として newline$(改行)、tab$(タブ)、shellDirectory$(ホームディレクトリ)があります。詳しくはScripting 5.1. Variablesを参照して下さい。
    clearinfo
    predefined$ = "newline$ : "+newline$+" tab$ : "+tab$+" shellDirectory$ : "+shellDirectory$
    print 'predefined$'
  • ファイル名がわかっていて拡張子を除去したい場合などは、以下のように書きます。*14
    clearinfo
    filename1$ = "R00M0036.TextGrid"
    filename2$ = filename1$ - ".TextGrid"
    print 'filename1$''newline$''filename2$''newline$'
    #ついでに、ファイル名の冒頭1文字を取得するには
    head$ = left$(filename1$,1)
    print 'head$'

ファイル入出力

  • ファイルを新規で作って文字列を書き出すには、untitled script ウインドウに以下を貼り付けて「Run」 > 「Run」(ファイルパスは適宜書き換えて下さい)
    #ファイルの新規作成(指定した文字列の書き込み)
    output$ = "Hello World!"
    output$ > C:\\Users\\miyazawa\\Desktop\\output.txt
    • ファイルのディレクトリパスを変数で指定することもできます。
      #ファイルの新規作成(ディレクトリパスを指定して書き込み)
      output$ = "Hello World!"
      directory$ = "C:\Users\miyazawa\Desktop\"
      output$ > 'directory$'output.txt
  • ファイルに文字列を追記するには、上に続けて以下を実行します。
    #追記
    fileappend "C:\\Users\\miyazawa\\Desktop\\output.txt" 'newline$''Hello World 2!!'

指定した.wavファイルのフォルマント周波数を求める

  • C:\sound フォルダのモノラル音声ファイル sound1.wav を読み込んで、フォルマント解析を行った結果を C:\sound の sound1.TextGrid に書き出したい場合、その操作のPraatスクリプトは以下のようになります。
    do ("Read from file...", "C:/sound/sound1.wav")
    selectObject ("Sound sound1")
    do ("To Formant (burg)...", 0.01, 5, 5500, 0.02, 50)
    do ("Save as text file...", "C:/sound/sound1.TextGrid")
    do ("Remove")
    selectObject ("Sound sound1")
    do ("Remove")
  • 解析した結果をタブ区切りのテキストファイルで書き出したい場合、以下のようにします。
    do ("Read from file...", "E:/Users/m-kouki/Desktop/a.wav")
    selectObject ("Sound a")
    do ("To Formant (burg)...", 0.01, 5, 5500, 0.02, 50)
    Down to Table... no yes 6 no 3 yes 3 yes
    Write to table file:  "E:/Users/m-kouki/Desktop/a.Table"
    do ("Remove")
    selectObject ("Sound a")
    do ("Remove")

指定したフォルダ内の全.wavファイルの平均ピッチ・ピッチレンジを求める*15

  • 連番のファイルを順番に解析する も参照して下さい。持続時間の短いファイルを分析対象外にしたい場合は、指定したフォルダ内の全.wavファイルのMFCCを求めてテキストファイルに出力する を参照して下さい。
    clearinfo
    
    #フォルダのパス(書き換えて下さい)
    directory$ = "C:/sound"
    
    #フォルダ内の全ての.wav形式のファイル名を取得
    Create Strings as file list...  list 'directory$'/*.wav
    number_files = Get number of strings
    #各ファイルを順番に処理
    for i from 1 to number_files
        #今回のファイルの名前を取得
        selectObject ("Strings list")
        current_token$ = Get string... 'i'
        #拡張子を除去したファイル名(オブジェクト名)を得る
        objname$ = current_token$ - ".wav"
    
        #.wavファイルを読み込む
        do ("Read from file...", "'directory$'/'current_token$'")
        do ("To Pitch...", 0.01, 75, 600)
        selectObject ("Pitch 'objname$'")
    
        # ピッチの平均値を得る
        f_mean = Get mean... 0 0 Hertz
        # ピッチの最大値を得る
        f_max = Get maximum... 0 0 Hertz Parabolic
        # ピッチの最小値を得る
        f_min = Get minimum... 0 0 Hertz Parabolic
        # ピッチレンジを求める
        f_range = f_max - f_min
    
        # 結果をinfoウインドウに出力する
        print 'directory$','current_token$','f_mean','f_range''newline$'
    
        do ("Remove")
        selectObject ("Sound 'objname$'")
        do ("Remove")
    endfor

指定したフォルダ内の全.wavファイルのMFCCを求めてテキストファイルに出力する

  • 連番のファイルを順番に解析する も参照して下さい。
  • 以下では、フレームサイズ25ms、フレームシフトサイズ1msでc1~c12を求めています。
    clearinfo
    
    #WAVファイルのフォルダパス(書き換えて下さい)
    directoryW$ = "C:/sound"
    #出力ファイルのフォルダパス(書き換えて下さい)
    directoryO$ = "E:\Users\m-kouki\Desktop\MFCCtxt"
    
    #フォルダ内の全ての.wav形式のファイル名を取得
    Create Strings as file list...  list 'directoryW$'/*.wav
    number_files = Get number of strings
    #各ファイルを順番に処理
    for i from 1 to number_files
        #今回のファイルの名前を取得
        selectObject ("Strings list")
        current_token$ = Get string... 'i'
        #拡張子を除去したファイル名(オブジェクト名)を得る
        objname$ = current_token$ - ".wav"
    
        #.wavファイルを読み込む
        do ("Read from file...", "'directoryW$'/'current_token$'")
        #このファイルの持続時間を得る
        duration = Get total duration
    
        #このファイルの持続時間がフレーム長の2倍より長いときだけ以下の処理
        if duration > 0.050
            #MFCC解析
            do ("To MFCC...", 12, 0.025, 0.001, 100, 100, 0)
            selectObject ("MFCC 'objname$'")
            #テーブルに書き出す
            do ("To TableOfReal...", "no")
            do ("Save as headerless spreadsheet file...", "'directoryO$'/'current_token$'.txt")
    
            do ("Remove")
            selectObject ("MFCC 'objname$'")
            do ("Remove")
        endif
        selectObject ("Sound 'objname$'")
        do ("Remove")
    endfor

連番のファイルを順番に解析する

  • C:\sound フォルダに入っているモノラルの音声ファイル sound1.wav sound2.wav sound3.wav を順番にフォルマントを解析して、sound1.TextGrid sound2.TextGrid sound3.TextGrid で書きだすには
  • untitled script ウインドウに以下を貼り付けて「Run >「Run」
    #フォルダのパス
    directory$ = "C:/sound"
    #1~3までループ
    for i from 1 to 3
        #「(フォルダのパス)sound(ループ番号).wav」を読み込む
        do ("Read from file...", "'directory$'/sound'i'.wav")
        # フォルマント解析
        To Formant (burg)... 0.01 5 5500 0.02 50
        #「(フォルダのパス)sound(ループ番号).wav」を書きだす
        do ("Write to text file...", "'directory$'/sound'i'.TextGrid")
        # オブジェクトを削除する
        Remove
        # Soundオブジェクト"sound'i'"を選択する
        selectObject ("Sound sound'i'")
        Remove
    endfor

特定フォルダ内の全ファイルを順番に解析する

  • C:\sound フォルダに入っている任意の数・任意の名称の .wav 形式ファイル(モノラル)を順番にフォルマント解析して、解析結果を各ファイル名に「.TextGrid」を追記した名前で書きだすには
  • untitled script ウインドウに以下を貼り付けて「Run」>「Run」
    clearinfo
    #フォルダのパス
    directory$ = "C:/sound"
    #フォルダ内の全ての.wav形式のファイル名を取得
    Create Strings as file list...  list 'directory$'/*.wav
    number_files = Get number of strings
    #各ファイルを順番に処理
    for i from 1 to number_files
        #今回のファイルの名前を取得
        selectObject ("Strings list")
        current_token$ = Get string... 'i'
        #拡張子を除去したファイル名(オブジェクト名)を得る
        objname$ = current_token$ - ".wav"
    
        #.wavファイルを読み込む
        do ("Read from file...", "'directory$'/'current_token$'")
        do ("To Formant (burg)...", 0.01, 5, 5500, 0.02, 50)
    
        #Praat標準の形式で書きだす
        do ("Save as text file...", "'directory$'/'objname$'.TextGrid")
    
        #オブジェクトを削除する
        Remove
        selectObject ("Sound 'objname$'")
        Remove
    endfor
    selectObject ("Strings list")
    Remove
  • 指定したフォルダから見て3階層下にあるフォルダの中の全ての.wavファイルに対して処理を行うには
    clearinfo
    #フォルダのパス(第一階層)
    directory_1$ = "C:/sound"
    #第一階層のフォルダ内の全てのフォルダ名を取得
    Create Strings as directory list... directoryList 'directory_1$'
    number_directries_1 = Get number of strings
    #各フォルダを順番に処理
    for i from 1 to number_directries_1
        #第二階層のフォルダ名を取得
        selectObject ("Strings directoryList")
        thisdirectory_2$ = Get string... 'i'
        directory_2$ = directory_1$+"/"+thisdirectory_2$
        print lv2: 'directory_2$''newline$'
    
        #第二階層のフォルダ内の全てのフォルダ名を取得
        Create Strings as directory list... directoryList 'directory_2$'
        number_directries_2 = Get number of strings
        #各フォルダを順番に処理
        for j from 1 to number_directries_2
            #第三階層のフォルダ名を取得
            selectObject ("Strings directoryList")
            thisdirectory_3$ = Get string... 'j'
            directory_3$ = directory_2$+"/"+thisdirectory_3$
            print lv3: 'directory_3$''newline$'
    
            #第三階層のフォルダ内の全ての.wav形式のファイル名を取得
            Create Strings as file list...  list 'directory_3$'/*.wav
            number_files = Get number of strings
            #各ファイルを順番に処理
            for l from 1 to number_files
                #今回のファイルの名前を取得
                selectObject ("Strings list")
                current_token$ = Get string... 'l'
                #.wavファイルを読み込む
                Read from file... 'directory_3$'/'current_token$'
    
                #ここで処理を記述する
    
            endfor
            selectObject ("Strings list")
            Remove
    
        endfor
        selectObject ("Strings directoryList")
        Remove
    endfor
    selectObject ("Strings directoryList")
    Remove
    • このように、大量のファイルを読み込んで処理する場合は、各オブジェクトをRemoveしておかないとメモリエラーが出てしまいます。オブジェクトの削除を参照してください。

TextGridを読み込んで、特定の要素のみを書き出す

  • ここでは例として、日本語話し言葉コーパス で提供している TextGrid を解析してみます。*16
    • 以下のサンプルファイルを使います。*17
    • これは以下のような構造になっています。
      File type = "ooTextFile"
      Object class = "TextGrid"
      (略)
      size = 4 
      item []: 
          item [1]:
              class = "IntervalTier" 
              name = "word" 
              xmin = 0 
              xmax = 1421.7640000000001 
              intervals: size = 4232 
              intervals [1]:
                  xmin = 0 
                  xmax = 7.273889 
                  text = "#" 
              intervals [2]:
                  xmin = 7.273889 
                  xmax = 7.737846 
                  text = "(F eH)" 
      (略)
          item [2]:
              class = "IntervalTier" 
              name = "seg" 
      (略)
          item [3]:
              class = "TextTier" 
              name = "break" 
      (略)
          item [4]:
              class = "TextTier" 
              name = "tone" 
      (略)
      • item数はCSJでは7ですが、このサンプルファイルでは4までです。
    • C:/sound/CSJsample.TextGrid の item[1](word層)のテキスト、開始時間、終了時間のみを取り出して、C:/sound/CSJsample.TextGrid.txt に書きだすスクリプト
      clearinfo
      directory$ = "(フォルダのパス)"
      #フォルダ内の全ての.wav形式のファイル名を取得
      Create Strings as file list...  list 'directory$'/*.wav
      number_files = Get number of strings
      #各ファイルを順番に処理
      for i from 1 to number_files
          #今回のファイルの名前を取得
          selectObject ("Strings list")
          current_token$ = Get string... 'i'
      
          #拡張子を除去したファイル名(オブジェクト名)を得る
          objname$ = current_token$ - ".wav"
      
          #.wavファイルを読み込む
          do ("Read from file...", "'directory$'/'current_token$'")
          output$ = Get total duration
      
          print 'objname$'	
          print 'output$'
          print 'newline$'
      
          #オブジェクトを削除する
          selectObject ("Sound 'objname$'")
          Remove
      endfor
      selectObject ("Strings list")
      Remove
      • 書きだすとき、「begin_time:3」と書けば小数点以下3位まで書き出します(4位で四捨五入)
      • 以下のようなタブ区切りのファイルが出力されます。
        #	0	7.274
        (F eH)	7.274	7.738
        (略)
      • 同様の処理をデータテーブルを使って行った結果はこちら
  • なお、書きだすファイルの先頭行にヘッダ情報を書き出したい場合は、上記スクリプトの for 文の直前に以下を追記します。
    # ファイルを読み込む
    do ("Read from file...", "C:/sound/CSJsample.TextGrid")
    selectObject ("TextGrid CSJsample")
    
    # 書きだすファイルを初期化
    filedelete ("C:/sound/CSJsample.TextGrid.txt")
    
    # item[1](word層)の intervals の総数(word要素の総数)を得る
    number_of_intervals = Get number of intervals... 1
    
    # intervals(各要素)を順番に処理していく
    for i from 1 to number_of_intervals
         selectObject ("TextGrid CSJsample")
         # item[1] の intervals[i] の text を得る
         interval_label$ = Get label of interval... 1 'i'
         # item[1] の intervals[i] の xmin を得る
         begin_time = Get starting point... 1 'i'
         # item[1] の intervals[i] の xmax を得る
         end_time = Get end point... 1 'i'
    
         # ファイルに書き出す
         fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''begin_time:3''tab$''end_time:3''newline$'
    endfor
    
    selectObject ("TextGrid CSJsample")
    Remove
    • 以下のようなタブ区切りのファイルが出力されます。
      word	begintime	endtime
      #	0	7.274
      (F eH)	7.274	7.738
      (略)
  • 前後の行にアクセスすることも可能です。例えば、直前の word とその開始時間、直後の word とその終了時間を書き出すには、上記のfor文を以下のように変更します。
    #ヘッダを書き出す
    header$ = "word"+tab$+"begintime"+tab$+"endtime"+newline$
    header$ > C:/sound/CSJsample.TextGrid.txt
  • 以下のようなタブ区切りのファイルが出力されます。1列目から順番に「単語名, 単語開始時間, 単語終了時間, 一つ前の単語名, 一つ前の単語の開始時間, 一つ後の単語名, 一つ後の単語の終了時間」です。
    (F eH)	7.274	7.738	#	0	(F eH)	8.214
    (F eH)	7.738	8.214	(F eH)	7.274	seNse'H	8.726
    seNse'H	8.214	8.726	(F eH)	7.738	no	8.86
    no	8.726	8.86	seNse'H	8.214	go	8.973
    (略)

TextGridを読み込んで、指定した条件の値のみを書き出す(&正規表現&文字列操作)

  • if文を使います(参考:Example: doing something to every selected Sound
    • C:/sound/CSJsample.TextGrid の item[1](word層)を解析して、「持続時間が 0.50[s] 以上の語のみ」をC:/sound/CSJsample.TextGrid.txt に書きだしたいなら、以下のように書きます。
       ()
      # intervals(各要素)を順番に処理していく ※ エラー回避のため i の開始、終了番号が変わっています
      for i from 2 to number_of_intervals - 1
           selectObject ("TextGrid CSJsample")
           # item[1] の intervals[i] の text を得る
           interval_label$ = Get label of interval... 1 'i'
           # item[1] の intervals[i] の xmin を得る
           begin_time = Get starting point... 1 'i'
           # item[1] の intervals[i] の xmax を得る
           end_time = Get end point... 1 'i'
      
           # item[1] の intervals[i-1](一つ前のword要素)の text を得る
           interval_label_preceding$ = Get label of interval... 1 i - 1
           # item[1] の intervals[i-1](一つ前のword要素)の xmin を得る
           begin_time_preceding = Get starting point... 1 i - 1
      
           # item[1] の intervals[i+1] (一つ後のword要素)の text を得る
           interval_label_following$ = Get label of interval... 1 i + 1
           # item[1] の intervals[i+1] (一つ後のword要素)の xmax を得る
           end_time_following = Get end point... 1 i + 1
      
           # ファイルに書き出す
           fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''begin_time:3''tab$''end_time:3''tab$''interval_label_preceding$''tab$''begin_time_preceding:3''tab$''interval_label_following$''tab$''end_time_following:3''newline$'
      endfor
       ()
      • 結果は以下のようになります(4列目が持続時間)
        #	0	7.274	7.274
        seNse'H	8.214	8.726	0.512
        #	10.991	11.564	0.573
        (略)
    • 複数の条件指定も可能です。0.50[秒]以上に加えて、「"#"以外の単語」のみを取り出すには、上記のif文を以下のように変更します。
      # ファイルを読み込む
      do ("Read from file...", "C:/sound/CSJsample.TextGrid")
      selectObject ("TextGrid CSJsample")
      
      # 書きだすファイルを初期化
      filedelete ("C:/sound/CSJsample.TextGrid.txt")
      # item[1](word層)の intervals の総数(word要素の総数)を得る
      number_of_intervals = Get number of intervals... 1
      # intervals(各要素)を順番に処理していく
      for i from 1 to number_of_intervals
           selectObject ("TextGrid CSJsample")
           # item[1] の intervals[i] の text を得る
           interval_label$ = Get label of interval... 1 'i'
           # item[1] の intervals[i] の xmin を得る
           begin_time = Get starting point... 1 'i'
           # item[1] の intervals[i] の xmax を得る
           end_time = Get end point... 1 'i'
      
           # 持続時間を求める
           duration = end_time - begin_time
           # 条件判断
           if duration >= 0.50
                # ファイルに書き出す
                fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''begin_time:3''tab$''end_time:3''tab$''duration:3''newline$'
           endif
      
      endfor
      selectObject ("TextGrid CSJsample")
      Remove
      • 結果は以下のようになります。
        seNse'H	8.214	8.726	0.512
  • 正規表現で抽出条件を指定することも出来ます。0.40[秒]以上に加えて、「aH,eH,iH,oH,uH」のいずれかをどこかに含む単語のみを取り出すには、if文を以下のように変更します。*18
     ()
         # 条件判断
         if duration >= 0.50 and interval_label$ != "#"
              # ファイルに書き出す
              fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''begin_time:3''tab$''end_time:3''tab$''duration:3''newline$'
         endif
     ()
    • index_regexは「第一引数で指定した文字列の中で、第二引数で指定した文字列が出現する位置を返す」関数です(Formulas 5. String functions を参照)。指定した文字列が存在しなければ0を返します。ここでは「0でないとき」という条件を指定して、出現したかどうかを判定しています。
    • 「[aeiou]H」は正規表現です*19。詳しくは Regular expressions を参照。
    • 結果は以下のようになります。
      (F eH)	7.274	7.738	0.464
      (F eH)	7.738	8.214	0.476
      kyoHdoH	11.763	12.174	0.410
  • 上記の正規表現は、必ず a, e, i, o, u に H が後続する文字列にしかマッチしません。アクセント核記号「'」を含む「e'H」のようなwordにもマッチさせたい場合は、正規表現 [aeiou]'?H を使います。ここで、"?"は「直前の文字が0個または1個」を意味していて、a, e, i, o, u と H の間に「'」があっても、なくてもマッチします。*20
    • 参考用スクリプト(by 西川賢哉 様
      #----------------------------------------------
      str$ = "kawai'H"
      clearinfo
      if index_regex(str$,"[aiueo]'?H") <> 0
          appendInfoLine: str$
      endif
      #----------------------------------------------

指定した時間区間の切り出しと解析

  • C:\sound フォルダに入っている sound1.wav を読み込んで、1.100[秒]~1.600[秒]の区間だけを取り出してフォルマントを解析して、sound1_soundpart.TextGrid で書きだすには、以下のスクリプトを実行します。*21
     ()
         # 条件判断
         if duration >= 0.40 and index_regex(interval_label$, "[aeiou]H") != 0
              # ファイルに書き出す
              fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''begin_time:3''tab$''end_time:3''tab$''duration:3''newline$'
         endif
     ()
    • 第三引数のRectangularは(おそらく)方形窓で切り出し。(≒切り出した端の平滑化処理なし)
  • C:\sound フォルダに入っている sound1.wav を読み込んで、全体のフォルマントを解析し、ファイルの時間的中心点( (終了時間 - 開始時間) / 2)のフォルマントの値を得るには、以下のスクリプトを実行します。
    clearinfo
    # ファイルを読み込む
    do ("Read from file...", "C:/sound/sound1.wav")
    selectObject ("Sound sound1")
    # 開始時間・終了時間を得る
    start_time = Get start time
    end_time = Get end time
    # 時間的中心点の時間を得る
    center_time = (end_time - start_time) / 2
    # フォルマント解析
    do ("To Formant (burg)...", 0.01, 5, 5500, 0.02, 50)
    # 時間的中心点の第一・第二フォルマントを得る
    formant_one = Get value at time: 1, center_time, "Hertz", "Linear"
    formant_two = Get value at time: 2, center_time, "Hertz", "Linear"
    # 情報ウインドウに表示する
    print 'center_time','formant_one','formant_two''newline$'
    # メモリ開放
    Remove
    selectObject ("Sound sound1")
    Remove
    • 結果は以下のようになります。
      0.11665532879818594,630.9603036852504,1192.343426813945

指定した時間を含むTier要素の抽出

  • C:\sound フォルダに入っている fileCSJsample.TextGrid を読み込んで、3.200[秒]の時点を含む item[1](word層)の intervals(word要素)のラベルと、開始・終了時間を取り出すには、以下のスクリプトを実行します。
    # ファイルを読み込む
    do ("Read from file...", "C:/sound/sound1.wav")
    selectObject ("Sound sound1")
    
    do ("Extract part...", 1.100, 1.600, "rectangular", 1, "no")
    do ("To Formant (burg)...", 0.01, 5, 5500, 0.02, 50)
    do ("Save as text file...", "C:/sound/sound1_soundpart.TextGrid")
    select all
    Remove

TextGridのTier間の照合

  • TextGridを読み込んで、特定の要素のみを書き出す と同様に「item[1](word層)の終了時間」を求めて、その時間に最も近い「item [3](brake層)」の値を出力するには*22
    # ファイルを読み込む
    do ("Read from file...", "C:/sound/CSJsample.TextGrid")
    selectObject ("TextGrid CSJsample")
    
    # 3.200[秒]の時点を含むword要素のインデックス番号を得る(第一引数はitem番号)
    word_index = Get interval at time... 1 3.200
    # そのラベルと開始・終了時間を得る(第一引数はitem番号)
    word$ = Get label of interval... 1 word_index
    begin_time = Get starting point... 1 word_index
    end_time = Get end point... 1 word_index
    
    print 'word$''newline$''begin_time''newline$''end_time'
    
    selectObject ("TextGrid CSJsample")
    Remove
    • 結果は以下のようになります。
      #	7.274	F	7.738
      (F eH)	7.738	F	7.738
      (F eH)	8.214	F	8.214
      • 2列目がword層の終了時間、新しく追記された3列目がbrake層のラベル、4列目がbrake層の終了時間

TextGridの数値の集計(フォルマント)

  • ここ で作ったフォルマント解析結果のファイル C:\sound\sound1.TextGrid を読み込んで、第二フォルマントの1.500[秒]時点の値、全体の平均値、中央値、最大値、最小値、を順番に表示するには、以下のスクリプトを実行します。*23
    # ファイルを読み込む
    do ("Read from file...", "C:/sound/CSJsample.TextGrid")
    selectObject ("TextGrid CSJsample")
    # 書きだすファイルを初期化
    filedelete ("C:/sound/CSJsample.TextGrid.txt")
    # item[1](word層)の intervals の総数(word要素の総数)を得る
    number_of_intervals = Get number of intervals... 1
    # intervals(各要素)を順番に処理していく
    for i from 1 to number_of_intervals
         selectObject ("TextGrid CSJsample")
         # item[1] の intervals[i] の text を得る
         interval_label$ = Get label of interval... 1 'i'
         # item[1] の intervals[i] の xmax を得る
         end_time = Get end point... 1 'i'
    
         # end_time と item[3](break層)の各要素の時間を比較して、最も値が近いitem[3](break層)の要素番号を取得する 
         break_index = Get nearest index from time... 3 end_time
         # item[3](break層)の break_index 番目の要素のラベルを取得する
         boundary$ = Get label of point... 3 break_index
         # item[3](break層)の break_index 番目の要素の時間を取得する
         boundary_time = Get time of point... 3 break_index
    
         # ファイルに書き出す
         fileappend "C:/sound/CSJsample.TextGrid.txt" 'interval_label$''tab$''end_time:3''tab$''boundary$''tab$''boundary_time:3''newline$'
    endfor
    
    selectObject ("TextGrid CSJsample")
    Remove
    • 各処理の引数の「0 0」に任意の開始時間、終了時間を与えることで、指定した時間区間のみの集計も可能です。
    • Formant: Get value at time... コマンドは、指定した時間と一致するフレームがなかった場合、フレームとフレームの間を補完して*24、予測値を出力します。
    • 各処理の詳細、およびその他のフォルマント型のオブジェクトに対して実行可能な操作は、公式マニュアルのFormant を参照してください。

TextGridの数値の集計(ピッチ)

  • TextGridの集計(フォルマント)と同じ要領でできるはずですが、引数の指定方法が若干違います。第一引数(上の例では「2」を指定していたところ)を除いて実行してください。
    • ピッチ型のオブジェクトに対して実行可能な操作は、公式マニュアルのPitch を参照してください。*25

データテーブルを作る

  • Praat では New > Tables > Create Table with column names... でデータテーブルを作ることができます。
    • TextGridを読み込んで、特定の要素のみを書き出す で行った「item[1](word層) のテキスト、開始時間、終了時間」をテーブルに代入して、最後に出力するには、以下のようにします。*26
      clearinfo
      # ファイルを読み込む
      do ("Read from file...", "C:/sound/sound1.TextGrid")
      # フォルマント型のTextGridであれば、以下のオブジェクトができる(selectを明示しなくても選択されている)
      selectObject ("Formant sound1")
      
      # 第二フォルマントの1.500[秒]時点の値を得る
      f_two_point = Get value at time... 2 0.150 Hertz Linear
      print 'f_two_point''newline$'
      
      # 第二フォルマントの平均値を得る
      f_two_mean = Get mean... 2 0 0 Hertz
      print 'f_two_mean''newline$'
      
      # 第二フォルマントの中央値を得る
      f_two_median = Get quantile... 2 0 0 Hertz 0.50
      print 'f_two_median''newline$'
      
      # 第二フォルマントの最大値を得る
      f_two_max = Get maximum... 2 0 0 Hertz Parabolic
      print 'f_two_max''newline$'
      
      # 第二フォルマントの最小値を得る
      f_two_min = Get minimum... 2 0 0 Hertz Parabolic
      print 'f_two_min''newline$'
      
      Remove
      • 「Create Table with column names...」の第一引数はテーブル名、第二引数は行数(この時点では行数が不明なので1とし、for文の中で「Append row」を実行しています*27)、第三引数以降は各列のラベル
      • 実行すると Praat Objectsウインドウに Tableオブジェクトができるので、選択して「Edit」を押すと以下のように表示されます。
        Praat_tablesample01.png
      • また、タブ区切りのテキストファイル word_table.txt が保存されます。

オブジェクトの削除(Remove)

  • 【注】以下はオブジェクト名を使ったやり方です。「音声コーパス屋の雑記帳」> 「Praatスクリプト:オブジェクトの選択」 および 「Praatスクリプト:オブジェクトの削除」(西川様)に、オブジェクトIDを使った新しい方法がまとめられています。
  • 大量のwavファイルを順番に処理するときなどは、オブジェクトの削除をしないとすぐメモリエラーになってしまいます。
  • Removeコマンドを使います。
    • 例:C:\sound フォルダに入っている全ての .wav 形式ファイルを順番にサンプリング周波数を16kHzに変換して、「ファイル名_16000.wav」という名前で書き出すには
      # テーブルを作る
      word_table = Create Table with column names... word_table 1 table_word_label table_begin_time table_end_time
      
      # ファイルを読み込む
      do ("Read from file...", "C:/sound/CSJsample.TextGrid")
      selectObject ("TextGrid CSJsample")
      # item[1](word層)の intervals の総数(word要素の総数)を得る
      number_of_intervals = Get number of intervals... 1
      # intervals(各要素)を順番に処理していく
      for i from 1 to number_of_intervals
           selectObject ("TextGrid CSJsample")
           # item[1] の intervals[i] の text を得る
           interval_label$ = Get label of interval... 1 'i'
           # item[1] の intervals[i] の xmin を得る
           begin_time = Get starting point... 1 'i'
           # item[1] の intervals[i] の xmax を得る
           end_time = Get end point... 1 'i'
      
           # テーブルに各要素を代入
           selectObject ("Table word_table")
           Set string value... i table_word_label 'interval_label$'
           Set string value... i table_begin_time 'begin_time'
           Set string value... i table_end_time 'end_time'
      
           # テーブルの行数を増やす
           Append row
      endfor
      selectObject ("TextGrid CSJsample")
      Remove
      
      # テーブルをタブ区切りで保存
      selectObject ("Table word_table")
      do ("Save as tab-separated file...", "C:/sound/word_table.txt")
      Remove
      • オブジェクトが作られた直後であれば、そのオブジェクトが選択されているので、ただ「Remove」をすればOK。
      • listオブジェクトであれば、オブジェクト名は「Strings list」であるので、「select Strings list」でそのオブジェクトを選択して「Remove」でOK。
    • Soundオブジェクト名は、「Sound (拡張子を除いたそのファイル名)」なので、selectでも正確なオブジェクト名を指定しなければエラーになってしまう。ここではInfoコマンドで、事前にファイル名 objectname$ を得ておいて、それをオブジェクト名に指定した。拡張子を除いたファイル名が得られるので、ファイル名のリネーム時にも便利。

音素自動ラベリング(音声認識)との連携

Tips

メモリーオーバーエラーが出て解析が止まってしまったとき

  • オブジェクトの削除 がうまくいっていない場合が多いです。Praat Objectsウインドウを開いて、「Objects:」に何かオブジェクトが残っているなら、毎回の処理でRemoveコマンドを使ってオブジェクトを削除することを検討します。
  • 仮想メモリの上限を上げる。常駐ソフトを停止させる。エクスプローラを停止させるなどで解決できるかもしれません。
  • メモリ容量の大きいPCを使うのが一番手っ取り早いようです。
  • 重たい解析(リサンプリングや、短い窓長でフォルマント解析をするなど)を行う場合は上記の対応でもどうしてもエラーが出ます。その場合は、LongSoundオブジェクトとして読み込んで(「Open」>「Open long sound file...」)、Soundオブジェクトに分割して(「Exract part...」>Time range[s]で開始・終了時間を指定*29)、別々に解析を行います。

半角括弧「(」「)」をファイル名に含む場合

  • 半角括弧のファイル名は、Praatオブジェクトに取り込まれた際にアンダーバー「_」に置き換わります。例えば「data(1).wav」を読み込むと、オブジェクト名は「data_1_.wav」になります。
  • Praatスクリプトでオブジェクト名を指定する場合、例えば以下のようにしてアンダーバーに置換する必要があります(参考:Formulas 5. String functions)。
    #フォルダのパス
    directory$ = "C:/sound/"
    #フォルダ内の全ての.wav形式のファイル名を取得
    Create Strings as file list...  list 'directory$'/*.wav
    number_files = Get number of strings
    #各ファイルを順番に処理
    for i from 1 to number_files
        #今回のファイルの名前を取得
        selectObject ("Strings list")
        current_token$ = Get string... 'i'
        #.wavファイルを読み込む
        do ("Read from file...", "'directory$'/'current_token$'")
    
        #このオブジェクトの名前を得ておく
        info$ = Info
        objectname$ = extractLine$(info$, "Object name: ")
    
        #サンプリング周波数を変換する
        Resample... 16000 50
        do ("Write to WAV file...", "'directory$'/'objectname$'_16000.wav")
        print wav: 'directory$'/'objectname$'_16000.wav'newline$'
    
        #サンプリング周波数変換後のオブジェクトを削除する
        Remove
        #サンプリング周波数変換前のオブジェクトを削除する
        selectObject ("Sound 'objectname$'")
        Remove
    endfor
    selectObject ("Strings list")
    Remove

コマンドラインで Praat を実行したいとき

  • sendpraat.exe を使う
  • sendpraatの引数としてPraatスクリプトを指定すればOK.

録音とラベリング

動画ラベリングツールとの連携

  • ELAN がPraatとの連携をサポートしている。

リンク


*1 Praatの記法については、「音声コーパス屋の雑記帳」>「Praatスクリプト:シンタクスの変遷」(西川様)に詳しくまとめられています。
*2 Copyright (C) 1992-2014 by Paul Boersma and David Weenink.
*3 北原真冬, 田嶋圭一, "言語学者の道具箱: Praatで音声を可視化する", 月刊言語, 2008年7月 - 2008年12月(全6回)(リンク切れ)にも詳細な情報があります(サポートページ参照)。
*4 田中邦佳 様に教えて頂きました。
*5 MATLABパッケージ VoiceSauce (Yen-Liang Shue, EDU, 2011) を使用しています。
*6 Formantオブジェクトを書き出したテキストファイルは、「TextGrid形式(Praatのアノテーション形式)」とは異なります。西川様、ご指摘ありがとうございました。
*7 西川賢哉 様に教えていただきました。いつも本当にありがとうございます。
*8 コーパス加工用プログラム/日本語話し言葉コーパス(CSJ)/音素の開始・終了時間を取得する を参照して下さい。
*9 R Note/音響解析データの統計解析/散布図 を参照して下さい
*10 MATLABパッケージ VoiceSauce (Yen-Liang Shue, EDU, 2011) を使用しています。
*11 山本先生、リンク情報をお教えいただき、誠にありがとうございました。
*12 西川賢哉 様、小西隆之 様に教えていただきました。
*13 西川賢哉 様に教えていただきました。
*14 Ricardo Bion 様のスクリプトを参考にさせていただきました。
*15 東大のH様にご指摘いただきました。誠にありがとうございました。
*16 日本語話し言葉コーパス:TextGridの利用方法 も参照して下さい。
*17 サンプルファイル公開に関しまして、問題があれば大変お手数ですがご指摘下さい。すぐに公開を停止いたします。
*18 西川賢哉 様に教えていただき、記述のご監修をいただきました。ありがとうございます!!
*19 [] は「その中のどれか1文字」を表します(西川さんにご指摘いただきました)
*20 西川賢哉 様にいただいたコメントを引用しています。
*21 新谷敬人 様、五十嵐陽介 様のスクリプトを参考にさせていただきました。
*22 Ricardo Bion 様のスクリプトを参考にさせていただきました。
*23 新谷敬人 様、五十嵐陽介 様のスクリプトを参考にさせていただきました。
*24 この例では引数に 'Linear' を指定しているので線形補完されます。
*25 Get maximum... や Get minimum... などはウェブマニュアルに説明がありませんが、実行することはできます。
*26 Ricardo Bion 様のスクリプトを参考にさせていただきました。
*27 列数を追加したいときは「Append column... (列のラベル名)」とします。
*28 Copyright (c) 1991-2009 京都大学 河原研究室, Copyright (c) 1997-2000 情報処理振興事業協会(IPA), Copyright (c) 2000-2005 奈良先端科学技術大学院大学 鹿野研究室, Copyright (c) 2005-2009 名古屋工業大学 Julius開発チーム
*29 Preserve timesのチェックは外しても問題ありませんが、どのような機能かは未確認 → 2014/12/07 切り出した各ファイルの最初の秒数を0から開始するか、元ファイルの開始秒数からとするかの設定とのこと、流通科学大学 山本先生に教えていただきました。誠にありがとうございました。