1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.audio; 18 19 import android.content.Context; 20 import android.media.AudioFormat; 21 import android.media.AudioManager; 22 import android.media.AudioTrack; 23 import android.media.MediaPlayer; 24 import android.net.Uri; 25 import android.net.rtp.AudioStream; 26 import android.util.Log; 27 28 import com.android.cts.verifier.audio.wavelib.PipeShort; 29 30 import java.io.IOException; 31 32 public class SoundPlayerObject extends Thread { 33 private static final String LOGTAG = "SoundPlayerObject"; 34 private MediaPlayer mMediaPlayer; 35 private boolean isInitialized = false; 36 private boolean isRunning = false; 37 38 public PipeShort mPipe = new PipeShort(65536); 39 private short[] mAudioShortArray; 40 41 public AudioTrack mAudioTrack; 42 public int mSamplingRate = 48000; 43 private int mChannelConfigOut = AudioFormat.CHANNEL_OUT_MONO; 44 private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 45 int mMinPlayBufferSizeInBytes = 0; 46 int mMinBufferSizeInSamples = 0; 47 48 private int mStreamType = AudioManager.STREAM_MUSIC; 49 private int mResId = -1; 50 private boolean mUseMediaPlayer = true; 51 private float mBalance = 0.5f; //0 left, 1 right 52 getCurrentResId()53 public int getCurrentResId() { 54 return mResId; 55 } 56 getStreamType()57 public int getStreamType () { 58 return mStreamType; 59 } 60 run()61 public void run() { 62 setPriority(Thread.MAX_PRIORITY); 63 isRunning = true; 64 while (isRunning) { 65 66 if (!mUseMediaPlayer && isInitialized && isPlaying()) { 67 int valuesAvailable = mPipe.availableToRead(); 68 if (valuesAvailable > 0) { 69 70 int valuesOfInterest = valuesAvailable; 71 if (mMinBufferSizeInSamples < valuesOfInterest) { 72 valuesOfInterest = mMinBufferSizeInSamples; 73 } 74 mPipe.read(mAudioShortArray, 0,valuesOfInterest); 75 //inject into output. 76 mAudioTrack.write(mAudioShortArray, 0, valuesOfInterest); 77 } 78 } else { 79 try { 80 sleep(10); 81 } catch (InterruptedException e) { 82 e.printStackTrace(); 83 } 84 } 85 } 86 } 87 setBalance(float balance)88 public void setBalance(float balance) { 89 mBalance = balance; 90 if (mUseMediaPlayer) { 91 if (mMediaPlayer != null) { 92 float left = Math.min(2.0f * (1.0f - mBalance), 1.0f); 93 float right = Math.min(2.0f * mBalance, 1.0f); 94 mMediaPlayer.setVolume(left, right); 95 log(String.format("Setting balance to %f", mBalance)); 96 } 97 } 98 } 99 setStreamType(int streamType)100 public void setStreamType(int streamType) { 101 mStreamType = streamType; 102 } 103 rewind()104 public void rewind() { 105 if (mUseMediaPlayer) { 106 if (mMediaPlayer != null) { 107 mMediaPlayer.seekTo(0); 108 } 109 } 110 } 111 setSoundWithResId(Context context, int resId)112 public void setSoundWithResId(Context context, int resId) { 113 boolean playing = isPlaying(); 114 //release player 115 releasePlayer(); 116 mResId = resId; 117 if (mUseMediaPlayer) { 118 mMediaPlayer = new MediaPlayer(); 119 try { 120 log("opening resource with stream type: " + mStreamType); 121 mMediaPlayer.setAudioStreamType(mStreamType); 122 mMediaPlayer.setDataSource(context.getApplicationContext(), 123 Uri.parse("android.resource://com.android.cts.verifier/" + resId)); 124 mMediaPlayer.prepare(); 125 } catch (IOException e) { 126 e.printStackTrace(); 127 } 128 mMediaPlayer.setLooping(true); 129 setBalance(mBalance); 130 } else { 131 mMinPlayBufferSizeInBytes = AudioTrack.getMinBufferSize(mSamplingRate, 132 mChannelConfigOut, mAudioFormat); 133 134 mMinBufferSizeInSamples = mMinPlayBufferSizeInBytes / 2; 135 mAudioShortArray = new short[mMinBufferSizeInSamples * 4]; 136 137 mAudioTrack = new AudioTrack(mStreamType, 138 mSamplingRate, 139 mChannelConfigOut, 140 mAudioFormat, 141 mMinPlayBufferSizeInBytes, 142 AudioTrack.MODE_STREAM /* FIXME runtime test for API level 9 , 143 mSessionId */); 144 mPipe.flush(); 145 isInitialized = true; 146 } 147 148 log("done preparing media player"); 149 if (playing) 150 play(true); //start playing if it was playing before 151 } 152 isPlaying()153 public boolean isPlaying() { 154 boolean result = false; 155 if (mUseMediaPlayer) { 156 if (mMediaPlayer != null) { 157 result = mMediaPlayer.isPlaying(); 158 } 159 } else { 160 if (mAudioTrack != null) { 161 result = mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING; 162 } 163 } 164 return result; 165 } 166 play(boolean play)167 public void play(boolean play) { 168 if (mUseMediaPlayer) { 169 if (mMediaPlayer != null) { 170 if (play) { 171 mMediaPlayer.start(); 172 } else { 173 mMediaPlayer.pause(); 174 } 175 } 176 } else { 177 if (mAudioTrack != null && isInitialized) { 178 if (play) { 179 mPipe.flush(); 180 mAudioTrack.flush(); 181 mAudioTrack.play(); 182 } else { 183 mAudioTrack.pause(); 184 } 185 } 186 } 187 } 188 finish()189 public void finish() { 190 play(false); 191 releasePlayer(); 192 } 193 releasePlayer()194 private void releasePlayer() { 195 if (mMediaPlayer != null) { 196 mMediaPlayer.stop(); 197 mMediaPlayer.release(); 198 mMediaPlayer = null; 199 } 200 201 if (mAudioTrack != null) { 202 mAudioTrack.stop(); 203 mAudioTrack.release(); 204 mAudioTrack = null; 205 } 206 isInitialized = false; 207 } 208 209 /* 210 Misc 211 */ log(String msg)212 private static void log(String msg) { 213 Log.v(LOGTAG, msg); 214 } 215 } 216