FileSynthesisCallbackpublic class FileSynthesisCallback extends AbstractSynthesisCallback Speech synthesis request that writes the audio to a WAV file. |
Fields Summary |
---|
private static final String | TAG | private static final boolean | DBG | private static final int | MAX_AUDIO_BUFFER_SIZE | private static final int | WAV_HEADER_LENGTH | private static final short | WAV_FORMAT_PCM | private final Object | mStateLock | private int | mSampleRateInHz | private int | mAudioFormat | private int | mChannelCount | private FileChannel | mFileChannel | private final android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher | mDispatcher | private final Object | mCallerIdentity | private boolean | mStarted | private boolean | mDone | protected int | mStatusCodeStatus code of synthesis |
Methods Summary |
---|
public int | audioAvailable(byte[] buffer, int offset, int length)
if (DBG) {
Log.d(TAG, "FileSynthesisRequest.audioAvailable(" + buffer + "," + offset
+ "," + length + ")");
}
FileChannel fileChannel = null;
synchronized (mStateLock) {
if (mStatusCode == TextToSpeech.STOPPED) {
if (DBG) Log.d(TAG, "Request has been aborted.");
return errorCodeOnStop();
}
if (mStatusCode != TextToSpeech.SUCCESS) {
if (DBG) Log.d(TAG, "Error was raised");
return TextToSpeech.ERROR;
}
if (mFileChannel == null) {
Log.e(TAG, "File not open");
mStatusCode = TextToSpeech.ERROR_OUTPUT;
return TextToSpeech.ERROR;
}
if (!mStarted) {
Log.e(TAG, "Start method was not called");
return TextToSpeech.ERROR;
}
fileChannel = mFileChannel;
}
try {
fileChannel.write(ByteBuffer.wrap(buffer, offset, length));
return TextToSpeech.SUCCESS;
} catch (IOException ex) {
Log.e(TAG, "Failed to write to output file descriptor", ex);
synchronized (mStateLock) {
cleanUp();
mStatusCode = TextToSpeech.ERROR_OUTPUT;
}
return TextToSpeech.ERROR;
}
| private void | cleanUp()Must be called while holding the monitor on {@link #mStateLock}.
closeFile();
| private void | closeFile()Must be called while holding the monitor on {@link #mStateLock}.
// File will be closed by the SpeechItem in the speech service.
mFileChannel = null;
| public int | done()
if (DBG) Log.d(TAG, "FileSynthesisRequest.done()");
FileChannel fileChannel = null;
int sampleRateInHz = 0;
int audioFormat = 0;
int channelCount = 0;
synchronized (mStateLock) {
if (mDone) {
Log.w(TAG, "Duplicate call to done()");
// This is not an error that would prevent synthesis. Hence no
// setStatusCode is set.
return TextToSpeech.ERROR;
}
if (mStatusCode == TextToSpeech.STOPPED) {
if (DBG) Log.d(TAG, "Request has been aborted.");
return errorCodeOnStop();
}
if (mDispatcher != null && mStatusCode != TextToSpeech.SUCCESS &&
mStatusCode != TextToSpeech.STOPPED) {
mDispatcher.dispatchOnError(mStatusCode);
return TextToSpeech.ERROR;
}
if (mFileChannel == null) {
Log.e(TAG, "File not open");
return TextToSpeech.ERROR;
}
mDone = true;
fileChannel = mFileChannel;
sampleRateInHz = mSampleRateInHz;
audioFormat = mAudioFormat;
channelCount = mChannelCount;
}
try {
// Write WAV header at start of file
fileChannel.position(0);
int dataLength = (int) (fileChannel.size() - WAV_HEADER_LENGTH);
fileChannel.write(
makeWavHeader(sampleRateInHz, audioFormat, channelCount, dataLength));
synchronized (mStateLock) {
closeFile();
if (mDispatcher != null) {
mDispatcher.dispatchOnSuccess();
}
return TextToSpeech.SUCCESS;
}
} catch (IOException ex) {
Log.e(TAG, "Failed to write to output file descriptor", ex);
synchronized (mStateLock) {
cleanUp();
}
return TextToSpeech.ERROR;
}
| public void | error(int errorCode)
if (DBG) Log.d(TAG, "FileSynthesisRequest.error()");
synchronized (mStateLock) {
if (mDone) {
return;
}
cleanUp();
mStatusCode = errorCode;
}
| public void | error()
error(TextToSpeech.ERROR_SYNTHESIS);
| public int | getMaxBufferSize()
return MAX_AUDIO_BUFFER_SIZE;
| public boolean | hasFinished()
synchronized (mStateLock) {
return mDone;
}
| public boolean | hasStarted()
synchronized (mStateLock) {
return mStarted;
}
| private java.nio.ByteBuffer | makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount, int dataLength)
int sampleSizeInBytes = AudioFormat.getBytesPerSample(audioFormat);
int byteRate = sampleRateInHz * sampleSizeInBytes * channelCount;
short blockAlign = (short) (sampleSizeInBytes * channelCount);
short bitsPerSample = (short) (sampleSizeInBytes * 8);
byte[] headerBuf = new byte[WAV_HEADER_LENGTH];
ByteBuffer header = ByteBuffer.wrap(headerBuf);
header.order(ByteOrder.LITTLE_ENDIAN);
header.put(new byte[]{ 'R", 'I", 'F", 'F" });
header.putInt(dataLength + WAV_HEADER_LENGTH - 8); // RIFF chunk size
header.put(new byte[]{ 'W", 'A", 'V", 'E" });
header.put(new byte[]{ 'f", 'm", 't", ' " });
header.putInt(16); // size of fmt chunk
header.putShort(WAV_FORMAT_PCM);
header.putShort((short) channelCount);
header.putInt(sampleRateInHz);
header.putInt(byteRate);
header.putShort(blockAlign);
header.putShort(bitsPerSample);
header.put(new byte[]{ 'd", 'a", 't", 'a" });
header.putInt(dataLength);
header.flip();
return header;
| public int | start(int sampleRateInHz, int audioFormat, int channelCount)
if (DBG) {
Log.d(TAG, "FileSynthesisRequest.start(" + sampleRateInHz + "," + audioFormat
+ "," + channelCount + ")");
}
FileChannel fileChannel = null;
synchronized (mStateLock) {
if (mStatusCode == TextToSpeech.STOPPED) {
if (DBG) Log.d(TAG, "Request has been aborted.");
return errorCodeOnStop();
}
if (mStatusCode != TextToSpeech.SUCCESS) {
if (DBG) Log.d(TAG, "Error was raised");
return TextToSpeech.ERROR;
}
if (mStarted) {
Log.e(TAG, "Start called twice");
return TextToSpeech.ERROR;
}
mStarted = true;
mSampleRateInHz = sampleRateInHz;
mAudioFormat = audioFormat;
mChannelCount = channelCount;
if (mDispatcher != null) {
mDispatcher.dispatchOnStart();
}
fileChannel = mFileChannel;
}
try {
fileChannel.write(ByteBuffer.allocate(WAV_HEADER_LENGTH));
return TextToSpeech.SUCCESS;
} catch (IOException ex) {
Log.e(TAG, "Failed to write wav header to output file descriptor", ex);
synchronized (mStateLock) {
cleanUp();
mStatusCode = TextToSpeech.ERROR_OUTPUT;
}
return TextToSpeech.ERROR;
}
| void | stop()
synchronized (mStateLock) {
if (mDone) {
return;
}
if (mStatusCode == TextToSpeech.STOPPED) {
return;
}
mStatusCode = TextToSpeech.STOPPED;
cleanUp();
if (mDispatcher != null) {
mDispatcher.dispatchOnStop();
}
}
|
|