【问题标题】:Text to Speech get System default pitch and speech rateText to Speech 获取系统默认音高和语速
【发布时间】:2019-04-23 22:04:43
【问题描述】:

当用户将网络合成语音设置为默认值时,我的应用程序会缓存经常出现的请求,以防止未来出现网络延迟。

我的代码here 演示了我是如何做到这一点的。简而言之,它将引擎名称和话语与请求相匹配,如果它们匹配,我会流式传输缓存的音频,而不是使用 TTS 引擎。

如果用户随后在 Android 文本到语音设置中更改了他们的音调和语速,缓存的音频当然将不再反映这一点,需要忽略并“重新缓存”,或者相应地处理音频。

我的问题:如何获得系统默认设置,用于音高和语速。

设置 Pitch & Rate,TextToSpeech API 中提供了公开的方法:

/**
 * Sets the speech rate.
 *
 * This has no effect on any pre-recorded speech.
 *
 * @param speechRate Speech rate. {@code 1.0} is the normal speech rate,
 *            lower values slow down the speech ({@code 0.5} is half the normal speech rate),
 *            greater values accelerate it ({@code 2.0} is twice the normal speech rate).
 *
 * @return {@link #ERROR} or {@link #SUCCESS}.
 */
public int setSpeechRate(float speechRate) {
    if (speechRate > 0.0f) {
        int intRate = (int)(speechRate * 100);
        if (intRate > 0) {
            synchronized (mStartLock) {
                mParams.putInt(Engine.KEY_PARAM_RATE, intRate);
            }
            return SUCCESS;
        }
    }
    return ERROR;
}

/**
 * Sets the speech pitch for the TextToSpeech engine.
 *
 * This has no effect on any pre-recorded speech.
 *
 * @param pitch Speech pitch. {@code 1.0} is the normal pitch,
 *            lower values lower the tone of the synthesized voice,
 *            greater values increase it.
 *
 * @return {@link #ERROR} or {@link #SUCCESS}.
 */
public int setPitch(float pitch) {
    if (pitch > 0.0f) {
        int intPitch = (int)(pitch * 100);
        if (intPitch > 0) {
            synchronized (mStartLock) {
                mParams.putInt(Engine.KEY_PARAM_PITCH, intPitch);
            }
            return SUCCESS;
        }
    }
    return ERROR;
}

鉴于上述方法都导致将值放入绑定 TTS 引擎 (link) 的 Private Bundle

private final Bundle mParams = new Bundle();

我使用反射来查看这些值是否被绑定引擎默认/持久化或注入。下面是一个精简示例,其中the Class 扩展了TextToSpeech

private int getSpeechRate() {

    Bundle reflectBundle;

    try {

        final Field f = this.getClass().getSuperclass().getDeclaredField(TTSDefaults.BOUND_PARAMS);
        f.setAccessible(true);
        reflectBundle = (Bundle) f.get(this);

        if (reflectBundle != null && !reflectBundle.isEmpty()) {
                examineBundle(reflectBundle);

            if (reflectBundle.containsKey(TTSDefaults.KEY_PARAM_RATE)) {

                final int reflectRate = reflectBundle.getInt(TTSDefaults.KEY_PARAM_RATE);

                // log

                return reflectRate;

            } else {
                // missing
            }

        } else {
            // empty or null
        }

    } catch (final NoSuchFieldException e) {
    } catch (final IllegalAccessException e) {
    } catch (final NullPointerException e) {
    }

    return -1;
}

/**
 * For debugging the bundle extras
 *
 * @param bundle containing potential extras
 */
private void examineBundle(@Nullable final Bundle bundle) {

    if (bundle != null) {
        final Set<String> keys = bundle.keySet();
        //noinspection Convert2streamapi
        for (final String key : keys) {
            Log.v(CLS_NAME, "examineBundle: " + key + " ~ " + bundle.get(key));
        }
    }
}

这些值丢失了,因此,也许可以理解,这不是它们“全局”持久化的方式。

当我第一次尝试解决这个问题时,我认为这将是微不足道的 - 我希望事实证明是这样的,但我就是只见树木不见森林......

感谢您阅读本文 - 帮助!

【问题讨论】:

    标签: java android text-to-speech saiy


    【解决方案1】:

    首先,我假设您熟悉 TextToSpeech 源代码。

    我认为您无法通过反射获得音高和语速。这些值存储在 TextToSpeech 类的实例变量中,每次查询文本时都会将它们提供给引擎。这意味着当您调用 setSpeechRatesetPitch 方法时,它们不会更改全局文本到语音设置的音调和语速。

    除此之外,pitchspeech rate 在 Android 安全系统设置中定义,用户必须通过系统 UI 或专用 API(系统应用程序或 root 访问)显式修改这些值的首选项,不是由应用程序直接修改的。

    使用以下代码阅读与音调和语速相关的安全设置:

    Settings.Secure.getInt(getContentResolver(), Settings.Secure.TTS_DEFAULT_RATE);
    Settings.Secure.getInt(getContentResolver(), Settings.Secure.TTS_DEFAULT_PITCH);
    

    Google TalkbackTextToSpeechSettings 中可以看到略有不同的用法。

    Settings.SettingNotFoundException包围,如果没有设置值,将被抛出,在这种情况下你可以回退到the hiddenTextToSpeech.Engine.FALLBACK_TTS_DEFAULT_PITCH的等效值

    或者,您可以添加一个额外的参数作为默认值。

    Settings.Secure.getInt(getContentResolver(), Settings.Secure.TTS_DEFAULT_PITCH, FALLBACK_TTS_DEFAULT_PITCH);
    

    【讨论】:

    • 谢谢您-我搜索了该死的安全设置,但不知何故没有找到您引用的那些...它们正在为我返回值,但除非用户在TextToSpeech 设置(或应用程序直接更改安全设置)。也许这就是为什么您没有在测试中获得值的原因?我将稍微编辑您的答案,以便将来的读者更简洁。让我知道您对编辑感到满意,我会奖励您。
    • 你是对的,我没有改变它们。您的编辑对我来说看起来不错,只是它没有提到 null 情况。如果你得到 null,假设 TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_PITCH,你会怎么做?
    • 啊,我需要重新编辑。应该是getInt()。如果没有默认值,就会抛出异常。我还将添加替代默认值选项。
    【解决方案2】:

    上面写着document

    语速。 1.0 是正常语速,较低的值会减慢语速(0.5 是正常语速的一半),较大的值会加快语速(2.0 是正常语速的两倍)。

    演讲音调。 1.0 是正常音高,数值越低合成语音的音调越低,数值越大则音调越高。

    所以,setPitch((float) 1.0)setSpeechRate((float) 1.0) 设置了默认的音调和语速。

    【讨论】:

      【解决方案3】:

      如果您需要将设备设置中的音高设置为 TextToSpeech,请尝试以下操作:

      float pitch = Settings.Secure.getFloat(context.getContentResolver(), Settings.Secure.TTS_DEFAULT_PITCH);
      textToSpeech.setPitch((float) (pitch / 100.0));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-29
        • 2016-03-12
        相关资源
        最近更新 更多