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 */
16package android.tts;
17
18import android.media.AudioManager;
19import android.media.AudioSystem;
20import 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
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