Java — Фонетическая транскрипция — Преобразование одного формата в другой на SAMPA

#java #text-to-speech

#java #преобразование текста в речь

Вопрос:

У меня есть строка, которая представляет собой фонетическую транскрипцию текста в так называемом формате lia_phon (французский фонематизатор). Строка выглядит примерно так:

ttoujjourr ттуджурр

Эта строка является фонетической транскрипцией французского слова «toujours» (означает всегда).

Что я хочу сделать, так это преобразовать эту строку в формат SAMPA, учитывая список эквивалентности между фонемами lia_phon и sampa.

Итак, например, у нас есть:

(LIA_phon, SAMPA)

tt, t

ou, u

jj, Z

rr, R

Итак, слово «toujours» в формате SAMPA — это tuZuR.

Я хотел бы автоматически конвертировать word из Java. Есть идеи, как это сделать? Я работаю в системе TTS Mary TTS, которая работает исключительно с фонемами SAMPA.

Большое спасибо,

Эмма

Ответ №1:

Предполагая, что LIA_phon фонемы всегда имеют длину в 2 символа, вы могли бы создать простой Map способ хранения преобразований. Затем вы могли бы написать метод, который выполняет итерацию по LIA_phon входной строке по 2 символа за раз, ищет фонемы из 2 символов на вашей карте и добавляет их к StringBuilder экземпляру. Ниже я написал реализацию и подтвердил, что она работает с модульным тестированием (также приведенным ниже).

LiaPhon.java

 import java.util.HashMap;
import java.util.Map;

public class LiaPhon {
    private final static Map<String,String> LIA_PHONE_TO_SAMPA = new HashMap<String,String>();
    static {
        LIA_PHONE_TO_SAMPA.put("tt", "t");
        LIA_PHONE_TO_SAMPA.put("ou", "u");
        LIA_PHONE_TO_SAMPA.put("jj", "Z");
        LIA_PHONE_TO_SAMPA.put("rr", "R");
        // etc.
    }

    public static String liaPhone2SAMPA(String liaPhon) {
         int length = liaPhon.length();
         if (length % 2 != 0) {
             throw new IllegalArgumentException("LIA_phon must contain an even number of characters!");
         }
         StringBuilder sampa = new StringBuilder();
         for (int i=0; i<length; i =2) {
             String liaPhonPhoneme = liaPhon.substring(i, i 2);
             String sampaPhoneme = LIA_PHONE_TO_SAMPA.get(liaPhonPhoneme);
             if (sampaPhoneme == null) {
                 throw new IllegalArgumentException("Unrecognized LIA_phon phoneme: "   liaPhonPhoneme);
             }
             sampa.append(sampaPhoneme);
         }
         return sampa.toString();
    }
}
  

LiaPhonTest.java

 import static org.junit.Assert.*;

import org.junit.Test;

public class LiaPhonTest {
    @Test
    public void testLiaPhone2SAMPA() {
        assertEquals("tuZuR", LiaPhon.liaPhone2SAMPA("ttoujjourr"));
    }

    @Test(expected=IllegalArgumentException.class)
    public void testLiaPhone2SAMPAWithOddNumberOfLetters() {
        LiaPhon.liaPhone2SAMPA("ttoujjour");
    }   

    @Test(expected=IllegalArgumentException.class)
    public void testLiaPhone2SAMPAWithInvalidPhoneme() {
        LiaPhon.liaPhone2SAMPA("ttoujj$$ourr");
    }   
}
  

Комментарии:

1. @user779712: Всегда пожалуйста. Пожалуйста, отметьте мой ответ правильным, нажав на галочку слева от ответа.

Ответ №2:

Звучит как довольно простая операция замены строки.

 public static Map<String, String> liaToSampa = new HashMap<String, String>();
static {
liaToSampa.put("tt", "t");
liaToSampa.out("ou","u");
liatoSampa.put("jj","Z");
liaToSampa.put("rr","R");
}
// etc

public static String translateLiaToSampa(String liaWord) {
   String result = liaWord;
   for (Map.Entry<String, String> entry : liaToSampa.entrySet()) {
       String liaPhoneme = entry.getKey();
       String sampaPhoneme = entry.getValue();
       result = result.replaceAll(liaPhoneme, sampaPhoneme);
   }
   return resu<
}
  

Комментарии:

1. Большое вам спасибо, это работает! Считаете ли вы, что это более оптимизированный способ сделать это по сравнению с решением Asaph?

2. @user779712 мое решение гораздо менее эффективно, но, возможно, более понятно. Вам решать, насколько производительной вам нужна эта часть приложения.