在praat脚本中寻找多个单词

时间:2017-10-22 19:14:59

标签: phonetics praat

我正在编写一个praat脚本,它将在多个文件中搜索单词列表。这就是我到目前为止所拥有的。它只放大到程序中的第一个单词,并且不会循环其余的单词。我认为这与选择的内容有关。对于$(document).on('hidden.bs.modal','#pickoptionmodal',function(e){ e.preventDefault(); $("#pickoptionmodal").remove(); }); ,仅选择文本网格,但随后在注释器中,两者都被选中。我需要脚本继续搜索每个间隔,以便也可以找到过程中的其他单词。

For i through n

编辑:根据答案,修改后的脚本。

directory$ = "directory"
listfile$ = "test.txt"

Read Strings from raw text file... 'directory$'/'listfile$'
last = Get number of strings

# loop through each file
for a from 1 to last
    listfile2$ = listfile$ - ".txt"
    select Strings 'listfile2$'
    textgrid$ = Get string... 'a'
    Read from file... 'directory$'/'textgrid$'
    object_name$ = selected$("TextGrid")

    Read from file... 'directory$'/'object_name$'.wav

    # rearrange tiers 
    select TextGrid 'object_name$'
    Duplicate tier: 3, 1, "MAU"
    Remove tier: 4
    Insert interval tier: 1, "subphone"

    # find target word
    n = Get number of intervals: 3  
    for i to n

@instance: "strikes"
@instance: "raindrops"
@instance: "and"
@instance: "rainbow"
@instance: "into"
@instance: "round"
@instance: "its"
@instance: "its"

procedure instance: .target_word$

    label$ = Get label of interval: 3, i
        if label$ == .target_word$
        index = i
        i += n

# get the start and end point of the word
startpoint = Get starting point... 3 index
endpoint = Get end point... 3 index

        select TextGrid 'object_name$'
        plus Sound 'object_name$'
        View & Edit
        editor TextGrid 'object_name$'

# annotation
Select... startpoint endpoint
Zoom to selection
pause Annotate stops then continue
Close
endeditor

        endif # if the label = target word
    endfor # for number of intervals



select TextGrid 'object_name$'
Write to text file: directory$ + "/" + object_name$ + "_editedtext.TextGrid"

select all
minus Strings 'listfile2$'
Remove

endproc

#writeInfoLine: "done!"
#select Strings 'listfile2$'
endfor # for each of the files
clearinfo
print That's it!

3 个答案:

答案 0 :(得分:3)

您编写的脚本不是非常小心缩进,所以我尝试将其格式化,以便更容易理解发生了什么。从某种意义上说,确实如此。但是,尽管如此,还是需要付出一些努力才能理解。

正如普拉特所看到的那样,这里是关于正在发生的事情的一步一步的跟进:

  1. 在第8行中,您启动了for循环:for a from 1 to last

  2. 在该循环中,在第25行,您开始第二个:for i to n

  3. 在第二个循环中,在第27行,您调用名为instance的过程。

    此时,Praat会跳到定义该过程的 last 行(因此,如果您多次定义它,则只能获得最后一行)。由于只有一个,Praat跳到第36行:procedure instance: .target_word$

  4. 在该程序中(顺便说一句,在for循环中定义,这是......不寻常)你有一个if块:if label$ == .target_word$

    < / LI>
  5. 在该块结束时,endfor递增控制变量(在本例中为i)并关闭for循环。但哪一个

    您可能希望它关闭我们输入的最后一个for循环(这就是我所做的)。但实际上,Praat似乎跟踪打开for和关闭endfor语句,并将它们垂直映射。

    我没有足够详细地查看解释器以确定完全会发生什么,但在这种情况下,结果与映射最低{{1}的结果相同(=最接近脚本底部的那个)到最高endfor,依此类推。

    (这很可能真正发生的事情(否则多个不重叠的循环不起作用),但这并不重要:重要的是 a { {1}}只关闭单个 for,无论脚本位于何处或Praat看到它。另外,这是不是< / em> endfor会发生什么。)

    无论准确的规则如何,for都会映射到我们在第2点(即第25行)输入的第二个endproc。所以我们回到那个循环的第一行(第26行)。

  6. 现在我们第二次到第27行 (这次是第二次间隔),我们再次调用endfor。我们还没到for

  7. 重复所有时间间隔,每次将@instance: "strikes"递增1(每当我们点击@instance: "raindrops"时),直到i变为endfor。这次,当我们致电i时,我们会经过n区块,然后我们再次从第5点开始到达@instance

    Praat顺从地增加控制变量(现在为if),并检查for循环开始时设置的结束条件。在这种情况下,Praat知道for循环在endfor时结束,并且从i = n + 1开始,而不是跳回到顶部,它继续前进。

    仅限现在,在完成第一个文件的所有间隔后,我们实际上是否已到达程序的结尾

  8. 程序最终结束。 Praat记得我们在第3点进入了这个程序,然后我们正在读第27行。所以,尽职尽责,它继续读取第28行,这是对同一程序的另一次调用:i == n

  9. 这里(终于!)它会死去。

    它死了,因为控制变量i = n + 1现在是@instance: "raindrops"(它变成了第7点)。这通常不会发生,因为您通常不会为已经完成的循环命中i语句。但在这种情况下我们这样做。因此,当Praat试图在n + 1间隔的TextGrid中读取间隔endfor的标签时......它抱怨说间隔号太大了。因为它是。

    你最初的问题(它只做部分工作,而不是真正死亡)我无法重现,因为在i块中你实际上手动更改了i-1的值(这是风险),if块仅在标签在TextGrid中足够早地匹配时才会被执行(足够早以便在脚本爆炸之前发生)。

  10. 您可以通过脚本结构的简化版本看到这整个混乱:

    i

    要解决此问题,您可能应该重新构建代码,使其遵循或多或少的模式:

    if

    这是非常有教育意义的。 :)

答案 1 :(得分:1)

尝试在程序init之后添加select TextGrid 'object_name$'

procedure instance: .target_word$

    select TextGrid 'object_name$'

    label$ = Get label of interval: 3, i
    if label$ == .target_word$
         index = i
         i += n

答案 2 :(得分:0)

我得到了它的工作! for循环上的manual page很有帮助。如果有人发现它有用,请参考以下代码。

cacheFirst = (request) => {
    var mycache;
    return caches.open('mycache')
        .then(cache => {
            mycache = cache;
            cache.match(request);
        })
        .then(match => match || fetch(request, {credentials: 'include'}))
        .then(response => {
            mycache.put(request, response.clone());
            return response;
        })
}

addEventListener('fetch', event => event.respondWith(cacheFirst(event.request)));