blob: f5f5fcf2b876684fdcc6b5d4debf11aadf88c1dd [file] [log] [blame]
Jean-Michel Trivi700ec652009-05-27 15:01:59 -07001/*
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 */
16package android.tts;
17
Jean-Michel Trivi9440bce2009-07-13 10:12:37 -070018import android.media.AudioManager;
19import android.media.AudioSystem;
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070020import android.util.Log;
21import 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")
33public class SynthProxy {
34
Jean-Michel Trivi0320f8b2010-01-11 14:04:50 -080035 // 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.
Jean-Michel Trivi1105f0f2010-03-15 15:37:51 -070039 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
Jean-Michel Trivi0320f8b2010-01-11 14:04:50 -080042 private final static float PICO_FILTER_SHELF_SLOPE = 1.0f; // Q
43
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070044 //
45 // External API
46 //
47
48 /**
49 * Constructor; pass the location of the native TTS .so to use.
50 */
Jean-Michel Trivi76dd7882010-03-17 22:07:13 -070051 public SynthProxy(String nativeSoLib, String engineConfig) {
Jean-Michel Trivi0320f8b2010-01-11 14:04:50 -080052 boolean applyFilter = nativeSoLib.toLowerCase().contains("pico");
Jean-Michel Trivic6120192010-03-07 14:29:58 -080053 Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter);
Jean-Michel Trivi900e0d02010-03-18 11:07:45 -070054 native_setup(new WeakReference<SynthProxy>(this), nativeSoLib, engineConfig);
Jean-Michel Trivi0320f8b2010-01-11 14:04:50 -080055 native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION,
56 PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070057 }
58
59 /**
60 * Stops and clears the AudioTrack.
61 */
Charles Chena3f89292009-07-06 14:12:36 -070062 public int stop() {
63 return native_stop(mJniData);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070064 }
65
66 /**
Jean-Michel Trivi09f8db72009-08-31 10:41:55 -070067 * 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 /**
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070079 * Synthesize speech and speak it directly using AudioTrack.
80 */
Jean-Michel Trivi9d2d26a2011-01-05 16:08:21 -080081 public int speak(String text, int streamType, float volume, float pan) {
82 Log.i(TAG, "speak() on stream "+ streamType);
Jean-Michel Trivi9440bce2009-07-13 10:12:37 -070083 if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) {
Jean-Michel Trivi9d2d26a2011-01-05 16:08:21 -080084 return native_speak(mJniData, text, streamType, volume, pan);
Jean-Michel Trivi9440bce2009-07-13 10:12:37 -070085 } else {
86 Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType);
Jean-Michel Trivi9d2d26a2011-01-05 16:08:21 -080087 return native_speak(mJniData, text, AudioManager.STREAM_MUSIC, volume, pan);
Jean-Michel Trivi9440bce2009-07-13 10:12:37 -070088 }
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070089 }
90
91 /**
92 * Synthesize speech to a file. The current implementation writes a valid
93 * WAV file to the given path, assuming it is writable. Something like
94 * "/sdcard/???.wav" is recommended.
95 */
Charles Chena3f89292009-07-06 14:12:36 -070096 public int synthesizeToFile(String text, String filename) {
Jean-Michel Trivi9d2d26a2011-01-05 16:08:21 -080097 Log.i(TAG, "synthesizeToFile() to file "+ filename);
Charles Chena3f89292009-07-06 14:12:36 -070098 return native_synthesizeToFile(mJniData, text, filename);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -070099 }
100
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700101 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700102 * Queries for language support.
103 * Return codes are defined in android.speech.tts.TextToSpeech
104 */
105 public int isLanguageAvailable(String language, String country, String variant) {
106 return native_isLanguageAvailable(mJniData, language, country, variant);
107 }
108
109 /**
Jean-Michel Trivi900e0d02010-03-18 11:07:45 -0700110 * Updates the engine configuration.
Jean-Michel Trivi76dd7882010-03-17 22:07:13 -0700111 */
112 public int setConfig(String engineConfig) {
Jean-Michel Trivi54a3dcd2010-03-18 14:50:06 -0700113 return native_setConfig(mJniData, engineConfig);
Jean-Michel Trivi76dd7882010-03-17 22:07:13 -0700114 }
115
116 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700117 * Sets the language.
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700118 */
Charles Chena3f89292009-07-06 14:12:36 -0700119 public int setLanguage(String language, String country, String variant) {
120 return native_setLanguage(mJniData, language, country, variant);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700121 }
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700122
Jean-Michel Trivid6d03e02009-06-25 18:37:55 -0700123 /**
124 * Loads the language: it's not set, but prepared for use later.
125 */
Charles Chena3f89292009-07-06 14:12:36 -0700126 public int loadLanguage(String language, String country, String variant) {
127 return native_loadLanguage(mJniData, language, country, variant);
Jean-Michel Trivid6d03e02009-06-25 18:37:55 -0700128 }
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700129
130 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700131 * Sets the speech rate.
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700132 */
Charles Chena3f89292009-07-06 14:12:36 -0700133 public final int setSpeechRate(int speechRate) {
134 return native_setSpeechRate(mJniData, speechRate);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700135 }
136
Jean-Michel Trivi2ea53492009-06-23 13:44:40 -0700137 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700138 * Sets the pitch of the synthesized voice.
Jean-Michel Trivi2ea53492009-06-23 13:44:40 -0700139 */
Charles Chena3f89292009-07-06 14:12:36 -0700140 public final int setPitch(int pitch) {
141 return native_setPitch(mJniData, pitch);
Jean-Michel Trivi2ea53492009-06-23 13:44:40 -0700142 }
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700143
144 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700145 * Returns the currently set language, country and variant information.
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700146 */
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700147 public String[] getLanguage() {
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700148 return native_getLanguage(mJniData);
149 }
150
151 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700152 * Gets the currently set rate.
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700153 */
154 public int getRate() {
155 return native_getRate(mJniData);
156 }
157
158 /**
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700159 * Shuts down the native synthesizer.
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700160 */
161 public void shutdown() {
162 native_shutdown(mJniData);
163 }
164
165 //
166 // Internal
167 //
168
169 protected void finalize() {
170 native_finalize(mJniData);
171 mJniData = 0;
172 }
173
174 static {
Jean-Michel Trivi1f4b92a2009-06-02 16:02:31 -0700175 System.loadLibrary("ttssynthproxy");
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700176 }
177
178 private final static String TAG = "SynthProxy";
179
180 /**
181 * Accessed by native methods
182 */
183 private int mJniData = 0;
184
Jean-Michel Trivi900e0d02010-03-18 11:07:45 -0700185 private native final int native_setup(Object weak_this, String nativeSoLib,
186 String engineConfig);
Jean-Michel Trivi0320f8b2010-01-11 14:04:50 -0800187
188 private native final int native_setLowShelf(boolean applyFilter, float filterGain,
189 float attenuationInDb, float freqInHz, float slope);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700190
191 private native final void native_finalize(int jniData);
192
Charles Chen35b86c22009-07-06 10:51:48 -0700193 private native final int native_stop(int jniData);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700194
Jean-Michel Trivi09f8db72009-08-31 10:41:55 -0700195 private native final int native_stopSync(int jniData);
196
Jean-Michel Trivi9d2d26a2011-01-05 16:08:21 -0800197 private native final int native_speak(int jniData, String text, int streamType, float volume,
198 float pan);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700199
Charles Chen35b86c22009-07-06 10:51:48 -0700200 private native final int native_synthesizeToFile(int jniData, String text, String filename);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700201
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700202 private native final int native_isLanguageAvailable(int jniData, String language,
203 String country, String variant);
204
Charles Chen35b86c22009-07-06 10:51:48 -0700205 private native final int native_setLanguage(int jniData, String language, String country,
Jean-Michel Trivi679d7282009-06-16 15:36:28 -0700206 String variant);
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700207
Charles Chen35b86c22009-07-06 10:51:48 -0700208 private native final int native_loadLanguage(int jniData, String language, String country,
Jean-Michel Trivid6d03e02009-06-25 18:37:55 -0700209 String variant);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700210
Jean-Michel Trivi54a3dcd2010-03-18 14:50:06 -0700211 private native final int native_setConfig(int jniData, String engineConfig);
Jean-Michel Trivi900e0d02010-03-18 11:07:45 -0700212
Charles Chen35b86c22009-07-06 10:51:48 -0700213 private native final int native_setSpeechRate(int jniData, int speechRate);
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700214
Charles Chen35b86c22009-07-06 10:51:48 -0700215 private native final int native_setPitch(int jniData, int speechRate);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700216
Jean-Michel Trivibee1c7e2009-06-29 15:55:05 -0700217 private native final String[] native_getLanguage(int jniData);
Jean-Michel Trivi700ec652009-05-27 15:01:59 -0700218
219 private native final int native_getRate(int jniData);
220
221 private native final void native_shutdown(int jniData);
222
223
224 /**
225 * Callback from the C layer
226 */
227 @SuppressWarnings("unused")
228 private static void postNativeSpeechSynthesizedInJava(Object tts_ref,
229 int bufferPointer, int bufferSize) {
230
231 Log.i("TTS plugin debug", "bufferPointer: " + bufferPointer
232 + " bufferSize: " + bufferSize);
233
234 SynthProxy nativeTTS = (SynthProxy)((WeakReference)tts_ref).get();
235 // TODO notify TTS service of synthesis/playback completion,
236 // method definition to be changed.
237 }
238}