Peatükk 20 Praati skriptid edasijõudnutele
Siin peatükis tutvume keerukamate Praati skriptielementidega, mis ei anna kokku ühte tervikuna töötavat skripti, nagu eelmises peatükis 19, aga eelmise peatüki skripti saab siin esitatavate funktsioonidega täiendada. See peatükk sobib edasijõudnud skriptijatele. Siiski ei anna see ammendavat ülevaadet Praati rikkalikust skriptikeelest, mida iga kasutaja võib Praati enda võrdlemisi hea manuaali põhjal edasi avastada.
20.1 Tingimused ja võrratused
20.1.1 Tingimuste kombineerimine
Ühte if-endif konstruktsiooni saab kokku panna mitu tingimust:
- peab vastama kahele tingimusele
- peab vastama ühele kahest tingimusest
- peab vastama ühele, aga mitte teisele tingimusele
Tingimusi võib muidugi olla ka rohkem kui kaks ja neid saab sulgudega rühmitada:
- peab vastama ühele tingimusele või teisele kahe tingimuse kombinatsioonile
- peab vastama kahele tingimusele, millest üks on kahe alternatiiviga
Kui ühel muutujal võib olla kaks võimalikku sobivat väärtust, siis peab need eraldi tingimustena välja kirjutama:
20.1.2 Sõnaliste muutujate võrdlemine
Eelmises peatükis 19.8 on öeldud, et sõnaliste muutujate puhul saab ainult küsida, kas on võrdne (näiteks "a" = "a") või mittevõrdne ("a" <> "b"). Lisaks sellele on siiski mõningaid võimalusi veel: saab küsida, kas üks tekstistring on suurem või väiksem kui teine, aga suurust mõõdetakse tähemärkide tähestikulises järjekorras. Reeglid on sellised:
- mida kaugemal tähestikus täht asub, seda suurem (
"a" < "b"), - väiketähed on suuremad kui suurtähed (
"A" < "a"), - pikem string on suurem, kui lühemal ei ole tähestikus kaugemal paiknevat osa (
"a" < "aa"ja"a" < "ab", aga"c" > "ab"), - numbrimärgid on tähtedest väiksemad (
"1" < "a").
20.1.3 Tingimused valemis
Üldiselt tuleb Praati skriptis kõik käsud kirjutada eraldi ridadele. Väike erand on valemid, mis võivad sisaldada ka tingimusi. Üldjuhul oleks tingimus esimesel real, siis käsuread, mis tingimuse täitmise korral rakenduvad, seejärel else eraldi real, sellele järgnevad käsuread, mis rakenduvad esimese rea tingimuse mittetäitmisel (ehk muudel juhtudel), ning lõpuks rida endif, näiteks kui muutuja x väärtus on 1, siis m väärtus on 15, kõikide muude x vääruste korral on m väärtus 30:
Sellise tingimuslause saab kirjutada ka üherealise valemina:
Sellist lühikest tingimuslauset if TINGIMUS then VÄÄRTUS else VÄÄRTUS fi saab kasutada ainult ühe tingimuse ja ühe alternatiivse väärtuse korral. Siia ei saa lisada elsif tingimust. Kui tingimusi on mitu, siis peab ikkagi pikalt eraldi ridadega kirjutama, näiteks:
Ent igal juhul, kui valem sisaldab käske, siis lühemat süntaksit kasutada ei saa, sest käsk peab ikkagi alati olema omaette real. Näiteks kui tahame, et sõltuvalt i väärtusest rakendatakse kas algus- või lõpuaja leidmise käsku:
for i to 2
if i = 1
aeg_'i' = Get start time of interval: 1, 1
else
aeg_'i' = Get end time of interval: 1, 1
endif
endfor
kestus = aeg_2 - aeg_1Kuigi paljudes teistes skriptikeeltes on võimalik käske üksteise sisse istutada ja käske valemitega kombineerida, ei ole kahjuks Praati skriptikeeles see võimalik ja nt selline käsurida annab veateate:
# See annab veateate!
dur = (Get end time of interval: 1, 1) –
... (Get start time of interval: 1, 1) * 1000Seega tuleb see lahti kirjutada vähemalt kolme reaga nii, et iga käsk on eraldi real ning seejärel saame teha tehte käsu väljundiks olnud väärtustega.
20.2 Tehted arvuliste muutujatega
Märgid:
- liitmine +
- lahutamine -
- korrutamine *
- jagamine /
- astendamine ^
Kui on tarvis ruutjuurt, siis selle asemel saab astendada astmele 1/2: nt 3 ruudus ehk 3 astmel 2 on 3^2; ruutjuure saame sama märgiga: ruutjuur üheksast = 9^(1/2).81
Jagatise täisarvulise poole annab div. Jagatise jäägi annab mod. Näiteks:
20.3 Stringi funktsioonid
Siin vaatame funktsioone, millega tekstist otsinguid teha. See, kus seda Praatis praktiliselt vaja läheb, on näiteks siis, kui TextGrid’il on ühele kihile märgitud sõnad ja tahame sealt leida sõnu, mis algavad või sisaldavad mingit kindlat tähekombinatsiooni.
20.3.1 Üksühesed vastavused
Olgu meil näiteks sõna „kellanöörike“ (et oleks piisavalt pikk ja sisaldaks korduvaid tähemärgijärgnevusi), kust hakkame mingeid märgijadasid otsima, nimetame selle muutujaks a$. Siin alapeatükis on selguse mõttes esitatud käsuridade järel valge taustaga tekstikastis ka selle väljund.
Tekstiosa stringi algusest. left$("tekst", n) leiab teksti algusest n esimest tähemärki. Nt muutuja a$ vasakult kaks esimest tähemärki (kellanöörike):
## kellanöörike esimesed kaks tähte on ke
Tekstiosa stringi lõpust. Täpselt samamoodi töötab right$("tekst", n) teksti lõpust. Leiame muutuja a$ paremalt kaks esimest tähemärki (kellanöörike):
## kellanöörike viimased kaks tähte on ke
Tekstiosa stringi keskelt. Alates a$ kuuendast märgist kolm märki (kellanöörike; esimene number tähistab märki alates millest, teine number mitu märki):
## kellanöörike kuues kuni kaheksas täht on nöö
Mitmendast tähemärgist algab? Funktsioon index("abcd", "ab") otsib esimesest stringist teist stringi algust, ehk mitmendast tähemärgist see algab esimest korda. Kui teise stringiga kattuvat osa esimeses ei ole, siis on vastus 0 (aga vastus siin näites on 6):
a$ = "kellanöörike"
d$ = mid$ (a$, 6,3)
f = index (a$,d$)
appendInfoLine: "sõnas ", a$, " algab ", d$, " ", f, ". tähest"## sõnas kellanöörike algab nöö 6. tähest
Funktsioon rindex() otsib tekstis tekstiosa viimase (ehk paremalt esimese) esinemise algust (vastus on 11):
"a$ = "kellanöörike"
c$ = right$ (a$, 2)
g = rindex (a$,c$)
appendInfoLine: "sõnas ", a$, " viimane ", c$, " ", g, ". tähest"## sõnas kellanöörike viimane ke 11. tähest
Järgmised käsud startsWith ja endsWith otsivad, kas string a$ algab stringiga c$ ja lõppeb stringiga b$ (ehk siin siis kontrollib, kas algus ja lõpp on samasugused). Vastus esitatakse arvulisena, kuid on tõlgendatav tõeväärtusena ehk 1 = TÕENE, 0 = VÄÄR.
a$ = "kellanöörike"
b$ = left$ (a$, 2)
c$ = right$ (a$, 2)
h = startsWith (a$,c$)
i = endsWith (a$, b$)
if h = 1 and i = 1
appendInfoLine: a$, " algus ja lõpp on mõlemad ", c$
elsif h = 0 and i = 0
appendInfoLine: a$, " algus ja lõpp on erinevad"
endif## kellanöörike algus ja lõpp on mõlemad ke
Asendused. Funktsioon replace$(algstring$, osaMidaVahetame$, millegaVahetame$, mitmelKorral) asendab tekstis ühe või mitu tähemärki mingi muu tekstistringiga. Kui asenduste arvu tähistav viimane argument on 0, siis toimub vahetus kõigil kordadel. Kui asenduste arvuks seada näiteks 2, siis asendatakse (kuni) kaks esimest esinemisjuhtumit ja ülejäänud otsitava esinemised jäävad asendamata. Vahetame sõnas kellanöörike ühe (esimese) ke-järjendi võ-ga:
a$ = "kellanöörike"
b$ = left$ (a$, 2)
j$ = replace$ (a$, b$, "võ", 1)
appendInfoLine: j$, " on, kui 1. silp ", b$, " vahetada ära võ-ga"## võllanöörike on, kui 1. silp ke vahetada ära võ-ga
Tekstistringi (muutuja) pikkus tähemärkides. legth("tekst") annab stringi pikkuse tähemärkides:
## 12 tähte on kellanöörike kokku
20.3.2 Otsingud ja asendused regulaaravaldistega
Regulaaravaldistega saab otsingut üldistada ja painlikumaks teha. Kui sa pole varem regulaaravaldistega otseselt kokku puutunud, siis tõenäoliselt oled näiteks Windowsi failisüsteemi otsingus näinud võimalust otsida kõiki mingit tüüpi faile, nt Wordi dokumente nii, et paned otsingusse „*.docx“. See tärn tähistab seal otsingus „ükskõik milliseid tähemärke“.
Regulaaravaldisi saab kasutada paljudes erinevates programmeerimiskeeltes ja üldjoontes toimivad nad Praatis ka samamoodi nagu muudes keeltes. Mõned regulaaravaldise süntaksi elemendid:
- . (punkt) tähistab ükskõik mis sümbolit. Nt
".a"vasteteks on „ma“, „sa“, „ta“, „ka“ jne; - ? (küsimärk) tähistab eelneva sümboli kordumist null korda või üks kord. Nt
"tal?"vasteteks on „ta“ ja „tal“, aga mitte „tall“; - + (pluss) tähistab eelneva sümboli kordumist üks või enam korda. Nt
"ma+"vasteteks on „ma“ ja „maa“, aga mitte „m“; - * (tärn) tähistab eelneva sümboli kordumist null või enam korda. Nt
"sam*"vasteteks on „sa“ ja „samm“, aga ka „sammmmmmmm“, kui selline sõna peaks esinema; - {x} (loogelised sulud) tähistab eelneva sümboli kordumist x korda. Näiteks
"a{2}"vasteks on „aa“; - {x,y} tähistab eelneva sümboli kordumist x kuni y korda. Näiteks
"a{1,2}"vasteteks on „a“ ja „aa“; - [] (nurksulud) – esineb üks nurksulgudes olevatest sümbolitest, nt
"[vk]ana"vasteteks on „vana“ ja „kana“; - \ (längkriips) tõlgendab järgnevat sümbolit sümbolina, kui sama sümbol võiks muidu tähistada mingit regulaaravaldise süntaksi elementi. Seda peab kasutama siis, kui otsida näiteks foneetikakorpusest liitsõnu, sest korpuse sõnatasandi märgenduses on liitsõnapiir tähitatud plussmärgiga, nt
"keele\+teadus"82 või SAMPA transkriptsiooni /æ/ vastet {, nt sõna täna"t\{nA".83 Längkriipsu sümbol on eesti klaviatuuril klahvikombinatsioonis [AltGr] ja [+].
Tekstiosa otsing regulaaravaldisega. Käsk index_regex otsib ühest stringist teise stringi algust (samamoodi kui lihtsalt index, aga otsitavat stringi tõlgendatakse regulaaravaldise, mitte üksühese tähemärgijärjendina). Näiteks:
## 8. tähemärgist algab ö..k
Regulaaravaldisele "ö..k" vastab sõnas kellanöörike järjend alates teisest ö-st, sest punkt tähistab ühte täpsustamata tähemärki ja seega kaks punkti on kaks täpsustamata tähemärki, mille vasteks siin sõnas on siis tähemärgid r ja i.
Ja sama asi viimase kattumise kohta (mis annab sama vastuse, sest otsingule sobivat tähemärgijada esineb sõnas ainult ühe korra).
a$ = "kellanöörike"
l = rindex_regex (a$, "ö.*k")
appendInfoLine: l, ". tähest algab mingi ö.*k viimast korda"## 8. tähest algab mingi ö.*k viimast korda
Tekstiasendused regulaaravaldistega. Asendame stringis a$ alates a-st kuni i-ni, kui nende vahel on ükskõik mitu tähte, u-ga. Viimane arvuline argument tähistab seda, et kui stringis a$ oleks seda kombinatsiooni rohkem kui korra, siis mitmel juhul (vasakult lugedes) asendus tehakse, ning väärtus 0 tähendab, et kõigil kordadel.
a$ = "kellanöörike"
m$ = replace_regex$ (a$, "a.*i", "u", 0)
appendInfoLine: "'m$' on, kui sõnas 'a$' a.*i vahetada u vastu"## kelluke on, kui sõnas kellanöörike a.*i vahetada u vastu
Paneme esimesed viis tähte topelt:
a$ = "kellanöörike"
n$ = replace_regex$ (a$, ".", "&&", 5)
appendInfoLine: n$, " on esimesed 5 tähte topelt"## kkeellllaanöörike on esimesed 5 tähte topelt
20.4 Peatused ja väljumine
20.4.1 Skripti peatamine
Kui mingitel ebasobivatel tingimustel ei saa skripti edasi jooksutada (nt objektiloendis peaksid olema valitud mingid failid, mida ei ole Praatis avatud, või TextGrid’il on mingi tasandi märgendus puudu, mille olemasolu skript eeldab), saab skripti seisma panna käsuga exitScript. Nt:
# küsime 2. märgenduskihi nime
kiht2$ = Get tier name: 2
# kui see ei ole häälikud, peatame skripti
if not kiht2$ = "häälikud"
exitScript: "Teisel kihil pole häälikud!"
endif
# Kui skript ei ole katkestatud, oli kihi nimi "häälikud"
writeInfoLine: "Teise kihi nimi on häälikud."Juhul kui teise märgenduskihi nimi ei ole „häälikud“, lõppeb skript ja ette visatakse dialoogiaken sõnumiga „Teisel kihil pole häälikud!“. Kui kihte on vähemalt 2 ja 2. kihi nimi on häälikud, jookseb skript lõpuni ja infoaknasse trükitakse tekst, et 2. kihi nimi oli „häälikud“. Juhul kui aga TextGrid’il polegi 2. kihti, ei jõua skript esimesest reast kaugemale ja lõpetab veateatega.
Käsuga pauseScript saab skriptis teha pausi, et seda kas jätkata või katkestada. Ekraanile ilmub dialoogiaken, kus on nupud Continue ja Stop. Kui skriptis käsule pauseScript järgneb mingi tekst, siis see kuvatakse ka dialoogiaknasse, nt:
kiht2$ = Get tier name: 2
if not kiht2$ = "häälikud"
exitScript: "Teisel kihil pole häälikud!"
endif
pauseScript: "Kiht on olemas. Kas soovid jätkata?"
### ... muud käsudPausi on kindlasti mõistlik kasutada skripti kirjutades tsüklite puhul, mille käitumises päris kindel ei ole. Nii saab peatada skripti, kuhu on näiteks kogemata sattunud igikestev tsükkel. Saab aga ka näiteks teha pausi, et midagi vahepeal salvestada, teha objektile mõni muudatus käsitsi vms.
20.4.2 Paus dialoogiaknaga
Vahel on vaja skriptis mõnda muutujat määrata skripti keskel, aga selleks oleks vaja dialoogiakent, mille kaudu uusi väärtuseid sisestada. Peatükis 19.10 lisasime skriptile dialoogiakna form-endform konstruktsiooniga, kuid sellega saab dialoogiakent esile kutsuda ainult skripti alguses. Kui dialoogiaken peab ilmuma rohkem kui ühe korra või mitte kohe skripti alguses, saab kasutada beginPause-endPause konstruktsiooni, mis üldiselt töötab samadel põhimõtetel nagu form-endform. Näiteks saab niimoodi käsitsi kontrollida skriptiga saadud põhitooniväärtusi: skript käib tsükliga läbi TextGrid-objektil märgitud intervallid, leiab intervalli keskmise põhitooniväärtuse ning teeb pausi, visates ette dialoogiakna, kus on see põhitooniväärtus kirjas. Nüüd saab kasutaja teha lahti SoundEditor’i, kontrollida, kas põhitooniväärtus on õige, vajadusel seda korrigeerida ja skripti jooksutamist jätkata. Jätkates kirjutatakse väärtus infoaknasse.
fail$ = "minufaili"
for i to nSegm
selectObject: "TextGrid " + fail$
segm$ = Get label of interval: 1, i
alg = Get start point: 1, i
lop = Get end point: 1, i
selectObject: "Pitch " + fail$
f0_vaartus = Get mean: alg, lop, "Hertz"
beginPause: "kontrolli F0 väärtust"
comment: "kontrolli põhitooni siin segmendis"
word: "segm", segm$
positive: "f0_vaartus", f0vaartus
comment: "Jätkamiseks vajuta nuppu Edasi"
endPause: "Edasi", 1
appendInfoLine: segm$, tab$, f0_vaartus
endforPausi lõpu jaoks saab ka mitu erinevat nuppu lisada ja eri nupuvajutustele erinevad jätkamistingimused lisada. Näiteks nupud „OK“ ja „Eemalda“, nii et esimesele vajutades läheb tulemus tabelisse kirja, aga teise puhul mitte:
20.5 Tsüklid, protseduurid, hüpped
Siia alajaotusesse on pandud kokku Praati skriptielemendid, mis rikuvad skripti lineaarset kulgu.
Peatükis 19.4 oli juttu for-tsüklitest, mis kordavad tegevust kindlas ette antud vahemikus ja liiguvad edasi üheväärtuseliste sammudega. Siin tutvume tsüklitega, mis on kombineeritud tingimustega: repeat- ja while-tsüklid on pisut erineva loogikaga, aga mõlemad kordavad tsüklit seni, kuni mingid tingimused kehtivad.
Protseduurid võimaldavad samuti mingit skripti osa korrata, aga natuke lõdvemalt määratletud struktuuriga. Kui oled R-i süntaksiga tuttav, siis protseduur on nagu R-i funktsioon. Lõpuks vaatame hüppeid, mis võimaldavad vabalt skriptis edasi või tagasi liikuda.
20.5.1 repeat-tsüklid
Lisaks tsüklitele, millega saab midagi teha mingi arv kordi, on tsüklid, millega saab korrata midagi seni, kuni tulemus vastab mingitele tingimustele. Näiteks järgmine skriptike simuleerib täringuviskeid kahe täringuga. Vaatame, mitme viskega tuleb 12 silma:
visked = 0
repeat
silmad = randomInteger (1,6) + randomInteger (1,6)
visked += 1
until silmad = 12
appendInfoLine: "Mul läks ", visked, " viset, et saada 12 silma."## Mul läks 25 viset, et saada 12 silma.
Käsk randomInteger (1,6) genereerib ühe juhusliku täisarvu vahemikus 1–6. Käske korratakse seni, kuni saadakse sobiv tulemus. Muutuja visked loeb kokku, mitu korda tsüklit korratakse (enne alustamist on väärtus 0, iga kord liidetakse 1).
Praktilisem näide sellise tsükli kasutamisest oleks näiteks siis, kui TextGrid’ile on märgitud häälikute piirid ja on vaja mõõta näiteks f0 väärtust vokaali algusest, aga helilisus algab mõnel segmendil natuke hiljem või lõppeb natuke hiljem, kui on segmendi piir. Näiteks:
repeat
pohitoon = Get value at time: haalikuAlgus, "Hertz", "Linear"
haalikuAlgus += 0.001
until pohitoon <> undefinedSiin liigutakse hääliku alguspunktist ühe millisekundi võrra edasi seni, kuni põhitooni väärtus on midagi muud kui undefined (teadmata väärtus, mis näiteks R-is on NA; on arvuline väärtus). Sellega peab aga ettevaatlik olema, sest kui häälik on helitu, siis liigub skript kuni järgmise helilise hääliku alguseni. Selle pärast võiks ka täpsustada tsükli lõputingimust, et ei liigutaks hääliku piiridest kaugemale, nt
Ettevaatust! Enne repeat-tsükli käivitamist peab olema kindel, et tingimustele sobiv väärtus ka leidub, muidu ei välju Praat sellest tsüklist kunagi ja kui tsükli sees on ka näiteks käsk kirjutada midagi infoaknasse, võib juhtuda, et seda ei saa peatada muidu, kui pead Praati jõuga sulgema või lausa arvutile restardi tegema. Mõistlik oleks until rea ette skripti testimise ajaks panna üks paus, mis peatub igal tsükli jooksmise korral, ja kui oled juba kindel, et kõik töötab, nagu peab, siis paus ära koristada:
repeat
pohitoon = Get value at time: haalikuAlgus, "Hertz", "Linear"
pauseScript: "Punktis ",haalikuAlgus, " f0 = ", pohitoon
haalikuAlgus += 0.001
until pohitoon <> undefinedSiis saab skripti valutult katkestada, kui tundub, et kuskil on mingi viga.
20.5.2 while-tsüklid
Peale for- ja repeat-tsüklite on veel while-tsüklid. Need kordavad mingit toimingut seni, kuni saadakse tingimustele mittesobiv vastus. Näiteks:
Sellest näites töötab see tsükkel küll täpselt sama moodi kui for-tsükkel, olles pealegi kohmakam. See, mis siin on viiel real, saaks for-tsüklis hakkama kolme reaga:
Seda on aga mõtet kasutada siis, kui muutuja väärtus on lähteseisus teadmata ja pole ka teada, mismoodi ta väärtused järgnevatel juhtudel muutuvad, näiteks juhuslike arvudega:
clearinfo
x = randomInteger (0,10)
while x > 0
appendInfoLine: "x = ", x
x = randomInteger (0,10)
endwhileETTEVAATUST! Nagu repeat-tsükli puhul, peab tingimustele sobiv väärtus muutuma nii, et millalgi tuleb tingimustele mittevastav väärtus, muidu ei välju Praat sellest tsüklist mitte kunagi. St ridade while ja endwhile vahel peab muutuja kunagi saama sellise väärtuse, mis tingimustele ei vastaks. Järgnev tsükkel kestab igavesti, lõpetab ainult restart. Seepärast on soovitatav nii skript ise kui objektiloendis olevad salvestamata asjad enne skripti käivitamist salvestada.
20.5.3 Protseduurid
Protseduurid on skripti terviklikud osad, millele skriptis saab viidata. See on nagu eraldi skript ühe skripti sees. Näiteks kui meil on skript, mis otsib TextGrid’ilt midagi ja erinevate tingimuste korral teeb vastete esinemisel mingi hulga samu protseduure, siis selle asemel, et iga tingimuse juurde kõik käsud välja kirjutada, võime panna viite protseduurile ja protseduuri enda kirjutada lahti skripti lõppu.
Järgnevast näitest skripti põhiosa sisaldab tsüklit, mis käib läbi
TextGrid’i 1. märgenduskihi ja otsib sealt sõnu, mis vastaksid mingitele tingimustele. Siin näites on tingimuseks, et sõna esimesed neli tähemärki on „mant“ (millega saame „Põhjatuule ja päikese“ tekstist kätte sõna mantel erinevad käändevormid) või sõna on „päike“. Iga vaste leidmisel kutsutakse esile protseduur @pohitoon.
Protseduur ise, mis sisaldab mitut käsku (siin sõna alguse-lõpu leidmist, Sound-objektist põhitooni leidmist ja tulemuste trükkimist infoaknasse), asub skripti lõpus. Oluline on, et see oleks lineaarselt jooksva skriptiosa järel peale kõikide skripti sees olevate tsüklite ja tingimuste lõppu.
clearinfo
# üks põhjatuule-päikese Sound ja TextGrid on objektiloendis
# ja TextGrid-objekt on valitud
fail$ = selected$("TextGrid")
intd = Get number of intervals: 1
for i to intd
selectObject: "TextGrid " + fail$
i$ = Get label of interval: 1, i
if left$(i$, 4)= "mant"
@pohitoon
elsif i$ = "päike"
@pohitoon
endif
endfor
# Siia maani jookseb skript lineaarselt
# SIIN ON SKRIPTI LÕPP.
# SIIT ALGAB PROTSEDUUR.
# Seda juppi procedure-endproc ridade vahel
# jooksutatakse iga kord, kui põhiosas esineb @pohitoon
procedure pohitoon
alg = Get start point: 1, i
lop = Get end point: 1, i
selectObject: "Sound " + fail$
temp1 = Extract part: alg, lop, "rectangular", 1, "yes"
temp2 = noprogress To Pitch: 0, 75, 600
f0 = Get mean: alg, lop, "Hertz"
appendInfoLine: i$, tab$, round(f0)
plusObject: temp1
Remove
endproc20.5.4 goto-label-hüpped
Kui üldiselt skriptid jooksevad lineaarselt algusest lõpuni, siis seda lineaarsust saab Praati skriptikeeles lõhkuda hüpetega mingite kindlate märgisega (label) tähistatud kohtade juurde. Kui oled tuttav html-keelega, siis märgised on nagu ankrud ja hüpped on nagu hüperlingid neile akrupunktidele.
Ankrupunkti tähistab skriptis label ja linki sellele ankrule goto.
Teeme nüüd hoopis hüpetega läbi eelmise näite, kus ptk 20.5.3 kasutasime protseduuri. Tegemist pole küll selle Praati süntaksielemendi kasutamise kõige elegantsema näitega, aga ehk aitab paralleel eelnevaga funktsiooni paremini mõista.
Hüppeid Praatis kasutatakse kõige rohkem Demoakent juhtivates skriptides, mille kohta vaata näidet peatükist 20.12.
clearinfo
# üks põhjatuule-päikese Sound ja TG on objektiloendis valitud
fail$ = selected$("TextGrid")
intd = Get number of intervals: 1
for i to intd
selectObject: "TextGrid " + fail$
i$ = Get label of interval: 1, i
if left$(i$, 4)= "mant"
goto POHITOON
elsif i$ = "päike"
goto POHITOON
endif
label TAGASITSYKLISSE
endfor
# Kuna nüüd leibeli POHITOON taga pole protseduur,
# jookseks skript edasi, aga paneme siia hüppe päris lõppu
goto END
label POHITOON
alg = Get start point: 1, i
lop = Get end point: 1, i
selectObject: "Sound " + fail$
temp1 = Extract part: alg, lop, "rectangular", 1, "yes"
temp2 = noprogress To Pitch: 0, 75, 600
f0 = Get mean: alg, lop, "Hertz"
appendInfoLine: i$, tab$, round(f0)
plusObject: temp1
Remove
goto TAGASITSYKLISSE
label END
# siin on skripti lõpp20.6 Vektorid
Tavalisel muutujal võib Praati skriptikeeles olla ainult üks väärtus, aga ka Praatis saab kasutada vektoreid. Vektori muutujanime lõppu tuleb lisada sümbol # ning väärtused loogelistes sulgudes komadega eraldada.
Üksikute väärtuste pärimiseks tuleb lisada muutuja nime lõppu vektorielemendi indeks nurksulgudes:
Indeksi väärtus võib olla sisestatud ka läbi teise muutuja. Nii saab näiteks teha tsükli, mis ükshaaval vektori elemendid läbi käib:
clearinfo
arvud# = {3, 5, 14, -10}
for i to size(arvud#)
appendInfoLine: i, ". arv: ", arvud#[i]
endforSarnaselt tavalistele muutujatele tuleb sõnaliste väärtustega vektor tähistada ka dollarimärgiga:
Sõnalise vektori väärtuseks saavad olla tekstistringid ja vektoris sonad$# on viimane väärtus 43 sisestatud jutumärkides, ilma jutumärkideta saaks veateate.
Arvuliste vektoritega saab teha ka mõningaid tehteid (leida summat, standardhälvet jms), samuti on Praati skriptikeeles maatriksid ehk kahemõõtmelised mitmest väärtusest koosnevad muutujad, kuid nendest võimalustest võib põhjalikumalt lugeda Praati manuaalist.
20.7 Eeldefineeritud muutujad
Praati skriptides saab kasutada mõningaid eeldefineeritud sõnalisi muutujaid, mille sisu on kas alati sama või tuleb operatsioonisüsteemist. Kahte neist oleme juba kasutanud. Need on tab$, mis tekitab tabulatsioonimärgi, ja newline$, mis tekitab reavahetuse. Lisaks neile on mõned muutujad, millega saab määrata katalooge:
homeDirectory$– kasutaja kodukataloog operatsioonisüsteemis, nt Windowsis võiks see ollaC:\Users\partelja Macis/Users/partel;preferencesDirectory$– kasutaja Praati eelistuste kataloog (sinna salvestuvad nt SoundEditor’i seaded, pluginad jms):- Windowsis
C:\Users\partel\Praat; - Macis
/Users/partel/Library/Preferences/Praat Prefs. Macis võib olla kataloog Library kasutaja eest peidetud;
- Windowsis
temporaryDirectory$– ajutine kataloog;shellDirectory$– kataloog, kuhu Praat on installitud, Windowsis näiteksC:\Program Files\Praat.
Tõenäoselt on vaja kahte esimest ja pigem harvem kahte viimast. Eeldefineeritud muutujaga on hea kodukataloogi märkida näiteks siis, kui skript peab salvestama tulemused kuhugi faili, aga skripti kasutavad eri kasutajad või kui töötad mitmes arvutis, kus on erinevad operatsioonisüsteemid või erinev kasutajatunnus. Siis saad lihtsalt oma kodukausta teha sama nimega kataloogi (või lasta skriptil kataloog teha) ega pea seda skriptis muutma.
Erinevates operatsioonisüsteemides on failiaadressides kasutatav kausta eraldav märk erinev. Kui Windowsis on see tagurpidi kaldkriips (\, Eesti klaviatuuril [AltGr]+[+]), siis Unix/Linux/Mac kasutavad selleks tavalist kaldkriipsu (/, [Shift]+[7]) ja vanemad Mac-id (vanemad kui OS X) hoopis koolonit. Praat õnneks oskab kaldkriipsu asendada vastava süsteemi märgiga. Seetõttu on mõistlik kasutada määratud kodukataloogi tähistavat muutujat koos tavalise kaldkriipsuga, nt
Sellisel juhul on üsna kindel, et selline kaust on olemas ja kasutajale ligipääsetav.
Arvuti kellaaega saab pärida muutujaga date$(). Seda on vahel hea näiteks tulemuste faili algusesse ja/või lõppu logida – näiteks kui andmete faili lisamine on seatud nii, et skript ei kirjuta olemasolevat faili üle ning oled skripti mitu korda jooksutanud, leiab ajatempli järgi failist üles kõige uuemad andmed.
## Mon Mar 2 22:43:44 2026
Kui on pikem skript ja tahame teada, kui palju aega kulub selle jooksutamiseks, siis selleks on käsk stopwatch ehk stopper. Iga käsurida stopwatch annab eelmisest stopwatch mainimisest kulunud aja, nullib stopperi ja paneb selle uuesti käima. Seda saab näiteks kasutada siis, kui on ressursimahukam skript, mis kogub andmeid mitmest failist, ja tahame logida infoaknasse iga tsükli ringi lõpus, kui palju aega kulus (et selle põhjal hinnata, kui kaua veel aega võiks minna). Järgmises näites on stopper lisatud varasemale täringuviske näitele:
clearinfo
stopwatch
for i to 10
visked = 0
repeat
silmad = randomInteger (1,6) + randomInteger (1,6)
visked += 1
until silmad = 12
aeg = stopwatch
appendInfoLine: i, ".korral ", visked, " viset, ", aeg, " sek."
endfor## 1.korral 33 viset, 7.38329254090786e-05 sek.
## 2.korral 24 viset, 4.8459041863679886e-05 sek.
## 3.korral 24 viset, 3.9499951526522636e-05 sek.
## 4.korral 28 viset, 4.2833155021071434e-05 sek.
## 5.korral 70 viset, 7.566693238914013e-05 sek.
## 6.korral 13 viset, 2.38749198615551e-05 sek.
## 7.korral 12 viset, 2.1625077351927757e-05 sek.
## 8.korral 30 viset, 4.3165870010852814e-05 sek.
## 9.korral 67 viset, 7.183407433331013e-05 sek.
## 10.korral 120 viset, 0.00011287513189017773 sek.
Arvulistest muutujatest on eeldefineeritud veel mõned konstandid:
pi = 3,141592653589793,
e = 2,718281828459045.
Kuna need on konstandid, siis nende nimedega muid muutujaid ei saa kasutada.
20.8 Hoiatuste ja sõnumite ignoreerimine
Kui skriptis on mingi selline käsk, mille arvutamine on üldiselt mahukas ja Praat näitab progressiakent, mida on võimalik katkestada (nt To Pitch käsud), siis vajaduse korral saab selle progressiakna ära peita. Kui skriptis on palju kordusi käsul, mis progressiakna esile kutsub, on mõistlik see ära peita kahel põhjusel: esiteks, ilma selleta on skript oluliselt kiirem, ja teiseks, kui skript taustal jookseb ja teed samal ajal midagi muud, siis on tüütu, kui midagi kogu aeg vilgub. Selleks, et progressiakent ei ilmuks, tuleb käsu ette kirjutada noprogress:
Aeg-ajalt on mõned käsud, mis annavad mingeid hoiatus- või veateatesõnumeid. Hoiatussõnumid on skripti puhul üsna tülikad, sest otseselt mingit viga nad ei põhjusta, aga skript jääb selle taha seisma, kuni kasutaja vajutab OK-nuppu. Hoiatussõnum hüppab dialoogiaknana ette näiteks siis, kui tahame Sound- või TextGrid-objekti salvestada, aga selle nimega fail on juba olemas. On muidugi ohtlik olemasolevaid faile üle kirjutada, aga kui näiteks tahame skriptiga lisada TextGrid’ile mingeid märgendeid ja iga muudatuse järel faili salvestada, on tülikas, kui skript iga kord selle koha peal seisma jääb. nowarn vastava käsu ees ignoreerib hoiatusi:
Kui üritame rakendada dünaamilise menüü käsku valele objektile, annab Praat veateate ja skript lõpetab jooksmise. Veateate saab ka näiteks sellisel juhul, kui tahame eemaldada objekte, aga ühtegi objekti ei ole valitud või ei ole ühtegi objekti objektiloendis. Siis aitab nocheck:
20.9 Failid ja kaustad
20.9.1 Failide lugemine ja kirjutamine
Kui skripti paljude eri failide peal jooksutada, on hea, kui skript kontrollib kõigepealt, et fail oleks olemas või loetav. Kui faili ei ole, saab kasutajale tehnilise veateate asemel anda selge sõnumi, et faili pole. Järgnev näide küsib, kas arvuti töölaual on kataloogis nimega „pohjatuul“ fail nimega „POHJA_006-006_M.wav“.
kaust$ = homeDirectory$ + "/Desktop/pohjatuul/"
fail$ = "POHJA_006-006_M.wav"
loetav = fileReadable: kaust$ + fail$Funktsiooni fileReadable vastus on jällegi arvuliselt esitatud tõeväärtus, ehk siis 1 = TÕENE (fail on olemas ja loetav), 0 = VÄÄR (faili pole või see ei ole loetav). Viimase rea võib ka asendada if-lausega:
if fileReadable: kaust$ + fail$
Read from file: kaust$ + fail$
Play
else
writeInfoLine: "Seda faili pole!"
endifTekstifaili võib ka kohe muutuja väärtuseks lugeda. Seda teeb käsk readFile (juhul kui faili sisu on üks arv), või readFile$ (sõnalise muutuja puhul). Näiteks kui mul kaustas „pohjatuul“ oleks tekstifail „POHJA_006-006_M.txt“, mis sisaldab helifaili „POHJA_006-006_M.wav“ transkriptsiooni, saaks selle teksti lugeda muutuja x$ väärtuseks.
kaust$ = homeDirectory$ + "/Desktop/pohjatuul/"
fail$ = "POHJA_006-006_M.txt"
x = fileReadable: kaust$ + fail$
if x=1
x$ = readFile$: kaust$ + fail$
writeInfo: x$
endifMuutuja sisu saab saata faili käskudega writeFile, writeFileLine ja appendFile, appendFileLine. write ja append vahe on selles, et kui sama nimega fail on juba olemas, siis write kirjutab selle üle, append lisab olemasoleva faili lõppu. Käsk tahab vähemalt kahte argumenti: peale koolonit faili aadress ja seejärel tekst, mis faili kirjutatakse. Teksti (muutujaid) võib ka mitu olla nagu järgmises näites:
for i to 100
if i = 1
writeFile: homeDirectory$+"/Desktop/test.txt", "See on ", i,
... ". kord.", newline$
else
appendFile: homeDirectory$+"/Desktop/test.txt", "See on ", i,
... ". kord.", newline$
endif
endforLõpuks saab faili vajaduse korral ka ära kustutada (kui selline fail on, sest kui faili pole, siis ei juhtu midagi, veateadet ei saa):
Eelmise näite võib ka natuke teisiti kirja panna nii, et kõigepealt küsime, kas selline fail on olemas, ja kui on, kustutame ära, ning seejärel tekitame teksti lisamisega uue faili:
x = fileReadable: homeDirectory$ + "/Desktop/test.txt"
if x=1
deleteFile: homeDirectory$ + "/Desktop/test.txt"
endif
for i to 100
appendFileLine: homeDirectory$ + "/Desktop/test.txt", "See on ",
... i, ". kord."
endforFaili saab salvestada ka infoakna sisu:
20.9.2 Kaustade loomine ja kustutamine ning süsteemikäsud
Vahel on tarvis skriptiga tekitada terve hulk uusi faile, mis võiksid minna eraldi uude kataloogi. createFolder: "uus_kataloog" on Praati skripti käsk kausta loomiseks. Kui selline kaust on juba olemas, siis seda üle ei kirjutata. Kui katalooginimi ei ole antud täisaadressina, siis tehakse vastava nimega kataloog sinna kataloogi, kuhu skript on salvestatud. Proovime uut kataloogi luua arvuti töölauale, määrates kodukataloogi asukoha eeldefineeritud muutujaga homeDirectory$.
Sageli Windowsi süsteemis see käsk aga millegipärast ei tööta. Siis on võimalik kasutada süsteemikäske, mis töötavad operatsioonisüsteemi käsureal (Windowsis CommandLine, Macis Terminal). Käsu runSystem kaudu saab rakendada kõiki süsteemikäske. Nii Windowsis kui Macis on käsurea kataloogi loomise käsk mkdir katalooginimi. Praati skriptis oleks see siis:
Nagu Praati käsk createFolder, teeb mkdir alamkausta nimega uus_kataloog sinna kataloogi, kuhu skript on salvestatud. Kui anda loodavale kaustale täisaadress, tuleb nüüd arvestada seda, et kui kasutad Windowsi, siis siin peavad kaustu eraldavad kaldkriipsud olema längkriipsud, nagu Windowsi failisüsteem neid kasutab, sest runSystem saadab järgneva käsurea sisu otse Windowsi süsteemile.
Kausta kustutamiseks on Windowsi ja Maci süsteemis erinevad käsud. Windowsis
ja Macis
Käsurea võib ka mitmest muutujast kokku panna. Käsu runSystem järel võib olla mitu komadega eristatud muutujat või väärtust, need pannakse üheks tekstistringiks kokku. Tähele tuleks panna seda, et tekst kokku peab andma käsurea nii, nagu see süsteemi käsureale peaks minema, nii näiteks peab käsu rm ja kataloogiaadressi vahel olema tühik.
20.9.3 Failinimekirjad
Ühte skripti saab terve kataloogitäie failide peal jooksutada. Selleks on vaja luua nimekiri kataloogis olevate failide nimedest, mida saab teha käsuga Create Strings as file list..., mille leiab objektiakna menüüst New > Generics > Strings. See käsk teeb Strings-objekti, mille sisuks on määratud kataloogis asuvate failinimede loend. Skriptis saab teha tsükli, mis Strings-objektist ükshaaval failinimesid pärib, et neid faile siis avada ja nendega edasi töötada. Järgnevas näites avame kataloogist WAV-faile, mängime neid ja paneme uuesti kinni. Kui skript asub akustiliste meetodite repositooriumi kaustas, siis seal on alamkaust taju/stiimulid/, kus on ptk 17.3 juhiste järgi loodud stiimulfailid, mida proovime järgnevas näites lugeda. Muutuja dir$ väärtuseks võid panna ka vastava kataloogi täisaadressi oma arvutis.
dir$ = "taju/stiimulid/"
nimekiri = Create Strings as file list: "fileList", dir$ + "*.wav"
faile = Get number of strings
for fail to faile
selectObject: nimekiri
fnimi$ = Get string: fail
Read from file: dir$ + fnimi$
Play
Remove
endfor
selectObject: nimekiri
RemoveStrings on objekt, mis sisaldab mingisugust nimekirja, antud juhul siis nimekirja failinimedest. Objekti saab avada käsuga View & Edit (vt joonis 20.1). Käsud, millega skriptis failinimesid pärida, leiab menüüst Query: esmalt peab küsima, mitu nime nimekirjas on käsuga Get number of strings ning tsükli sees iga üksiku failinime pärimiseks Get string.... Menüüst Modify leiab käsu Randomize, millega saab nimekirja juhuslikku järjekorda ajada, kui failinimekirja kasutada näiteks Demoakna skriptiga (vt ptk 20.12) tajutestis stiimulite esitamiseks.
Joonis 20.1. Strings-objekt failinimekirjaga Praati graafilises kasutajaliideses.
Võrdlemisi hiljuti (aastal 2021 Praati versiooniga 6.1.38) on lisandunud ka skriptikeele funktsioon, millega ilma String-objekti vahenduseta saab lugeda failinimekirja vektorina. Vektorist saab seejärel tsüklis ükshaaval failinimesid pärida (vt vektorite kohta 20.6).
dir$ = "taju/stiimulid"
failid$# = fileNames$#(dir$)
for i to size(failid$#)
fail$ = failid$# [i]
appendInfoLine: fail$
endfor## stim_F1_200.wav
## stim_F1_300.wav
## stim_F1_400.wav
## stim_F1_500.wav
## stim_F1_600.wav
## stim_F1_700.wav
## stim_F1_800.wav
20.9.4 Praati objektide valimine
Kui muidu oleme nimetanud selectObjects: järel objektitüüpi ja failinime (nagu on kirjeldatud ptk 19.7), siis lisaks nimele on objektidel ka numbrid. Iga objekt saab objektiloendis sessiooni piires unikaalse järjekorranumbri. Näiteks kui Praat lahti teha ja avada näiteks üks helifail ja üks TextGrid-fail, siis see esimesena avatud Sound-objekt on järjekorras esimene ja TextGrid on teine. Neid numbreid saame kasutada selleks, et objekti valida, nt valime objektiloendis esimese objekti:
Objekti nime järgi objekti valimise puhul on piirang, et kui meil on objektiloendis mitu sama nimega objekti, siis nimega pöördumine viib meid objektiloendis viimase vastavanimelise objekti juurde. Olukord, et sama nimega objekte on mitu, võib tekkida näiteks siis, kui oleme lõiganud pikemast Sound-objektist välja tükke ega ole neid pidevalt ümber nimetanud – siis on loendis mitu objekti nimega „Sound untitled“. Järjekorranumbritega valimise puhul on aga piirang see, et numeratsioon kehtib ainult Praati sessiooni piires ning kui panna Praat kinni ja uuesti avada, ei pruugi sama objekt sama numbrit saada.
Kui kasutame skriptis käsku, mis faili avab või loob, siis me saame ühe skripti jooksutamise piires selle järjekorranumbri salvestada muutujaks ja skripti piires selle muutuja kaudu objekti valida. Nii on võimalik väga selgelt jälgida, et ühe skripti piires loetud või loodud objektidele oleksid suunatud õiged käsud. Kui on aga tarvis mitut objekti valida, siis lisaks valitule teise objekti valimiseks on käsk plusObject. Järgmises näites loeme Praati Sound-objekti ja salvestame selle numbri muutujasse heli. Seejärel teeme sellest Pitch-objekti ja järjekorranumbri muutujaks pohitoon. Siis joonistame põhitoonikontuuri ja lõpetuseks valime Sound- ja TextGrid-objektid ja eemaldame objektiloendist.
20.10 Toimetamisakna skriptid
Siiamaani oleme vaadanud ainult üldiseid skripte, kus töötavad objekti- ja pildiakna käsud. Üldised skriptid toimetamisakende käske kasutada ei saa. Põhjus on erinevas loogikas: toimetamisaknas arvestab käsk kursori paiknemist x-y teljel, st näiteks kui SoundEditor’is küsime käsuga Get Pitch põhitooni väärtust, siis sõltub vastus sellest, kus sel hetkel kursor asub; objektiaknas Pitch-objektilt sama asja küsides aga peame ise käsu argumentidega ütlema, mis ajateljepunktist väärtust tahame. Kuid ka toimetamisakende käsud on täiel määral skriptitavad.
Ava mõni toimetamisaken (vali mõni objekt objektiaknast ja vajuta nuppu View & Edit). Toimetamisakna skriptid töötavad ainult ühe Editor’i sees vastava objekti Editor’i käskudega. Näiteks on siin TextGridEditor’i skript, mis poolitab teisel segmenteerimiskihil valitud segmendi (vt ka ptk 14.1.2).
segmalgus = Get start of selection
segmkestus = Get selection length
pool = segmkestus / 2
piir = segmalgus + pool
Move cursor to: piir
Add interval on tier 2
Move to nearest zero crossingSelle skripti jaoks peab olema avatud toimetamisaken Sound- ja TextGrid-objektiga, samuti peab olema TextGrid’il vähemalt 2 märgenduskihti ja mingi ajaintervall peab olema kursoriga valitud. Skript küsib kursoriga valitud lõigu algusaega ja kestust, jagab kestuse kahega ning liigutab kursori selle intervalli võrra edasi. Seejärel lisab skript piiri kursori asukohale ning nihutab piiri kohakuti helilaine lähima nullpunktiga.
20.11 Toimetamisakna käsud üldise skripti sees
Toimetamisakende käske on siiski võimalik kasutada ka üldises skriptis. Siis tuleb skriptil kõigepealt toimetamisaken avada (või peab see olema avatud enne skripti jooksutamist) ja suunata käsud Editor’ile. Näiteks saab neid kasutada koos pauseScript käsuga selleks, et kasutaja saaks skripti jooksutamise käigus välja otsitud kohas käsitsi märgendust kontrollida või muuta ning seejärel saab skript näiteks faili salvestada või mingid analüüsid võtta.
# ...mingid eelnevad käsud, mis otsivad TextGridilt mingisugust
# märgendust ja kui nad selle leiavad, siis
# valime TextGridi ja küsime segmendi algus- ja lõpuaega
selectObject: "TextGrid " + fail$
sAlg = Get starting point: k, j
sLop = Get end point: k, j
# lisame valikusse Sound objekti ja avame Editori
plusObject: "Sound " + fail$
View & Edit
# Nüüd suunatakse käsud editorile
editor: "TextGrid " + fail$
# valime kursoriga segmendi algusest lõpuni
Select: sAlg, sLop
# zoomime selle segmendi ekraanile
Zoom: sAlg, sLop
# teeme skriptis pausi, et kasutaja saaks
# editoris toimetada ja edasi minna
beginPause: "Kontrolli märgendust"
comment: "segm " + string$(j) + " oleks vaja kontrollida"
tegevus = endPause: "Loobu", "Salvesta", 2, 1
# kui kasutaja on pausi lõpetanud, paneme editori kinni
# ja sulgeme editorile käskude suunamise
Close
endeditor
# siit jätkub tavaskript
# kui kasutaja vajutas Salvesta nuppu, siis salvestame TextGridi
if segmKontrolliTegevus = 2
selectObject: "TextGrid " + fail$
Save as text file: fail$ + ".TextGrid"
endif
20.12 Demoaken
Praati demoakent saab kasutada katsete läbiviimiseks, aga ka kasvõi PowerPointi asemel slaidiesitluste tegemiseks. Demoaken on lihtsalt üks täiendav menüüdeta aken, kuhu saab kuvada sama sisu, mis muidu läheks pildiaknasse. Selleks tuleb lihtsalt käsurea algusesse muidu pildiaknas toimivate käskude ette lisada demo. Näiteks:
Create Sound as pure tone: "tone", 1, 0, 0.1, 44100, 100,
... 0.2, 0.01, 0.01
demo Draw: 0, 0, 0, 0, "yes", "curve"
demo Text top: "yes", "See on siinusheli sagedusega 100 hertsi."
RemoveKui pilte või slaide on rohkem kui üks, siis tuleb vahepeal eelmine sisu ära kustutada ja seejärel uus joonistada. Ning kuna skript muidu jookseb algusest lõpuni järjest nii kiiresti kui arvuti protsessor seda võimaldab, on vaja lisada slaidivahetuse koha peale paus. Demoaknas saab ka salvestada koordinaadid, kuhu hiirega klikiti, nii on võimalik programmeerida edasi või tagasi liikumiseks nupud. Skriptis edasi-tagasi liikumiseks on hea kasutada goto-hüppeid (vt ptk 20.5.4).
Create Sound as pure tone: "tone", 1, 0, 0.1, 44100, 100,
... 0.2, 0.01, 0.01
# kustutab eelneva, kui midagi demoakanas juba oli
demo Erase all
# määrame joonisele ruudukese akna keskel
demo Select outer viewport: 20, 80, 20, 80
demo Draw: 0, 0, 0, 0, "yes", "curve"
demo Text top: "yes", "See on siinusheli sagedusega 100 hertsi."
Remove
# aktiveerime jälle kogu akna pinna
demo Select outer viewport: 0, 100, 0, 100
# määrame akna telgede skaala,
# mis helilaine joonistamisega sai muud väärtused
demo Axes: 0, 1, 0, 1
demo Paint rounded rectangle: "pink", 0.8, 1, 0, 0.1, 4
demo Text special: 0.9, "Centre", 0.05, "Half", "Helvetica",
... 14, "0", "Järgmine"
# siit edasi minemiseks oodatakse tegevust, mis on kas klikk
# roosa nupu peal või ükskõik mis klahvi vajutamine,
# mõlemal juhul hüpatakse leibeli NEXT juurde
while demoWaitForInput ( )
if demoClickedIn (0.8, 1, 0, 0.1) or demoKeyPressed()
goto NEXT
endif
endwhile
# see on teine slaid
label NEXT
Create Sound as pure tone: "tone", 1, 0, 0.1, 44100, 500,
... 0.2, 0.01, 0.01
demo Erase all
demo Select outer viewport: 20, 80, 20, 80
demo Draw: 0, 0, 0, 0, "yes", "curve"
demo Text top: "yes", "See on siinusheli sagedusega 500 hertsi."
RemoveDemoakna skriptiga on võimalik teha keerukamaid tajukatseid kui ExperimentMFC võimaldab (vt ptk 18.1), näiteks katseid, kus katseisik peab stiimulile reageerima kõnega, mida salvestatakse. Hetkel on sellise katse disaini puhul Praati kõige suurem puudus see, et skriptiga saab juhtida ainult etteantud kestusega salvestust käsuga Record Sound (fixed time)....84 Salvestusfunktsiooni ei saa nupuvajutusega kinni panna siis, kui katseisik on lõpetanud, mis tähendab, et kui katseisikul kulub prognoositust kauem aega, jääb lõpp salvestamata, aga kui tal kulub vähem aega, siis peab ootama, kuni salvestus lõppeb.
Siin üks veidi lihtsam näide ilma heli salvestamiseta. Teeme ühe katse, kus katseisik peab hindama kuuldud heli kõrgust. Seda katset saaks edukalt ka ExperimentMFC’ga teha.
skoor = 0
demo Erase all
demo Text special: 0, "Left", 0.5, "Half", "Helvetica", 18, "0",
... "Tere tulemast katsesse. Alustamiseks vajuta tühikut."
demo Paint rounded rectangle: "pink", 0.8, 1, 0, 0.1, 4
demo Text special: 0.9, "Centre", 0.05, "Half", "Helvetica", 14,
... "0", "Alustame"
while demoWaitForInput ( )
if demoClickedIn (0.8, 1, 0, 0.1) or demoKeyPressed()
goto KATSE
endif
endwhile
label KATSE
# genereerime vektori 10 numbriga vahemikus 1-5
x# = randomInteger#(10, 1, 5)
for i to 10
tmp = Create Sound as pure tone: "tone", 1, 0, 0.4, 44100,
... 100 * x# [i], 0.2, 0.01, 0.01
demo Erase all
demo Text special: 0.5, "Center", 0.8, "Half", "Helvetica",
... 36, "0", "Mis sagedusega on heli, mida kuuled?"
# nupud vastuste jaoks
demo Paint rounded rectangle: "pink", 0, 0.1, 0.4, 0.5, 4
demo Paint rounded rectangle: "pink", 0.2, 0.3, 0.4, 0.5, 4
demo Paint rounded rectangle: "pink", 0.4, 0.5, 0.4, 0.5, 4
demo Paint rounded rectangle: "pink", 0.6, 0.7, 0.4, 0.5, 4
demo Paint rounded rectangle: "pink", 0.8, 0.9, 0.4, 0.5, 4
# kiri nupu peal
demo Text special: 0.05, "Center", 0.45, "Half", "Helvetica",
... 14, "0", "100"
demo Text special: 0.25, "Center", 0.45, "Half", "Helvetica",
... 14, "0", "200"
demo Text special: 0.45, "Center", 0.45, "Half", "Helvetica",
... 14, "0", "300"
demo Text special: 0.65, "Center", 0.45, "Half", "Helvetica",
... 14, "0", "400"
demo Text special: 0.85, "Center", 0.45, "Half", "Helvetica",
... 14, "0", "500"
# mängime stiimulit ja eemaldame selle peale mängimist
Play
Remove
while demoWaitForInput ( )
if demoClickedIn (0, 0.1, 0.4, 0.5)
vastus = 100
elsif demoClickedIn (0.2, 0.3, 0.4, 0.5)
vastus = 200
elsif demoClickedIn (0.4, 0.5, 0.4, 0.5)
vastus = 300
elsif demoClickedIn (0.6, 0.7, 0.4, 0.5)
vastus = 400
elsif demoClickedIn (0.8, 0.9, 0.4, 0.5)
vastus = 500
endif
goto VASTUS
endwhile
label VASTUS
demo Erase all
if vastus = 100*x# [i]
skoor += 1
demo Text special: 0.5, "Center", 0.8, "Half", "Helvetica",
... 36, "0", "Õige, see heli on " + string$(vastus) + " Hz."
else
demo Text special: 0.5, "Center", 0.8, "Half", "Helvetica",
... 36, "0", "Vale vastus, see heli on " +
... string$(100*x# [i]) + " Hz."
endif
demo Paint rounded rectangle: "pink", 0.8, 1, 0, 0.1, 4
demo Text special: 0.9, "Centre", 0.05, "Half", "Helvetica",
... 14, "0", "Edasi"
while demoWaitForInput ( )
if demoClickedIn (0.8, 1, 0, 0.1) or demoKeyPressed()
goto EDASI
endif
endwhile
label EDASI
endfor
label LOPP
demo Erase all
demo Text special: 0, "Left", 0.5, "Half", "Helvetica",
... 18, "0", "Katse sai läbi. Vastasid " +
... string$(skoor) + " korda õigesti."Selle näitega lõpetame katsetused Praati skriptidega siin õpikus. Me ei ole käinud läbi kõiki Praati skripti võimalusi, kuid neid võib omal käel edasi avastada Praati manuaali toel. Kui aga sulle tundub Praati skriptikeel kohmakas ja ebamugav, siis peatükis 21 vaatame põgusalt üle, kuidas foneetilisi andmeid koguda ja analüüsida programmiga R.
Astendamist tähistava sümboli leiab eesti klaviatuuril [AltGr]+[ä] kombinatsiooni alt.↩︎
Sümbol „+“ tähistab muidu eelneva sümboli kordumist ja otsing
"keele+teadus"võiks anda vasteks „keeleteadus“ ilma plussmärgita ning „keeleeteadus“ või „keeleeeeeeteadus“ jne, aga mitte „keele+teadus“.↩︎Kui kasutada lihtsalt algava loogelise sulu sümbolit regulaaravaldises, nt
"t{nA", saaks vastuseks veateate.↩︎See käsk on peidetud, aga
Praat>Settings>Buttonssaab selle üles otsida ja ka menüüs nähtavaks teha. Skriptis töötab käsk aga ka peidus olevana.↩︎