Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Stress rules for Latin

Help
Jan Willem
2007-05-10
2013-06-12
  • Jan Willem
    Jan Willem
    2007-05-10

    Hello,

    I and another student are trying to create an eSpeak voice for classical Latin.
    Currently we are working on stress rules.
    For Latin, this should not be too difficult. The five vowels /a/, /e/, /i/, /u/ and /o/ each have a 'long' and 'short' version.
    The basic rules for stress are:
    -2 syllables: accent on first syllable
    -3 or more syllables: accent on penultimate syllable if it is a LONG vowel, and on the antepenultimate if it is a SHORT vowel.

    How would we go about implementing these rules in the _rules file?
    Is there a way to create two symbols that stand for long and short vowels, respectively? (We could not figure out how to do this from the documentation).

    Thanks in advance, Jan-Willem & Maarten

     
    • >The five vowels each have a 'long' and 'short' version.

      How can you tell from the spelling whether a vowel is 'long' or 'short'?
      Do you rely on the text being marked so that long vowels have an accent mark?

      You can have different phonemes for the long and short versions of each vowel. The convention is to use a colon to indicate a long vowel.
      [a]  short "a"
      [a:] long "a"

      Note that the colon symbol can be either part of a phoneme name or a separate phoneme (i.e. [a:] is [a]+[:]).  In your case it's probably better to have separate long phonemes, including the ":".

      You could probably make rules in the  la_rules  file do determine the stress, but it would be complicated.  It would be simpler to use program code in function  SetWordStress() in source code file  dictionary.cpp  to implement the rule: stress on the penultimate syllable, unless it is not long, in which case on the antepenultimate.  In the phoneme file (ph_latin) you can give the long vowels, [a:] [e:] [i:] [o:] [u:] the attribute "long" which the code in SetWordStress() can test.  I can add this code if you wish.

      But my main question about Latin, is the ambiguity in the spelling.  From:
      http://en.wikipedia.org/wiki/Latin_spelling_and_pronunciation
      "Latin orthography did not distinguish between long and short
      vowels, nor between the vocalic and consonantal uses of I and V."

      You state: "accent on penultimate syllable if it is a LONG vowel".  The wikipedia article says it depends on "syllable weight", so the rule is "accent on penultimate syllable if it is a HEAVY", where a syllable is "heavy" either if it has a long vowel, or a short vowel followed by two consonants.  The  SetWordStress() function already has some code to determine heavy syllables, although this may need to be modified for Latin.

       
    • Jan Willem
      Jan Willem
      2007-05-10

      Hi,

      Thanks for your swift reply.
      We do have different phonemes for the long and short vowels (actually it is not just a difference in length but also in quality).
      The distinction made on Wikipedia is indeed better than the one I gave above.
      As for your question on spelling, the source for our Latin is an online dictionary (the input for eSpeak will consist of lemma words and example sentences). The dictionary indicates vowel length/quality with diacritics (macrons), so that will not be a problem.
      We'll take a look at the source code.

       
    • M Tromp
      M Tromp
      2007-05-19

      At a later stage we might have to look at the source code more carefully to add more features to the latin synthesis. For now this was not necessary, because we managed to implement the stress rules by means of the la_rules file.
      Looking at source code was useful though. For instance, it showed us how to put the stress on the penultimate syllable by default, by using the 'stressrule' attribute in the voice file, which is not documented.
      Our dictionary rule file now describes all exceptions where the stress should be on the antepenultimate syllable. Since there is no way of indicating how many syllables follow in the matching conditions of a rule this was a bit tricky. The @ symbol, that indicates that there is at least one more vowel, is not very powerful. It does not allow you to indicate that more than one vowel follows. Moreover, vowels are sometimes not pronounced as such (qu -> qw) and the letter v is a vowel in some latin orthographies. A regular expression-like syntax would prove useful to describe the matching rules.
      Another problem is that vowels with macrons are treated as the ones without macrons by the dictionary. Setting the ISO 8859 character set number in the voice file does not help. Neither does the approach used in the en_rules file for Greek letters. In fact Greek letters are not translated according to these rules by the English synthesis. We use doubled vowels instead of the ones with macrons now to indicate the long variants, however we prefer macrons.
      Here is a sample of the la_rules file to give an idea what is looks like.

      .group a
                   a            a

                   // Weak syllable
                   a (A         =a // diphtongs and gemminates match more strongly
                   a (CA        =a
                   a (CA%       =a
                   a (Cae       =a
                   a (Cau       =a
                   a (Cei       =a
                   a (Ceu       =a
                   a (Coe       =a
                   a (quA       =a // u is not a vowel here
      //           a (Cvv       =a // v is a vowel in some orthographies

                   // Weak syllable but not penultimate
                   a (A%@       a
                   a (oe@       a
                   a (CAC@      a
                   a (CAA       a //diphtongs and gemminates match more strongly
                   a (CA%@      a
                   a (Cae@      a
                   a (Cau@      a
                   a (Cei@      a
                   a (Ceu@      a
                   a (Coe@      a
                   a (quae@     a // ae is the only diphtong that follow qu in practice
                   a (quA%@     a
      //           a (Cvv@      a

                   aa (+++      a:
                   ae (+++      aI
                   au (+++      aU

      I tried compiling the source using Microsoft Visual C++ 2005 (v8.0), but I got some errors. Here is the fragment of the compilation log with the errors:

      ...
      e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\src\voices.cpp(1396) : error C2143: syntax error : missing ';' before 'const'
      e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\src\voices.cpp(1396) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
      e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\src\voices.cpp(1454) : error C2146: syntax error : missing ';' before identifier 'espeak_VOICE'
      e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\src\voices.cpp(1454) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
      e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\src\voices.cpp(1454) : error C2086: 'int ESPEAK_API' : redefinition
      ...

      Are there perhaps some settings I need to change before I can compile it?

       
      • > tried compiling the source using Microsoft Visual C++ 2005 (v8.0), but I got some errors.

        "ESPEAK_API" needed for DLL and Shared Library versions, but not for stand-alone versions of eSpeak.  Define it as nothing in  speech.h.  This has been fixed for eSpeak 1.25 (now available).
          #define ESPEAK_API

        >Looking at source code was useful though. For instance, it showed us how to put the stress on the penultimate syllable by default, by using the 'stressrule' attribute in the voice file,

        Yes.  I would usually add a section in SelectTranslator() in tr_languages.cpp for each language which sets its attributes.  Some of these can also be set (or changed) in the voice file.  I'll add a 'la' section for the next development version of eSpeak after 1.25.  This will be available at http://espeak.sf.net/test/latest.html.

        > The @ symbol, that indicates that there is at least one more vowel, is not very powerful. It does not allow you to indicate that more than one vowel follows.

        You can perhaps use multiple @ to detect multiple syllables.  @@ will match two vowels which are separated by a non-vowel.  A single @ will match one more consecutive vowels.  I have also added a new symbol, X, in version 1.24.12. This matches on "no more vowels until the word boundary".  So a rule:
           a (CX

        matches on "a", followed by a consonant, and then possibly more non-vowels.

        As you say, the ambiguity of whether 'v' and 'i' are vowels is a problem.

        > A regular expression-like syntax would prove useful to describe the matching rules.

        Yes, but eSpeak was originally designed for English (which has a large number of rules) and to run on a slow processor.  So writing a larger number of simple rules is probably more efficient.

        > Another problem is that vowels with macrons are treated as the ones without macrons by the dictionary.

        By default, if an accented letter is not recognized by la_rules, eSpeak replaces it by the corresponding non-accented character.

        You can add a group in la_rules for each accented letter (a-macron, e-macron, etc) and treat then as separate letters.  See pt_rules as an example.  Alternatively, eSpeak has a mechanism in which certain characters in the input text are replaced by either one or two replacement characters before starting the translation.  Currently this is only available in the program code.  This is used for Croatian (see language case L('h','t') in tr_languages) to replace cyrillic characters by latin characters.

         
    • M Tromp
      M Tromp
      2007-05-19

      >By default, if an accented letter is not recognized by la_rules, eSpeak replaces it by the corresponding non-accented character.

      >You can add a group in la_rules for each accented letter (a-macron, e-macron, etc) and treat then as separate letters. See pt_rules as an example. Alternatively, eSpeak has a mechanism in which certain characters in the input text are replaced by either one or two replacement characters before starting the translation. Currently this is only available in the program code. This is used for Croatian (see language case L('h','t') in tr_languages) to replace cyrillic characters by latin characters.

      This is what I tried. Strangely it does work for many diacritics, but not for the macron.

       
      • > Strangely it does work for many diacritics, but not for the macron. 

        I've just tried it here and it works OK.
        I added a rule to es_rules translate a-macron to vowel [u].
        Then I spoke input text which included a-macron and it spoke vowel [u] rather than [a].
        Note that the *_rules and *_list files must use UTF-8 encoding for non-ascii characters.

        Are you using a single character a-macron (character cide U+101) or two characters, 'a' (U+61) + combining_macron (character code U+304) ?

        Are you using the command-line version of eSpeak or the sapi5 version?
        Is your input text UTF-8?  If not, what character encoding are you using?

         
        • M Tromp
          M Tromp
          2007-05-19

          You are quite right. It does work! However it does not in espeakedit, which is what I used for the testing.
          Thanks a lot for your help! This new 'X' symbol is really useful. Compiling works now with the added macro, only linking still doesn't work:

          Generating Code...
          Compiling manifest to resources...
          Linking...
          tr_english.obj : error LNK2001: unresolved external symbol "protected: virtual int __thiscall Translator::ChangePhonemes(struct PHONEME_LIST2 *,int,int,struct PHONEME_TAB *,struct CHANGEPH *)" (?ChangePhonemes@Translator@@MAEHPAUPHONEME_LIST2@@HHPAUPHONEME_TAB@@PAUCHANGEPH@@@Z)
          tr_languages.obj : error LNK2001: unresolved external symbol "protected: virtual int __thiscall Translator::ChangePhonemes(struct PHONEME_LIST2 *,int,int,struct PHONEME_TAB *,struct CHANGEPH *)" (?ChangePhonemes@Translator@@MAEHPAUPHONEME_LIST2@@HHPAUPHONEME_TAB@@PAUCHANGEPH@@@Z)
          translate.obj : error LNK2019: unresolved external symbol "protected: virtual int __thiscall Translator::ChangePhonemes(struct PHONEME_LIST2 *,int,int,struct PHONEME_TAB *,struct CHANGEPH *)" (?ChangePhonemes@Translator@@MAEHPAUPHONEME_LIST2@@HHPAUPHONEME_TAB@@PAUCHANGEPH@@@Z) referenced in function "int __cdecl IsAlpha(unsigned int)" (?IsAlpha@@YAHI@Z)
          translate.obj : error LNK2019: unresolved external symbol "private: void __thiscall Translator::MakePhonemeList(int,int)" (?MakePhonemeList@Translator@@AAEXHH@Z) referenced in function "public: void * __thiscall Translator::TranslateClause(struct _iobuf *,void const *,int *,char * *)" (?TranslateClause@Translator@@QAEPAXPAU_iobuf@@PBXPAHPAPAD@Z)
          .\Debug/espeak.exe : fatal error LNK1120: 2 unresolved externals
          Build log was saved at "file://e:\espeak-1.24.11\espeak-1.24.11\windows_cmd\Debug\BuildLog.htm"
          espeak - 5 error(s), 226 warning(s)
          ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

           
          • > However it does not in espeakedit, which is what I used for the testing.

            That sounds like a character set problem.  When you type a-macron into the espeakedit text window, what character code(s) does espeakedit receive?  If it receives it as UTF-8 then it should be OK.  If you're using an 8-bit character set, then it can't be Latin1 (ISO-8859-1) because that doesn't include the macron-vowels.  Perhaps you're using Latin4 (ISO-8859-4), which does include the macron-vowels.

            But I've just checked.  eSpeak doesn't include the Latin4 character data!
            I've fixed this now for eSpeak 1.25.01, which is available at http://espeak.sf.net/test/latest.html

            I've also include a Latin section in tr_languages.cpp.  This sets the stress rule to 2 (penultimate) and the 8-bit character set to Latin4.  Perhaps espeakedit will now recognise macron-vowels?

            > This new 'X' symbol is really useful.

            You need eSpeak version 1.24.12 of later.

            > Compiling works now with the added macro, only linking still doesn't work:

            Probably source file  phonemelist.cpp  is not included in the compilation.  The .dsp file is fixed to include it in eSpeak 1.25.

             
            • M Tromp
              M Tromp
              2007-05-23

              Macrons it still don't work in eSpeakedit. The text window displays unicode, but it appears to convert it's contents to some more restricted character set. This problem is not just with the latin synthesis. For instance, the greek characters used with the english synthesis aren't handled properly either.

              There is something I overlooked when making the dictionary rules. Apart from the diphthongs ae, au, eu, and oe, there are more letter combinations which need to be treated as one. There is ph, th, and ch which are pronounced as one phoneme, but also ng, qu, pr, tr, cr, chr, br, dr, gr, pl, cl, bl, and gl need to be treated as one. This will lead to a combinatorial explosion of rules if I were to write out all possibilities. Would it be possible to create symbols that match classes of letter combinations?
              e.g.:
              P = {ng, qu, pr, tr, cr, chr, br, dr, gr, pl, cl, bl, gl, ph, th, ch}
              Q = {ae, au, eu, oe}

              By the way, I managed to get a little further compiling the program. Now it asks for the Portaudio library PAStaticWMME.lib. I'll need to obtain that first.

               
              • > Macrons it still don't work in eSpeakedit.

                Try version 1.25.05 of espeakedit at  http://espeak.sf.net/test/latest.html.
                Previously it was linked with the non-unicode version of wxWidgets.

                > Now it asks for the Portaudio library PAStaticWMME.lib.

                I've now included this in  espeak-1.25.05.zip,  in the directory windows_cmd.
                Note that the command-line version of eSpeak will need the input text to be either UTF-8 or Latin4 (ISO-8859-4).

                > There are more letter combinations which need to be treated as one. This will lead to a combinatorial explosion of rules if I were to write out all possibilities.

                Please can you give me your la_rules, which assume there are symbols (as you suggest) to represent these consonant and diphthong combinations?  So that I can see what you need to do.  If the rules are similar for each vowel (.group a, .group e, etc), then just one of these will be sufficient.

                 
                • M Tromp
                  M Tromp
                  2007-05-30

                  eSpeakedit works great now. Thanks!

                  This is what I'd like to have as the rule set for 'a'. The rules for the other vowels are very similar.

                  .group a
                               a            a

                               // Weak penultimate syllable: put stress on antepenutimate
                               a (AX        =a
                               a (FX        =a
                               a (CAX       =a
                               a (CFX       =a
                               a (x         a
                               a (GAX       =a
                               a (GFX       =a
                              
                               // Diphtongs
                               ae (+++      aI
                               au (+++      aU

                  Here, symbol F should match the diphtongs, which are letter combinations {ae, au, eu, oe}
                  Symbol G should match any of the combinations {ng, qu, pr, tr, cr, chr, br, dr, gr, pl, cl, bl, gl, ph, th, ch}
                  Other choices than F and G for these classes are of cource fine. If this does not fit well in the current architecture a symbol for plosives {b, p, d, t, g, c, k, q} would already help a lot.

                   
                  • You can now define letter sequences for matching in rules, in eSpeak 1.25.14, available at:
                    http://espeak.sf.net/test/latest

                    Define these at the start of your  la_rules  file as follows:

                    .L01  ae au eu oe
                    .L02  ng qu pr tr cr chr br dr gr pl cl bl gl ph th ch

                    Each definition must start with dot L and a two digit number in the range 1 to 19.
                    Each letter sequence has one or more characters.

                    Use them in the following rules as follows:
                       a (L01X   =a
                       a (L02L01X  =a
                    etc.

                    Is Latin working OK now?
                    Which set of phonemes are you using? Italian?
                    If you send me your data files, and notes on the orthography of the input text, I'll include them in the eSpeak releases.

                     
  • zlorf
    zlorf
    2012-10-27

    Hi,

    I'm trying to use eSpeak to read latin poetry. I tested macrons and they work okay.
    But I would like also to explicitely mark accents. I mean, is it possible to turn off default accent rules and provide input with accents like this:

    'Āt rēg'īna grav'ī

    I know that I could use phenomem (like [] ), but that is not desired way (I don't know how to "translate" text into phenomens).

    The only idea that came to my mind is as follow:
    1. Enter text with macrons to eSpeak with -qx flags
    2. Take output (phenomens) and parse it, stripping default accents and placing proper ones.

    With regards,
    Jacek Tomaszewski

     
  • > I would like also to explicitely mark accents.

    If you mark the long vowels with macrons, could the stressed syllables be determined automatically with rules?

    Or is Latin stress ambiguous even if the long vowels are known?

     
  • zlorf
    zlorf
    2012-10-29

    Maybe in prosaic text stress rules are quite clear - and I think you have implemented them well. But for poetic, metric text - accents are there, where the meter demands. :)

     
  • zlorf
    zlorf
    2012-10-30

    Example:

    Āt rēgīna gravī jāmdūdūm saucia cūra
    

    Is translated to:

    [[_ a:t_ Re:g'i:na_ g@-*'awi:_ ja:md'u:du:m_ s'aUkI;a_ k'u:Ra_]]
    

    whereas it should be:

    [[_ 'a:t_ Re:g'i:na_ g@-*aw'i:_ ja:md'u:du:m_ s'aUkI;a_ k'u:Ra_]]
    

    Note accent at begining and difference in gravi.

     
  • OK, we need a symbol which you can use to indicate the stressed syllable.  Apostrophe and other quotation marks may not be suitable because it's ambiguous at the start or end of a word.  It may indicate a quotation.

    Another option would be to put an accent mark on a vowel (as is done in Spanish), but in Latin some vowels already have a macron to indicate a long vowel, and it may not be simple to type both a macron and an accent on a vowel.

    We could have 3 types of vowel marks: stress, macron (long vowel), and  stress+long (perhaps circumflex accent?), but that may be too complicated.

    Or we could use some other symbol to indicate stress, such as a plus-sign '+'.  That would need a an exception in the eSpeak program to indicate that this symbol can occur inside a word in Latin (although it's really only a convention for your own use).

    Any ideas?

     
  • zlorf
    zlorf
    2012-11-16

    The last option sounds best for me (and it could be + sign or @, whatever), although there need to be also the way to turn default accenting off.