1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package com.android.tts.compat; 17 18import android.speech.tts.SynthesisCallback; 19import android.speech.tts.SynthesisRequest; 20import android.util.Log; 21 22/** 23 * The SpeechSynthesis class provides a high-level api to create and play 24 * synthesized speech. This class is used internally to talk to a native 25 * TTS library that implements the interface defined in 26 * frameworks/base/include/tts/TtsEngine.h 27 * 28 */ 29public class SynthProxy { 30 31 static { 32 System.loadLibrary("ttscompat"); 33 } 34 35 private final static String TAG = "SynthProxy"; 36 37 // Default parameters of a filter to be applied when using the Pico engine. 38 // Such a huge filter gain is justified by how much energy in the low frequencies is "wasted" at 39 // the output of the synthesis. The low shelving filter removes it, leaving room for 40 // amplification. 41 private final static float PICO_FILTER_GAIN = 5.0f; // linear gain 42 private final static float PICO_FILTER_LOWSHELF_ATTENUATION = -18.0f; // in dB 43 private final static float PICO_FILTER_TRANSITION_FREQ = 1100.0f; // in Hz 44 private final static float PICO_FILTER_SHELF_SLOPE = 1.0f; // Q 45 46 private long mJniData = 0; 47 48 /** 49 * Constructor; pass the location of the native TTS .so to use. 50 */ 51 public SynthProxy(String nativeSoLib, String engineConfig) { 52 boolean applyFilter = shouldApplyAudioFilter(nativeSoLib); 53 Log.v(TAG, "About to load "+ nativeSoLib + ", applyFilter=" + applyFilter); 54 mJniData = native_setup(nativeSoLib, engineConfig); 55 if (mJniData == 0) { 56 throw new RuntimeException("Failed to load " + nativeSoLib); 57 } 58 native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION, 59 PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE); 60 } 61 62 // HACK: Apply audio filter if the engine is pico 63 private boolean shouldApplyAudioFilter(String nativeSoLib) { 64 return nativeSoLib.toLowerCase().contains("pico"); 65 } 66 67 /** 68 * Stops and clears the AudioTrack. 69 */ 70 public int stop() { 71 return native_stop(mJniData); 72 } 73 74 /** 75 * Synchronous stop of the synthesizer. This method returns when the synth 76 * has completed the stop procedure and doesn't use any of the resources it 77 * was using while synthesizing. 78 * 79 * @return {@link android.speech.tts.TextToSpeech#SUCCESS} or 80 * {@link android.speech.tts.TextToSpeech#ERROR} 81 */ 82 public int stopSync() { 83 return native_stopSync(mJniData); 84 } 85 86 public int speak(SynthesisRequest request, SynthesisCallback callback) { 87 return native_speak(mJniData, request.getText(), callback); 88 } 89 90 /** 91 * Queries for language support. 92 * Return codes are defined in android.speech.tts.TextToSpeech 93 */ 94 public int isLanguageAvailable(String language, String country, String variant) { 95 return native_isLanguageAvailable(mJniData, language, country, variant); 96 } 97 98 /** 99 * Updates the engine configuration. 100 */ 101 public int setConfig(String engineConfig) { 102 return native_setProperty(mJniData, "engineConfig", engineConfig); 103 } 104 105 /** 106 * Sets the language. 107 */ 108 public int setLanguage(String language, String country, String variant) { 109 return native_setLanguage(mJniData, language, country, variant); 110 } 111 112 /** 113 * Loads the language: it's not set, but prepared for use later. 114 */ 115 public int loadLanguage(String language, String country, String variant) { 116 return native_loadLanguage(mJniData, language, country, variant); 117 } 118 119 /** 120 * Sets the speech rate. 121 */ 122 public final int setSpeechRate(int speechRate) { 123 return native_setProperty(mJniData, "rate", String.valueOf(speechRate)); 124 } 125 126 /** 127 * Sets the pitch of the synthesized voice. 128 */ 129 public final int setPitch(int pitch) { 130 return native_setProperty(mJniData, "pitch", String.valueOf(pitch)); 131 } 132 133 /** 134 * Returns the currently set language, country and variant information. 135 */ 136 public String[] getLanguage() { 137 return native_getLanguage(mJniData); 138 } 139 140 /** 141 * Shuts down the native synthesizer. 142 */ 143 public void shutdown() { 144 native_shutdown(mJniData); 145 mJniData = 0; 146 } 147 148 @Override 149 protected void finalize() { 150 if (mJniData != 0) { 151 Log.w(TAG, "SynthProxy finalized without being shutdown"); 152 native_finalize(mJniData); 153 mJniData = 0; 154 } 155 } 156 157 private native final long native_setup(String nativeSoLib, String engineConfig); 158 159 private native final int native_setLowShelf(boolean applyFilter, float filterGain, 160 float attenuationInDb, float freqInHz, float slope); 161 162 private native final void native_finalize(long jniData); 163 164 private native final int native_stop(long jniData); 165 166 private native final int native_stopSync(long jniData); 167 168 private native final int native_speak(long jniData, String text, SynthesisCallback request); 169 170 private native final int native_isLanguageAvailable(long jniData, String language, 171 String country, String variant); 172 173 private native final int native_setLanguage(long jniData, String language, String country, 174 String variant); 175 176 private native final int native_loadLanguage(long jniData, String language, String country, 177 String variant); 178 179 private native final int native_setProperty(long jniData, String name, String value); 180 181 private native final String[] native_getLanguage(long jniData); 182 183 private native final void native_shutdown(long jniData); 184 185} 186