Synteza mowy I: Fonemizacja

15.11.2009 - Krzysztof Kercz
TrudnośćTrudność

No dobrze - teraz, gdy wiemy już czym tak naprawdę jest głoska, możemy wreszcie spróbować opisać ją w przyjaźniejszy dla nas sposób, tzn. pisząc sobie odpowiednią klasę w jakimś języku programowania! Ja wybrałem do tego celu Pythona (http://python.org), jako że jest to język odpowiednio wysokopoziomowy i wybitnie przyjazny programiście. Można by sarkać na jego niezbyt wielką wydajność, jednak byłoby to sarkanie pozbawiano sensu, gdyż akurat w syntezie mowy wydajność języka nie jest kluczem do sukcesu.

Chcemy zaprojektować klasę opisującą wszystkie interesujące nas własności głosek. Do tego celu nasz program będzie musiał posiadać jakąś wiedzę - dajmy mu ją więc! Proponuję utworzyć plik Gloska.txt i wpisać do niego:

#stopien_zblizenia
zwarto-wybuchowa:b,p,d,t,g,k
zwarto-szczelinowa:dz,c,dzi,ci,drz,cz,ci
szczelinowa:v,w,f,z,s,rz,sz,zi,si,ch
nosowa:m,n,ni
drżąca:r
boczna:l
półsamogłoskowa:ll,j
otwarta:a,an,o,on,e,en,y,i,u
#dzwieczne
b,m,v,w,d,dz,z,n,dzi,zi,ni,drz,rz,r,g,a,an,o,on,e,en,y,i,u

Teraz trzeba będzie wczytać te dane do programu. Tworzymy zbiór głosek dźwięcznych, oraz słownik, w którym kluczami będą nazwy głosek, a wartościami - stopień zbliżenia narządów mowy przy ich artykulacji. Pokażę tutaj jeszcze jak to zrobić, żebyśmy oswoili się z Pythonem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dzSet = set()           # zbiór dzSet głosek dźwięcznych
szDic = {}              # słownik szDic ze stopniem zbliżenia narządów mowy dla każdej głoski
 
for line in open('Gloska.txt'):                     # czytamy plik linia po linii
        if line.startswith('#stopien_zblizenia'):   # sprawdzamy w której części pliku jesteśmy
                part = 0
                continue
        elif line.startswith('#dzwieczne'):
                part = 1
                continue
 
        if part == 0:
                val, keys = line.strip().decode('utf-8').split(':')     
                for k in keys.split(','):
                        szDic[k] = val
        elif part == 1:
                for gl in line.strip().decode('utf-8').split(','):
                        dzSet.add(gl)

Jest jeszcze jedna rzecz. Chcielibyśmy znać pary komplementarnych pod względem dźwięczności głosek, tzn. /d/ i /t/, /b/ i /p/ etc. Stwórzmy więc odpowiedni słownik (co prawda na razie nie będziemy z nich korzystać, ale - przydadzą się później):

1
2
3
4
5
6
7
8
9
dz_bdz = [("b", "p"), ("dz", "c"), ("dzi", "ci"), ("drz", "cz"), ("d", "t"),
                        ("w", "f"),("g", "k"),("z", "s"),("zi", "si"),("rz", "sz")]
dz_bdz = dict(dz_bdz + map(lambda (x, y): (y,x), dz_bdz))
 
"""
Przykład użycia:
>>> dz_bdz['t']
'd'
"""

Mając te przygotowania za sobą, jesteśmy gotowi do stworzenia naszej klasy, nazwijmy ją Gloska. Chcemy móc napisać a = Gloska('a') i w zmiennej a mieć obiekt w pełni opisujący głoskę /a/. Zacznijmy więc:

1
2
3
4
5
6
7
8
9
class Gloska:
        
        def __init__(self, name):
                self.name = name
                self.dzwieczna = name in dzSet
                self.stopien_zblizenia = szDic[name]
                #typ określa, czy głoska jest samogłoską czy spółgłoską
                self.typ = u'samogłoska' if self.stopien_zblizenia == u'otwarta' else u'spółgłoska'
                self.nosowa = name[-1] == u'n' or self.stopien_zblizenia == u'nosowa'

Et Voila! Właśnie powstała klasa, którą będziemy odtąd posługiwać się bardzo często. Dodajmy jej metody pozwalające na ładne wyświetlanie:

1
2
3
4
5
def __repr__(self):
                return u'<"%s"(%s)>' % (self.name, u'dz' if self.dzwieczna else u'bdz')
        
def __str__(self):
        return u'<\%s>' \% self.name    

Odpalmy teraz interpreter Pythona i spróbujmy pobawić się naszą klasą:

1
2
3
4
5
>>> en = Gloska('en')               # en jest teraz obiektem przechowującym głoskę /en/
>>> print en                        # wypiszmy go sobie ładnie
<en>
>>> en.stopien_zblizenia            # zdobądźmy jakieś informacje o naszej głosce
u'otwarta'

Jak widać, wszystko działa zgodnie z naszymi oczekiwaniami, możemy więc przejść dalej

5
Twoja ocena: Brak Ocena: 5 (3 ocen)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com