文本到语音发音数字,如“4th”、“8ths”或“2nd”

Text to speech pronouncing numbers like "4th", "8ths", or "2nd"

前一段时间我写了一些代码,将 Double 转换为字符串,其中字符串被格式化为可读分数。

举个例子

4.75 => "4 and 3 4ths"
1.5 => "1 and 1 half"
1.33 => "1 and 1 3rd"

大多数数字的发音都符合预期,但有一些明显的例外。而不是将文本“4ths”发音为 "fourths",而是发音为 "four tee ache ess"。这是一个演示这一点的例子。

//this works
tts.speak("1 and 3 fourths", TextToSpeech.QUEUE_FLUSH, null);    
//this works
tts.speak("1 and 1 3rd", TextToSpeech.QUEUE_FLUSH, null); 
//this works
tts.speak("1 and 1 4th", TextToSpeech.QUEUE_FLUSH, null); 

//this does not work
tts.speak("1 and 3 4ths", TextToSpeech.QUEUE_FLUSH, null);
//this does not work
tts.speak("1 and 3 4thes", TextToSpeech.QUEUE_FLUSH, null);
//this does not work
tts.speak("1 and 3 4th-s", TextToSpeech.QUEUE_FLUSH, null);

最奇怪的是,大约一年前,当我第一次编写代码时,它运行良好,"ths" 后缀的发音正如人们所期望的那样。也许我在这一点上弄错了......

无论如何,问题似乎是数字后跟 2 个字母读起来像一个完整的单词,而数字后跟 3 个或更多字母读起来像一系列数字。我 可以 通过将所有数字替换为对应的单词来增加算法的复杂性,但是我在这方面工作的时间越长,我就越开始认为我正在重新发明轮子。 API 似乎并不表示为 speak() 方法指定发音的方式。我错过了什么吗?

这种行为将因 TextToSpeech 引擎而异——例如,Google TTS 引擎的行为将不同于 SVOX PICO(模拟器 < API 24)引擎...因此每个引擎的行为略有不同并不是您的错...如果有任何发音控制,则引擎负责通过设置将它们直接提供给最终用户。

您可能只是在与以前不同的引擎上进行测试...甚至是对同一引擎的更新。

您可以只测试三星、Google 和 PICO 等主要引擎,并尝试找到行为的共同点。我怀疑你是对的:在这种情况下拼出单词是最好的选择。

您可以将要使用的引擎指定为 TextToSpeech 构造函数的最后一个参数 (String),并且您可以通过转到 (home\settings\language&locale\TTS) 或者像这样的代码:

private ArrayList<String> whatEnginesAreInstalled(Context context) {
    final Intent ttsIntent = new Intent();
    ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
    final PackageManager pm = context.getPackageManager();
    final List<ResolveInfo> list = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);
    ArrayList<String> installedEngineNames = new ArrayList<>();
    for (ResolveInfo r : list) {
        String engineName = r.activityInfo.applicationInfo.packageName;
        installedEngineNames.add(engineName);

        // just logging the version number out of interest
        String version = "null";
        try {
            version = pm.getPackageInfo(engineName,
            PackageManager.GET_META_DATA).versionName;
            } catch (Exception e) {
                Log.i("XXX", "try catch error");
            }
        Log.i("XXX", "we found an engine: " + engineName);
        Log.i("XXX", "version: " + version);
    }
    return installedEngineNames;
}

正如 Boober Bunz 所解释的,这些功能因引擎而异。它也可能会随着较新版本的引擎而改变。我建议最好的选择是将所有内容都转换为单词,例如 Fourths 以使其在引擎之间保持一致。为了快速修复,您可以尝试 4th's,因为它似乎比您提到的其他无效词更有效。