#By XIONG Ziyu #last modify: 2022/01/03 #Praat version: 6.1.05 #功能:针对不同发音人的音高数据进行时长和频率的规整处理,并将二者放在一起作图, # 以便于比较二者的异同,还可计算规整后的音高相关系数以及二者之间的残差等数据; #参数说明: # PitchTier_Filename_Of_Speaker_A:发音人A的某个音高数据文件(*.PitchTier),作为基准数据; # TextGrid_Filename_Of_Speaker_A: 与上一文件相关联的标注文件(*.TextGrid),用于获取音节时间信息; # PitchTier_Filename_Of_Speaker_B:发音人B对应的音高数据文件(*.PitchTier),用于规整处理; # TextGrid_Filename_Of_Speaker_B: 与上一文件相关联的标注文件(*.TextGrid),用于获取音节时间信息; # None_Syllable_Markers:标注中的非音节性成分,其音高数据将被忽略; # Syllable_Tier_Index:标注文件中音节所在的层级; # Pitch_Mean_for_New_PitchTier:拟合的音高数据均值,如果为0,则以基准音高数据的均值为拟合均值;如果为1,则不修改基频均值。 # Pitch_Range_Factor_for_New_PitchTier:拟合的音高音域缩放系数,如果为1,则不缩放, # 如果为0,则根据发音人A的音域自动缩放,其他可自行设置,建议在0.8-1.2之间 # 缩放时,音域下限基本保持不变,通过调节音域上限实现缩放目标。 # Smooth_PitchTier:对音高数据进行平滑处理,设置相应的系数,如果为0,则不做平滑处理。 # Top_Title:图片的顶部标题内容; # Pitch_Color_For_Speaker_B:发音人B的音高数据作图颜色; # Erase_all,设置为1时则清空作图窗口中原有的内容; form 不同发音人的音高数据规整与对比 sentence PitchTier_Filename_Of_Speaker_A f:\语音库\汉语语料\f001\f001001_01.PitchTier sentence TextGrid_Filename_Of_Speaker_A f:\语音库\汉语语料\f001\f001001_01.TextGrid sentence PitchTier_Filename_Of_Speaker_B f:\语音库\汉语语料\m005\m005001_01.PitchTier sentence TextGrid_Filename_Of_Speaker_B f:\语音库\汉语语料\m005\m005001_01.TextGrid sentence None_Syllable_Markers sil;silb;silv;tl positive Syllable_Tier_Index 2 real Pitch_Mean_for_New_PitchTier_(Hz) 0 real Pitch_Range_Factor_for_New_PitchTier 0 real Smooth_PitchTier_(Hz) 12 sentence Top_Title 灰色为基准发音人 A 的音高数据,其他颜色的数据是由脚本程序基于其他发音人的音高数据自动生成的:读同一段话,先基于音节边界信息将其他发音人的音高数据与基准发音人的音高数据进行时间对齐处理,然后根据基准发音人和其他发音人的音高均值对其他发音人的音高数据进行规整,以消除二者的音阶差异,便于比较其异同 optionmenu Pitch_Color_For_Speaker_B: 2 option Black option Blue option Red option Yellow option Green boolean Erase_all 1 endform Create TextGrid: 0, 1, "Mary John bell", "bell" select all Remove Text reading preferences: "UTF-8" Text writing preferences: "UTF-8" colorList1$="black" colorList2$="blue" colorList3$="red" colorList4$="yellow" colorList5$="green" if none_Syllable_Markers$!="" none_Syllable_Markers$=replace$(none_Syllable_Markers$,",",";",0) none_Syllable_Markers$=replace$(none_Syllable_Markers$," ",";",0) none_Syllable_Markers$=replace$(none_Syllable_Markers$,",",";",0) none_Syllable_Markers$=replace$(none_Syllable_Markers$,";",";",0) none_Syllable_Markers$=replace$(none_Syllable_Markers$,"、",";",0) endif none_Syllable_Markers$=";"+none_Syllable_Markers$+";" pitchTier_A$=pitchTier_Filename_Of_Speaker_A$ pitchTier_A$=replace$(pitchTier_A$,"/","\",0) pitchTier_B$=pitchTier_Filename_Of_Speaker_B$ pitchTier_B$=replace$(pitchTier_B$,"/","\",0) textGrid_A$=textGrid_Filename_Of_Speaker_A$ textGrid_A$=replace$(textGrid_A$,"/","\",0) textGrid_B$=textGrid_Filename_Of_Speaker_B$ textGrid_B$=replace$(textGrid_B$,"/","\",0) Read from file: "'pitchTier_A$'" adur=Get total duration Rename: "A" Create TextGrid: 0, 'adur', "SYLLABLE", "" Rename: "A" Read from file: "'textGrid_A$'" Rename: "TEMP" aNums=Get number of intervals: 'syllable_Tier_Index' preTime=0 for i from 1 to aNums selectObject: "TextGrid TEMP" st=Get start time of interval: 'syllable_Tier_Index', 'i' et=Get end time of interval: 'syllable_Tier_Index', 'i' lab$=Get label of interval: 'syllable_Tier_Index', 'i' if index(none_Syllable_Markers$,";"+lab$+";")=0 and lab$!="" selectObject: "TextGrid A" if st>preTime and stpreTime and stpreTime and stpreTime and st0 Formula: "10^(log10(self/opMin_B)*pRangefactor)*opMin_B" endif rpMean_B=Get mean (points): 0, 0 rpStdv_B=Get standard deviation (points): 0, 0 pMean_B=rpMean_B pStdv_B=rpStdv_B rpNums_B=Get number of points To Pitch: 0.01, 60, 600 rpMin_B=Get minimum: 0, 0, "Hertz", "Parabolic" rpMax_B=Get maximum: 0, 0, "Hertz", "Parabolic" rpRange_B=12*log10(rpMax_B/rpMin_B)/log10(2) rdur=Get total duration Remove selectObject: "TextGrid A" aNums=Get number of intervals: 1 for i from 1 to aNums ost'i'=Get start time of interval: 1, 'i' oet'i'=Get end time of interval: 1, 'i' lab$=Get label of interval: 1, 'i' osd'i'$="" while index("0123456789 ",right$(lab$,1))>0 and lab$!="" if index("0123456789",right$(lab$,1))>0 osd'i'$=right$(lab$,1) endif lab$=left$(lab$,length(lab$)-1) endwhile if right$(lab$,1)="r" and lab$!="er" lab$=left$(lab$,length(lab$)-1) endif olab'i'$=lab$ endfor if pitch_Mean_for_New_PitchTier>0 pMean_A=pitch_Mean_for_New_PitchTier endif if pitch_Mean_for_New_PitchTier=1 pMean_A=pMean_B endif Create PitchTier: "B2A", 0, 'adur' syl=0 selectObject: "TextGrid B" nNums=Get number of intervals: 1 for i from 1 to nNums selectObject: "TextGrid B" nst'i'=Get start time of interval: 1, 'i' net'i'=Get end time of interval: 1, 'i' lab$=Get label of interval: 1, 'i' while index("0123456789 ",right$(lab$,1))>0 and lab$!="" lab$=left$(lab$,length(lab$)-1) endwhile if right$(lab$,1)="r" and lab$!="er" lab$=left$(lab$,length(lab$)-1) endif nlab'i'$=lab$ selectObject: "PitchTier B" st=nst'i' et=net'i' spos=Get high index from time: 'st' epos=Get low index from time: 'et' cpos=0 if epos>=spos and nlab'i'$!="" k=0 for j from syl+1 to aNums if olab'j'$=nlab'i'$ syl=j cpos=j j=999999 endif k=k+1 if k>4 j=999999 endif endfor endif if cpos>0 for k from spos to epos selectObject: "PitchTier B" v=Get value at index: 'k' t=Get time from index: 'k' ct=(t-st)/(et-st) cst=ost'cpos' cet=oet'cpos' t=cst+(cet-cst)*ct selectObject: "PitchTier B2A" v=10^(log10(v/pMean_B))*pMean_A Add point: 't', 'v:1' endfor endif endfor selectObject: "PitchTier B2A" npMean_B=Get mean (points): 0, 0 npStdv_B=Get standard deviation (points): 0, 0 ndur=Get total duration npNums_B=Get number of points To Pitch: 0.01, 60, 600 npMin_B=Get minimum: 0, 0, "Hertz", "Parabolic" npMax_B=Get maximum: 0, 0, "Hertz", "Parabolic" npRange_B=12*log10(npMax_B/npMin_B)/log10(2) if smooth_PitchTier>0 selectObject: "PitchTier B2A" Remove selectObject: "Pitch B2A" Smooth: 'smooth_PitchTier' Down to PitchTier Rename: "TMP" Create PitchTier: "B2A", 0, 'adur' selectObject: "PitchTier A" for i from 1 to opNums_A selectObject: "PitchTier A" t=Get time from index: 'i' selectObject: "PitchTier TMP" v=Get value at time: 't' selectObject: "PitchTier B2A" Add point: 't', 'v:1' endfor selectObject: "Pitch B2A" plusObject: "Pitch B2A" plusObject: "PitchTier TMP" Remove endif selectObject: "PitchTier B2A" spMean_B=Get mean (points): 0, 0 spStdv_B=Get standard deviation (points): 0, 0 sdur=Get total duration spNums_B=Get number of points To Pitch: 0.01, 60, 600 spMin_B=Get minimum: 0, 0, "Hertz", "Parabolic" spMax_B=Get maximum: 0, 0, "Hertz", "Parabolic" spRange_B=12*log10(spMax_B/spMin_B)/log10(2) Remove Create Table with column names: "TMP", 0, "TIME_A SYLLABLE Pitch_A Pitch_B" selectObject: "PitchTier A" pNums=Get number of points cMax=0 cMin=10000 syl=1 rNum=0 diff=0 for p from 1 to pNums selectObject: "PitchTier A" v=Get value at index: 'p' t=Get time from index: 'p' selectObject: "PitchTier B2A" n=Get value at time: 't' cpos=0 syll$="" for j from syl to aNums if t>ost'j' and t<=oet'j' and cpos=0 syl=j cpos=j j=999999 endif endfor if cpos>0 syll$=olab'cpos'$+osd'cpos'$ endif if syll$!="" diff=diff+(n-v)^2 selectObject: "Table TMP" Append row rNum=rNum+1 Set numeric value: 'rNum', "TIME_A", 't:3' Set numeric value: 'rNum', "Pitch_A", 'v:1' Set numeric value: 'rNum', "Pitch_B", 'n:1' Set string value: 'rNum', "SYLLABLE", "'syll$'" if cMaxv cMin=v endif if cMin>n cMin=n endif endif endfor diff=(diff/(rNum-1))^0.5 res$=Report correlation (Pearson r): "Pitch_A", "Pitch_B", 0.025 corr=extractNumber(res$,"=") cMax=round(cMax)+10 cMin=round(cMin)-10 sfn$=pitchTier_B$ sfn$=left$(pitchTier_B$,rindex(pitchTier_B$,".")-1) sfn$=right$(sfn$,length(sfn$)-rindex(sfn$,"\")) sfn$=left$(pitchTier_A$,rindex(pitchTier_A$,".")-1)+"-"+sfn$+"('pitch_Mean_for_New_PitchTier'-'pitch_Range_Factor_for_New_PitchTier'-'smooth_PitchTier').txt" selectObject: "Table TMP" Save as tab-separated file: "'sfn$'" txt$="'newline$'" txt$=txt$+"发音人A的Pitch数据文件:'newline$''pitchTier_A$''newline$'" txt$=txt$+"发音人A的TextGrid数据文件:'newline$''textGrid_A$''newline$'" txt$=txt$+"发音人B的Pitch数据文件:'newline$''pitchTier_B$''newline$'" txt$=txt$+"发音人B的TextGrid数据文件:'newline$''textGrid_B$''newline$'" txt$=txt$+"TextGrid数据文件中的音节层级为:'syllable_Tier_Index''newline$'" txt$=txt$+"TextGrid数据文件中被剔除出的标注有:'none_Syllable_Markers$''newline$'" txt$=txt$+"'newline$'基础数据如下:'newline$'" txt$=txt$+"发音人A的文件时长为:'adur:3'秒'newline$'" txt$=txt$+"发音人A的音高点数为:'opNums_A'个'newline$'" txt$=txt$+"发音人A的音高均值为:'opMean_A:1'Hz'newline$'" txt$=txt$+"发音人A的音高标准差为:'opStdv_A:1'Hz'newline$'" txt$=txt$+"发音人A的音高最大值为:'opMax_A:1'Hz'newline$'" txt$=txt$+"发音人A的音高最小值为:'opMin_A:1'Hz'newline$'" txt$=txt$+"发音人A的音域范围为:'opRange_A:1'St'newline$''newline$'" txt$=txt$+"发音人B的文件时长为:'bdur:3'秒'newline$'" txt$=txt$+"发音人B的音高点数为:'opNums_B'个'newline$'" txt$=txt$+"发音人B的音高均值(原)为:'opMean_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高标准差(原)为:'opStdv_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最大值(原)为:'opMax_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最小值(原)为:'opMin_B:1'Hz'newline$'" txt$=txt$+"发音人B的音域范围(原)为:'opRange_B:1'St'newline$''newline$'" txt$=txt$+"音高范围修改系数为:'pRangefactor:3''newline$'" txt$=txt$+"发音人B的文件时长(修改音域后)为:'rdur:3'秒'newline$'" txt$=txt$+"发音人B的音高点数(修改音域后)为:'rpNums_B'个'newline$'" txt$=txt$+"发音人B的音高均值(修改音域后)为:'rpMean_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高标准差(修改音域后)为:'rpStdv_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最大值(修改音域后)为:'rpMax_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最小值(修改音域后)为:'rpMin_B:1'Hz'newline$'" txt$=txt$+"发音人B的音域范围(修改音域后)为:'rpRange_B:1'St'newline$''newline$'" txt$=txt$+"目标音高均值为:'pMean_A:1'Hz'newline$'" txt$=txt$+"发音人B的文件时长(修改均值后)为:'ndur:3'秒'newline$'" txt$=txt$+"发音人B的音高点数(修改均值后)为:'npNums_B'个'newline$'" txt$=txt$+"发音人B的音高均值(修改均值后)为:'npMean_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高标准差(修改均值后)为:'npStdv_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最大值(修改均值后)为:'npMax_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最小值(修改均值后)为:'npMin_B:1'Hz'newline$'" txt$=txt$+"发音人B的音域范围(修改均值后)为:'npRange_B:1'St'newline$''newline$'" txt$=txt$+"音高平滑阈值:'smooth_PitchTier:1'Hz'newline$'" txt$=txt$+"发音人B的文件时长(平滑后)为:'sdur:3'秒'newline$'" txt$=txt$+"发音人B的音高点数(平滑后)为:'spNums_B'个'newline$'" txt$=txt$+"发音人B的音高均值(平滑后)为:'spMean_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高标准差(平滑后)为:'spStdv_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最大值(平滑后)为:'spMax_B:1'Hz'newline$'" txt$=txt$+"发音人B的音高最小值(平滑后)为:'spMin_B:1'Hz'newline$'" txt$=txt$+"发音人B的音域范围(平滑后)为:'spRange_B:1'St'newline$''newline$'" txt$=txt$+"发音人A和发音人B的音高数据(规整后)相关系数为:'corr:3''newline$'" txt$=txt$+"发音人A和发音人B的各点音高数据(规整后)残差为:'diff:1'Hz'newline$'" echo 'txt$' info$=txt$ wid=adur*3.6 Select outer viewport: 0, 'wid', 0, 2.5 if erase_all=1 Erase all selectObject: "PitchTier A" Grey Speckle size: 3 Draw: 0, 0, 'cMin', 'cMax', "yes", "lines and speckles" endif Speckle size: 2 Colour: colorList'pitch_Color_For_Speaker_B'$ selectObject: "PitchTier B2A" Draw: 0, 0, 'cMin', 'cMax', "yes", "lines and speckles" if erase_all=1 Black Select outer viewport: 0, 'wid', 0, 3 Axes: 0, 1, 0, 1 Paint rectangle: "white", 0, 1, 0, 0.15 selectObject: "TextGrid A" Draw: 0, 0, "no", "no", "no" Select outer viewport: 0, 'wid', 0, 3 Axes: 0, 1, 0, 1 if top_Title$!="" txt$=top_Title$ txt$=replace$(txt$,"\","/",0) txt$=replace$(txt$,"_","-",0) Text top: "no", "'txt$'" endif endif Select outer viewport: 0, 'wid', 0, 3 png$=sfn$-".txt"+".png" Save as 300-dpi PNG file: "'png$'" pfn$=sfn$-".txt"+".PitchTier" selectObject: "PitchTier B2A" Save as text file: "'pfn$'" ini$=sfn$-".txt"+".ini" filedelete 'ini$' fileappend "'ini$'" 'info$' exitScript: "已完成,请查阅以下数据文件:'newline$''sfn$''newline$''png$''newline$''pfn$''newline$'"