1 /* 2 * Copyright (C) 2009 Google Inc. 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 */ 16 package android.tts; 17 18 import android.media.AudioManager; 19 import android.media.AudioSystem; 20 import android.util.Log; 21 import java.lang.ref.WeakReference; 22 23 /** 24 * @hide 25 * 26 * The SpeechSynthesis class provides a high-level api to create and play 27 * synthesized speech. This class is used internally to talk to a native 28 * TTS library that implements the interface defined in 29 * frameworks/base/include/tts/TtsEngine.h 30 * 31 */ 32 @SuppressWarnings("unused") 33 public class SynthProxy { 34 35 // Default parameters of a filter to be applied when using the Pico engine. 36 // Such a huge filter gain is justified by how much energy in the low frequencies is "wasted" at 37 // the output of the synthesis. The low shelving filter removes it, leaving room for 38 // amplification. 39 private final static float PICO_FILTER_GAIN = 5.0f; // linear gain 40 private final static float PICO_FILTER_LOWSHELF_ATTENUATION = -18.0f; // in dB 41 private final static float PICO_FILTER_TRANSITION_FREQ = 1100.0f; // in Hz 42 private final static float PICO_FILTER_SHELF_SLOPE = 1.0f; // Q 43 44 // 45 // External API 46 // 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 = nativeSoLib.toLowerCase().contains("pico"); 53 Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter); 54 native_setup(new WeakReference<SynthProxy>(this), nativeSoLib, engineConfig); 55 native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION, 56 PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE); 57 } 58 59 /** 60 * Stops and clears the AudioTrack. 61 */ 62 public int stop() { 63 return native_stop(mJniData); 64 } 65 66 /** 67 * Synchronous stop of the synthesizer. This method returns when the synth 68 * has completed the stop procedure and doesn't use any of the resources it 69 * was using while synthesizing. 70 * 71 * @return {@link android.speech.tts.TextToSpeech.SUCCESS} or 72 * {@link android.speech.tts.TextToSpeech.ERROR} 73 */ 74 public int stopSync() { 75 return native_stopSync(mJniData); 76 } 77 78 /** 79 * Synthesize speech and speak it directly using AudioTrack. 80 */ 81 public int speak(String text, int streamType) { 82 if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) { 83 return native_speak(mJniData, text, streamType); 84 } else { 85 Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType); 86 return native_speak(mJniData, text, AudioManager.STREAM_MUSIC); 87 } 88 } 89 90 /** 91 * Synthesize speech to a file. The current implementation writes a valid 92 * WAV file to the given path, assuming it is writable. Something like 93 * "/sdcard/???.wav" is recommended. 94 */ 95 public int synthesizeToFile(String text, String filename) { 96 return native_synthesizeToFile(mJniData, text, filename); 97 } 98 99 /** 100 * Queries for language support. 101 * Return codes are defined in android.speech.tts.TextToSpeech 102 */ 103 public int isLanguageAvailable(String language, String country, String variant) { 104 return native_isLanguageAvailable(mJniData, language, country, variant); 105 } 106 107 /** 108 * Updates the engine configuration. 109 */ 110 public int setConfig(String engineConfig) { 111 return native_setConfig(mJniData, engineConfig); 112 } 113 114 /** 115 * Sets the language. 116 */ 117 public int setLanguage(String language, String country, String variant) { 118 return native_setLanguage(mJniData, language, country, variant); 119 } 120 121 /** 122 * Loads the language: it's not set, but prepared for use later. 123 */ 124 public int loadLanguage(String language, String country, String variant) { 125 return native_loadLanguage(mJniData, language, country, variant); 126 } 127 128 /** 129 * Sets the speech rate. 130 */ 131 public final int setSpeechRate(int speechRate) { 132 return native_setSpeechRate(mJniData, speechRate); 133 } 134 135 /** 136 * Sets the pitch of the synthesized voice. 137 */ 138 public final int setPitch(int pitch) { 139 return native_setPitch(mJniData, pitch); 140 } 141 142 /** 143 * Returns the currently set language, country and variant information. 144 */ 145 public String[] getLanguage() { 146 return native_getLanguage(mJniData); 147 } 148 149 /** 150 * Gets the currently set rate. 151 */ 152 public int getRate() { 153 return native_getRate(mJniData); 154 } 155 156 /** 157 * Shuts down the native synthesizer. 158 */ 159 public void shutdown() { 160 native_shutdown(mJniData); 161 } 162 163 // 164 // Internal 165 // 166 167 protected void finalize() { 168 native_finalize(mJniData); 169 mJniData = 0; 170 } 171 172 static { 173 System.loadLibrary("ttssynthproxy"); 174 } 175 176 private final static String TAG = "SynthProxy"; 177 178 /** 179 * Accessed by native methods 180 */ 181 private int mJniData = 0; 182 183 private native final int native_setup(Object weak_this, String nativeSoLib, 184 String engineConfig); 185 186 private native final int native_setLowShelf(boolean applyFilter, float filterGain, 187 float attenuationInDb, float freqInHz, float slope); 188 189 private native final void native_finalize(int jniData); 190 191 private native final int native_stop(int jniData); 192 193 private native final int native_stopSync(int jniData); 194 195 private native final int native_speak(int jniData, String text, int streamType); 196 197 private native final int native_synthesizeToFile(int jniData, String text, String filename); 198 199 private native final int native_isLanguageAvailable(int jniData, String language, 200 String country, String variant); 201 202 private native final int native_setLanguage(int jniData, String language, String country, 203 String variant); 204 205 private native final int native_loadLanguage(int jniData, String language, String country, 206 String variant); 207 208 private native final int native_setConfig(int jniData, String engineConfig); 209 210 private native final int native_setSpeechRate(int jniData, int speechRate); 211 212 private native final int native_setPitch(int jniData, int speechRate); 213 214 private native final String[] native_getLanguage(int jniData); 215 216 private native final int native_getRate(int jniData); 217 218 private native final void native_shutdown(int jniData); 219 220 221 /** 222 * Callback from the C layer 223 */ 224 @SuppressWarnings("unused") 225 private static void postNativeSpeechSynthesizedInJava(Object tts_ref, 226 int bufferPointer, int bufferSize) { 227 228 Log.i("TTS plugin debug", "bufferPointer: " + bufferPointer 229 + " bufferSize: " + bufferSize); 230 231 SynthProxy nativeTTS = (SynthProxy)((WeakReference)tts_ref).get(); 232 // TODO notify TTS service of synthesis/playback completion, 233 // method definition to be changed. 234 } 235 } 236