Home | History | Annotate | Download | only in tts
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 package android.speech.tts;
     17 
     18 import android.content.Context;
     19 import android.media.AudioSystem;
     20 import android.media.AudioTrack;
     21 import android.media.MediaPlayer;
     22 import android.net.Uri;
     23 import android.os.ConditionVariable;
     24 import android.speech.tts.TextToSpeechService.AudioOutputParams;
     25 import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
     26 import android.util.Log;
     27 
     28 class AudioPlaybackQueueItem extends PlaybackQueueItem {
     29     private static final String TAG = "TTS.AudioQueueItem";
     30 
     31     private final Context mContext;
     32     private final Uri mUri;
     33     private final AudioOutputParams mAudioParams;
     34 
     35     private final ConditionVariable mDone;
     36     private MediaPlayer mPlayer;
     37     private volatile boolean mFinished;
     38 
     39     AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher,
     40             Object callerIdentity,
     41             Context context, Uri uri, AudioOutputParams audioParams) {
     42         super(dispatcher, callerIdentity);
     43 
     44         mContext = context;
     45         mUri = uri;
     46         mAudioParams = audioParams;
     47 
     48         mDone = new ConditionVariable();
     49         mPlayer = null;
     50         mFinished = false;
     51     }
     52     @Override
     53     public void run() {
     54         final UtteranceProgressDispatcher dispatcher = getDispatcher();
     55 
     56         dispatcher.dispatchOnStart();
     57 
     58         int sessionId = mAudioParams.mSessionId;
     59         mPlayer = MediaPlayer.create(
     60                 mContext, mUri, null, mAudioParams.mAudioAttributes,
     61                 sessionId > 0 ? sessionId : AudioSystem.AUDIO_SESSION_ALLOCATE);
     62         if (mPlayer == null) {
     63             dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT);
     64             return;
     65         }
     66 
     67         try {
     68             mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
     69                 @Override
     70                 public boolean onError(MediaPlayer mp, int what, int extra) {
     71                     Log.w(TAG, "Audio playback error: " + what + ", " + extra);
     72                     mDone.open();
     73                     return true;
     74                 }
     75             });
     76             mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
     77                 @Override
     78                 public void onCompletion(MediaPlayer mp) {
     79                     mFinished = true;
     80                     mDone.open();
     81                 }
     82             });
     83 
     84             setupVolume(mPlayer, mAudioParams.mVolume, mAudioParams.mPan);
     85             mPlayer.start();
     86             mDone.block();
     87             finish();
     88         } catch (IllegalArgumentException ex) {
     89             Log.w(TAG, "MediaPlayer failed", ex);
     90             mDone.open();
     91         }
     92 
     93         if (mFinished) {
     94             dispatcher.dispatchOnSuccess();
     95         } else {
     96             dispatcher.dispatchOnStop();
     97         }
     98     }
     99 
    100     private static void setupVolume(MediaPlayer player, float volume, float pan) {
    101         final float vol = clip(volume, 0.0f, 1.0f);
    102         final float panning = clip(pan, -1.0f, 1.0f);
    103 
    104         float volLeft = vol, volRight = vol;
    105         if (panning > 0.0f) {
    106             volLeft *= (1.0f - panning);
    107         } else if (panning < 0.0f) {
    108             volRight *= (1.0f + panning);
    109         }
    110         player.setVolume(volLeft, volRight);
    111     }
    112 
    113     private static final float clip(float value, float min, float max) {
    114         return value < min ? min : (value < max ? value : max);
    115     }
    116 
    117     private void finish() {
    118         try {
    119             mPlayer.stop();
    120         } catch (IllegalStateException ex) {
    121             // Do nothing, the player is already stopped
    122         }
    123         mPlayer.release();
    124     }
    125 
    126     @Override
    127     void stop(int errorCode) {
    128         mDone.open();
    129     }
    130 }
    131