Text to Speech 获取系统默认音调和语速

Text to Speech get System default pitch and speech rate

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

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

如果用户随后在 Android Text to Speech Settings 中改变了他们的音调和语速,缓存的音频当然将不再反映这一点,需要被忽略和 're-cached',或者相应地处理音频。

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

设置 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();

我使用反射来查看这些值是 defaulted/persisted 还是由绑定引擎注入的。下面是一个浓缩示例,其中 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));
        }
    }
}

缺少值,因此,也许可以理解,这不是它们 'globally' 保留的方式。

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

感谢您阅读到这里 - 帮助!

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

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

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

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

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

Google Talkback and TextToSpeechSettings.

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

Settings.SettingNotFoundException 括起来,如果没有设置值将被抛出,在这种情况下你可以回退到 the hidden TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_PITCH

的等效值

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

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

它在 document

中说

Speech rate. 1.0 is the normal speech rate, lower values slow down the speech (0.5 is half the normal speech rate), greater values accelerate it (2.0 is twice the normal speech rate).

Speech pitch. 1.0 is the normal pitch, lower values lower the tone of the synthesized voice, greater values increase it.

因此,setPitch((float) 1.0)setSpeechRate((float) 1.0) 设置默认音高和语速。

如果您需要从设备设置到您的 TextToSpeech 来设置音调,请试试这个:

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