1 /* 2 * Copyright (C) 2016 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 android.media.audio.cts; 18 19 import android.annotation.RawRes; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.content.res.AssetFileDescriptor; 23 import android.content.res.Resources; 24 import android.media.AudioAttributes; 25 import android.media.AudioFormat; 26 import android.media.AudioManager; 27 import android.media.AudioProfile; 28 import android.media.AudioTimestamp; 29 import android.media.AudioTrack; 30 import android.media.audio.cts.R; 31 import android.platform.test.annotations.AppModeSdkSandbox; 32 import android.util.Log; 33 34 import com.android.compatibility.common.util.CtsAndroidTestCase; 35 import com.android.compatibility.common.util.NonMainlineTest; 36 37 import java.io.BufferedInputStream; 38 import java.io.ByteArrayOutputStream; 39 import java.io.InputStream; 40 import java.nio.ByteBuffer; 41 import java.nio.ByteOrder; 42 import java.nio.ShortBuffer; 43 import java.util.ArrayList; 44 import java.util.List; 45 import java.util.Random; 46 47 // Test the Java AudioTrack surround sound and HDMI passthrough. 48 // Most tests involve creating a track with a given format and then playing 49 // a few seconds of audio. The playback is verified by measuring the output 50 // sample rate based on the AudioTimestamps. 51 52 @NonMainlineTest 53 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 54 public class AudioTrackSurroundTest extends CtsAndroidTestCase { 55 private static final String TAG = "AudioTrackSurroundTest"; 56 57 private static final double MAX_RATE_TOLERANCE_FRACTION = 0.01; 58 private static final boolean LOG_TIMESTAMPS = false; // set true for debugging 59 // just long enough to measure the rate 60 private static final long SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS = 5000; 61 // AC3 and IEC61937 tracks require more time 62 private static final long SAMPLE_RATE_LONG_TEST_DURATION_MILLIS = 12000; 63 64 // Should we fail if there is no PCM16 profile reported? 65 // This can happen if, for example, an ATV set top box does not have its HDMI cable plugged in. 66 private static final boolean REQUIRE_PCM_PROFILE = false; 67 68 private final static long NANOS_PER_MILLISECOND = 1000000L; 69 private final static int MILLIS_PER_SECOND = 1000; 70 private final static long NANOS_PER_SECOND = NANOS_PER_MILLISECOND * MILLIS_PER_SECOND; 71 72 private final static int RES_AC3_SPDIF_VOICE_32000 = R.raw.voice12_32k_128kbps_15s_ac3_spdif; 73 private final static int RES_AC3_SPDIF_VOICE_44100 = R.raw.voice12_44k_128kbps_15s_ac3_spdif; 74 private final static int RES_AC3_SPDIF_VOICE_48000 = R.raw.voice12_48k_128kbps_15s_ac3_spdif; 75 private final static int RES_AC3_VOICE_48000 = R.raw.voice12_48k_128kbps_15s_ac3; 76 77 private static int mLastPlayedEncoding = AudioFormat.ENCODING_INVALID; 78 79 // Profiles that support various encodings. 80 private static AudioProfile mProfilePCM16 = null; 81 private static AudioProfile mProfileAC3 = null; 82 private static AudioProfile mProfileE_AC3 = null; 83 private static AudioProfile mProfileDTS = null; 84 private static AudioProfile mProfileDTS_HD = null; 85 private static AudioProfile mProfileIEC61937 = null; 86 87 private static AudioAttributes mAudioAttributes = null; 88 log(String testName, String message)89 private static void log(String testName, String message) { 90 Log.i(TAG, "[" + testName + "] " + message); 91 } 92 logw(String testName, String message)93 private static void logw(String testName, String message) { 94 Log.w(TAG, "[" + testName + "] " + message); 95 } 96 loge(String testName, String message)97 private static void loge(String testName, String message) { 98 Log.e(TAG, "[" + testName + "] " + message); 99 } 100 101 // This is a special method that is called automatically before each test. 102 @Override setUp()103 protected void setUp() throws Exception { 104 // Note that I tried to only scan for encodings once but the static 105 // data did not persist properly. That may be a bug. 106 // For now, just scan before every test. 107 scanProfilesForEncodings(); 108 } 109 scanProfilesForEncodings()110 private void scanProfilesForEncodings() throws Exception { 111 final String MTAG = "scanProfilesForEncodings"; 112 // Scan profiles to see which encodings are supported. 113 AudioManager audioManager = (AudioManager) getContext() 114 .getSystemService(Context.AUDIO_SERVICE); 115 mAudioAttributes = new AudioAttributes.Builder() 116 .setUsage(AudioAttributes.USAGE_MEDIA) 117 .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) 118 .build(); 119 List<AudioProfile> profiles = audioManager.getDirectProfilesForAttributes(mAudioAttributes); 120 if (profiles.size() == 0) { 121 log(MTAG, "no direct profiles for media + music found"); 122 } 123 for (AudioProfile profile : profiles) { 124 log(MTAG, "scanning profiles, profile = " + profile.toString()); 125 if (profile.getEncapsulationType() == AudioProfile.AUDIO_ENCAPSULATION_TYPE_IEC61937) { 126 mProfileIEC61937 = profile; 127 log(MTAG, "mProfileIEC61937 set to " + profile); 128 break; 129 } else { // AudioProfile.AUDIO_ENCAPSULATION_TYPE_NONE 130 switch (profile.getFormat()) { 131 case AudioFormat.ENCODING_PCM_16BIT: 132 mProfilePCM16 = profile; 133 log(MTAG, "mProfilePCM16 set to " + profile); 134 break; 135 case AudioFormat.ENCODING_AC3: 136 mProfileAC3 = profile; 137 log(MTAG, "mProfileAC3 set to " + profile); 138 break; 139 case AudioFormat.ENCODING_E_AC3: 140 mProfileE_AC3 = profile; 141 log(MTAG, "mProfileE_AC3 set to " + profile); 142 break; 143 case AudioFormat.ENCODING_DTS: 144 mProfileDTS = profile; 145 log(MTAG, "mProfileDTS set to " + profile); 146 break; 147 case AudioFormat.ENCODING_DTS_HD: 148 mProfileDTS_HD = profile; 149 log(MTAG, "mProfileDTS_HD set to " + profile); 150 break; 151 default: 152 // This is OK. It is just an encoding that we don't care about. 153 break; 154 } 155 } 156 157 } 158 } 159 160 // Load a resource into a byte[] loadRawResourceBytes(@awRes int id)161 private byte[] loadRawResourceBytes(@RawRes int id) throws Exception { 162 InputStream is = getContext().getResources().openRawResource(id); 163 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 164 try (BufferedInputStream bis = new BufferedInputStream(is)) { 165 for (int b = bis.read(); b != -1; b = bis.read()) { 166 bos.write(b); 167 } 168 } 169 return bos.toByteArray(); 170 } 171 172 // Load a resource into a short[] loadRawResourceShorts(@awRes int id)173 private short[] loadRawResourceShorts(@RawRes int id) throws Exception { 174 byte[] byteBuffer = loadRawResourceBytes(id); 175 ShortBuffer shortBuffer = 176 ByteBuffer.wrap(byteBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); 177 // Unfortunately, ShortBuffer.array() works with allocated buffers only. 178 short[] mainBuffer = new short[byteBuffer.length / 2]; 179 for (int i = 0; i < mainBuffer.length; i++) { 180 mainBuffer[i] = shortBuffer.get(); 181 } 182 return mainBuffer; 183 } 184 testLoadSineSweep()185 public void testLoadSineSweep() throws Exception { 186 final String TEST_NAME = "testLoadSineSweep"; 187 short[] shortData = loadRawResourceShorts(R.raw.sinesweepraw); 188 assertTrue(TEST_NAME + ": load sinesweepraw as shorts", shortData.length > 100); 189 byte[] byteData = loadRawResourceBytes(R.raw.sinesweepraw); 190 assertTrue(TEST_NAME + ": load sinesweepraw as bytes", byteData.length > shortData.length); 191 } 192 createAudioTrack(int sampleRate, int encoding, int channelConfig)193 private static AudioTrack createAudioTrack(int sampleRate, int encoding, int channelConfig) { 194 final String TEST_NAME = "createAudioTrack"; 195 int minBufferSize = AudioTrack.getMinBufferSize( 196 sampleRate, channelConfig, 197 encoding); 198 assertTrue(TEST_NAME + ": getMinBufferSize", minBufferSize > 0); 199 int bufferSize = minBufferSize * 3; // plenty big 200 AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 201 sampleRate, channelConfig, 202 encoding, bufferSize, 203 AudioTrack.MODE_STREAM); 204 return track; 205 } 206 207 static class TimestampAnalyzer { 208 ArrayList<AudioTimestamp> mTimestamps = new ArrayList<AudioTimestamp>(); 209 AudioTimestamp mPreviousTimestamp = null; 210 timestampToString(AudioTimestamp timestamp)211 static String timestampToString(AudioTimestamp timestamp) { 212 if (timestamp == null) 213 return "null"; 214 return "(pos = " + timestamp.framePosition + ", nanos = " + timestamp.nanoTime + ")"; 215 } 216 217 // Add timestamp if unique and valid. addTimestamp(AudioTrack track)218 void addTimestamp(AudioTrack track) { 219 AudioTimestamp timestamp = new AudioTimestamp(); 220 boolean gotTimestamp = track.getTimestamp(timestamp); 221 if (gotTimestamp) { 222 // Only save timestamps after the data is flowing. 223 boolean accepted = mPreviousTimestamp != null 224 && timestamp.framePosition > 0 225 && timestamp.nanoTime != mPreviousTimestamp.nanoTime 226 && timestamp.framePosition != mPreviousTimestamp.framePosition; 227 if (accepted) { 228 mTimestamps.add(timestamp); 229 } 230 Log.d(TAG, (accepted ? "" : "NOT ") + "added ts " + timestampToString(timestamp)); 231 mPreviousTimestamp = timestamp; 232 } 233 } 234 checkIndividualTimestamps(int sampleRate)235 void checkIndividualTimestamps(int sampleRate) { 236 AudioTimestamp previous = null; 237 double sumDeltaSquared = 0.0; 238 int populationSize = 0; 239 double maxDeltaMillis = 0.0; 240 // Make sure the timestamps are smooth and don't go retrograde. 241 for (AudioTimestamp timestamp : mTimestamps) { 242 if (previous != null) { 243 244 assertTrue("framePosition must be monotonic", 245 timestamp.framePosition >= previous.framePosition); 246 assertTrue("nanoTime must be monotonic", 247 timestamp.nanoTime >= previous.nanoTime); 248 249 if (timestamp.framePosition > previous.framePosition) { 250 // Measure timing jitter. 251 // Calculate predicted duration based on measured rate and compare 252 // it with actual duration. 253 final double TOLERANCE_MILLIS = 2.0; 254 long elapsedFrames = timestamp.framePosition - previous.framePosition; 255 long elapsedNanos = timestamp.nanoTime - previous.nanoTime; 256 double measuredMillis = elapsedNanos / (double) NANOS_PER_MILLISECOND; 257 double expectedMillis = elapsedFrames * (double) MILLIS_PER_SECOND 258 / sampleRate; 259 double deltaMillis = measuredMillis - expectedMillis; 260 sumDeltaSquared += deltaMillis * deltaMillis; 261 populationSize++; 262 // We only issue a warning here because the CDD does not mandate a 263 // specific tolerance. 264 double absDeltaMillis = Math.abs(deltaMillis); 265 if (absDeltaMillis > TOLERANCE_MILLIS) { 266 Log.w(TAG, "measured time exceeds expected" 267 + ", srate = " + sampleRate 268 + ", frame = " + timestamp.framePosition 269 + ", expected = " + expectedMillis 270 + ", measured = " + measuredMillis + " (msec)" 271 ); 272 } 273 if (absDeltaMillis > maxDeltaMillis) { 274 maxDeltaMillis = absDeltaMillis; 275 } 276 } 277 } 278 previous = timestamp; 279 } 280 Log.d(TAG, "max abs(delta) from expected duration = " + maxDeltaMillis + " msec"); 281 if (populationSize > 0) { 282 double deviation = Math.sqrt(sumDeltaSquared / populationSize); 283 Log.d(TAG, "standard deviation from expected duration = " + deviation + " msec"); 284 } 285 } 286 287 // Use collected timestamps to estimate a sample rate. estimateSampleRate()288 double estimateSampleRate() { 289 Log.w(TAG, "timestamps collected: " + mTimestamps.size()); 290 assertTrue("expect many timestamps, got " + mTimestamps.size(), 291 mTimestamps.size() > 10); 292 // Use first and last timestamp to get the most accurate rate. 293 AudioTimestamp first = mTimestamps.get(0); 294 AudioTimestamp last = mTimestamps.get(mTimestamps.size() - 1); 295 return calculateSampleRate(first, last); 296 } 297 298 /** 299 * @param timestamp1 300 * @param timestamp2 301 */ calculateSampleRate(AudioTimestamp timestamp1, AudioTimestamp timestamp2)302 private double calculateSampleRate(AudioTimestamp timestamp1, AudioTimestamp timestamp2) { 303 long elapsedFrames = timestamp2.framePosition - timestamp1.framePosition; 304 long elapsedNanos = timestamp2.nanoTime - timestamp1.nanoTime; 305 double measuredRate = elapsedFrames * (double) NANOS_PER_SECOND / elapsedNanos; 306 if (LOG_TIMESTAMPS) { 307 Log.i(TAG, "calculateSampleRate(), elapsedFrames =, " + elapsedFrames 308 + ", measuredRate =, " 309 + (int) measuredRate); 310 } 311 return measuredRate; 312 } 313 } 314 315 // Class for looping a recording for several seconds and measuring the sample rate. 316 // This is not static because it needs to call getContext(). 317 abstract class SamplePlayerBase { 318 private final int mSampleRate; 319 private final int mEncoding; 320 private final int mChannelConfig; 321 private int mBlockSize = 512; 322 protected int mOffset = 0; 323 protected AudioTrack mTrack; 324 private final TimestampAnalyzer mTimestampAnalyzer = new TimestampAnalyzer(); 325 SamplePlayerBase(int sampleRate, int encoding, int channelConfig)326 SamplePlayerBase(int sampleRate, int encoding, int channelConfig) { 327 mSampleRate = sampleRate; 328 mEncoding = encoding; 329 mChannelConfig = channelConfig; 330 } 331 332 // Use abstract write to handle byte[] or short[] data. writeBlock(int numSamples)333 protected abstract int writeBlock(int numSamples); 334 primeBuffer()335 private int primeBuffer() { 336 // Will not block when track is stopped. 337 return writeBlock(Integer.MAX_VALUE); 338 } 339 340 // Add a warning to the assert message that might help folks figure out why their 341 // PCM test is failing. getPcmWarning()342 private String getPcmWarning() { 343 return (mProfilePCM16 == null && AudioFormat.isEncodingLinearPcm(mEncoding)) 344 ? " (No PCM profile!)" : ""; 345 } 346 playAndMeasureRate(long testDurationMillis)347 public void playAndMeasureRate(long testDurationMillis) throws Exception { 348 final String TEST_NAME = "playAndMeasureRate"; 349 350 if (mLastPlayedEncoding == AudioFormat.ENCODING_INVALID || 351 !AudioFormat.isEncodingLinearPcm(mEncoding) || 352 !AudioFormat.isEncodingLinearPcm(mLastPlayedEncoding)) { 353 Log.d(TAG, "switching from format: " + mLastPlayedEncoding 354 + " to: " + mEncoding 355 + " requires sleep"); 356 // Switching between compressed formats may require 357 // some time for the HAL to adjust and give proper timing. 358 // One second should be ok, but we use 2 just in case. 359 Thread.sleep(2000 /* millis */); 360 } 361 mLastPlayedEncoding = mEncoding; 362 363 log(TEST_NAME, String.format("test using rate = %d, encoding = 0x%08x", 364 mSampleRate, mEncoding)); 365 // Create a track and prime it. 366 mTrack = createAudioTrack(mSampleRate, mEncoding, mChannelConfig); 367 try { 368 assertEquals(TEST_NAME + ": track created " + getPcmWarning(), 369 AudioTrack.STATE_INITIALIZED, 370 mTrack.getState()); 371 372 int bytesWritten = 0; 373 mOffset = primeBuffer(); // prime the buffer 374 assertTrue(TEST_NAME + ": priming offset = " + mOffset + ", " + getPcmWarning(), 375 mOffset > 0); 376 bytesWritten += mOffset; 377 378 // Play for a while. 379 mTrack.play(); 380 381 log(TEST_NAME, "native rate = " 382 + mTrack.getNativeOutputSampleRate(mTrack.getStreamType())); 383 long elapsedMillis = 0; 384 long startTime = System.currentTimeMillis(); 385 while (elapsedMillis < testDurationMillis) { 386 writeBlock(mBlockSize); 387 elapsedMillis = System.currentTimeMillis() - startTime; 388 mTimestampAnalyzer.addTimestamp(mTrack); 389 } 390 391 // Did we underrun? Allow 0 or 1 because there is sometimes 392 // an underrun on startup. 393 int underrunCount1 = mTrack.getUnderrunCount(); 394 assertTrue(TEST_NAME + ": too many underruns, got " + underrunCount1 395 + ", " + getPcmWarning(), 396 underrunCount1 < 2); 397 398 // Estimate the sample rate and compare it with expected. 399 double estimatedRate = mTimestampAnalyzer.estimateSampleRate(); 400 Log.d(TAG, "measured sample rate = " + estimatedRate); 401 assertEquals(TEST_NAME + ": measured sample rate " + getPcmWarning(), 402 mSampleRate, estimatedRate, mSampleRate * MAX_RATE_TOLERANCE_FRACTION); 403 404 // Check for jitter or retrograde motion in each timestamp. 405 mTimestampAnalyzer.checkIndividualTimestamps(mSampleRate); 406 407 } finally { 408 mTrack.release(); 409 } 410 } 411 } 412 413 // Create player for short[] 414 class SamplePlayerShorts extends SamplePlayerBase { 415 private final short[] mData; 416 SamplePlayerShorts(int sampleRate, int encoding, int channelConfig)417 SamplePlayerShorts(int sampleRate, int encoding, int channelConfig) { 418 super(sampleRate, encoding, channelConfig); 419 mData = new short[64 * 1024]; 420 // Fill with noise. We should not hear the noise for IEC61937. 421 int amplitude = 8000; 422 Random random = new Random(); 423 for (int i = 0; i < mData.length; i++) { 424 mData[i] = (short)(random.nextInt(amplitude) - (amplitude / 2)); 425 } 426 } 427 SamplePlayerShorts(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId)428 SamplePlayerShorts(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId) 429 throws Exception { 430 super(sampleRate, encoding, channelConfig); 431 mData = loadRawResourceShorts(resourceId); 432 assertTrue("SamplePlayerShorts: load resource file as shorts", mData.length > 0); 433 } 434 435 @Override writeBlock(int numShorts)436 protected int writeBlock(int numShorts) { 437 int result = 0; 438 int shortsToWrite = numShorts; 439 int shortsLeft = mData.length - mOffset; 440 if (shortsToWrite > shortsLeft) { 441 shortsToWrite = shortsLeft; 442 } 443 if (shortsToWrite > 0) { 444 result = mTrack.write(mData, mOffset, shortsToWrite); 445 mOffset += result; 446 } else { 447 mOffset = 0; // rewind 448 } 449 return result; 450 } 451 } 452 453 // Create player for byte[] 454 class SamplePlayerBytes extends SamplePlayerBase { 455 private final byte[] mData; 456 SamplePlayerBytes(int sampleRate, int encoding, int channelConfig)457 SamplePlayerBytes(int sampleRate, int encoding, int channelConfig) { 458 super(sampleRate, encoding, channelConfig); 459 mData = new byte[128 * 1024]; 460 } 461 SamplePlayerBytes(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId)462 SamplePlayerBytes(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId) 463 throws Exception { 464 super(sampleRate, encoding, channelConfig); 465 mData = loadRawResourceBytes(resourceId); 466 assertTrue("SamplePlayerBytes: load resource file as bytes", mData.length > 0); 467 } 468 469 @Override writeBlock(int numBytes)470 protected int writeBlock(int numBytes) { 471 int result = 0; 472 int bytesToWrite = numBytes; 473 int bytesLeft = mData.length - mOffset; 474 if (bytesToWrite > bytesLeft) { 475 bytesToWrite = bytesLeft; 476 } 477 if (bytesToWrite > 0) { 478 result = mTrack.write(mData, mOffset, bytesToWrite); 479 mOffset += result; 480 } else { 481 mOffset = 0; // rewind 482 } 483 return result; 484 } 485 } 486 testPlayAC3Bytes()487 public void testPlayAC3Bytes() throws Exception { 488 if (mProfileAC3 != null) { 489 SamplePlayerBytes player = new SamplePlayerBytes( 490 48000, AudioFormat.ENCODING_AC3, AudioFormat.CHANNEL_OUT_STEREO, 491 RES_AC3_VOICE_48000); 492 player.playAndMeasureRate(SAMPLE_RATE_LONG_TEST_DURATION_MILLIS); 493 } 494 } 495 testPlayAC3Shorts()496 public void testPlayAC3Shorts() throws Exception { 497 if (mProfileAC3 != null) { 498 SamplePlayerShorts player = new SamplePlayerShorts( 499 48000, AudioFormat.ENCODING_AC3, AudioFormat.CHANNEL_OUT_STEREO, 500 RES_AC3_VOICE_48000); 501 player.playAndMeasureRate(SAMPLE_RATE_LONG_TEST_DURATION_MILLIS); 502 } 503 } 504 testPlayIEC61937_32000()505 public void testPlayIEC61937_32000() throws Exception { 506 if (mProfileIEC61937 != null) { 507 SamplePlayerShorts player = new SamplePlayerShorts( 508 32000, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO, 509 RES_AC3_SPDIF_VOICE_32000); 510 player.playAndMeasureRate(SAMPLE_RATE_LONG_TEST_DURATION_MILLIS); 511 } 512 } 513 testPlayIEC61937_44100()514 public void testPlayIEC61937_44100() throws Exception { 515 if (mProfileIEC61937 != null) { 516 SamplePlayerShorts player = new SamplePlayerShorts( 517 44100, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO, 518 RES_AC3_SPDIF_VOICE_44100); 519 player.playAndMeasureRate(SAMPLE_RATE_LONG_TEST_DURATION_MILLIS); 520 } 521 } 522 testPlayIEC61937_48000()523 public void testPlayIEC61937_48000() throws Exception { 524 if (mProfileIEC61937 != null) { 525 SamplePlayerShorts player = new SamplePlayerShorts( 526 48000, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO, 527 RES_AC3_SPDIF_VOICE_48000); 528 player.playAndMeasureRate(SAMPLE_RATE_LONG_TEST_DURATION_MILLIS); 529 } 530 } 531 testPcmSupport()532 public void testPcmSupport() throws Exception { 533 if (REQUIRE_PCM_PROFILE) { 534 // There should always be a fake PCM profile available. 535 assertTrue("testPcmSupport: PCM should be supported." 536 + " On ATV device please check HDMI connection.", 537 mProfilePCM16 != null); 538 } 539 } 540 isPcmTestingEnabled()541 private boolean isPcmTestingEnabled() { 542 return (mProfilePCM16 != null || !REQUIRE_PCM_PROFILE); 543 } 544 testPlaySineSweepShorts()545 public void testPlaySineSweepShorts() throws Exception { 546 if (isPcmTestingEnabled()) { 547 SamplePlayerShorts player = new SamplePlayerShorts( 548 44100, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO, 549 R.raw.sinesweepraw); 550 player.playAndMeasureRate(SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS); 551 } 552 } 553 testPlaySineSweepBytes()554 public void testPlaySineSweepBytes() throws Exception { 555 if (isPcmTestingEnabled()) { 556 SamplePlayerBytes player = new SamplePlayerBytes( 557 44100, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO, 558 R.raw.sinesweepraw); 559 player.playAndMeasureRate(SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS); 560 } 561 } 562 testPlaySineSweepBytes48000()563 public void testPlaySineSweepBytes48000() throws Exception { 564 if (isPcmTestingEnabled()) { 565 SamplePlayerBytes player = new SamplePlayerBytes( 566 48000, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO, 567 R.raw.sinesweepraw); 568 player.playAndMeasureRate(SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS); 569 } 570 } 571 testPlaySineSweepShortsMono()572 public void testPlaySineSweepShortsMono() throws Exception { 573 if (isPcmTestingEnabled()) { 574 SamplePlayerShorts player = new SamplePlayerShorts(44100, AudioFormat.ENCODING_PCM_16BIT, 575 AudioFormat.CHANNEL_OUT_MONO, 576 R.raw.sinesweepraw); 577 player.playAndMeasureRate(SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS); 578 } 579 } 580 testPlaySineSweepBytesMono()581 public void testPlaySineSweepBytesMono() 582 throws Exception { 583 if (isPcmTestingEnabled()) { 584 SamplePlayerBytes player = new SamplePlayerBytes(44100, AudioFormat.ENCODING_PCM_16BIT, 585 AudioFormat.CHANNEL_OUT_MONO, R.raw.sinesweepraw); 586 player.playAndMeasureRate(SAMPLE_RATE_SHORT_TEST_DURATION_MILLIS); 587 } 588 } 589 590 } 591