• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 package com.android.tts.compat;
17 
18 import android.speech.tts.SynthesisCallback;
19 import android.speech.tts.SynthesisRequest;
20 import 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  */
29 public 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      */
SynthProxy(String nativeSoLib, String engineConfig)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
shouldApplyAudioFilter(String nativeSoLib)63     private boolean shouldApplyAudioFilter(String nativeSoLib) {
64         return nativeSoLib.toLowerCase().contains("pico");
65     }
66 
67     /**
68      * Stops and clears the AudioTrack.
69      */
stop()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      */
stopSync()82     public int stopSync() {
83         return native_stopSync(mJniData);
84     }
85 
speak(SynthesisRequest request, SynthesisCallback callback)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      */
isLanguageAvailable(String language, String country, String variant)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      */
setConfig(String engineConfig)101     public int setConfig(String engineConfig) {
102         return native_setProperty(mJniData, "engineConfig", engineConfig);
103     }
104 
105     /**
106      * Sets the language.
107      */
setLanguage(String language, String country, String variant)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      */
loadLanguage(String language, String country, String variant)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      */
setSpeechRate(int speechRate)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      */
setPitch(int pitch)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      */
getLanguage()136     public String[] getLanguage() {
137         return native_getLanguage(mJniData);
138     }
139 
140     /**
141      * Shuts down the native synthesizer.
142      */
shutdown()143     public void shutdown() {
144         native_shutdown(mJniData);
145         mJniData = 0;
146     }
147 
148     @Override
finalize()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 
native_setup(String nativeSoLib, String engineConfig)157     private native final long native_setup(String nativeSoLib, String engineConfig);
158 
native_setLowShelf(boolean applyFilter, float filterGain, float attenuationInDb, float freqInHz, float slope)159     private native final int native_setLowShelf(boolean applyFilter, float filterGain,
160             float attenuationInDb, float freqInHz, float slope);
161 
native_finalize(long jniData)162     private native final void native_finalize(long jniData);
163 
native_stop(long jniData)164     private native final int native_stop(long jniData);
165 
native_stopSync(long jniData)166     private native final int native_stopSync(long jniData);
167 
native_speak(long jniData, String text, SynthesisCallback request)168     private native final int native_speak(long jniData, String text, SynthesisCallback request);
169 
native_isLanguageAvailable(long jniData, String language, String country, String variant)170     private native final int  native_isLanguageAvailable(long jniData, String language,
171             String country, String variant);
172 
native_setLanguage(long jniData, String language, String country, String variant)173     private native final int native_setLanguage(long jniData, String language, String country,
174             String variant);
175 
native_loadLanguage(long jniData, String language, String country, String variant)176     private native final int native_loadLanguage(long jniData, String language, String country,
177             String variant);
178 
native_setProperty(long jniData, String name, String value)179     private native final int native_setProperty(long jniData, String name, String value);
180 
native_getLanguage(long jniData)181     private native final String[] native_getLanguage(long jniData);
182 
native_shutdown(long jniData)183     private native final void native_shutdown(long jniData);
184 
185 }
186