the text to phoneme conversion
Overview
Aramacao employs two different ways for converting text into phonemes. The first way is to use a dictionary where every possible word is listed along the phonemes that make it: this method is currently used for the English language. The second way is to use some general rules to translate any given letter to a corresponding phoneme: this method is currently used for the Italian and Spanish languages.
The code
The relevant code for converting text into phonemes is in the file script_breakdown.c. All the functions defined in script_breakdown.c are called by functions defined in the script.c file.
These functions can be classified as follows:
- Wrappers
-
these functions call the right functions to convert a given string of text into phonemes, given an integer input which identifies a chosen language
- script_breakdown_line
-
this function is used when adding or editing a line of text
- script_breakdown_word
-
this function is only used when editing a word
- Utility
-
these are functions used for common tasks
- script_breakdown_common
-
breaks a line into words and then uses a pointer to function for calling the right function to convert those words into phonemes, the pointer to function is passed from script_breakdown_line
- script_breakdown_phoneme_init
-
this small function initializes a new phoneme
- get_char
-
returns a character at a given position in a string
- Converters
-
these functions can convert a given word of a certain language into phonemes
- ___breakdown_phoneme
-
when the laguage selected is "none" (0)
- en_breakdown_phoneme
-
for the English language (1), this function uses a dictionary
- it_breakdown_phoneme
-
for the Italian language (2)
- es_breakdown_phoneme
-
for the Spanish language (3)
_______________________ | | | script_breakdown_line | |_______________________| | ___________|_____________ | | | script_breakdown_common | |___________._____________| :..................................... ___________:__________ : ___________:__________ : | |:| |: | ___breakdown_phoneme |:| it_breakdown_phoneme |: |______________________|:|______________________|: | : | : | ___________:__________ | ___________:__________ | | ||| | | | en_breakdown_phoneme ||| es_breakdown_phoneme | | |______________________|||______________________| | | | | | | | | ____|___________|______________ | | | |---| | | script_breakdown_phoneme_init | | | |_______________________________|---+-----| | | | _|________ | | | '---| get_char | |__________|
The phoneme set
Aramacao internally uses the phoneme set of the Carnegie Mellon University Pronouncing Dictionary. So the phoneme names are the same as those used by the CMU Pronouncing Dictionary. An extra phoneme (STOP) was added, it is a mute (rest position) phoneme.
Phoneme Example Translation IPA ------- ------- ----------- --- AA odd AA D ɒ AE at AE T æ AH hut HH AH T ʌ AO ought AO T ɑ AW cow K AW aʊ AY hide HH AY D aɪ B be B IY b CH cheese CH IY Z tʃ D dee D IY d DH thee DH IY ð EH Ed EH D e ER hurt HH ER T ɜ EY ate EY T eɪ F fee F IY f G green G R IY N g HH he HH IY h IH it IH T ɪ IY eat IY T i JH gee JH IY dʒ K key K IY k L lee L IY l M me M IY m N knee N IY n NG ping P IH NG ŋ OW oat OW T oʊ OY toy T OY ɔɪ P pee P IY p R read R IY D r S sea S IY s SH she SH IY ʃ T tea T IY t TH theta TH EY T AH θ UH hood HH UH D ʊ UW two T UW u V vee V IY v W we W IY w Y yield Y IY L D j Z zee Z IY z ZH seizure S IY ZH ER ʒ STOP rest position (no sound)
The CMU Pronouncing Dictionary refers to the American English pronunciation. |
Dictionary based conversion
The function script_breakdown_common calls the function used to convert a word into phonemes using as arguments: a file handler (for the dictionary file), a pointer to the first character of the word, a pointer to the last character (\0) and a pointer to a Word struct.
An excerpt of the CMU dictionary:
APPRECIATION AH0 P R IY2 SH IY0 EY1 SH AH0 N APPRECIATIVE AH0 P R IY1 SH IY0 EY2 T IH0 V APPRECIATIVELY AH0 P R IY1 SH IY0 EY2 T IH0 V L IY0 APPREHEND AE2 P R AH0 HH EH1 N D
The en_breakdown_phoneme function has to: strip punctuation characters (e.g. apples → apples), convert all the characters to uppercase (apples → APPLES), cycle through all the entries of the dictionary and finally extract the phonemes.
It calls script_breakdown_phoneme_init to initialize the phoneme.
If a word is not found in the dictionary, every characters of that word is converted in a "rest position" phoneme. It may be a foreign word or an onomatopoeic word: those words can be manually edited later.
Rules based conversion
The function script_breakdown_common calls the function used to convert a word into phonemes with the arguments: a NULL file handler (for the unused dictionary file), a pointer to the first character of the word, a pointer to the last character (\0) and a pointer to a Word struct.
The it_breakdown_phoneme function has to: cycle through all the characters of the given word, usually ignore non-letter characters, translate those characters into corresponding phonemes.
Since the phonemic value of a letter may depend on the following letters, the function get_char is used to retrieve one or more characters from the string to assign the correct phonemic value.
switch (get_char(copy->str, i)) { ... case 'h': break; ... }
switch (get_char(copy->str, i)) { ... case 'd': p = D; break; ... }
switch (get_char(copy->str, i)) { ... case 'x': p = K; p_1 = S; break; ... }
switch (get_char(copy->str, i)) { ... case 'c': switch (get_char(copy->str, i+1)) { case 'i': switch (get_char(copy->str, i+2)) { case 'i': case 172: /* ì - non esiste */ case 'e': case 168: case 169: case 'o': case 178: case 179: case 'u': case 185: case 'a': case 160: case 161: i++; default: p = CH; break; } break; case 172: /* ì */ case 'e': case 168: /* è */ case 169: /* é */ p = CH; break; default: p = K; break; } break; ... }
Once the phoneme is determined it calls script_breakdown_phoneme_init to initialize said phoneme.
Example
Or: how the "none" language was added.
Creating a function for conversion
The "none" language simply convert every character of a word into a "rest" (STOP) phoneme.
The code is therefore very simple.
void ___breakdown_phoneme(FILE *fp, guchar *ap, guchar *bp, Word *word) { guint i; for (i = 0; i < bp - ap; i++) { Phoneme *phoneme = script_breakdown_phoneme_init(STOP); word->phonemes = g_slist_append(word->phonemes, phoneme); } }
This function must be added to the script_breakdown.c file, including a function prototype at the beginning of the file.
void ___breakdown_phoneme(FILE *, guchar *, guchar *, Word *);
Adding the conversion function to the list
At the beginning of the script_breakdown.c file there is a list of function pointers called LANG_FUNC_LIST. You have to add your newly created function at the end of the list:
void (* LANG_FUNC_LIST[]) (FILE *, guchar *, guchar *, Word *) = { ... ___breakdown_phoneme, };
Adding a dictionary file
Even if your function does not use a dictionary, you have to add one to the list LANG_DIC_LIST. Since ___breakdown_phoneme does not need a dictionary, it suffices to add an empty string at the end of the list:
gchar * LANG_DIC_LIST[] = { ... "", };
If otherwise your function need a dictionary, you have to add the name of the dictionary file, e.g. "EN_dictionary.txt".
Aramacao will search for that file in its dic directory.
You may need to add your dictionary to the aramacaodic_DATA array located in Makefile.am if you want to install it through make install. |
Adding your language to the list of supported languages
Now you have to search for the script_lang_list function in the script.c file. It is the first one.
You have to add your language name to the LANG_LIST list:
gchar * script_lang_list(gint k) { gchar * LANG_LIST[] = { ... _("none"), ""}; gchar * ret = malloc(sizeof(LANG_LIST[k])); strcpy(ret, LANG_LIST[k]); return ret; }