FileDocCategorySizeDatePackage
FileSynthesisCallback.javaAPI DocAndroid 5.1 API10002Thu Mar 12 22:22:10 GMT 2015android.speech.tts

FileSynthesisCallback

public 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
mStatusCode
Status code of synthesis
Constructors Summary
FileSynthesisCallback(FileChannel fileChannel, android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher dispatcher, Object callerIdentity, boolean clientIsUsingV2)


       
                
        super(clientIsUsingV2);
        mFileChannel = fileChannel;
        mDispatcher = dispatcher;
        mCallerIdentity = callerIdentity;
        mStatusCode = TextToSpeech.SUCCESS;
    
Methods Summary
public intaudioAvailable(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 voidcleanUp()
Must be called while holding the monitor on {@link #mStateLock}.

        closeFile();
    
private voidcloseFile()
Must be called while holding the monitor on {@link #mStateLock}.

        // File will be closed by the SpeechItem in the speech service.
        mFileChannel = null;
    
public intdone()

        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 voiderror(int errorCode)

        if (DBG) Log.d(TAG, "FileSynthesisRequest.error()");
        synchronized (mStateLock) {
            if (mDone) {
                return;
            }
            cleanUp();
            mStatusCode = errorCode;
        }
    
public voiderror()

        error(TextToSpeech.ERROR_SYNTHESIS);
    
public intgetMaxBufferSize()

        return MAX_AUDIO_BUFFER_SIZE;
    
public booleanhasFinished()

        synchronized (mStateLock) {
            return mDone;
        }
    
public booleanhasStarted()

        synchronized (mStateLock) {
            return mStarted;
        }
    
private java.nio.ByteBuffermakeWavHeader(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 intstart(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;
        }
    
voidstop()

        synchronized (mStateLock) {
            if (mDone) {
                return;
            }
            if (mStatusCode == TextToSpeech.STOPPED) {
                return;
            }

            mStatusCode = TextToSpeech.STOPPED;
            cleanUp();
            if (mDispatcher != null) {
                mDispatcher.dispatchOnStop();
            }
        }