summaryrefslogtreecommitdiffstats
path: root/core/java/android/speech/tts
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2011-07-01 10:13:54 +0100
committerNarayan Kamath <narayan@google.com>2011-07-14 17:04:28 +0100
commitc3da8818f0598b3ab2cd6f4168349da6d0f72cb1 (patch)
tree1a6b88171e41fd5780f1f6562f561412d6e4bec1 /core/java/android/speech/tts
parent1a70f093273fb58e4c7778c8e064b4489c0bd7d8 (diff)
downloadframeworks_base-c3da8818f0598b3ab2cd6f4168349da6d0f72cb1.zip
frameworks_base-c3da8818f0598b3ab2cd6f4168349da6d0f72cb1.tar.gz
frameworks_base-c3da8818f0598b3ab2cd6f4168349da6d0f72cb1.tar.bz2
Remove the completeAudioAvailable API.
Measurements have shown that the audio track in streaming mode is pretty efficient as is, thanks to dalvik's JNI implementation. Also, in streaming mode write( ) blocks until all data has been copied to the mixer, which is the kind of behaviour we want so that we don't have to explicitly block in our code. Also, the java AudioTrack is thread-safe with respect to stop( ) calls during write, which means we can do everything completeAudioAvailable did, just as efficiently without it. Change-Id: I70a8a108d94c7260676673979b5ea29f37fa5db4
Diffstat (limited to 'core/java/android/speech/tts')
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java56
-rw-r--r--core/java/android/speech/tts/FileSynthesisCallback.java31
-rw-r--r--core/java/android/speech/tts/PlaybackSynthesisCallback.java34
-rw-r--r--core/java/android/speech/tts/SynthesisCallback.java28
4 files changed, 8 insertions, 141 deletions
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 1210941..dea708a 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -31,8 +31,7 @@ class AudioPlaybackHandler {
private static final int SYNTHESIS_START = 1;
private static final int SYNTHESIS_DATA_AVAILABLE = 2;
- private static final int SYNTHESIS_COMPLETE_DATA_AVAILABLE = 3;
- private static final int SYNTHESIS_DONE = 4;
+ private static final int SYNTHESIS_DONE = 3;
private static final int PLAY_AUDIO = 5;
private static final int PLAY_SILENCE = 6;
@@ -120,10 +119,6 @@ class AudioPlaybackHandler {
mQueue.add(new ListEntry(SYNTHESIS_DATA_AVAILABLE, token));
}
- void enqueueSynthesisCompleteDataAvailable(SynthesisMessageParams token) {
- mQueue.add(new ListEntry(SYNTHESIS_COMPLETE_DATA_AVAILABLE, token));
- }
-
void enqueueSynthesisDone(SynthesisMessageParams token) {
mQueue.add(new ListEntry(SYNTHESIS_DONE, token));
}
@@ -280,8 +275,6 @@ class AudioPlaybackHandler {
handleSynthesisDataAvailable(msg);
} else if (entry.mWhat == SYNTHESIS_DONE) {
handleSynthesisDone(msg);
- } else if (entry.mWhat == SYNTHESIS_COMPLETE_DATA_AVAILABLE) {
- handleSynthesisCompleteDataAvailable(msg);
} else if (entry.mWhat == PLAY_AUDIO) {
handleAudio(msg);
} else if (entry.mWhat == PLAY_SILENCE) {
@@ -424,54 +417,11 @@ class AudioPlaybackHandler {
return;
}
- final AudioTrack track = params.mAudioTrack;
+ final AudioTrack audioTrack = params.mAudioTrack;
final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat);
final int lengthInBytes = params.mBytesWritten;
+ final int lengthInFrames = lengthInBytes / bytesPerFrame;
- blockUntilDone(track, bytesPerFrame, lengthInBytes);
- }
-
- private void handleSynthesisCompleteDataAvailable(MessageParams msg) {
- final SynthesisMessageParams params = (SynthesisMessageParams) msg;
- if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
-
- params.mLogger.onPlaybackStart();
-
- // Channel config and bytes per frame are checked before
- // this message is sent.
- int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount);
- int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(params.mAudioFormat);
-
- SynthesisMessageParams.ListEntry entry = params.getNextBuffer();
-
- if (entry == null) {
- Log.w(TAG, "completeDataAvailable : No buffers available to play.");
- return;
- }
-
- final AudioTrack audioTrack = new AudioTrack(params.mStreamType, params.mSampleRateInHz,
- channelConfig, params.mAudioFormat, entry.mLength, AudioTrack.MODE_STATIC);
-
- // So that handleDone can access this correctly.
- params.mAudioTrack = audioTrack;
-
- try {
- audioTrack.write(entry.mBytes, entry.mOffset, entry.mLength);
- setupVolume(audioTrack, params.mVolume, params.mPan);
- audioTrack.play();
- blockUntilDone(audioTrack, bytesPerFrame, entry.mLength);
- if (DBG) Log.d(TAG, "Wrote data to audio track successfully : " + entry.mLength);
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Playback error", ex);
- } finally {
- handleSynthesisDone(msg);
- }
- }
-
-
- private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame,
- int lengthInBytes) {
- int lengthInFrames = lengthInBytes / bytesPerFrame;
int currentPosition = 0;
while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) {
if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 4f4b3fb..5808919 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -187,37 +187,6 @@ class FileSynthesisCallback extends AbstractSynthesisCallback {
}
}
- @Override
- public int completeAudioAvailable(int sampleRateInHz, int audioFormat, int channelCount,
- byte[] buffer, int offset, int length) {
- synchronized (mStateLock) {
- if (mStopped) {
- if (DBG) Log.d(TAG, "Request has been aborted.");
- return TextToSpeech.ERROR;
- }
- }
- FileOutputStream out = null;
- try {
- out = new FileOutputStream(mFileName);
- out.write(makeWavHeader(sampleRateInHz, audioFormat, channelCount, length));
- out.write(buffer, offset, length);
- mDone = true;
- return TextToSpeech.SUCCESS;
- } catch (IOException ex) {
- Log.e(TAG, "Failed to write to " + mFileName + ": " + ex);
- mFileName.delete();
- return TextToSpeech.ERROR;
- } finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException ex) {
- Log.e(TAG, "Failed to close " + mFileName + ": " + ex);
- }
- }
- }
-
private byte[] makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
int dataLength) {
// TODO: is AudioFormat.ENCODING_DEFAULT always the same as ENCODING_PCM_16BIT?
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index 38030a6..04bd745 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -53,8 +53,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
// Handler associated with a thread that plays back audio requests.
private final AudioPlaybackHandler mAudioTrackHandler;
- // A request "token", which will be non null after start() or
- // completeAudioAvailable() have been called.
+ // A request "token", which will be non null after start() has been called.
private SynthesisMessageParams mToken = null;
// Whether this request has been stopped. This is useful for keeping
// track whether stop() has been called before start(). In all other cases,
@@ -206,35 +205,4 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
stop();
}
- @Override
- public int completeAudioAvailable(int sampleRateInHz, int audioFormat, int channelCount,
- byte[] buffer, int offset, int length) {
- int channelConfig = AudioPlaybackHandler.getChannelConfig(channelCount);
- if (channelConfig == 0) {
- Log.e(TAG, "Unsupported number of channels :" + channelCount);
- return TextToSpeech.ERROR;
- }
-
- int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(audioFormat);
- if (bytesPerFrame < 0) {
- Log.e(TAG, "Unsupported audio format :" + audioFormat);
- return TextToSpeech.ERROR;
- }
-
- synchronized (mStateLock) {
- if (mStopped) {
- return TextToSpeech.ERROR;
- }
- SynthesisMessageParams params = new SynthesisMessageParams(
- mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher, mCallingApp, mLogger);
- params.addBuffer(buffer, offset, length);
-
- mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
- mToken = params;
- }
-
- return TextToSpeech.SUCCESS;
- }
-
}
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index 1b80e40..d70c371 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -22,19 +22,16 @@ package android.speech.tts;
* {@link #start}, then {@link #audioAvailable} until all audio has been provided, then finally
* {@link #done}.
*
- * Alternatively, the engine can provide all the audio at once, by using
- * {@link #completeAudioAvailable}.
*
* {@link #error} can be called at any stage in the synthesis process to
- * indicate that an error has occured, but if the call is made after a call
- * to {@link #done} or {@link #completeAudioAvailable} it might be discarded.
+ * indicate that an error has occurred, but if the call is made after a call
+ * to {@link #done}, it might be discarded.
*/
public interface SynthesisCallback {
/**
* @return the maximum number of bytes that the TTS engine can pass in a single call of
- * {@link #audioAvailable}. This does not apply to {@link #completeAudioAvailable}.
- * Calls to {@link #audioAvailable} with data lengths larger than this
- * value will not succeed.
+ * {@link #audioAvailable}. Calls to {@link #audioAvailable} with data lengths
+ * larger than this value will not succeed.
*/
public int getMaxBufferSize();
@@ -69,23 +66,6 @@ public interface SynthesisCallback {
public int audioAvailable(byte[] buffer, int offset, int length);
/**
- * The service can call this method instead of using {@link #start}, {@link #audioAvailable}
- * and {@link #done} if all the audio data is available in a single buffer.
- *
- * @param sampleRateInHz Sample rate in HZ of the generated audio.
- * @param audioFormat Audio format of the generated audio. Must be one of
- * the ENCODING_ constants defined in {@link android.media.AudioFormat}.
- * @param channelCount The number of channels. Must be {@code 1} or {@code 2}.
- * @param buffer The generated audio data. This method will not hold on to {@code buffer},
- * so the caller is free to modify it after this method returns.
- * @param offset The offset into {@code buffer} where the audio data starts.
- * @param length The number of bytes of audio data in {@code buffer}.
- * @return {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
- */
- public int completeAudioAvailable(int sampleRateInHz, int audioFormat,
- int channelCount, byte[] buffer, int offset, int length);
-
- /**
* The service should call this method when all the synthesized audio for a request has
* been passed to {@link #audioAvailable}.
*