搜索

iVocaloid论坛

查看: 2889|回复: 3
打印 上一主题 下一主题

【Trick】从Octave调用Praat的方法 [复制链接]

Sleepwalking

我不是技术宅!

Lv.5-章鱼须

Rank: 5Rank: 5Rank: 5

0
9
0


UID: 111156
权限: 40
属性: 宇宙人
发帖: 201 (1精)
积分: 540
章鱼: 3
大葱: 14
茄子: 2688
注册:2012/8/18
存在感:476
跳转到指定楼层
[1L]楼主
Zleepwalking 发表于 2015/1/11 18:10:08 |只看该作者 |倒序浏览
本帖最后由 Zleepwalking 于 2015/1/11 18:11 编辑

Octave是一个很好用的数值计算软件,Matlab的绝佳替代;Praat是一个很棒的语音分析软件。在语音科学实验中我们常需要提取语音特征,并进行数值处理,然而Praat本身(Praat脚本)的数值计算不太方便,若能将两者结合会带来许多便利。这个简短的例子介绍如何从Octave调用Praat,对音频文件进行分析,并将结果返回到Octave。

假设的应用场景:我们要打开特定的语音文件,分析Pulses(PointProcess),存到vector里。
基本思想是,用system()带上参数启动Praat,执行一段事先写好的Praat脚本,分析结果输出到stdout,被Octave以字符串形式读取,再把字符串转换成向量类型。

先写出一个从打开文件到转换成PointProcess的Praat脚本:
min_freq = 75
max_freq =600
sound =do("Read fromfile...", file_name$)
pp =do("ToPointProcess (periodic, cc)...", min_freq,max_freq)
其中file_name$是一个存放文件名的字符串变量。

Praat提供了non-gui的启动方式:
praat script.praat[arguments_to_script]
其中arguments_to_script是传递给脚本的参数,在脚本中加上form,Praat会按顺序把参数赋值到form中的变量里。于是上述Praat脚本改成:

form Audio File to PointProcess
   sentence File_name
   positive Min_freq 75
   positive Max_freq 600
endform
sound =do("Readfrom file...", file_name$)
pp =do("ToPointProcess (periodic, cc)...", min_freq,max_freq)
注意form内的变量名首字母可以大写,尽管实际被声明的变量名还是小写开头的。

然后在Octave中用 system(sprintf("praat script.praat%s %f %f", filename, min_freq,max_freq))便可从Octave调用Praat,请注意filename应当是绝对路径,否则Praat无法读取文件。
接下来在脚本里用appendInfoLine把PointProcess的数据输出到stdout:
n = do("Get number of points")
for ifrom 1 ton
   t = do("Get time fromindex...", i)
   appendInfoLine: t
endfor
至此Praat脚本部分已经完成。使用如下Octave程序调用Praat并获得输出:
[status output] = system(sprintf("praatbuild_corpus/praat_psola.praat %s\
   %f %f", filename, min_freqmax_freq));
严谨起见,应当检查status以确保Praat是否执行成功,这里省略。
output是一个1*n的字符向量,将它先转换成包含若干字符串的Cell Array:
praatcell = strsplit(output)';
然后逐个转换成数值:
praatmat = zeros(rows(praatcell) - 1,1);
for i= 1:rows(praatcell)- 1
   praatmat(i) = str2num(praatcell{i, 1});
end
(似乎没有直接支持Cell Array操作的字符串转数值函数,若有更好的方法请告知我,谢谢。)

完工。

对于较多的输出,执行速度可能会受Praat解释器的牵制,故不宜在Praat脚本中出现大量循环。这种情况下建议将对象存为ShortText/Binary/CSV,然后由Octave读取。
另,不要用Parallel工具包的pararrayfun/parcellfun并行调用这段代码,经测试会卡死。若要并行化,可能的一个方法是在本地开多个Octave运行server.m,在本地组建cluster,然后连接到localhost,分配到不同的处理器核心。



知识共享许可协议 除非另有声明,本帖内容采用 署名-非商业-相同方式共享 3.0 许可协议 授权,且需注明出处,所有权利归发帖人。

使用道具 举报

Rank: 4Rank: 4

0
29
0


UID: 112484
权限: 30
属性: 不明
发帖: 142 (0精)
积分: 361
章鱼: 6
大葱: 6
茄子: 1451
注册:2012/11/3
存在感:117
[2L]沙发
lazydog 发表于 2015/1/11 20:13:00 -手机频道 |只看该作者
不明觉厉占沙发

使用道具 举报

StarBrilliant

Lv.2-鱼仔酱

Rank: 2Rank: 2

0
0
0


UID: 129091
权限: 10
属性: 両性
发帖: 25 (0精)
积分: 24
章鱼: 0
大葱: 1
茄子: 470
注册:2014/2/7
存在感:97
[3L]板凳
m13253 发表于 2015/1/13 01:12:11 |只看该作者
我现在发现 SciPy 和 NumPy 异常好用。
而且有不少 MOOC 用的 Python 而不是 Matlab 了。

所以有办法从 SciPy 调用 Praat 么?
Python 的话应该可以 FFI 挂上 Praat 的动态链接库吧。

我再去研究研究好了。

使用道具 举报

Sleepwalking

我不是技术宅!

Lv.5-章鱼须

Rank: 5Rank: 5Rank: 5

0
9
0


UID: 111156
权限: 40
属性: 宇宙人
发帖: 201 (1精)
积分: 540
章鱼: 3
大葱: 14
茄子: 2688
注册:2012/8/18
存在感:476
[4L]地板
Zleepwalking 发表于 2015/1/13 11:21:37 |只看该作者
m13253 发表于 2015/1/13 01:12
我现在发现 SciPy 和 NumPy 异常好用。
而且有不少 MOOC 用的 Python 而不是 Matlab 了。

Praat提供了非常丰富的外部调用方式,如果不太考虑效率,用和本楼同样的方法即可。
另,大概是因为历史原因,做研究大多用的还是Matlab,再加上相关领域很多现成的库都是Matlab写的(如Auditory Tool Kit, TTSBox, octave-forge),所以我用Octave比较多。

使用道具 举报

您需要登录后才可以回帖 登录 | 注册/sign up

申请友链|Archiver|iVocaloid - 自由,开放,合作,共享    | 版权持有者点击这里进行举报

GMT+8, 2025/6/7 01:31

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部