PlaybackSynthesisCallback.java revision 8d1fc2403b8277e68d7816b2bbf05464a4c7a58a
150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert/* 250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Copyright (C) 2011 The Android Open Source Project 350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * 450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not 550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * use this file except in compliance with the License. You may obtain a copy of 650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * the License at 750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * 850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * 1050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Unless required by applicable law or agreed to in writing, software 1150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 1250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 1350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * License for the specific language governing permissions and limitations under 1450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * the License. 1550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert */ 1650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringertpackage android.speech.tts; 1750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 18b956f37e375bb2588208d4b5e8a40fae6fae5f86Narayan Kamathimport android.os.Bundle; 198d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamathimport android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher; 2050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringertimport android.util.Log; 2150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 2250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert/** 2350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Speech synthesis request that plays the audio as it is received. 2450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert */ 2550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringertclass PlaybackSynthesisRequest extends SynthesisRequest { 2650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 2750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private static final String TAG = "PlaybackSynthesisRequest"; 2850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private static final boolean DBG = false; 2950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 3050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private static final int MIN_AUDIO_BUFFER_SIZE = 8192; 3150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 3250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert /** 3350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Audio stream type. Must be one of the STREAM_ contants defined in 3450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * {@link android.media.AudioManager}. 3550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert */ 3650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private final int mStreamType; 3750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 3850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert /** 3950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Volume, in the range [0.0f, 1.0f]. The default value is 4050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * {@link TextToSpeech.Engine#DEFAULT_VOLUME} (1.0f). 4150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert */ 4250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private final float mVolume; 4350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 4450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert /** 4550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * Left/right position of the audio, in the range [-1.0f, 1.0f]. 4650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert * The default value is {@link TextToSpeech.Engine#DEFAULT_PAN} (0.0f). 4750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert */ 4850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private final float mPan; 4950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 508d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath /** 518d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath * Guards {@link #mAudioTrackHandler}, {@link #mToken} and {@link #mStopped}. 528d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath */ 5350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private final Object mStateLock = new Object(); 548d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 558d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // Handler associated with a thread that plays back audio requests. 568d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath private final AudioPlaybackHandler mAudioTrackHandler; 578d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // A request "token", which will be non null after start() or 588d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // completeAudioAvailable() have been called. 598d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath private SynthesisMessageParams mToken = null; 608d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // Whether this request has been stopped. This is useful for keeping 618d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // track whether stop() has been called before start(). In all other cases, 628d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath // a non-null value of mToken will provide the same information. 6350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert private boolean mStopped = false; 6450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 658d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath private volatile boolean mDone = false; 668d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 678d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath private final UtteranceCompletedDispatcher mDispatcher; 688d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 698d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath PlaybackSynthesisRequest(String text, Bundle params, int streamType, float volume, float pan, 708d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher) { 71b956f37e375bb2588208d4b5e8a40fae6fae5f86Narayan Kamath super(text, params); 7250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert mStreamType = streamType; 7350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert mVolume = volume; 7450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert mPan = pan; 75c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath mAudioTrackHandler = audioTrackHandler; 768d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mDispatcher = dispatcher; 7750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 7850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 7950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert @Override 8050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert void stop() { 8150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert if (DBG) Log.d(TAG, "stop()"); 828d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 8350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert synchronized (mStateLock) { 848d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (mToken == null || mStopped) { 858d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath Log.w(TAG, "stop() called twice, before start(), or after done()"); 868d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath return; 878d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath } 888d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mAudioTrackHandler.stop(mToken); 898d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mToken = null; 9050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert mStopped = true; 9150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 9250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 9350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 9471e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert @Override 9571e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert public int getMaxBufferSize() { 9671e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert // The AudioTrack buffer will be at least MIN_AUDIO_BUFFER_SIZE, so that should always be 9771e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert // a safe buffer size to pass in. 9871e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert return MIN_AUDIO_BUFFER_SIZE; 9971e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 10071e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 101360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert @Override 102360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert boolean isDone() { 103360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert return mDone; 104360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert } 105360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert 10650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert @Override 10750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert public int start(int sampleRateInHz, int audioFormat, int channelCount) { 10850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert if (DBG) { 10950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert Log.d(TAG, "start(" + sampleRateInHz + "," + audioFormat 11050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert + "," + channelCount + ")"); 11150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 11250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 1138d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath int channelConfig = AudioPlaybackHandler.getChannelConfig(channelCount); 1148d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (channelConfig == 0) { 1158d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath Log.e(TAG, "Unsupported number of channels :" + channelCount); 1168d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath return TextToSpeech.ERROR; 1178d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath } 1188d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 11950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert synchronized (mStateLock) { 12050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert if (mStopped) { 1218d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (DBG) Log.d(TAG, "stop() called before start(), returning."); 12250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.ERROR; 12350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1248d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath SynthesisMessageParams params = new SynthesisMessageParams( 1258d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan, 1268d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mDispatcher); 1278d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mAudioTrackHandler.enqueueSynthesisStart(params); 12850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 1298d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mToken = params; 13050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 13150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 13250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.SUCCESS; 13350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 13450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 13550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 13650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert @Override 13750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert public int audioAvailable(byte[] buffer, int offset, int length) { 13850e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert if (DBG) { 13950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert Log.d(TAG, "audioAvailable(byte[" + buffer.length + "]," 14071e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert + offset + "," + length + ")"); 14171e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 142c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath if (length > getMaxBufferSize() || length <= 0) { 143c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath throw new IllegalArgumentException("buffer is too large or of zero length (" + 144c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath + length + " bytes)"); 14550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1468d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 14750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert synchronized (mStateLock) { 1488d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (mToken == null) { 14950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.ERROR; 15050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1518d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 152c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath // Sigh, another copy. 153c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath final byte[] bufferCopy = new byte[length]; 154c90f1c815dc06d5bb563474a340f7bb158fab2e2Narayan Kamath System.arraycopy(buffer, offset, bufferCopy, 0, length); 1558d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mToken.addBuffer(bufferCopy); 1568d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken); 15750e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1588d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 1598d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath return TextToSpeech.SUCCESS; 16050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 16150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert 16250e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert @Override 16350e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert public int done() { 16450e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert if (DBG) Log.d(TAG, "done()"); 1658d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 16650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert synchronized (mStateLock) { 1678d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (mDone) { 1688d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath Log.w(TAG, "Duplicate call to done()"); 16950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.ERROR; 17050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1718d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 1728d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mDone = true; 1738d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 1748d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (mToken == null) { 17550e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.ERROR; 17650e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 1778d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 1788d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mAudioTrackHandler.enqueueSynthesisDone(mToken); 17950e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 18050e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert return TextToSpeech.SUCCESS; 18150e657bb2d005568f5dd8bc1d904d07b0d94018fBjorn Bringert } 18271e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 18371e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert @Override 184360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert public void error() { 1858d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (DBG) Log.d(TAG, "error() [will call stop]"); 1868d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath stop(); 187360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert } 188360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert 189360eb168d6f9c967543852c7bbab370ef5d8c1bdBjorn Bringert @Override 19071e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert public int completeAudioAvailable(int sampleRateInHz, int audioFormat, int channelCount, 19171e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert byte[] buffer, int offset, int length) { 1928d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath int channelConfig = AudioPlaybackHandler.getChannelConfig(channelCount); 1938d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (channelConfig == 0) { 1948d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath Log.e(TAG, "Unsupported number of channels :" + channelCount); 1958d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath return TextToSpeech.ERROR; 1968d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath } 1978d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath 1988d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(audioFormat); 1998d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath if (bytesPerFrame < 0) { 2008d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath Log.e(TAG, "Unsupported audio format :" + audioFormat); 2018d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath return TextToSpeech.ERROR; 20271e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 20371e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 20471e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert synchronized (mStateLock) { 20571e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert if (mStopped) { 20671e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert return TextToSpeech.ERROR; 20771e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 2088d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath SynthesisMessageParams params = new SynthesisMessageParams( 2098d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan, 2108d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mDispatcher); 2118d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath params.addBuffer(buffer, offset, length); 21271e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 2138d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params); 2148d1fc2403b8277e68d7816b2bbf05464a4c7a58aNarayan Kamath mToken = params; 21571e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 21671e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 21771e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert return TextToSpeech.SUCCESS; 21871e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert } 21971e0b4807797c602e7fc787d00d27c4f9c92a507Bjorn Bringert 22053f6f95308854e7da1fcd15081030d7de2fc5a7fNarayan Kamath} 221