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.AudioManager;
     20 import android.media.MediaPlayer;
     21 import android.net.Uri;
     22 import android.os.ConditionVariable;
     23 import android.speech.tts.TextToSpeechService.AudioOutputParams;
     24 import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
     25 import android.util.Log;
     26 
     27 class AudioPlaybackQueueItem extends PlaybackQueueItem {
     28     private static final String TAG = "TTS.AudioQueueItem";
     29 
     30     private final Context mContext;
     31     private final Uri mUri;
     32     private final AudioOutputParams mAudioParams;
     33 
     34     private final ConditionVariable mDone;
     35     private MediaPlayer mPlayer;
     36     private volatile boolean mFinished;
     37 
     38     AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher,
     39             Object callerIdentity,
     40             Context context, Uri uri, AudioOutputParams audioParams) {
     41         super(dispatcher, callerIdentity);
     42 
     43         mContext = context;
     44         mUri = uri;
     45         mAudioParams = audioParams;
     46 
     47         mDone = new ConditionVariable();
     48         mPlayer = null;
     49         mFinished = false;
     50     }
     51     @Override
     52     public void run() {
     53         final UtteranceProgressDispatcher dispatcher = getDispatcher();
     54 
     55         dispatcher.dispatchOnStart();
     56 
     57         int sessionId = mAudioParams.mSessionId;
     58         mPlayer = MediaPlayer.create(
     59                 mContext, mUri, null, mAudioParams.mAudioAttributes,
     60                 sessionId > 0 ? sessionId : AudioManager.AUDIO_SESSION_ID_GENERATE);
     61         if (mPlayer == null) {
     62             dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT);
     63             return;
     64         }
     65 
     66         try {
     67             mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
     68                 @Override
     69                 public boolean onError(MediaPlayer mp, int what, int extra) {
     70                     Log.w(TAG, "Audio playback error: " + what + ", " + extra);
     71                     mDone.open();
     72                     return true;
     73                 }
     74             });
     75             mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
     76                 @Override
     77                 public void onCompletion(MediaPlayer mp) {
     78                     mFinished = true;
     79                     mDone.open();
     80                 }
     81             });
     82 
     83             setupVolume(mPlayer, mAudioParams.mVolume, mAudioParams.mPan);
     84             mPlayer.start();
     85             mDone.block();
     86             finish();
     87         } catch (IllegalArgumentException ex) {
     88             Log.w(TAG, "MediaPlayer failed", ex);
     89             mDone.open();
     90         }
     91 
     92         if (mFinished) {
     93             dispatcher.dispatchOnSuccess();
     94         } else {
     95             dispatcher.dispatchOnStop();
     96         }
     97     }
     98 
     99     private static void setupVolume(MediaPlayer player, float volume, float pan) {
    100         final float vol = clip(volume, 0.0f, 1.0f);
    101         final float panning = clip(pan, -1.0f, 1.0f);
    102 
    103         float volLeft = vol, volRight = vol;
    104         if (panning > 0.0f) {
    105             volLeft *= (1.0f - panning);
    106         } else if (panning < 0.0f) {
    107             volRight *= (1.0f + panning);
    108         }
    109         player.setVolume(volLeft, volRight);
    110     }
    111 
    112     private static final float clip(float value, float min, float max) {
    113         return value < min ? min : (value < max ? value : max);
    114     }
    115 
    116     private void finish() {
    117         try {
    118             mPlayer.stop();
    119         } catch (IllegalStateException ex) {
    120             // Do nothing, the player is already stopped
    121         }
    122         mPlayer.release();
    123     }
    124 
    125     @Override
    126     void stop(int errorCode) {
    127         mDone.open();
    128     }
    129 }
    130