summaryrefslogtreecommitdiffstats
path: root/packages/TtsService/src/android/tts/SynthProxy.java
blob: 5f283e11e247025453121c31843fd32632dced70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
 * Copyright (C) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package android.tts;

import android.media.AudioManager;
import android.media.AudioSystem;
import android.util.Log;
import java.lang.ref.WeakReference;

/**
 * @hide
 *
 * The SpeechSynthesis class provides a high-level api to create and play
 * synthesized speech. This class is used internally to talk to a native
 * TTS library that implements the interface defined in
 * frameworks/base/include/tts/TtsEngine.h
 *
 */
@SuppressWarnings("unused")
public class SynthProxy {

    // Default parameters of a filter to be applied when using the Pico engine.
    // Such a huge filter gain is justified by how much energy in the low frequencies is "wasted" at
    // the output of the synthesis. The low shelving filter removes it, leaving room for
    // amplification.
    private final static float PICO_FILTER_GAIN = 5.0f; // linear gain
    private final static float PICO_FILTER_LOWSHELF_ATTENUATION = -18.0f; // in dB
    private final static float PICO_FILTER_TRANSITION_FREQ = 1100.0f;     // in Hz
    private final static float PICO_FILTER_SHELF_SLOPE = 1.0f;            // Q

    //
    // External API
    //

    /**
     * Constructor; pass the location of the native TTS .so to use.
     */
    public SynthProxy(String nativeSoLib, String engineConfig) {
        boolean applyFilter = nativeSoLib.toLowerCase().contains("pico");
        Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter);
        native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
        native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION,
                PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE);
    }

    /**
     * Stops and clears the AudioTrack.
     */
    public int stop() {
        return native_stop(mJniData);
    }

    /**
     * Synchronous stop of the synthesizer. This method returns when the synth
     * has completed the stop procedure and doesn't use any of the resources it
     * was using while synthesizing.
     *
     * @return {@link android.speech.tts.TextToSpeech.SUCCESS} or
     *         {@link android.speech.tts.TextToSpeech.ERROR}
     */
    public int stopSync() {
        return native_stopSync(mJniData);
    }

    /**
     * Synthesize speech and speak it directly using AudioTrack.
     */
    public int speak(String text, int streamType) {
        if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) {
            return native_speak(mJniData, text, streamType);
        } else {
            Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType);
            return native_speak(mJniData, text, AudioManager.STREAM_MUSIC);
        }
    }

    /**
     * Synthesize speech to a file. The current implementation writes a valid
     * WAV file to the given path, assuming it is writable. Something like
     * "/sdcard/???.wav" is recommended.
     */
    public int synthesizeToFile(String text, String filename) {
        return native_synthesizeToFile(mJniData, text, filename);
    }

    /**
     * Queries for language support.
     * Return codes are defined in android.speech.tts.TextToSpeech
     */
    public int isLanguageAvailable(String language, String country, String variant) {
        return native_isLanguageAvailable(mJniData, language, country, variant);
    }

    /**
     * Sets the engine configuration.
     */
    public int setConfig(String engineConfig) {
        return android.speech.tts.TextToSpeech.SUCCESS;
    }

    /**
     * Sets the language.
     */
    public int setLanguage(String language, String country, String variant) {
        return native_setLanguage(mJniData, language, country, variant);
    }

    /**
     * Loads the language: it's not set, but prepared for use later.
     */
    public int loadLanguage(String language, String country, String variant) {
        return native_loadLanguage(mJniData, language, country, variant);
    }

    /**
     * Sets the speech rate.
     */
    public final int setSpeechRate(int speechRate) {
        return native_setSpeechRate(mJniData, speechRate);
    }

    /**
     * Sets the pitch of the synthesized voice.
     */
    public final int setPitch(int pitch) {
        return native_setPitch(mJniData, pitch);
    }

    /**
     * Returns the currently set language, country and variant information.
     */
    public String[] getLanguage() {
        return native_getLanguage(mJniData);
    }

    /**
     * Gets the currently set rate.
     */
    public int getRate() {
        return native_getRate(mJniData);
    }

    /**
     * Shuts down the native synthesizer.
     */
    public void shutdown()  {
        native_shutdown(mJniData);
    }

    //
    // Internal
    //

    protected void finalize() {
        native_finalize(mJniData);
        mJniData = 0;
    }

    static {
        System.loadLibrary("ttssynthproxy");
    }

    private final static String TAG = "SynthProxy";

    /**
     * Accessed by native methods
     */
    private int mJniData = 0;

    private native final int native_setup(Object weak_this, String nativeSoLib);

    private native final int native_setLowShelf(boolean applyFilter, float filterGain,
            float attenuationInDb, float freqInHz, float slope);

    private native final void native_finalize(int jniData);

    private native final int native_stop(int jniData);

    private native final int native_stopSync(int jniData);

    private native final int native_speak(int jniData, String text, int streamType);

    private native final int native_synthesizeToFile(int jniData, String text, String filename);

    private native final int  native_isLanguageAvailable(int jniData, String language,
            String country, String variant);

    private native final int native_setLanguage(int jniData, String language, String country,
            String variant);

    private native final int native_loadLanguage(int jniData, String language, String country,
            String variant);

    private native final int native_setSpeechRate(int jniData, int speechRate);

    private native final int native_setPitch(int jniData, int speechRate);

    private native final String[] native_getLanguage(int jniData);

    private native final int native_getRate(int jniData);

    private native final void native_shutdown(int jniData);


    /**
     * Callback from the C layer
     */
    @SuppressWarnings("unused")
    private static void postNativeSpeechSynthesizedInJava(Object tts_ref,
            int bufferPointer, int bufferSize) {

        Log.i("TTS plugin debug", "bufferPointer: " + bufferPointer
                + " bufferSize: " + bufferSize);

        SynthProxy nativeTTS = (SynthProxy)((WeakReference)tts_ref).get();
        // TODO notify TTS service of synthesis/playback completion,
        //      method definition to be changed.
    }
}