SGN-4010, Puheenkäsittelyn menetelmät Harjoitus 6, 18. ja 21.2.2010 1. (Matlab, 2 pistettä) Vokaalit ja soinnilliset konsonantit ovat lähes jaksollisia ja niillä on äänihuulten värähtelystä johtuva perustaajuus. Kirjoita Matlab-funktio estimatef0 perustaajuuden estimointiin. Funktio ottaa sisään puhesignaalin ja näytteenottotaajuuden ja piirtää ja palauttaa f 0 -vektorin, joka on laskettu 10 ms välein 30 ms:n mittaisille hanning-ikkunoiduille puhekehyksille. Estimointi tehdään autokorrelaation avulla residuaalille eli signaalille, josta on suodatettu pois formantti-informaatio (LPkäänteissuodatus). Homma toimii näin: a) Suunnittele fir1-komennolla 30-asteinen alipäästösuodatin jonka rajataajuus on 900 Hz, ja suodata puhesignaali tällä. Kohdat b) ja c) tehdään kehyksittäin. b) Laske 18-asteiset LP-kertoimet (help lpc) jokaiselle Hanning-ikkunoidulle kehykselle alipäästösuodatetusta signaalista. Poista formantit käänteissuodatuksella eli suodattamalla (help filter) kehys FIR-suotimella A(z). c) Laske residuaalille autokorrelaatio (help xcorr). Käytä optiota unbiased (tämä on se autokorrelaation variaatio joka ei vaimenna isoja viiveitä mutta jossa vastaavasti isojen viiveiden autokorrelaation estimaatit ovat epäluotettavia). Etsi maksimipiikki 70-350 Hz väliltä (eli viive, joka vastaa näitä taajuuksia). Tallenna f 0 -informaatio jokaiselle kehykselle. Testaa funktiotasi tiedostolla sentence.wav. Korkeat piikit johtuvat yleensä siitä, että jotkin kehykset ovat soinnittomia, eikä niissä ole varsinaista perustaajuutta. Sen lisäksi estimointi saattaa joskus löytää f 0 :n 1
monikertoja (ja joskus puolikkaita). Voit tarkistaa alla olevasta kuvasta, minkälaisen f 0 -käyrän Matlab-koodin suurinpiirtein pitäisi tuottaa. Sen alla on kuva Praatin antamasta f 0 -käyrästä, jossa soinnittomat kohdat on jätetty pois. 500 f 0 lauseelle sentence.wav 450 400 350 300 taajuus, Hz 250 200 150 100 50 0 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2 aika, s 500 Pitch (Hz) 0 0 2.135 Time (s) 2. (Matlab, 3 pistettä) Tässä harjoituksessa rakennetaan yksinkertainen (ja huono) leikkaa- 2
liimaa tyylinen puhesyntetisaattori, jolla on käytössä 25 puhetiedostoa. Puhetiedostojen lisäksi mukana ovat foneettiset nimikointitiedostot (label file) eli mitä äänteitä puhetiedosto sisältää missäkin kohdassa. Foneemien käyttö puhesynteesiyksikköinä ei ole järkevää, sillä ne ovat hyvin kontekstiriippuvaisia. Koartikulaatiolla tarkoitetaan vierekkäisten äänteiden vaikuttamista toisiinsa. Koartikulaation takia käytämme syntetisaattorissa difoneja foneemien sijaan. Difoni alkaa edellisen foneemin keskiosasta ja päättyy seuraavan foneemin keski-osaan. Esimerkiksi sana speech (foneemit /s//p//iy//ch/) sisältää difonit pau s, s p, p iy, iy ch ja ch pau missä pau tarkoittaa hiljaisuutta. Materiaali: Käytössäsi on 25 teksti- ja wav-tiedostoa (löytyvät paketista exercise5.zip kurssin kotisivulta), joiden nimi on samplen.wav (N = 1,..., 25). Esim. nimikointitiedosto label3.txt antaaa foneettisen transkription puhetiedostolle sample3.wav. Nimikointitiedostot ovat muotoa endingtime phoneme_name ja pau tarkoittaa hiljaisuutta. Apuna on myös funktio finddiphone.m (help finddiphone), jonka avulla voi etsiä difonia ja sen alku- ja loppuaikaa. Paketti exercise5.zip sisältää: 25 wav-tiedostoa (samplen.wav) 25 vastaavaa nimikointitiedostoa (labeln.txt) (huom. automaattisesti nimikoituja, eivät siis kovin tarkkoja) finddiphone.m Tehtävä: Tee funktio nimeltä speechsynthesizer. Funktio saa syötteeksi foneemisekvenssin cell-formaatissa eli esim. phseq = { s, p, iy, ch }; ja ulostulona antaa syntetisoidun puhevektorin. Synteesissä pitää liittää hiljaisuudet (pau) alku- ja loppupäähän. Etsitään difonia nimikointitiedostoista (huom. nimikointitiedosto sisältää foneemeja), apuna finddiphone.m-funktio (saa toki kirjoittaa omankin). Kun difoni löytyy jostain tiedostosta, voidaan lopettaa kyseisen difonin etsintä. Otetaan nimikointitiedostoa vastaavasta wav-tiedostosta difonia vastaava aikaväli ja liitetään se jo muodostettuun puheeseen. Jos jotain difonia 3
ei ole, funktio palauttaa tyhjän puhevektorin ja ilmoituksen All diphones could not be found (help disp). Esimerkki: syntetisoit sanan dog eli foneemisekvenssi /d//ao//g/ (phseq={ d, ao, g };). Vaihe 1: Etsi difoni pau d. Lue nimikointitiedosto ja syötä foneemit loppuaikoineen finddiphone-funktiolle. Toista kaikille nimikointitiedostoille kunnes löydät kyseisen difonin. Jos difonia ei löydy, ohjelma voi lopettaa (tai hakea loput difonit, mutta tuottaa tyhjän vektorin ja ilmoituksen). Jos haluttu difoni (pau d) löytyi, voit lopettaa etsimisen. Oletetaan, että difoni löytyi tiedostosta label5.txt ja vastaava ajanhetki olisi 0.35s-0.42s. Ota näitä aikoja vastaavat näytteet wavtiedostosta sample5.wav. Vaihe 2: Nyt haluat etsiä difonin d ao. Toimi kuten vaiheessa 1, mutta nyt difoni pitää liittää edellisen difonin perään. Vaihe 3: Siirry seuraavaan difoniin ja toista Vaihe 2 kunnes difoneja ei enää ole. Nimikointitiedostojen lukeminen ja funktion finddiphone.m käyttö onnistuu esimerkiksi näin: phonemeprev = d ; phonemenext = ao ; % READ THE LABEL FILE index = 3; % We want to read sample3.txt % and form the file name in the next line filename = [ label num2str(index).txt ]; fid = fopen(filename, r ); if(fid==-1) disp([ Cannot read filename]); else [data] = textscan(fid, %f%s ); fclose(fid); timing = data{1}; phonemes = data{2}; end [exists,starttime,endtime] = finddiphone(timing,... phonemes, phonemeprev, phonemenext); 4
Testisekvenssejä: Koodisi pitäisi pystyä syntetisoimaan seuraavat esimerkit. Muistathan, että koodisi pitää lisätä hiljaisuudet alkuun ja loppuun. phseq = { s, p, iy, ch }; % SPEECH phseq = { dh, ax, k, w, aa, l, ax,... t, iy, ih, z, v, eh, r, iy, b,... ae, d }; % THE QUALITY IS VERY BAD phseq = { hh, uw, aa, r, y, uw }; % WHO ARE YOU phseq = { sh, iy, ih, z, l, ah, k, iy }; %SHE IS LUCKY phseq = { ay, s, p, iy, k }; % I SPEAK Voit myös laittaa muita sisäänmenoja funktiolle ja jakaa tehtävää useampiin funktioihin. Sen lisäksi voit tehdä virhetarkistusta, mutta se ei ole mitenkään välttämätöntä. Muista kommentoida! Huomattavaa: Oikeassa lausekeleikkaussynteesissä (unit selection) on paljon enemmän dataa käytössä ja valinta tehdään huomattavasti paremmin. Valinnassa otetaan huomioon signaalin piirteiden jatkuvuus (spektraalinen, perustaajuus, energia) ja difonien konteksti. Sen lisäksi uuden yksikön liittäminen tehdään yleensä perustaajuusjaksosynkronisesti. 5