Praat脚本编程中文教程:实例讲解提取十点基频脚本

分类:Praat
 标签:Praat脚本,Praat中文教程,Praat编程
   修改 | 阅读(5796)| 评论(6)


如果本系列教程你是从头开始看的话,那么到这里相信很多人已经有了相应的基础了,但可能还有很多人看着前面的教程都是分开单个功能点进行讲解的,理解每一行代码应该没问题,但是要是真的给你一个需求,让你根据需求用学过的知识来实现,肯定很多人还是一头雾水。就像我当初开始学习编程时,老师教给你的都是基本语法,然后让你用程序实现“1+1”等于多少,复杂一点就让你实现“1、2、3、4……100”相加等于多少。心里就会很傻B地问:“写这程序有什么用?一点实质性的东西都做不出来!”。

现在,本节教程就根据一个很简单的例子来综合说明一下前面所学到的知识,整个脚本的思路是怎样的,具体到每一句是什么意思,在这一节会详细讲解。这个例子就是平时用得挺多的“提取10点基频”。

我们来看看整体的思路:

要提取十点基频,我们需要选中一段要提取的基频的音频,然后从选中的这一段音频中,从起始点到结束点,我们要平均将其分成9等份(为什么不是10等份?分成10等份,那从开始点到结束点,就会有11个点了,别说你想不明白这个,这是小学的数学了……)。然后我们就去取每一点上所对应的基频值,将其输出到输出窗口(Info窗口)中,当脚本执行完以后,我们的输出窗口中就会有10个数,就是我们提取出来的十点基频。

现在我们在整理一下上述思路中用到的东西,首先,选中一段音频,这是手动操作的,选中了之后我们要知道起始点和结束点,这个在Praat的菜单中可以看到有相应的功能,对应的菜单分别是【Query】菜单下的【Get start of selection】和【Get end of selection】。平均分成9等分,然后去取每一个点对应的基频值。平均!我们可以想到用循环,而不用对应到每一点去写一行脚本代码来提取。提取基频值,在【Pitch】菜单下的【Get pitch】。输出,我们可以使用第一篇教程中所说的所有输出语句,但值得注意的一点是writeInfowriteInfoLine的使用,如果忘了请回头看。

说到这里,不知道你们是否有思路了,如果您已经有思路了,可以自己来写一下,如果没思路,下面就给出完整的脚本代码。

start = Get start of selection
end = Get end of selection
if start=end
    exitScript: "请选中一段音频"
endif
for i from 0 to 9
   time = start + (end-start)/9*i
   Move cursor to... time
   pitch = Get pitch
   print 'pitch:0'
   if i < 9
      printtab
   endif
endfor
print 'newline$'
Select... start end

接下来,我就来给你们解释一下每一行代码的意思。

第一篇教程中,我说过:如果你要编写脚本程序,最好是用英文原版,因为你可以清楚看到每一个脚本命令怎样去写。并且让你们记住一句话:Praat大部分的脚本命令其实就是动态菜单或下拉菜单中的菜单项。

第1行:获取你选中那段音频的起始时间点,将其存入start变量中。我们为什么可以使用【Get start of selection】这个命令来获取起始时间点?就是因为在Sound窗口的【Query】菜单中有这一个菜单,所以我们在脚本中可以直接使用,这就是上面红色这句话的意思。菜单中所有的菜单项,都可以在脚本中使用。

第2行:获取你选中那段音频的结束时间点,将其存入end变量中。

第3行:if判断语句,判断起始点与结束点,如果起始点与结束点相等,就执行到第4行。

第4行:退出脚本,第3行的判断成立就执行到此,后面的脚本不会再执行。这个命令在前面没讲过,基本语法:【exitScript:"提示语句"】。在脚本中遇到这个命令后续脚本都不会再执行了。

第5行:与第3行的if语句构成完整的判断结构。

第6行:循环语句,变量i从0到9,正好10个点,也就是我们要提取的10点。这里为什么是从0开始,而不是从1开始,这是为了下面第7行的取值方便。

第7行:根据起始时间与结束时间,获取对应点的时间,将其存入time变量中。时间点的获取,起始时间+总时间(结束时间-起始时间)除以9,再乘以循环点,就是当前循环点对应的时间。比如刚开始,i=0,这时 time=start + 0,也就是当i=0时,time就等于起始点的时间,当i=1时,time=start+每一段的时间“(end-start)/9”乘于1,这就是第二个点所处的时间点,当i=2时,time=start+每一段的时间“(end-start)/9”乘于2,这就是第三个点所处的时间点……这就是在第6行时我们为什么要从0开始,如果从1开始的话,那这一行对应的就应该是(i-1),否则第一个点就会取不到值。

第8行:Move cursor to...】菜单项命令,将选中点移动到某个时间点上,后面跟上time参数,就是将选中点移动到time时间点上。

第9行:Get pitch】菜单项命令,用于获取当前选中时间点上的基频值,将其存入pitch变量中。

第10行:用print命令进行输出,后面跟上的'pitch:0',是对第9行中取得的基频值pitch进行输出,这里在pitch变量后面还有个冒号0“:0”,这是数值型的小数位数截取的,想保留多少位小数后面的数值就是多少,这里是只取整数,如果取一位小数可以这样写“'pitch:1'”,截取规则根据四舍五入。

第11-13行:如果i小于9就执行【printtab】命令。换句话说,在这个脚本里面,只有i=9时才不会执行此命令。“printtab”命令主要用于在输出窗口中打印一个制表符(tab),要这里我们要输出的每个基频值之间打印上一个制表符来分隔前后两个数。

第14行:与第6行构成完整的循环结构。

第15行:换行输出。命令“print 'newline$'”为输出一个新行。此行代码非必须,这里只是为了用户在一个音频里提取多段数据方便,下次再执行本脚本时,就会在新行继续输出数据。

第16行:Select...】菜单项命令,选中一段音频,后面跟上起始时间和结束时间。这里用于我们在提取完数据后让界面上还是选中我们之前选中的音频段。要不然就只是定位到结尾了。


好了,这次的实战代码就解释到这里,如果还有不明白的,可以直接发邮件给我。这只是做引导的一个实例,如果你有别的需求或者想法,可根据自己的想法来编写脚本,如果你想把脚本写好,那一定要进行各种尝试,单是靠看看我写的这些教程是不可能学会的。


原创作品,未经授权不可进行转载。


如您觉得本文对您有帮助,可以赞助博主一杯奶茶吗

    


【sunshine】评论于:2019-8-31 12:09:02    [回复本评论]

跪求大佬发一个共振峰提取的脚本

【sunshine】评论于:2019-8-31 12:01:38    [回复本评论]

soundN$=selected$("Sound") 显示这一行有问题,能帮我看一下吗?

这是全部:

form 对话框

positive Formant_Number_(no_more_than_5)3

boolean Create_TextGrid_(for_First_Time)0

endform

nf=formant_Number

createTextgrid=create_TextGrid

soundN$=selected$("Sound")

textGridN$=soundN$+"_Formant"

editor Sound 'soundN$'

Show analyses... yes no no yes no 10

time=Get cursor

for i from 1 to nf

f'i'=Get formant... 'i'

b'i'=Get bandwidth... 'i'

endfor

endeditor

if createTextgrid=1

if nf=5

To TextGrid... "F5 F4 F3 F2 F1" F5 F4 F3 F2 F1

endif

if nf=4

To TextGrid... "F4 F3 F2 F1" F4 F3 F2 F1

endif

if nf=3

To TextGrid... "F3 F2 F1" F3 F2 F1

endif

Rename... 'textGridN$'

endif

select TextGrid 'textGridN$'

for i from 1 to nf

fV=floor(f'i')

bV=floor(b'i')

txt$=fixed$(fV,0)+"-"+fixed$(bV,0)

Insert point... nf+1-i time 'txt$'

endfor

endif

select Sound 'soundN$'


【空间】评论于:2016-4-14 13:29:52    [回复本评论]

你好非常感谢您之前的解答,可是我这还有几个关于praat脚本的问题请教,你能给我一下您的邮箱么?如果可以的话那真是帮大忙了,万分感谢

邮箱在上面文章中有

【逍遥乐网博客】于16-04-15 10:19回复
【空间】评论于:2016-3-27 12:21:41    [回复本评论]

这个是提取声音共振峰脚本里的一段,运行的时候总说这一行出错误,能帮我看一下么?

Insert point... nf+1-i time'txt$'

下面是全部的

form 对话框

positive Formant_Number_(no_more_than_5)3

boolean Create_TextGrid_(for_First_Time)0

endform

nf=formant_Number

createTextgrid=create_TextGrid

soundN$=selected$("Sound")

textGridN$=soundN$+"_Formant"

editor Sound 'soundN$'

Show analyses... yes no no yes no 10

time=Get cursor

for i from 1 to nf

f'i'=Get formant... 'i'

b'i'=Get bandwidth... 'i'

endfor

endeditor

if createTextgrid=1

if nf=5

To TextGrid... "F5 F4 F3 F2 F1" F5 F4 F3 F2 F1

endif

if nf=4

To TextGrid... "F4 F3 F2 F1" F4 F3 F2 F1

endif

if nf=3

To TextGrid... "F3 F2 F1" F3 F2 F1

endif

Rename... 'textGridN$'

endif

select TextGrid 'textGridN$'

for i from 1 to nf

fV=floor(f'i')

bV=floor(b'i')

txt$=fixed$(fV,0)+"-"+fixed$(bV,0)

Insert point... nf+1-i time'txt$'

endfor

endif

select Sound 'soundN$'


Insert point... nf+1-i time'txt$'

改为:

Insert point... nf+1-i time 'txt$'

即在time后面加空格

【逍遥乐网博客】于16-03-27 12:44回复
您的昵称:*
QQ登录(无需注册直接登录可进行回复)
您的邮箱:(填写邮箱,如有回复可进行邮件通知)
验证码:
点击刷新