1 /* 2 * Copyright (C) 2009 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.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.testng.Assert.assertThrows; 25 26 import android.app.ActivityManager; 27 import android.content.Context; 28 import android.content.pm.PackageManager; 29 import android.media.AudioAttributes; 30 import android.media.AudioFormat; 31 import android.media.AudioManager; 32 import android.media.AudioPresentation; 33 import android.media.AudioTimestamp; 34 import android.media.AudioTrack; 35 import android.media.PlaybackParams; 36 import android.os.PersistableBundle; 37 import android.platform.test.annotations.Presubmit; 38 import android.util.Log; 39 40 import androidx.test.InstrumentationRegistry; 41 import androidx.test.filters.LargeTest; 42 import androidx.test.runner.AndroidJUnit4; 43 44 import com.android.compatibility.common.util.DeviceReportLog; 45 import com.android.compatibility.common.util.ResultType; 46 import com.android.compatibility.common.util.ResultUnit; 47 48 import java.nio.ByteBuffer; 49 import java.nio.FloatBuffer; 50 import java.nio.ShortBuffer; 51 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 55 @RunWith(AndroidJUnit4.class) 56 public class AudioTrackTest { 57 private String TAG = "AudioTrackTest"; 58 private final long WAIT_MSEC = 200; 59 private final int OFFSET_DEFAULT = 0; 60 private final int OFFSET_NEGATIVE = -10; 61 62 private void log(String testName, String message) { 63 Log.v(TAG, "[" + testName + "] " + message); 64 } 65 66 private void loge(String testName, String message) { 67 Log.e(TAG, "[" + testName + "] " + message); 68 } 69 70 // ----------------------------------------------------------------- 71 // private class to hold test results 72 private static class TestResults { 73 public boolean mResult = false; 74 public String mResultLog = ""; 75 76 public TestResults(boolean b, String s) { 77 mResult = b; 78 mResultLog = s; 79 } 80 } 81 82 // ----------------------------------------------------------------- 83 // generic test methods 84 public TestResults constructorTestMultiSampleRate( 85 // parameters tested by this method 86 int _inTest_streamType, int _inTest_mode, int _inTest_config, int _inTest_format, 87 // parameter-dependent expected results 88 int _expected_stateForMode) { 89 90 int[] testSampleRates = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; 91 String failedRates = "Failure for rate(s): "; 92 boolean localRes, finalRes = true; 93 94 for (int i = 0; i < testSampleRates.length; i++) { 95 AudioTrack track = null; 96 try { 97 track = new AudioTrack(_inTest_streamType, testSampleRates[i], _inTest_config, 98 _inTest_format, AudioTrack.getMinBufferSize(testSampleRates[i], 99 _inTest_config, _inTest_format), _inTest_mode); 100 } catch (IllegalArgumentException iae) { 101 Log.e("MediaAudioTrackTest", "[ constructorTestMultiSampleRate ] exception at SR " 102 + testSampleRates[i] + ": \n" + iae); 103 localRes = false; 104 } 105 if (track != null) { 106 localRes = (track.getState() == _expected_stateForMode); 107 track.release(); 108 } else { 109 localRes = false; 110 } 111 112 if (!localRes) { 113 // log the error for the test runner 114 failedRates += Integer.toString(testSampleRates[i]) + "Hz "; 115 // log the error for logcat 116 log("constructorTestMultiSampleRate", "failed to construct " 117 + "AudioTrack(streamType=" 118 + _inTest_streamType 119 + ", sampleRateInHz=" 120 + testSampleRates[i] 121 + ", channelConfig=" 122 + _inTest_config 123 + ", audioFormat=" 124 + _inTest_format 125 + ", bufferSizeInBytes=" 126 + AudioTrack.getMinBufferSize(testSampleRates[i], _inTest_config, 127 AudioFormat.ENCODING_PCM_16BIT) + ", mode=" + _inTest_mode); 128 // mark test as failed 129 finalRes = false; 130 } 131 } 132 return new TestResults(finalRes, failedRates); 133 } 134 135 // ----------------------------------------------------------------- 136 // AUDIOTRACK TESTS: 137 // ---------------------------------- 138 139 // ----------------------------------------------------------------- 140 // AudioTrack constructor and AudioTrack.getMinBufferSize(...) for 16bit PCM 141 // ---------------------------------- 142 143 // Test case 1: constructor for streaming AudioTrack, mono, 16bit at misc 144 // valid sample rates 145 @Test 146 public void testConstructorMono16MusicStream() throws Exception { 147 148 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 149 AudioTrack.MODE_STREAM, AudioFormat.CHANNEL_CONFIGURATION_MONO, 150 AudioFormat.ENCODING_PCM_16BIT, AudioTrack.STATE_INITIALIZED); 151 152 assertTrue("testConstructorMono16MusicStream: " + res.mResultLog, res.mResult); 153 } 154 155 // Test case 2: constructor for streaming AudioTrack, stereo, 16bit at misc 156 // valid sample rates 157 @Test 158 public void testConstructorStereo16MusicStream() throws Exception { 159 160 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 161 AudioTrack.MODE_STREAM, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 162 AudioFormat.ENCODING_PCM_16BIT, AudioTrack.STATE_INITIALIZED); 163 164 assertTrue("testConstructorStereo16MusicStream: " + res.mResultLog, res.mResult); 165 } 166 167 // Test case 3: constructor for static AudioTrack, mono, 16bit at misc valid 168 // sample rates 169 @Test 170 public void testConstructorMono16MusicStatic() throws Exception { 171 172 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 173 AudioTrack.MODE_STATIC, AudioFormat.CHANNEL_CONFIGURATION_MONO, 174 AudioFormat.ENCODING_PCM_16BIT, AudioTrack.STATE_NO_STATIC_DATA); 175 176 assertTrue("testConstructorMono16MusicStatic: " + res.mResultLog, res.mResult); 177 } 178 179 // Test case 4: constructor for static AudioTrack, stereo, 16bit at misc 180 // valid sample rates 181 @Test 182 public void testConstructorStereo16MusicStatic() throws Exception { 183 184 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 185 AudioTrack.MODE_STATIC, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 186 AudioFormat.ENCODING_PCM_16BIT, AudioTrack.STATE_NO_STATIC_DATA); 187 188 assertTrue("testConstructorStereo16MusicStatic: " + res.mResultLog, res.mResult); 189 } 190 191 // ----------------------------------------------------------------- 192 // AudioTrack constructor and AudioTrack.getMinBufferSize(...) for 8bit PCM 193 // ---------------------------------- 194 195 // Test case 1: constructor for streaming AudioTrack, mono, 8bit at misc 196 // valid sample rates 197 @Test 198 public void testConstructorMono8MusicStream() throws Exception { 199 200 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 201 AudioTrack.MODE_STREAM, AudioFormat.CHANNEL_CONFIGURATION_MONO, 202 AudioFormat.ENCODING_PCM_8BIT, AudioTrack.STATE_INITIALIZED); 203 204 assertTrue("testConstructorMono8MusicStream: " + res.mResultLog, res.mResult); 205 } 206 207 // Test case 2: constructor for streaming AudioTrack, stereo, 8bit at misc 208 // valid sample rates 209 @Test 210 public void testConstructorStereo8MusicStream() throws Exception { 211 212 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 213 AudioTrack.MODE_STREAM, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 214 AudioFormat.ENCODING_PCM_8BIT, AudioTrack.STATE_INITIALIZED); 215 216 assertTrue("testConstructorStereo8MusicStream: " + res.mResultLog, res.mResult); 217 } 218 219 // Test case 3: constructor for static AudioTrack, mono, 8bit at misc valid 220 // sample rates 221 @Test 222 public void testConstructorMono8MusicStatic() throws Exception { 223 224 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 225 AudioTrack.MODE_STATIC, AudioFormat.CHANNEL_CONFIGURATION_MONO, 226 AudioFormat.ENCODING_PCM_8BIT, AudioTrack.STATE_NO_STATIC_DATA); 227 228 assertTrue("testConstructorMono8MusicStatic: " + res.mResultLog, res.mResult); 229 } 230 231 // Test case 4: constructor for static AudioTrack, stereo, 8bit at misc 232 // valid sample rates 233 @Test 234 public void testConstructorStereo8MusicStatic() throws Exception { 235 236 TestResults res = constructorTestMultiSampleRate(AudioManager.STREAM_MUSIC, 237 AudioTrack.MODE_STATIC, AudioFormat.CHANNEL_CONFIGURATION_STEREO, 238 AudioFormat.ENCODING_PCM_8BIT, AudioTrack.STATE_NO_STATIC_DATA); 239 240 assertTrue("testConstructorStereo8MusicStatic: " + res.mResultLog, res.mResult); 241 } 242 243 // ----------------------------------------------------------------- 244 // AudioTrack constructor for all stream types 245 // ---------------------------------- 246 247 // Test case 1: constructor for all stream types 248 @Test 249 public void testConstructorStreamType() throws Exception { 250 // constants for test 251 final int TYPE_TEST_SR = 22050; 252 final int TYPE_TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 253 final int TYPE_TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 254 final int TYPE_TEST_MODE = AudioTrack.MODE_STREAM; 255 final int[] STREAM_TYPES = { AudioManager.STREAM_ALARM, AudioManager.STREAM_MUSIC, 256 AudioManager.STREAM_NOTIFICATION, AudioManager.STREAM_RING, 257 AudioManager.STREAM_SYSTEM, AudioManager.STREAM_VOICE_CALL }; 258 final String[] STREAM_NAMES = { "STREAM_ALARM", "STREAM_MUSIC", "STREAM_NOTIFICATION", 259 "STREAM_RING", "STREAM_SYSTEM", "STREAM_VOICE_CALL" }; 260 261 boolean localTestRes = true; 262 AudioTrack track = null; 263 // test: loop constructor on all stream types 264 for (int i = 0; i < STREAM_TYPES.length; i++) { 265 try { 266 // -------- initialization -------------- 267 track = new AudioTrack(STREAM_TYPES[i], TYPE_TEST_SR, TYPE_TEST_CONF, 268 TYPE_TEST_FORMAT, AudioTrack.getMinBufferSize(TYPE_TEST_SR, TYPE_TEST_CONF, 269 TYPE_TEST_FORMAT), TYPE_TEST_MODE); 270 } catch (IllegalArgumentException iae) { 271 loge("testConstructorStreamType", "exception for stream type " + STREAM_NAMES[i] 272 + ": " + iae); 273 localTestRes = false; 274 } 275 // -------- test -------------- 276 if (track != null) { 277 if (track.getState() != AudioTrack.STATE_INITIALIZED) { 278 localTestRes = false; 279 Log.e("MediaAudioTrackTest", 280 "[ testConstructorStreamType ] failed for stream type " 281 + STREAM_NAMES[i]); 282 } 283 // -------- tear down -------------- 284 track.release(); 285 } else { 286 localTestRes = false; 287 } 288 } 289 290 assertTrue("testConstructorStreamType", localTestRes); 291 } 292 293 // ----------------------------------------------------------------- 294 // AudioTrack construction with Builder 295 // ---------------------------------- 296 297 // Test case 1: build AudioTrack with default parameters, test documented default params 298 @Test 299 public void testBuilderDefault() throws Exception { 300 // constants for test 301 final String TEST_NAME = "testBuilderDefault"; 302 final int expectedDefaultEncoding = AudioFormat.ENCODING_PCM_16BIT; 303 final int expectedDefaultRate = 304 AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); 305 final int expectedDefaultChannels = AudioFormat.CHANNEL_OUT_STEREO; 306 // use Builder 307 final int buffSizeInBytes = AudioTrack.getMinBufferSize( 308 expectedDefaultRate, expectedDefaultChannels, expectedDefaultEncoding); 309 final AudioTrack track = new AudioTrack.Builder() 310 .setBufferSizeInBytes(buffSizeInBytes) 311 .build(); 312 // save results 313 final int observedState = track.getState(); 314 final int observedFormat = track.getAudioFormat(); 315 final int observedChannelConf = track.getChannelConfiguration(); 316 final int observedRate = track.getSampleRate(); 317 // release track before the test exits (either successfully or with an exception) 318 track.release(); 319 // compare results 320 assertEquals(TEST_NAME + ": Track initialized", AudioTrack.STATE_INITIALIZED, 321 observedState); 322 assertEquals(TEST_NAME + ": Default track encoding", expectedDefaultEncoding, 323 observedFormat); 324 assertEquals(TEST_NAME + ": Default track channels", expectedDefaultChannels, 325 observedChannelConf); 326 } 327 328 // Test case 2: build AudioTrack with AudioFormat, test it's used 329 @Test 330 public void testBuilderFormat() throws Exception { 331 // constants for test 332 final String TEST_NAME = "testBuilderFormat"; 333 final int TEST_RATE = 32000; 334 final int TEST_CHANNELS = AudioFormat.CHANNEL_OUT_STEREO; 335 // use Builder 336 final int buffSizeInBytes = AudioTrack.getMinBufferSize( 337 TEST_RATE, TEST_CHANNELS, AudioFormat.ENCODING_PCM_16BIT); 338 final AudioTrack track = new AudioTrack.Builder() 339 .setAudioAttributes(new AudioAttributes.Builder().build()) 340 .setBufferSizeInBytes(buffSizeInBytes) 341 .setAudioFormat(new AudioFormat.Builder() 342 .setChannelMask(TEST_CHANNELS).setSampleRate(TEST_RATE).build()) 343 .build(); 344 // save results 345 final int observedState = track.getState(); 346 final int observedChannelConf = track.getChannelConfiguration(); 347 final int observedRate = track.getSampleRate(); 348 // release track before the test exits (either successfully or with an exception) 349 track.release(); 350 // compare results 351 assertEquals(TEST_NAME + ": Track initialized", AudioTrack.STATE_INITIALIZED, 352 observedState); 353 assertEquals(TEST_NAME + ": Track channels", TEST_CHANNELS, observedChannelConf); 354 assertEquals(TEST_NAME + ": Track sample rate", TEST_RATE, observedRate); 355 } 356 357 // Test case 3: build AudioTrack with session ID, test it's used 358 @Test 359 public void testBuilderSession() throws Exception { 360 // constants for test 361 final String TEST_NAME = "testBuilderSession"; 362 // generate a session ID 363 final int expectedSessionId = new AudioManager(getContext()).generateAudioSessionId(); 364 // use builder 365 final AudioTrack track = new AudioTrack.Builder() 366 .setSessionId(expectedSessionId) 367 .build(); 368 // save results 369 final int observedSessionId = track.getAudioSessionId(); 370 // release track before the test exits (either successfully or with an exception) 371 track.release(); 372 // compare results 373 assertEquals(TEST_NAME + ": Assigned track session ID", expectedSessionId, 374 observedSessionId); 375 } 376 377 // Test case 4: build AudioTrack with AudioAttributes built from stream type, test it's used 378 @Test 379 public void testBuilderAttributesStream() throws Exception { 380 // constants for test 381 final String TEST_NAME = "testBuilderAttributesStream"; 382 // use a stream type documented in AudioAttributes.Builder.setLegacyStreamType(int) 383 final int expectedStreamType = AudioManager.STREAM_ALARM; 384 final int expectedContentType = AudioAttributes.CONTENT_TYPE_SPEECH; 385 final AudioAttributes attributes = new AudioAttributes.Builder() 386 .setLegacyStreamType(expectedStreamType) 387 .setContentType(expectedContentType) 388 .build(); 389 // use builder 390 final AudioTrack track = new AudioTrack.Builder() 391 .setAudioAttributes(attributes) 392 .build(); 393 // save results 394 final int observedStreamType = track.getStreamType(); 395 final AudioAttributes observedAttributes = track.getAudioAttributes(); 396 397 // release track before the test exits (either successfully or with an exception) 398 track.release(); 399 // compare results 400 assertEquals(TEST_NAME + ": track stream type", expectedStreamType, observedStreamType); 401 // attributes and observedAttributes should satisfy the overloaded equals. 402 assertEquals(TEST_NAME + ": observed attributes must match", 403 attributes, observedAttributes); 404 // also test content type was preserved in the attributes even though they 405 // were first configured with a legacy stream type 406 assertEquals(TEST_NAME + ": attributes content type", expectedContentType, 407 attributes.getContentType()); 408 } 409 410 // Test case 5: build AudioTrack with attributes and performance mode 411 @Test 412 public void testBuilderAttributesPerformanceMode() throws Exception { 413 // constants for test 414 final String TEST_NAME = "testBuilderAttributesPerformanceMode"; 415 final int testPerformanceModes[] = new int[] { 416 AudioTrack.PERFORMANCE_MODE_NONE, 417 AudioTrack.PERFORMANCE_MODE_LOW_LATENCY, 418 AudioTrack.PERFORMANCE_MODE_POWER_SAVING, 419 }; 420 // construct various attributes with different preset performance modes. 421 final AudioAttributes testAttributes[] = new AudioAttributes[] { 422 new AudioAttributes.Builder().build(), 423 new AudioAttributes.Builder().setFlags(AudioAttributes.FLAG_LOW_LATENCY).build(), 424 new AudioAttributes.Builder().setFlags(AudioAttributes.FLAG_DEEP_BUFFER).build(), 425 }; 426 for (int performanceMode : testPerformanceModes) { 427 for (AudioAttributes attributes : testAttributes) { 428 final AudioTrack track = new AudioTrack.Builder() 429 .setPerformanceMode(performanceMode) 430 .setAudioAttributes(attributes) 431 .build(); 432 // save results 433 final int actualPerformanceMode = track.getPerformanceMode(); 434 // release track before the test exits 435 track.release(); 436 final String result = "Attribute flags: " + attributes.getAllFlags() 437 + " set performance mode: " + performanceMode 438 + " actual performance mode: " + actualPerformanceMode; 439 Log.d(TEST_NAME, result); 440 assertTrue(TEST_NAME + ": " + result, 441 actualPerformanceMode == performanceMode // either successful 442 || actualPerformanceMode == AudioTrack.PERFORMANCE_MODE_NONE // or none 443 || performanceMode == AudioTrack.PERFORMANCE_MODE_NONE); 444 } 445 } 446 } 447 448 // ----------------------------------------------------------------- 449 // Playback head position 450 // ---------------------------------- 451 452 // Test case 1: getPlaybackHeadPosition() at 0 after initialization 453 @Test 454 public void testPlaybackHeadPositionAfterInit() throws Exception { 455 // constants for test 456 final String TEST_NAME = "testPlaybackHeadPositionAfterInit"; 457 final int TEST_SR = 22050; 458 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 459 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 460 final int TEST_MODE = AudioTrack.MODE_STREAM; 461 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 462 463 // -------- initialization -------------- 464 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 465 AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT), TEST_MODE); 466 // -------- test -------------- 467 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 468 assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0); 469 // -------- tear down -------------- 470 track.release(); 471 } 472 473 // Test case 2: getPlaybackHeadPosition() increases after play() 474 @Test 475 public void testPlaybackHeadPositionIncrease() throws Exception { 476 // constants for test 477 final String TEST_NAME = "testPlaybackHeadPositionIncrease"; 478 final int TEST_SR = 22050; 479 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 480 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 481 final int TEST_MODE = AudioTrack.MODE_STREAM; 482 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 483 484 // -------- initialization -------------- 485 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 486 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 487 2 * minBuffSize, TEST_MODE); 488 byte data[] = new byte[minBuffSize]; 489 // -------- test -------------- 490 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 491 track.write(data, OFFSET_DEFAULT, data.length); 492 track.write(data, OFFSET_DEFAULT, data.length); 493 track.play(); 494 Thread.sleep(100); 495 log(TEST_NAME, "position =" + track.getPlaybackHeadPosition()); 496 assertTrue(TEST_NAME, track.getPlaybackHeadPosition() > 0); 497 // -------- tear down -------------- 498 track.release(); 499 } 500 501 // Test case 3: getPlaybackHeadPosition() is 0 after flush(); 502 @Test 503 public void testPlaybackHeadPositionAfterFlush() throws Exception { 504 // constants for test 505 final String TEST_NAME = "testPlaybackHeadPositionAfterFlush"; 506 final int TEST_SR = 22050; 507 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 508 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 509 final int TEST_MODE = AudioTrack.MODE_STREAM; 510 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 511 512 // -------- initialization -------------- 513 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 514 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 515 2 * minBuffSize, TEST_MODE); 516 byte data[] = new byte[minBuffSize]; 517 // -------- test -------------- 518 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 519 track.write(data, OFFSET_DEFAULT, data.length); 520 track.write(data, OFFSET_DEFAULT, data.length); 521 track.play(); 522 Thread.sleep(WAIT_MSEC); 523 track.stop(); 524 track.flush(); 525 log(TEST_NAME, "position =" + track.getPlaybackHeadPosition()); 526 assertTrue(TEST_NAME, track.getPlaybackHeadPosition() == 0); 527 // -------- tear down -------------- 528 track.release(); 529 } 530 531 // Test case 3: getPlaybackHeadPosition() is 0 after stop(); 532 @Test 533 public void testPlaybackHeadPositionAfterStop() throws Exception { 534 // constants for test 535 final String TEST_NAME = "testPlaybackHeadPositionAfterStop"; 536 final int TEST_SR = 22050; 537 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 538 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 539 final int TEST_MODE = AudioTrack.MODE_STREAM; 540 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 541 final int TEST_LOOP_CNT = 10; 542 543 // -------- initialization -------------- 544 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 545 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 546 2 * minBuffSize, TEST_MODE); 547 byte data[] = new byte[minBuffSize]; 548 // -------- test -------------- 549 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 550 track.write(data, OFFSET_DEFAULT, data.length); 551 track.write(data, OFFSET_DEFAULT, data.length); 552 track.play(); 553 Thread.sleep(WAIT_MSEC); 554 track.stop(); 555 int count = 0; 556 int pos; 557 do { 558 Thread.sleep(WAIT_MSEC); 559 pos = track.getPlaybackHeadPosition(); 560 count++; 561 } while((pos != 0) && (count < TEST_LOOP_CNT)); 562 log(TEST_NAME, "position =" + pos + ", read count ="+count); 563 assertTrue(TEST_NAME, pos == 0); 564 // -------- tear down -------------- 565 track.release(); 566 } 567 568 // Test case 4: getPlaybackHeadPosition() is > 0 after play(); pause(); 569 @Test 570 public void testPlaybackHeadPositionAfterPause() throws Exception { 571 // constants for test 572 final String TEST_NAME = "testPlaybackHeadPositionAfterPause"; 573 final int TEST_SR = 22050; 574 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 575 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 576 final int TEST_MODE = AudioTrack.MODE_STREAM; 577 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 578 579 // -------- initialization -------------- 580 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 581 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 582 2 * minBuffSize, TEST_MODE); 583 byte data[] = new byte[minBuffSize]; 584 // -------- test -------------- 585 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 586 track.write(data, OFFSET_DEFAULT, data.length); 587 track.write(data, OFFSET_DEFAULT, data.length); 588 track.play(); 589 Thread.sleep(100); 590 track.pause(); 591 int pos = track.getPlaybackHeadPosition(); 592 log(TEST_NAME, "position =" + pos); 593 assertTrue(TEST_NAME, pos > 0); 594 // -------- tear down -------------- 595 track.release(); 596 } 597 598 // Test case 5: getPlaybackHeadPosition() remains 0 after pause(); flush(); play(); 599 @Test 600 public void testPlaybackHeadPositionAfterFlushAndPlay() throws Exception { 601 // constants for test 602 final String TEST_NAME = "testPlaybackHeadPositionAfterFlushAndPlay"; 603 final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO; 604 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 605 final int TEST_MODE = AudioTrack.MODE_STREAM; 606 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 607 final int TEST_SR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE); 608 609 // -------- initialization -------------- 610 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 611 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 612 2 * minBuffSize, TEST_MODE); 613 byte data[] = new byte[minBuffSize]; 614 // -------- test -------------- 615 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 616 track.write(data, OFFSET_DEFAULT, data.length); 617 track.write(data, OFFSET_DEFAULT, data.length); 618 track.play(); 619 Thread.sleep(100); 620 track.pause(); 621 622 int pos = track.getPlaybackHeadPosition(); 623 log(TEST_NAME, "position after pause =" + pos); 624 assertTrue(TEST_NAME, pos > 0); 625 626 track.flush(); 627 pos = track.getPlaybackHeadPosition(); 628 log(TEST_NAME, "position after flush =" + pos); 629 assertTrue(TEST_NAME, pos == 0); 630 631 track.play(); 632 pos = track.getPlaybackHeadPosition(); 633 log(TEST_NAME, "position after play =" + pos); 634 assertTrue(TEST_NAME, pos == 0); 635 636 Thread.sleep(100); 637 pos = track.getPlaybackHeadPosition(); 638 log(TEST_NAME, "position after 100 ms sleep =" + pos); 639 assertTrue(TEST_NAME, pos == 0); 640 // -------- tear down -------------- 641 track.release(); 642 } 643 644 // ----------------------------------------------------------------- 645 // Playback properties 646 // ---------------------------------- 647 648 // Common code for the testSetStereoVolume* and testSetVolume* tests 649 private void testSetVolumeCommon(String testName, float vol, boolean isStereo) throws Exception { 650 // constants for test 651 final int TEST_SR = 22050; 652 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 653 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 654 final int TEST_MODE = AudioTrack.MODE_STREAM; 655 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 656 657 // -------- initialization -------------- 658 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 659 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 660 2 * minBuffSize, TEST_MODE); 661 byte data[] = new byte[minBuffSize]; 662 // -------- test -------------- 663 track.write(data, OFFSET_DEFAULT, data.length); 664 track.write(data, OFFSET_DEFAULT, data.length); 665 track.play(); 666 if (isStereo) { 667 // TODO to really test this, do a pan instead of using same value for left and right 668 assertTrue(testName, track.setStereoVolume(vol, vol) == AudioTrack.SUCCESS); 669 } else { 670 assertTrue(testName, track.setVolume(vol) == AudioTrack.SUCCESS); 671 } 672 // -------- tear down -------------- 673 track.release(); 674 } 675 676 // Test case 1: setStereoVolume() with max volume returns SUCCESS 677 @Test 678 public void testSetStereoVolumeMax() throws Exception { 679 final String TEST_NAME = "testSetStereoVolumeMax"; 680 float maxVol = AudioTrack.getMaxVolume(); 681 testSetVolumeCommon(TEST_NAME, maxVol, true /*isStereo*/); 682 } 683 684 // Test case 2: setStereoVolume() with min volume returns SUCCESS 685 @Test 686 public void testSetStereoVolumeMin() throws Exception { 687 final String TEST_NAME = "testSetStereoVolumeMin"; 688 float minVol = AudioTrack.getMinVolume(); 689 testSetVolumeCommon(TEST_NAME, minVol, true /*isStereo*/); 690 } 691 692 // Test case 3: setStereoVolume() with mid volume returns SUCCESS 693 @Test 694 public void testSetStereoVolumeMid() throws Exception { 695 final String TEST_NAME = "testSetStereoVolumeMid"; 696 float midVol = (AudioTrack.getMaxVolume() - AudioTrack.getMinVolume()) / 2; 697 testSetVolumeCommon(TEST_NAME, midVol, true /*isStereo*/); 698 } 699 700 // Test case 4: setPlaybackRate() with half the content rate returns SUCCESS 701 @Test 702 public void testSetPlaybackRate() throws Exception { 703 // constants for test 704 final String TEST_NAME = "testSetPlaybackRate"; 705 final int TEST_SR = 22050; 706 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 707 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 708 final int TEST_MODE = AudioTrack.MODE_STREAM; 709 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 710 711 // -------- initialization -------------- 712 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 713 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 714 2 * minBuffSize, TEST_MODE); 715 byte data[] = new byte[minBuffSize]; 716 // -------- test -------------- 717 track.write(data, OFFSET_DEFAULT, data.length); 718 track.write(data, OFFSET_DEFAULT, data.length); 719 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 720 track.play(); 721 assertTrue(TEST_NAME, track.setPlaybackRate((int) (TEST_SR / 2)) == AudioTrack.SUCCESS); 722 // -------- tear down -------------- 723 track.release(); 724 } 725 726 // Test case 5: setPlaybackRate(0) returns bad value error 727 @Test 728 public void testSetPlaybackRateZero() throws Exception { 729 // constants for test 730 final String TEST_NAME = "testSetPlaybackRateZero"; 731 final int TEST_SR = 22050; 732 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 733 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 734 final int TEST_MODE = AudioTrack.MODE_STREAM; 735 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 736 737 // -------- initialization -------------- 738 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 739 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 740 minBuffSize, TEST_MODE); 741 // -------- test -------------- 742 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 743 assertTrue(TEST_NAME, track.setPlaybackRate(0) == AudioTrack.ERROR_BAD_VALUE); 744 // -------- tear down -------------- 745 track.release(); 746 } 747 748 // Test case 6: setPlaybackRate() accepts values twice the output sample 749 // rate 750 @Test 751 public void testSetPlaybackRateTwiceOutputSR() throws Exception { 752 // constants for test 753 final String TEST_NAME = "testSetPlaybackRateTwiceOutputSR"; 754 final int TEST_SR = 22050; 755 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 756 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 757 final int TEST_MODE = AudioTrack.MODE_STREAM; 758 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 759 760 // -------- initialization -------------- 761 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 762 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 763 2 * minBuffSize, TEST_MODE); 764 byte data[] = new byte[minBuffSize]; 765 int outputSR = AudioTrack.getNativeOutputSampleRate(TEST_STREAM_TYPE); 766 // -------- test -------------- 767 track.write(data, OFFSET_DEFAULT, data.length); 768 track.write(data, OFFSET_DEFAULT, data.length); 769 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 770 track.play(); 771 assertTrue(TEST_NAME, track.setPlaybackRate(2 * outputSR) == AudioTrack.SUCCESS); 772 // -------- tear down -------------- 773 track.release(); 774 } 775 776 // Test case 7: setPlaybackRate() and retrieve value, should be the same for 777 // half the content SR 778 @Test 779 public void testSetGetPlaybackRate() throws Exception { 780 // constants for test 781 final String TEST_NAME = "testSetGetPlaybackRate"; 782 final int TEST_SR = 22050; 783 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO; 784 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 785 final int TEST_MODE = AudioTrack.MODE_STREAM; 786 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 787 788 // -------- initialization -------------- 789 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 790 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 791 2 * minBuffSize, TEST_MODE); 792 byte data[] = new byte[minBuffSize]; 793 // -------- test -------------- 794 track.write(data, OFFSET_DEFAULT, data.length); 795 track.write(data, OFFSET_DEFAULT, data.length); 796 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 797 track.play(); 798 track.setPlaybackRate((int) (TEST_SR / 2)); 799 assertTrue(TEST_NAME, track.getPlaybackRate() == (int) (TEST_SR / 2)); 800 // -------- tear down -------------- 801 track.release(); 802 } 803 804 // Test case 8: setPlaybackRate() invalid operation if track not initialized 805 @Test 806 public void testSetPlaybackRateUninit() throws Exception { 807 // constants for test 808 final String TEST_NAME = "testSetPlaybackRateUninit"; 809 final int TEST_SR = 22050; 810 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 811 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 812 final int TEST_MODE = AudioTrack.MODE_STATIC; 813 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 814 815 // -------- initialization -------------- 816 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 817 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 818 minBuffSize, TEST_MODE); 819 // -------- test -------------- 820 assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 821 assertEquals(TEST_NAME, AudioTrack.ERROR_INVALID_OPERATION, 822 track.setPlaybackRate(TEST_SR / 2)); 823 // -------- tear down -------------- 824 track.release(); 825 } 826 827 // Test case 9: setVolume() with max volume returns SUCCESS 828 @Test 829 public void testSetVolumeMax() throws Exception { 830 final String TEST_NAME = "testSetVolumeMax"; 831 float maxVol = AudioTrack.getMaxVolume(); 832 testSetVolumeCommon(TEST_NAME, maxVol, false /*isStereo*/); 833 } 834 835 // Test case 10: setVolume() with min volume returns SUCCESS 836 @Test 837 public void testSetVolumeMin() throws Exception { 838 final String TEST_NAME = "testSetVolumeMin"; 839 float minVol = AudioTrack.getMinVolume(); 840 testSetVolumeCommon(TEST_NAME, minVol, false /*isStereo*/); 841 } 842 843 // Test case 11: setVolume() with mid volume returns SUCCESS 844 @Test 845 public void testSetVolumeMid() throws Exception { 846 final String TEST_NAME = "testSetVolumeMid"; 847 float midVol = (AudioTrack.getMaxVolume() - AudioTrack.getMinVolume()) / 2; 848 testSetVolumeCommon(TEST_NAME, midVol, false /*isStereo*/); 849 } 850 851 // ----------------------------------------------------------------- 852 // Playback progress 853 // ---------------------------------- 854 855 // Test case 1: setPlaybackHeadPosition() on playing track 856 @Test 857 public void testSetPlaybackHeadPositionPlaying() throws Exception { 858 // constants for test 859 final String TEST_NAME = "testSetPlaybackHeadPositionPlaying"; 860 final int TEST_SR = 22050; 861 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 862 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 863 final int TEST_MODE = AudioTrack.MODE_STREAM; 864 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 865 866 // -------- initialization -------------- 867 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 868 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 869 2 * minBuffSize, TEST_MODE); 870 byte data[] = new byte[minBuffSize]; 871 // -------- test -------------- 872 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 873 track.write(data, OFFSET_DEFAULT, data.length); 874 track.write(data, OFFSET_DEFAULT, data.length); 875 track.play(); 876 assertTrue(TEST_NAME, 877 track.setPlaybackHeadPosition(10) == AudioTrack.ERROR_INVALID_OPERATION); 878 // -------- tear down -------------- 879 track.release(); 880 } 881 882 // Test case 2: setPlaybackHeadPosition() on stopped track 883 @Test 884 public void testSetPlaybackHeadPositionStopped() throws Exception { 885 // constants for test 886 final String TEST_NAME = "testSetPlaybackHeadPositionStopped"; 887 final int TEST_SR = 22050; 888 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 889 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 890 final int TEST_MODE = AudioTrack.MODE_STATIC; 891 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 892 893 // -------- initialization -------------- 894 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 895 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 896 2 * minBuffSize, TEST_MODE); 897 byte data[] = new byte[minBuffSize]; 898 // -------- test -------------- 899 assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 900 track.write(data, OFFSET_DEFAULT, data.length); 901 track.write(data, OFFSET_DEFAULT, data.length); 902 assertEquals(TEST_NAME, AudioTrack.STATE_INITIALIZED, track.getState()); 903 track.play(); 904 track.stop(); 905 assertEquals(TEST_NAME, AudioTrack.PLAYSTATE_STOPPED, track.getPlayState()); 906 assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackHeadPosition(10)); 907 // -------- tear down -------------- 908 track.release(); 909 } 910 911 // Test case 3: setPlaybackHeadPosition() on paused track 912 @Test 913 public void testSetPlaybackHeadPositionPaused() throws Exception { 914 // constants for test 915 final String TEST_NAME = "testSetPlaybackHeadPositionPaused"; 916 final int TEST_SR = 22050; 917 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 918 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 919 final int TEST_MODE = AudioTrack.MODE_STATIC; 920 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 921 922 // -------- initialization -------------- 923 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 924 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 925 2 * minBuffSize, TEST_MODE); 926 byte data[] = new byte[minBuffSize]; 927 // -------- test -------------- 928 assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 929 track.write(data, OFFSET_DEFAULT, data.length); 930 track.write(data, OFFSET_DEFAULT, data.length); 931 assertEquals(TEST_NAME, AudioTrack.STATE_INITIALIZED, track.getState()); 932 track.play(); 933 track.pause(); 934 assertEquals(TEST_NAME, AudioTrack.PLAYSTATE_PAUSED, track.getPlayState()); 935 assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackHeadPosition(10)); 936 // -------- tear down -------------- 937 track.release(); 938 } 939 940 // Test case 4: setPlaybackHeadPosition() beyond what has been written 941 @Test 942 public void testSetPlaybackHeadPositionTooFar() throws Exception { 943 // constants for test 944 final String TEST_NAME = "testSetPlaybackHeadPositionTooFar"; 945 final int TEST_SR = 22050; 946 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 947 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 948 final int TEST_MODE = AudioTrack.MODE_STATIC; 949 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 950 951 // -------- initialization -------------- 952 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 953 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 954 2 * minBuffSize, TEST_MODE); 955 byte data[] = new byte[minBuffSize]; 956 // make up a frame index that's beyond what has been written: go from 957 // buffer size to frame 958 // count (given the audio track properties), and add 77. 959 int frameIndexTooFar = (2 * minBuffSize / 2) + 77; 960 // -------- test -------------- 961 assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 962 track.write(data, OFFSET_DEFAULT, data.length); 963 track.write(data, OFFSET_DEFAULT, data.length); 964 assertEquals(TEST_NAME, AudioTrack.STATE_INITIALIZED, track.getState()); 965 track.play(); 966 track.stop(); 967 assertEquals(TEST_NAME, AudioTrack.PLAYSTATE_STOPPED, track.getPlayState()); 968 assertEquals(TEST_NAME, AudioTrack.ERROR_BAD_VALUE, 969 track.setPlaybackHeadPosition(frameIndexTooFar)); 970 // -------- tear down -------------- 971 track.release(); 972 } 973 974 // Test case 5: setLoopPoints() fails for MODE_STREAM 975 @Test 976 public void testSetLoopPointsStream() throws Exception { 977 // constants for test 978 final String TEST_NAME = "testSetLoopPointsStream"; 979 final int TEST_SR = 22050; 980 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 981 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 982 final int TEST_MODE = AudioTrack.MODE_STREAM; 983 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 984 985 // -------- initialization -------------- 986 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 987 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 988 2 * minBuffSize, TEST_MODE); 989 byte data[] = new byte[minBuffSize]; 990 // -------- test -------------- 991 track.write(data, OFFSET_DEFAULT, data.length); 992 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 993 assertTrue(TEST_NAME, track.setLoopPoints(2, 50, 2) == AudioTrack.ERROR_INVALID_OPERATION); 994 // -------- tear down -------------- 995 track.release(); 996 } 997 998 // Test case 6: setLoopPoints() fails start > end 999 @Test 1000 public void testSetLoopPointsStartAfterEnd() throws Exception { 1001 // constants for test 1002 final String TEST_NAME = "testSetLoopPointsStartAfterEnd"; 1003 final int TEST_SR = 22050; 1004 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1005 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1006 final int TEST_MODE = AudioTrack.MODE_STATIC; 1007 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1008 1009 // -------- initialization -------------- 1010 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1011 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1012 minBuffSize, TEST_MODE); 1013 byte data[] = new byte[minBuffSize]; 1014 // -------- test -------------- 1015 track.write(data, OFFSET_DEFAULT, data.length); 1016 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1017 assertTrue(TEST_NAME, track.setLoopPoints(50, 0, 2) == AudioTrack.ERROR_BAD_VALUE); 1018 // -------- tear down -------------- 1019 track.release(); 1020 } 1021 1022 // Test case 6: setLoopPoints() success 1023 @Test 1024 public void testSetLoopPointsSuccess() throws Exception { 1025 // constants for test 1026 final String TEST_NAME = "testSetLoopPointsSuccess"; 1027 final int TEST_SR = 22050; 1028 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1029 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1030 final int TEST_MODE = AudioTrack.MODE_STATIC; 1031 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1032 1033 // -------- initialization -------------- 1034 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1035 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1036 minBuffSize, TEST_MODE); 1037 byte data[] = new byte[minBuffSize]; 1038 // -------- test -------------- 1039 track.write(data, OFFSET_DEFAULT, data.length); 1040 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1041 assertTrue(TEST_NAME, track.setLoopPoints(0, 50, 2) == AudioTrack.SUCCESS); 1042 // -------- tear down -------------- 1043 track.release(); 1044 } 1045 1046 // Test case 7: setLoopPoints() fails with loop length bigger than content 1047 @Test 1048 public void testSetLoopPointsLoopTooLong() throws Exception { 1049 // constants for test 1050 final String TEST_NAME = "testSetLoopPointsLoopTooLong"; 1051 final int TEST_SR = 22050; 1052 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1053 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1054 final int TEST_MODE = AudioTrack.MODE_STATIC; 1055 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1056 1057 // -------- initialization -------------- 1058 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1059 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1060 minBuffSize, TEST_MODE); 1061 byte data[] = new byte[minBuffSize]; 1062 int dataSizeInFrames = minBuffSize / 2; 1063 // -------- test -------------- 1064 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA); 1065 track.write(data, OFFSET_DEFAULT, data.length); 1066 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1067 assertTrue(TEST_NAME, track.setLoopPoints(10, dataSizeInFrames + 20, 2) == 1068 AudioTrack.ERROR_BAD_VALUE); 1069 // -------- tear down -------------- 1070 track.release(); 1071 } 1072 1073 // Test case 8: setLoopPoints() fails with start beyond what can be written 1074 // for the track 1075 @Test 1076 public void testSetLoopPointsStartTooFar() throws Exception { 1077 // constants for test 1078 final String TEST_NAME = "testSetLoopPointsStartTooFar"; 1079 final int TEST_SR = 22050; 1080 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1081 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1082 final int TEST_MODE = AudioTrack.MODE_STATIC; 1083 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1084 1085 // -------- initialization -------------- 1086 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1087 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1088 minBuffSize, TEST_MODE); 1089 byte data[] = new byte[minBuffSize]; 1090 int dataSizeInFrames = minBuffSize / 2;// 16bit data 1091 // -------- test -------------- 1092 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA); 1093 track.write(data, OFFSET_DEFAULT, data.length); 1094 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1095 assertTrue(TEST_NAME, 1096 track.setLoopPoints(dataSizeInFrames + 20, dataSizeInFrames + 50, 2) == 1097 AudioTrack.ERROR_BAD_VALUE); 1098 // -------- tear down -------------- 1099 track.release(); 1100 } 1101 1102 // Test case 9: setLoopPoints() fails with end beyond what can be written 1103 // for the track 1104 @Test 1105 public void testSetLoopPointsEndTooFar() throws Exception { 1106 // constants for test 1107 final String TEST_NAME = "testSetLoopPointsEndTooFar"; 1108 final int TEST_SR = 22050; 1109 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1110 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1111 final int TEST_MODE = AudioTrack.MODE_STATIC; 1112 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1113 1114 // -------- initialization -------------- 1115 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1116 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1117 minBuffSize, TEST_MODE); 1118 byte data[] = new byte[minBuffSize]; 1119 int dataSizeInFrames = minBuffSize / 2;// 16bit data 1120 // -------- test -------------- 1121 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_NO_STATIC_DATA); 1122 track.write(data, OFFSET_DEFAULT, data.length); 1123 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1124 int loopCount = 2; 1125 assertTrue(TEST_NAME, 1126 track.setLoopPoints(dataSizeInFrames - 10, dataSizeInFrames + 50, loopCount) == 1127 AudioTrack.ERROR_BAD_VALUE); 1128 // -------- tear down -------------- 1129 track.release(); 1130 } 1131 1132 // ----------------------------------------------------------------- 1133 // Audio data supply 1134 // ---------------------------------- 1135 1136 // Test case 1: write() fails when supplying less data (bytes) than declared 1137 @Test 1138 public void testWriteByteOffsetTooBig() throws Exception { 1139 // constants for test 1140 final String TEST_NAME = "testWriteByteOffsetTooBig"; 1141 final int TEST_SR = 22050; 1142 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1143 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1144 final int TEST_MODE = AudioTrack.MODE_STREAM; 1145 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1146 1147 // -------- initialization -------------- 1148 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1149 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1150 2 * minBuffSize, TEST_MODE); 1151 byte data[] = new byte[minBuffSize]; 1152 // -------- test -------------- 1153 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1154 int offset = 10; 1155 assertTrue(TEST_NAME, track.write(data, offset, data.length) == AudioTrack.ERROR_BAD_VALUE); 1156 // -------- tear down -------------- 1157 track.release(); 1158 } 1159 1160 // Test case 2: write() fails when supplying less data (shorts) than 1161 // declared 1162 @Test 1163 public void testWriteShortOffsetTooBig() throws Exception { 1164 // constants for test 1165 final String TEST_NAME = "testWriteShortOffsetTooBig"; 1166 final int TEST_SR = 22050; 1167 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1168 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1169 final int TEST_MODE = AudioTrack.MODE_STREAM; 1170 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1171 1172 // -------- initialization -------------- 1173 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1174 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1175 2 * minBuffSize, TEST_MODE); 1176 short data[] = new short[minBuffSize / 2]; 1177 // -------- test -------------- 1178 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1179 int offset = 10; 1180 assertTrue(TEST_NAME, track.write(data, offset, data.length) 1181 == AudioTrack.ERROR_BAD_VALUE); 1182 // -------- tear down -------------- 1183 track.release(); 1184 } 1185 1186 // Test case 3: write() fails when supplying less data (bytes) than declared 1187 @Test 1188 public void testWriteByteSizeTooBig() throws Exception { 1189 // constants for test 1190 final String TEST_NAME = "testWriteByteSizeTooBig"; 1191 final int TEST_SR = 22050; 1192 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1193 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1194 final int TEST_MODE = AudioTrack.MODE_STREAM; 1195 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1196 1197 // -------- initialization -------------- 1198 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1199 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1200 2 * minBuffSize, TEST_MODE); 1201 byte data[] = new byte[minBuffSize]; 1202 // -------- test -------------- 1203 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1204 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, data.length + 10) 1205 == AudioTrack.ERROR_BAD_VALUE); 1206 // -------- tear down -------------- 1207 track.release(); 1208 } 1209 1210 // Test case 4: write() fails when supplying less data (shorts) than 1211 // declared 1212 @Test 1213 public void testWriteShortSizeTooBig() throws Exception { 1214 // constants for test 1215 final String TEST_NAME = "testWriteShortSizeTooBig"; 1216 final int TEST_SR = 22050; 1217 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1218 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1219 final int TEST_MODE = AudioTrack.MODE_STREAM; 1220 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1221 1222 // -------- initialization -------------- 1223 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1224 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1225 2 * minBuffSize, TEST_MODE); 1226 short data[] = new short[minBuffSize / 2]; 1227 // -------- test -------------- 1228 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1229 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, data.length + 10) 1230 == AudioTrack.ERROR_BAD_VALUE); 1231 // -------- tear down -------------- 1232 track.release(); 1233 } 1234 1235 // Test case 5: write() fails with negative offset 1236 @Test 1237 public void testWriteByteNegativeOffset() throws Exception { 1238 // constants for test 1239 final String TEST_NAME = "testWriteByteNegativeOffset"; 1240 final int TEST_SR = 22050; 1241 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1242 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1243 final int TEST_MODE = AudioTrack.MODE_STREAM; 1244 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1245 1246 // -------- initialization -------------- 1247 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1248 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1249 2 * minBuffSize, TEST_MODE); 1250 byte data[] = new byte[minBuffSize]; 1251 // -------- test -------------- 1252 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1253 assertTrue(TEST_NAME, track.write(data, OFFSET_NEGATIVE, data.length - 10) == 1254 AudioTrack.ERROR_BAD_VALUE); 1255 // -------- tear down -------------- 1256 track.release(); 1257 } 1258 1259 // Test case 6: write() fails with negative offset 1260 @Test 1261 public void testWriteShortNegativeOffset() throws Exception { 1262 // constants for test 1263 final String TEST_NAME = "testWriteShortNegativeOffset"; 1264 final int TEST_SR = 22050; 1265 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1266 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1267 final int TEST_MODE = AudioTrack.MODE_STREAM; 1268 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1269 1270 // -------- initialization -------------- 1271 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1272 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1273 2 * minBuffSize, TEST_MODE); 1274 short data[] = new short[minBuffSize / 2]; 1275 // -------- test -------------- 1276 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1277 assertTrue(TEST_NAME, 1278 track.write(data, OFFSET_NEGATIVE, data.length - 10) == AudioTrack.ERROR_BAD_VALUE); 1279 // -------- tear down -------------- 1280 track.release(); 1281 } 1282 1283 // Test case 7: write() fails with negative size 1284 @Test 1285 public void testWriteByteNegativeSize() throws Exception { 1286 // constants for test 1287 final String TEST_NAME = "testWriteByteNegativeSize"; 1288 final int TEST_SR = 22050; 1289 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1290 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1291 final int TEST_MODE = AudioTrack.MODE_STREAM; 1292 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1293 1294 // -------- initialization -------------- 1295 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1296 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1297 2 * minBuffSize, TEST_MODE); 1298 byte data[] = new byte[minBuffSize]; 1299 // -------- test -------------- 1300 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1301 int dataLength = -10; 1302 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, dataLength) 1303 == AudioTrack.ERROR_BAD_VALUE); 1304 // -------- tear down -------------- 1305 track.release(); 1306 } 1307 1308 // Test case 8: write() fails with negative size 1309 @Test 1310 public void testWriteShortNegativeSize() throws Exception { 1311 // constants for test 1312 final String TEST_NAME = "testWriteShortNegativeSize"; 1313 final int TEST_SR = 22050; 1314 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1315 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1316 final int TEST_MODE = AudioTrack.MODE_STREAM; 1317 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1318 1319 // -------- initialization -------------- 1320 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1321 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1322 2 * minBuffSize, TEST_MODE); 1323 short data[] = new short[minBuffSize / 2]; 1324 // -------- test -------------- 1325 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1326 int dataLength = -10; 1327 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, dataLength) 1328 == AudioTrack.ERROR_BAD_VALUE); 1329 // -------- tear down -------------- 1330 track.release(); 1331 } 1332 1333 // Test case 9: write() succeeds and returns the size that was written for 1334 // 16bit 1335 @Test 1336 public void testWriteByte() throws Exception { 1337 // constants for test 1338 final String TEST_NAME = "testWriteByte"; 1339 final int TEST_SR = 22050; 1340 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1341 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1342 final int TEST_MODE = AudioTrack.MODE_STREAM; 1343 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1344 1345 // -------- initialization -------------- 1346 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1347 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1348 2 * minBuffSize, TEST_MODE); 1349 byte data[] = new byte[minBuffSize]; 1350 // -------- test -------------- 1351 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1352 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, data.length) == data.length); 1353 // -------- tear down -------------- 1354 track.release(); 1355 } 1356 1357 // Test case 10: write() succeeds and returns the size that was written for 1358 // 16bit 1359 @Test 1360 public void testWriteShort() throws Exception { 1361 // constants for test 1362 final String TEST_NAME = "testWriteShort"; 1363 final int TEST_SR = 22050; 1364 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1365 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1366 final int TEST_MODE = AudioTrack.MODE_STREAM; 1367 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1368 1369 // -------- initialization -------------- 1370 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1371 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1372 2 * minBuffSize, TEST_MODE); 1373 short data[] = new short[minBuffSize / 2]; 1374 // -------- test -------------- 1375 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1376 assertTrue(TEST_NAME, track.write(data, OFFSET_DEFAULT, data.length) == data.length); 1377 track.flush(); 1378 // -------- tear down -------------- 1379 track.release(); 1380 } 1381 1382 // Test case 11: write() succeeds and returns the size that was written for 1383 // 8bit 1384 @Test 1385 public void testWriteByte8bit() throws Exception { 1386 // constants for test 1387 final String TEST_NAME = "testWriteByte8bit"; 1388 final int TEST_SR = 22050; 1389 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1390 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1391 final int TEST_MODE = AudioTrack.MODE_STREAM; 1392 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1393 1394 // -------- initialization -------------- 1395 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1396 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1397 2 * minBuffSize, TEST_MODE); 1398 byte data[] = new byte[minBuffSize]; 1399 // -------- test -------------- 1400 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1401 assertEquals(TEST_NAME, data.length, track.write(data, OFFSET_DEFAULT, data.length)); 1402 // -------- tear down -------------- 1403 track.release(); 1404 } 1405 1406 // Test case 12: write() succeeds and returns the size that was written for 1407 // 8bit 1408 @Test 1409 public void testWriteShort8bit() throws Exception { 1410 // constants for test 1411 final String TEST_NAME = "testWriteShort8bit"; 1412 final int TEST_SR = 22050; 1413 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1414 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1415 final int TEST_MODE = AudioTrack.MODE_STREAM; 1416 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1417 1418 // -------- initialization -------------- 1419 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1420 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1421 2 * minBuffSize, TEST_MODE); 1422 short data[] = new short[minBuffSize / 2]; 1423 // -------- test -------------- 1424 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1425 assertEquals(TEST_NAME, data.length, track.write(data, OFFSET_DEFAULT, data.length)); 1426 // -------- tear down -------------- 1427 track.release(); 1428 } 1429 1430 // ----------------------------------------------------------------- 1431 // Getters 1432 // ---------------------------------- 1433 1434 // Test case 1: getMinBufferSize() return ERROR_BAD_VALUE if SR < 4000 1435 @Test 1436 public void testGetMinBufferSizeTooLowSR() throws Exception { 1437 // constant for test 1438 final String TEST_NAME = "testGetMinBufferSizeTooLowSR"; 1439 final int TEST_SR = 3999; 1440 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1441 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1442 1443 // -------- initialization & test -------------- 1444 assertTrue(TEST_NAME, AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT) == 1445 AudioTrack.ERROR_BAD_VALUE); 1446 } 1447 1448 // Test case 2: getMinBufferSize() return ERROR_BAD_VALUE if sample rate too high 1449 @Test 1450 public void testGetMinBufferSizeTooHighSR() throws Exception { 1451 // constant for test 1452 final String TEST_NAME = "testGetMinBufferSizeTooHighSR"; 1453 // FIXME need an API to retrieve AudioTrack.SAMPLE_RATE_HZ_MAX 1454 final int TEST_SR = AudioFormat.SAMPLE_RATE_HZ_MAX + 1; 1455 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1456 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1457 1458 // -------- initialization & test -------------- 1459 assertTrue(TEST_NAME, AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT) == 1460 AudioTrack.ERROR_BAD_VALUE); 1461 } 1462 1463 @Test 1464 public void testAudioTrackProperties() throws Exception { 1465 // constants for test 1466 final String TEST_NAME = "testAudioTrackProperties"; 1467 final int TEST_SR = 22050; 1468 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1469 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1470 final int TEST_MODE = AudioTrack.MODE_STREAM; 1471 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1472 1473 // -------- initialization -------------- 1474 int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1475 MockAudioTrack track = new MockAudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, 1476 TEST_FORMAT, 2 * minBuffSize, TEST_MODE); 1477 assertEquals(TEST_NAME, AudioTrack.STATE_INITIALIZED, track.getState()); 1478 assertEquals(TEST_NAME, TEST_FORMAT, track.getAudioFormat()); 1479 assertEquals(TEST_NAME, TEST_CONF, track.getChannelConfiguration()); 1480 assertEquals(TEST_NAME, TEST_SR, track.getSampleRate()); 1481 assertEquals(TEST_NAME, TEST_STREAM_TYPE, track.getStreamType()); 1482 final int hannelCount = 1; 1483 assertEquals(hannelCount, track.getChannelCount()); 1484 final int notificationMarkerPosition = 0; 1485 assertEquals(TEST_NAME, notificationMarkerPosition, track.getNotificationMarkerPosition()); 1486 final int markerInFrames = 2; 1487 assertEquals(TEST_NAME, AudioTrack.SUCCESS, 1488 track.setNotificationMarkerPosition(markerInFrames)); 1489 assertEquals(TEST_NAME, markerInFrames, track.getNotificationMarkerPosition()); 1490 final int positionNotificationPeriod = 0; 1491 assertEquals(TEST_NAME, positionNotificationPeriod, track.getPositionNotificationPeriod()); 1492 final int periodInFrames = 2; 1493 assertEquals(TEST_NAME, AudioTrack.SUCCESS, 1494 track.setPositionNotificationPeriod(periodInFrames)); 1495 assertEquals(TEST_NAME, periodInFrames, track.getPositionNotificationPeriod()); 1496 track.setState(AudioTrack.STATE_NO_STATIC_DATA); 1497 assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 1498 track.setState(AudioTrack.STATE_UNINITIALIZED); 1499 assertEquals(TEST_NAME, AudioTrack.STATE_UNINITIALIZED, track.getState()); 1500 int frameCount = 2 * minBuffSize; 1501 if (TEST_CONF == AudioFormat.CHANNEL_CONFIGURATION_STEREO) { 1502 frameCount /= 2; 1503 } 1504 if (TEST_FORMAT == AudioFormat.ENCODING_PCM_16BIT) { 1505 frameCount /= 2; 1506 } 1507 assertTrue(TEST_NAME, track.getNativeFrameCount() >= frameCount); 1508 assertEquals(TEST_NAME, track.getNativeFrameCount(), track.getBufferSizeInFrames()); 1509 } 1510 1511 @Test 1512 public void testReloadStaticData() throws Exception { 1513 // constants for test 1514 final String TEST_NAME = "testReloadStaticData"; 1515 final int TEST_SR = 22050; 1516 final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO; 1517 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; 1518 final int TEST_MODE = AudioTrack.MODE_STATIC; 1519 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1520 1521 // -------- initialization -------------- 1522 int bufferSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 1523 byte data[] = AudioHelper.createSoundDataInByteArray( 1524 bufferSize, TEST_SR, 1024 /* frequency */, 0 /* sweep */); 1525 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, 1526 bufferSize, TEST_MODE); 1527 // -------- test -------------- 1528 track.write(data, OFFSET_DEFAULT, bufferSize); 1529 assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED); 1530 track.play(); 1531 Thread.sleep(WAIT_MSEC); 1532 track.stop(); 1533 Thread.sleep(WAIT_MSEC); 1534 assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.reloadStaticData()); 1535 track.play(); 1536 Thread.sleep(WAIT_MSEC); 1537 track.stop(); 1538 // -------- tear down -------------- 1539 track.release(); 1540 } 1541 1542 @Presubmit 1543 @Test 1544 public void testPlayStaticDataShort() throws Exception { 1545 if (!hasAudioOutput()) { 1546 Log.w(TAG,"AUDIO_OUTPUT feature not found. This system might not have a valid " 1547 + "audio output HAL"); 1548 return; 1549 } 1550 // constants for test 1551 final String TEST_NAME = "testPlayStaticDataShort"; 1552 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_FLOAT; 1553 final int TEST_SR = 48000; 1554 final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO; 1555 final int TEST_MODE = AudioTrack.MODE_STATIC; 1556 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1557 final double TEST_SWEEP = 100; 1558 final int TEST_LOOPS = 1; 1559 final double TEST_FREQUENCY = 400; 1560 final long WAIT_TIME_MS = 150; // compensate for cold start when run in isolation. 1561 final double TEST_LOOP_DURATION = 0.25; 1562 1563 playOnceStaticData(TEST_NAME, TEST_MODE, TEST_STREAM_TYPE, TEST_SWEEP, 1564 TEST_LOOPS, TEST_FORMAT, TEST_FREQUENCY, TEST_SR, TEST_CONF, 1565 WAIT_TIME_MS, TEST_LOOP_DURATION); 1566 1567 } 1568 1569 @Test 1570 public void testPlayStaticData() throws Exception { 1571 if (!hasAudioOutput()) { 1572 Log.w(TAG,"AUDIO_OUTPUT feature not found. This system might not have a valid " 1573 + "audio output HAL"); 1574 return; 1575 } 1576 // constants for test 1577 final String TEST_NAME = "testPlayStaticData"; 1578 final int TEST_FORMAT_ARRAY[] = { // 6 chirps repeated (TEST_LOOPS+1) times, 3 times 1579 AudioFormat.ENCODING_PCM_8BIT, 1580 AudioFormat.ENCODING_PCM_16BIT, 1581 AudioFormat.ENCODING_PCM_FLOAT, 1582 }; 1583 final int TEST_SR_ARRAY[] = { 1584 12055, // Note multichannel tracks will sound very short at low sample rates 1585 48000, 1586 }; 1587 final int TEST_CONF_ARRAY[] = { 1588 AudioFormat.CHANNEL_OUT_MONO, // 1.0 1589 AudioFormat.CHANNEL_OUT_STEREO, // 2.0 1590 AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, // 7.1 1591 }; 1592 final int TEST_MODE = AudioTrack.MODE_STATIC; 1593 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1594 final double TEST_SWEEP = 100; 1595 final int TEST_LOOPS = 1; 1596 final double TEST_LOOP_DURATION=1; 1597 1598 for (int TEST_FORMAT : TEST_FORMAT_ARRAY) { 1599 double frequency = 400; // frequency changes for each test 1600 for (int TEST_SR : TEST_SR_ARRAY) { 1601 for (int TEST_CONF : TEST_CONF_ARRAY) { 1602 playOnceStaticData(TEST_NAME, TEST_MODE, TEST_STREAM_TYPE, TEST_SWEEP, 1603 TEST_LOOPS, TEST_FORMAT, frequency, TEST_SR, TEST_CONF, WAIT_MSEC, TEST_LOOP_DURATION); 1604 1605 frequency += 70; // increment test tone frequency 1606 } 1607 } 1608 } 1609 } 1610 1611 private void playOnceStaticData(String testName, int testMode, int testStreamType, 1612 double testSweep, int testLoops, int testFormat, double testFrequency, int testSr, 1613 int testConf, long waitMsec, double testLoopDuration) 1614 throws InterruptedException { 1615 // -------- initialization -------------- 1616 final int channelCount = Integer.bitCount(testConf); 1617 final int bufferFrames = (int)(testLoopDuration * testSr); 1618 final int bufferSamples = bufferFrames * channelCount; 1619 final int bufferSize = bufferSamples 1620 * AudioFormat.getBytesPerSample(testFormat); 1621 final double frequency = testFrequency / channelCount; 1622 final long MILLISECONDS_PER_SECOND = 1000; 1623 AudioTrack track = new AudioTrack(testStreamType, testSr, 1624 testConf, testFormat, bufferSize, testMode); 1625 assertEquals(testName, AudioTrack.STATE_NO_STATIC_DATA, track.getState()); 1626 1627 // -------- test -------------- 1628 1629 // test setLoopPoints and setPosition can be called here. 1630 assertEquals(testName, 1631 android.media.AudioTrack.SUCCESS, 1632 track.setPlaybackHeadPosition(bufferFrames/2)); 1633 assertEquals(testName, 1634 android.media.AudioTrack.SUCCESS, 1635 track.setLoopPoints( 1636 0 /*startInFrames*/, bufferFrames, 10 /*loopCount*/)); 1637 // only need to write once to the static track 1638 switch (testFormat) { 1639 case AudioFormat.ENCODING_PCM_8BIT: { 1640 byte data[] = AudioHelper.createSoundDataInByteArray( 1641 bufferSamples, testSr, 1642 frequency, testSweep); 1643 assertEquals(testName, 1644 bufferSamples, 1645 track.write(data, 0 /*offsetInBytes*/, data.length)); 1646 } break; 1647 case AudioFormat.ENCODING_PCM_16BIT: { 1648 short data[] = AudioHelper.createSoundDataInShortArray( 1649 bufferSamples, testSr, 1650 frequency, testSweep); 1651 assertEquals(testName, 1652 bufferSamples, 1653 track.write(data, 0 /*offsetInBytes*/, data.length)); 1654 } break; 1655 case AudioFormat.ENCODING_PCM_FLOAT: { 1656 float data[] = AudioHelper.createSoundDataInFloatArray( 1657 bufferSamples, testSr, 1658 frequency, testSweep); 1659 assertEquals(testName, 1660 bufferSamples, 1661 track.write(data, 0 /*offsetInBytes*/, data.length, 1662 AudioTrack.WRITE_BLOCKING)); 1663 } break; 1664 } 1665 assertEquals(testName, AudioTrack.STATE_INITIALIZED, track.getState()); 1666 // test setLoopPoints and setPosition can be called here. 1667 assertEquals(testName, 1668 android.media.AudioTrack.SUCCESS, 1669 track.setPlaybackHeadPosition(0 /*positionInFrames*/)); 1670 assertEquals(testName, 1671 android.media.AudioTrack.SUCCESS, 1672 track.setLoopPoints(0 /*startInFrames*/, bufferFrames, testLoops)); 1673 1674 track.play(); 1675 Thread.sleep((int)(testLoopDuration * MILLISECONDS_PER_SECOND) * (testLoops + 1)); 1676 Thread.sleep(waitMsec); 1677 1678 // Check position after looping. AudioTrack.getPlaybackHeadPosition() returns 1679 // the running count of frames played, not the actual static buffer position. 1680 int position = track.getPlaybackHeadPosition(); 1681 assertEquals(testName, bufferFrames * (testLoops + 1), position); 1682 1683 track.stop(); 1684 Thread.sleep(waitMsec); 1685 // -------- tear down -------------- 1686 track.release(); 1687 } 1688 1689 @Presubmit 1690 @Test 1691 public void testPlayStreamDataShort() throws Exception { 1692 // constants for test 1693 final String TEST_NAME = "testPlayStreamDataShort"; 1694 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 1695 final int TEST_SR = 48000; 1696 final int TEST_CONF = AudioFormat.CHANNEL_OUT_STEREO; 1697 final int TEST_MODE = AudioTrack.MODE_STREAM; 1698 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1699 final float TEST_SWEEP = 0; // sine wave only 1700 final boolean TEST_IS_LOW_RAM_DEVICE = isLowRamDevice(); 1701 final double TEST_FREQUENCY = 1000; 1702 final long NO_WAIT = 0; 1703 1704 playOnceStreamData(TEST_NAME, TEST_MODE, TEST_STREAM_TYPE, TEST_SWEEP, 1705 TEST_IS_LOW_RAM_DEVICE, TEST_FORMAT, TEST_FREQUENCY, TEST_SR, TEST_CONF, 1706 NO_WAIT); 1707 } 1708 1709 @Test 1710 public void testPlayStreamData() throws Exception { 1711 // constants for test 1712 final String TEST_NAME = "testPlayStreamData"; 1713 final int TEST_FORMAT_ARRAY[] = { // should hear 40 increasing frequency tones, 3 times 1714 AudioFormat.ENCODING_PCM_8BIT, 1715 AudioFormat.ENCODING_PCM_16BIT, 1716 AudioFormat.ENCODING_PCM_FLOAT, 1717 }; 1718 // due to downmixer algorithmic latency, source channels greater than 2 may 1719 // sound shorter in duration at 4kHz sampling rate. 1720 final int TEST_SR_ARRAY[] = { 1721 4000, 1722 44100, 1723 48000, 1724 96000, 1725 192000, 1726 }; 1727 final int TEST_CONF_ARRAY[] = { 1728 AudioFormat.CHANNEL_OUT_MONO, // 1.0 1729 AudioFormat.CHANNEL_OUT_STEREO, // 2.0 1730 AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER, // 3.0 1731 AudioFormat.CHANNEL_OUT_QUAD, // 4.0 1732 AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER, // 5.0 1733 AudioFormat.CHANNEL_OUT_5POINT1, // 5.1 1734 AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER, // 6.1 1735 AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, // 7.1 1736 }; 1737 final int TEST_MODE = AudioTrack.MODE_STREAM; 1738 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1739 final float TEST_SWEEP = 0; // sine wave only 1740 final boolean TEST_IS_LOW_RAM_DEVICE = isLowRamDevice(); 1741 1742 for (int TEST_FORMAT : TEST_FORMAT_ARRAY) { 1743 double frequency = 400; // frequency changes for each test 1744 for (int TEST_SR : TEST_SR_ARRAY) { 1745 for (int TEST_CONF : TEST_CONF_ARRAY) { 1746 playOnceStreamData(TEST_NAME, TEST_MODE, TEST_STREAM_TYPE, TEST_SWEEP, 1747 TEST_IS_LOW_RAM_DEVICE, TEST_FORMAT, frequency, TEST_SR, TEST_CONF, 1748 WAIT_MSEC); 1749 frequency += 50; // increment test tone frequency 1750 } 1751 } 1752 } 1753 } 1754 1755 private void playOnceStreamData(String testName, int testMode, int testStream, 1756 float testSweep, boolean isLowRamDevice, int testFormat, double testFrequency, 1757 int testSr, int testConf, long waitMsec) throws InterruptedException { 1758 final int channelCount = Integer.bitCount(testConf); 1759 if (isLowRamDevice 1760 && (testSr > 96000 || channelCount > 4)) { 1761 return; // ignore. FIXME: reenable when AF memory allocation is updated. 1762 } 1763 // -------- initialization -------------- 1764 final int minBufferSize = AudioTrack.getMinBufferSize(testSr, 1765 testConf, testFormat); // in bytes 1766 AudioTrack track = new AudioTrack(testStream, testSr, 1767 testConf, testFormat, minBufferSize, testMode); 1768 assertTrue(testName, track.getState() == AudioTrack.STATE_INITIALIZED); 1769 1770 // compute parameters for the source signal data. 1771 AudioFormat format = track.getFormat(); 1772 assertEquals(testName, testSr, format.getSampleRate()); 1773 assertEquals(testName, testConf, format.getChannelMask()); 1774 assertEquals(testName, channelCount, format.getChannelCount()); 1775 assertEquals(testName, testFormat, format.getEncoding()); 1776 final int sourceSamples = channelCount 1777 * AudioHelper.frameCountFromMsec(500, 1778 format); // duration of test tones 1779 final double frequency = testFrequency / channelCount; 1780 1781 int written = 0; 1782 // For streaming tracks, it's ok to issue the play() command 1783 // before any audio is written. 1784 track.play(); 1785 // -------- test -------------- 1786 1787 // samplesPerWrite can be any positive value. 1788 // We prefer this to be a multiple of channelCount so write() 1789 // does not return a short count. 1790 // If samplesPerWrite is very large, it is limited to the data length 1791 // and we simply write (blocking) the entire source data and not even loop. 1792 // We choose a value here which simulates double buffer writes. 1793 final int buffers = 2; // double buffering mode 1794 final int samplesPerWrite = 1795 (track.getBufferSizeInFrames() / buffers) * channelCount; 1796 switch (testFormat) { 1797 case AudioFormat.ENCODING_PCM_8BIT: { 1798 byte data[] = AudioHelper.createSoundDataInByteArray( 1799 sourceSamples, testSr, 1800 frequency, testSweep); 1801 while (written < data.length) { 1802 int samples = Math.min(data.length - written, samplesPerWrite); 1803 int ret = track.write(data, written, samples); 1804 assertEquals(testName, samples, ret); 1805 written += ret; 1806 } 1807 } 1808 break; 1809 case AudioFormat.ENCODING_PCM_16BIT: { 1810 short data[] = AudioHelper.createSoundDataInShortArray( 1811 sourceSamples, testSr, 1812 frequency, testSweep); 1813 while (written < data.length) { 1814 int samples = Math.min(data.length - written, samplesPerWrite); 1815 int ret = track.write(data, written, samples); 1816 assertEquals(testName, samples, ret); 1817 written += ret; 1818 } 1819 } 1820 break; 1821 case AudioFormat.ENCODING_PCM_FLOAT: { 1822 float data[] = AudioHelper.createSoundDataInFloatArray( 1823 sourceSamples, testSr, 1824 frequency, testSweep); 1825 while (written < data.length) { 1826 int samples = Math.min(data.length - written, samplesPerWrite); 1827 int ret = track.write(data, written, samples, 1828 AudioTrack.WRITE_BLOCKING); 1829 assertEquals(testName, samples, ret); 1830 written += ret; 1831 } 1832 } 1833 break; 1834 } 1835 1836 // For streaming tracks, AudioTrack.stop() doesn't immediately stop playback. 1837 // Rather, it allows the remaining data in the internal buffer to drain. 1838 track.stop(); 1839 Thread.sleep(waitMsec); // wait for the data to drain. 1840 // -------- tear down -------------- 1841 track.release(); 1842 Thread.sleep(waitMsec); // wait for release to complete 1843 } 1844 1845 @Test 1846 public void testPlayStreamByteBuffer() throws Exception { 1847 // constants for test 1848 final String TEST_NAME = "testPlayStreamByteBuffer"; 1849 final int TEST_FORMAT_ARRAY[] = { // should hear 4 tones played 3 times 1850 AudioFormat.ENCODING_PCM_8BIT, 1851 AudioFormat.ENCODING_PCM_16BIT, 1852 AudioFormat.ENCODING_PCM_FLOAT, 1853 }; 1854 final int TEST_SR_ARRAY[] = { 1855 48000, 1856 }; 1857 final int TEST_CONF_ARRAY[] = { 1858 AudioFormat.CHANNEL_OUT_STEREO, 1859 }; 1860 final int TEST_WRITE_MODE_ARRAY[] = { 1861 AudioTrack.WRITE_BLOCKING, 1862 AudioTrack.WRITE_NON_BLOCKING, 1863 }; 1864 final int TEST_MODE = AudioTrack.MODE_STREAM; 1865 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1866 final float TEST_SWEEP = 0; // sine wave only 1867 1868 for (int TEST_FORMAT : TEST_FORMAT_ARRAY) { 1869 double frequency = 800; // frequency changes for each test 1870 for (int TEST_SR : TEST_SR_ARRAY) { 1871 for (int TEST_CONF : TEST_CONF_ARRAY) { 1872 for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) { 1873 for (int useDirect = 0; useDirect < 2; ++useDirect) { 1874 // -------- initialization -------------- 1875 int minBufferSize = AudioTrack.getMinBufferSize(TEST_SR, 1876 TEST_CONF, TEST_FORMAT); // in bytes 1877 int bufferSize = 12 * minBufferSize; 1878 int bufferSamples = bufferSize 1879 / AudioFormat.getBytesPerSample(TEST_FORMAT); 1880 1881 // create audio track and confirm settings 1882 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, 1883 TEST_CONF, TEST_FORMAT, minBufferSize, TEST_MODE); 1884 assertEquals(TEST_NAME + ": state", 1885 AudioTrack.STATE_INITIALIZED, track.getState()); 1886 assertEquals(TEST_NAME + ": sample rate", 1887 TEST_SR, track.getSampleRate()); 1888 assertEquals(TEST_NAME + ": channel mask", 1889 TEST_CONF, track.getChannelConfiguration()); 1890 assertEquals(TEST_NAME + ": encoding", 1891 TEST_FORMAT, track.getAudioFormat()); 1892 1893 ByteBuffer bb = (useDirect == 1) 1894 ? ByteBuffer.allocateDirect(bufferSize) 1895 : ByteBuffer.allocate(bufferSize); 1896 bb.order(java.nio.ByteOrder.nativeOrder()); 1897 1898 // -------- test -------------- 1899 switch (TEST_FORMAT) { 1900 case AudioFormat.ENCODING_PCM_8BIT: { 1901 byte data[] = AudioHelper.createSoundDataInByteArray( 1902 bufferSamples, TEST_SR, 1903 frequency, TEST_SWEEP); 1904 bb.put(data); 1905 bb.flip(); 1906 } break; 1907 case AudioFormat.ENCODING_PCM_16BIT: { 1908 short data[] = AudioHelper.createSoundDataInShortArray( 1909 bufferSamples, TEST_SR, 1910 frequency, TEST_SWEEP); 1911 ShortBuffer sb = bb.asShortBuffer(); 1912 sb.put(data); 1913 bb.limit(sb.limit() * 2); 1914 } break; 1915 case AudioFormat.ENCODING_PCM_FLOAT: { 1916 float data[] = AudioHelper.createSoundDataInFloatArray( 1917 bufferSamples, TEST_SR, 1918 frequency, TEST_SWEEP); 1919 FloatBuffer fb = bb.asFloatBuffer(); 1920 fb.put(data); 1921 bb.limit(fb.limit() * 4); 1922 } break; 1923 } 1924 1925 boolean hasPlayed = false; 1926 int written = 0; 1927 while (written < bufferSize) { 1928 int ret = track.write(bb, 1929 Math.min(bufferSize - written, minBufferSize), 1930 TEST_WRITE_MODE); 1931 assertTrue(TEST_NAME, ret >= 0); 1932 written += ret; 1933 if (!hasPlayed) { 1934 track.play(); 1935 hasPlayed = true; 1936 } 1937 } 1938 1939 track.stop(); 1940 Thread.sleep(WAIT_MSEC); 1941 // -------- tear down -------------- 1942 track.release(); 1943 frequency += 200; // increment test tone frequency 1944 } 1945 } 1946 } 1947 } 1948 } 1949 } 1950 1951 @Test 1952 public void testPlayChannelIndexStreamBuffer() throws Exception { 1953 // should hear 4 tones played 3 or 4 times depending 1954 // on the device output capabilities (e.g. stereo or 5.1 or otherwise) 1955 final String TEST_NAME = "testPlayChannelIndexStreamBuffer"; 1956 final int TEST_FORMAT_ARRAY[] = { 1957 AudioFormat.ENCODING_PCM_8BIT, 1958 //AudioFormat.ENCODING_PCM_16BIT, 1959 //AudioFormat.ENCODING_PCM_FLOAT, 1960 }; 1961 final int TEST_SR_ARRAY[] = { 1962 48000, 1963 }; 1964 // The following channel index masks are iterated over and route 1965 // the AudioTrack channels to the output sink channels based on 1966 // the set bits in counting order (lsb to msb). 1967 // 1968 // For a stereo output sink, the sound may come from L and R, L only, none, or R only. 1969 // For a 5.1 output sink, the sound may come from a variety of outputs 1970 // as commented below. 1971 final int TEST_CONF_ARRAY[] = { // matches output sink channels: 1972 (1 << 0) | (1 << 1), // Stereo(L, R) 5.1(FL, FR) 1973 (1 << 0) | (1 << 2), // Stereo(L) 5.1(FL, FC) 1974 (1 << 4) | (1 << 5), // Stereo(None) 5.1(BL, BR) 1975 (1 << 1) | (1 << 2), // Stereo(R) 5.1(FR, FC) 1976 }; 1977 final int TEST_WRITE_MODE_ARRAY[] = { 1978 AudioTrack.WRITE_BLOCKING, 1979 AudioTrack.WRITE_NON_BLOCKING, 1980 }; 1981 final float TEST_SWEEP = 0; 1982 1983 for (int TEST_FORMAT : TEST_FORMAT_ARRAY) { 1984 for (int TEST_CONF : TEST_CONF_ARRAY) { 1985 double frequency = 800; // frequency changes for each test 1986 for (int TEST_SR : TEST_SR_ARRAY) { 1987 for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) { 1988 for (int useDirect = 0; useDirect < 2; ++useDirect) { 1989 AudioFormat format = new AudioFormat.Builder() 1990 .setEncoding(TEST_FORMAT) 1991 .setSampleRate(TEST_SR) 1992 .setChannelIndexMask(TEST_CONF) 1993 .build(); 1994 AudioTrack track = new AudioTrack.Builder() 1995 .setAudioFormat(format) 1996 .build(); 1997 assertEquals(TEST_NAME, 1998 AudioTrack.STATE_INITIALIZED, track.getState()); 1999 2000 // create the byte buffer and fill with test data 2001 final int frameSize = AudioHelper.frameSizeFromFormat(format); 2002 final int frameCount = 2003 AudioHelper.frameCountFromMsec(300 /* ms */, format); 2004 final int bufferSize = frameCount * frameSize; 2005 final int bufferSamples = frameCount * format.getChannelCount(); 2006 ByteBuffer bb = (useDirect == 1) 2007 ? ByteBuffer.allocateDirect(bufferSize) 2008 : ByteBuffer.allocate(bufferSize); 2009 bb.order(java.nio.ByteOrder.nativeOrder()); 2010 2011 switch (TEST_FORMAT) { 2012 case AudioFormat.ENCODING_PCM_8BIT: { 2013 byte data[] = AudioHelper.createSoundDataInByteArray( 2014 bufferSamples, TEST_SR, 2015 frequency, TEST_SWEEP); 2016 bb.put(data); 2017 bb.flip(); 2018 } break; 2019 case AudioFormat.ENCODING_PCM_16BIT: { 2020 short data[] = AudioHelper.createSoundDataInShortArray( 2021 bufferSamples, TEST_SR, 2022 frequency, TEST_SWEEP); 2023 ShortBuffer sb = bb.asShortBuffer(); 2024 sb.put(data); 2025 bb.limit(sb.limit() * 2); 2026 } break; 2027 case AudioFormat.ENCODING_PCM_FLOAT: { 2028 float data[] = AudioHelper.createSoundDataInFloatArray( 2029 bufferSamples, TEST_SR, 2030 frequency, TEST_SWEEP); 2031 FloatBuffer fb = bb.asFloatBuffer(); 2032 fb.put(data); 2033 bb.limit(fb.limit() * 4); 2034 } break; 2035 } 2036 2037 // start the AudioTrack 2038 // This can be done before or after the first write. 2039 // Current behavior for streaming tracks is that 2040 // actual playback does not begin before the internal 2041 // data buffer is completely full. 2042 track.play(); 2043 2044 // write data 2045 final long startTime = System.currentTimeMillis(); 2046 final long maxDuration = frameCount * 1000 / TEST_SR + 1000; 2047 for (int written = 0; written < bufferSize; ) { 2048 // ret may return a short count if write 2049 // is non blocking or even if write is blocking 2050 // when a stop/pause/flush is issued from another thread. 2051 final int kBatchFrames = 1000; 2052 int ret = track.write(bb, 2053 Math.min(bufferSize - written, frameSize * kBatchFrames), 2054 TEST_WRITE_MODE); 2055 // for non-blocking mode, this loop may spin quickly 2056 assertTrue(TEST_NAME + ": write error " + ret, ret >= 0); 2057 assertTrue(TEST_NAME + ": write timeout", 2058 (System.currentTimeMillis() - startTime) <= maxDuration); 2059 written += ret; 2060 } 2061 2062 // for streaming tracks, stop will allow the rest of the data to 2063 // drain out, but we don't know how long to wait unless 2064 // we check the position before stop. if we check position 2065 // after we stop, we read 0. 2066 final int position = track.getPlaybackHeadPosition(); 2067 final int remainingTimeMs = (int)((double)(frameCount - position) 2068 * 1000 / TEST_SR); 2069 track.stop(); 2070 Thread.sleep(remainingTimeMs); 2071 // tear down 2072 track.release(); 2073 // add a gap to make tones distinct 2074 Thread.sleep(100 /* millis */); 2075 frequency += 200; // increment test tone frequency 2076 } 2077 } 2078 } 2079 } 2080 } 2081 } 2082 2083 private boolean hasAudioOutput() { 2084 return getContext().getPackageManager() 2085 .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT); 2086 } 2087 2088 private boolean isLowRamDevice() { 2089 return ((ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE)) 2090 .isLowRamDevice(); 2091 } 2092 2093 @Test 2094 public void testGetTimestamp() throws Exception { 2095 if (!hasAudioOutput()) { 2096 Log.w(TAG, "AUDIO_OUTPUT feature not found. This system might not have a valid " 2097 + "audio output HAL"); 2098 return; 2099 } 2100 String streamName = "test_get_timestamp"; 2101 doTestTimestamp( 2102 22050 /* sampleRate */, 2103 AudioFormat.CHANNEL_OUT_MONO , 2104 AudioFormat.ENCODING_PCM_16BIT, 2105 AudioTrack.MODE_STREAM, 2106 streamName); 2107 } 2108 2109 @Test 2110 public void testFastTimestamp() throws Exception { 2111 if (!hasAudioOutput()) { 2112 Log.w(TAG, "AUDIO_OUTPUT feature not found. This system might not have a valid " 2113 + "audio output HAL"); 2114 return; 2115 } 2116 String streamName = "test_fast_timestamp"; 2117 doTestTimestamp( 2118 AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC), 2119 AudioFormat.CHANNEL_OUT_MONO, 2120 AudioFormat.ENCODING_PCM_16BIT, 2121 AudioTrack.MODE_STREAM, 2122 streamName); 2123 } 2124 2125 private void doTestTimestamp(int sampleRate, int channelMask, int encoding, int transferMode, 2126 String streamName) throws Exception { 2127 // constants for test 2128 final int TEST_LOOP_CNT = 10; 2129 final int TEST_BUFFER_MS = 100; 2130 final int TEST_USAGE = AudioAttributes.USAGE_MEDIA; 2131 2132 final int MILLIS_PER_SECOND = 1000; 2133 2134 // -------- initialization -------------- 2135 final int frameSize = 2136 AudioFormat.getBytesPerSample(encoding) 2137 * AudioFormat.channelCountFromOutChannelMask(channelMask); 2138 // see whether we can use fast mode 2139 final int nativeOutputSampleRate = 2140 AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC); 2141 Log.d(TAG, "Native output sample rate " + nativeOutputSampleRate); 2142 final boolean fast = (sampleRate == nativeOutputSampleRate); 2143 2144 AudioAttributes attributes = (fast ? new AudioAttributes.Builder() 2145 .setFlags(AudioAttributes.FLAG_LOW_LATENCY) : new AudioAttributes.Builder()) 2146 .setUsage(TEST_USAGE) 2147 .build(); 2148 AudioFormat format = new AudioFormat.Builder() 2149 //.setChannelIndexMask((1 << AudioFormat.channelCountFromOutChannelMask(channelMask)) - 1) 2150 .setChannelMask(channelMask) 2151 .setEncoding(encoding) 2152 .setSampleRate(sampleRate) 2153 .build(); 2154 // not specifying the buffer size in the builder should get us the minimum buffer size. 2155 AudioTrack track = new AudioTrack.Builder() 2156 .setAudioAttributes(attributes) 2157 .setAudioFormat(format) 2158 .setTransferMode(transferMode) 2159 .build(); 2160 assertEquals(AudioTrack.STATE_INITIALIZED, track.getState()); 2161 2162 try { 2163 // We generally use a transfer size of 100ms for testing, but in rare cases 2164 // (e.g. Bluetooth) this needs to be larger to exceed the internal track buffer. 2165 final int frameCount = 2166 Math.max(track.getBufferCapacityInFrames(), 2167 sampleRate * TEST_BUFFER_MS / MILLIS_PER_SECOND); 2168 track.play(); 2169 2170 // Android nanoTime implements MONOTONIC, same as our audio timestamps. 2171 final long trackStartTimeNs = System.nanoTime(); 2172 2173 final ByteBuffer data = ByteBuffer.allocate(frameCount * frameSize); 2174 data.order(java.nio.ByteOrder.nativeOrder()).limit(frameCount * frameSize); 2175 final AudioTimestamp timestamp = new AudioTimestamp(); 2176 2177 long framesWritten = 0; 2178 final AudioHelper.TimestampVerifier tsVerifier = 2179 new AudioHelper.TimestampVerifier(TAG, sampleRate); 2180 for (int i = 0; i < TEST_LOOP_CNT; ++i) { 2181 final long trackWriteTimeNs = System.nanoTime(); 2182 2183 data.position(0); 2184 assertEquals("write did not complete", 2185 data.limit(), track.write(data, data.limit(), AudioTrack.WRITE_BLOCKING)); 2186 assertEquals("write did not fill buffer", 2187 data.position(), data.limit()); 2188 framesWritten += data.limit() / frameSize; 2189 2190 // track.getTimestamp may return false if there are no physical HAL outputs. 2191 // This may occur on TV devices without connecting an HDMI monitor. 2192 // It may also be true immediately after start-up, as the mixing thread could 2193 // be idle, but since we've already pushed much more than the minimum buffer size, 2194 // that is unlikely. 2195 // Nevertheless, we don't want to have unnecessary failures, so we ignore the 2196 // first iteration if we don't get a timestamp. 2197 final boolean result = track.getTimestamp(timestamp); 2198 assertTrue("timestamp could not be read", result || i == 0); 2199 if (!result) { 2200 continue; 2201 } 2202 2203 tsVerifier.add(timestamp); 2204 2205 // Ensure that seen is greater than presented. 2206 // This is an "on-the-fly" read without pausing because pausing may cause the 2207 // timestamp to become stale and affect our jitter measurements. 2208 final long framesPresented = timestamp.framePosition; 2209 final int framesSeen = track.getPlaybackHeadPosition(); 2210 assertTrue("server frames ahead of client frames", 2211 framesWritten >= framesSeen); 2212 assertTrue("presented frames ahead of server frames", 2213 framesSeen >= framesPresented); 2214 } 2215 // Full drain. 2216 Thread.sleep(1000 /* millis */); 2217 // check that we are really at the end of playback. 2218 assertTrue("timestamp should be valid while draining", track.getTimestamp(timestamp)); 2219 // fast tracks and sw emulated tracks may not fully drain. we log the status here. 2220 if (framesWritten != timestamp.framePosition) { 2221 Log.d(TAG, "timestamp should fully drain. written: " 2222 + framesWritten + " position: " + timestamp.framePosition); 2223 } 2224 2225 tsVerifier.verifyAndLog(trackStartTimeNs, streamName); 2226 2227 } finally { 2228 track.release(); 2229 } 2230 } 2231 2232 @Test 2233 public void testVariableRatePlayback() throws Exception { 2234 final String TEST_NAME = "testVariableRatePlayback"; 2235 final int TEST_SR = 24000; 2236 final int TEST_FINAL_SR = 96000; 2237 final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO; 2238 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; // required for test 2239 final int TEST_MODE = AudioTrack.MODE_STATIC; // required for test 2240 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 2241 2242 final int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT); 2243 final int bufferSizeInBytes = minBuffSize * 100; 2244 final int numChannels = AudioFormat.channelCountFromOutChannelMask(TEST_CONF); 2245 final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT); 2246 final int bytesPerFrame = numChannels * bytesPerSample; 2247 final int frameCount = bufferSizeInBytes / bytesPerFrame; 2248 2249 AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, 2250 TEST_FORMAT, bufferSizeInBytes, TEST_MODE); 2251 2252 // create byte array and write it 2253 byte[] vai = AudioHelper.createSoundDataInByteArray(bufferSizeInBytes, TEST_SR, 2254 600 /* frequency */, 0 /* sweep */); 2255 assertEquals(vai.length, track.write(vai, 0 /* offsetInBytes */, vai.length)); 2256 2257 // sweep up test and sweep down test 2258 int[] sampleRates = {TEST_SR, TEST_FINAL_SR}; 2259 int[] deltaMss = {10, 10}; 2260 int[] deltaFreqs = {200, -200}; 2261 2262 for (int i = 0; i < 2; ++i) { 2263 int remainingTime; 2264 int sampleRate = sampleRates[i]; 2265 final int deltaMs = deltaMss[i]; 2266 final int deltaFreq = deltaFreqs[i]; 2267 final int lastCheckMs = 500; // check the last 500 ms 2268 2269 assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackRate(sampleRate)); 2270 track.play(); 2271 do { 2272 Thread.sleep(deltaMs); 2273 final int position = track.getPlaybackHeadPosition(); 2274 sampleRate += deltaFreq; 2275 sampleRate = Math.min(TEST_FINAL_SR, Math.max(TEST_SR, sampleRate)); 2276 assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackRate(sampleRate)); 2277 remainingTime = (int)((double)(frameCount - position) * 1000 2278 / sampleRate / bytesPerFrame); 2279 } while (remainingTime >= lastCheckMs + deltaMs); 2280 2281 // ensure the final frequency set is constant and plays frames as expected 2282 final int position1 = track.getPlaybackHeadPosition(); 2283 Thread.sleep(lastCheckMs); 2284 final int position2 = track.getPlaybackHeadPosition(); 2285 2286 final int tolerance60MsInFrames = sampleRate * 60 / 1000; 2287 final int expected = lastCheckMs * sampleRate / 1000; 2288 final int actual = position2 - position1; 2289 2290 // Log.d(TAG, "Variable Playback: expected(" + expected + ") actual(" + actual 2291 // + ") diff(" + (expected - actual) + ")"); 2292 assertEquals(expected, actual, tolerance60MsInFrames); 2293 track.stop(); 2294 } 2295 track.release(); 2296 } 2297 2298 // Test that AudioTrack stop limits drain to only those frames written at the time of stop. 2299 // This ensures consistent stop behavior on Android P and beyond, where data written 2300 // immediately after a stop doesn't get caught in the drain. 2301 @LargeTest 2302 @Test 2303 public void testStopDrain() throws Exception { 2304 final String TEST_NAME = "testStopDrain"; 2305 final int TEST_SR = 8000; 2306 final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO; // required for test 2307 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; // required for test 2308 final int TEST_MODE = AudioTrack.MODE_STREAM; // required for test 2309 final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC; 2310 2311 final int channelCount = AudioFormat.channelCountFromOutChannelMask(TEST_CONF); 2312 final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT); 2313 final int bytesPerFrame = channelCount * bytesPerSample; 2314 final int frameCount = TEST_SR * 3; // 3 seconds of buffer. 2315 final int bufferSizeInBytes = frameCount * bytesPerFrame; 2316 2317 final AudioTrack track = new AudioTrack( 2318 TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT, bufferSizeInBytes, TEST_MODE); 2319 2320 try { 2321 // Create 6 seconds of data, but send down only 3 seconds to fill buffer. 2322 final byte[] soundData = AudioHelper.createSoundDataInByteArray( 2323 bufferSizeInBytes * 2, TEST_SR, 600 /* frequency */, 0 /* sweep */); 2324 assertEquals("cannot fill AudioTrack buffer", 2325 bufferSizeInBytes, 2326 track.write(soundData, 0 /* offsetInBytes */, bufferSizeInBytes)); 2327 2328 // Set the track playing. 2329 track.play(); 2330 2331 // Note that the timings here are very generous for our test (really the 2332 // granularity we need is on the order of a second). If we don't get scheduled 2333 // to run within about a second or so - this should be extremely rare - 2334 // the result should be a false pass (rather than a false fail). 2335 2336 // After 1.5 seconds stop. 2337 Thread.sleep(1500 /* millis */); // Assume device starts within 1.5 sec. 2338 track.stop(); 2339 2340 // We should drain 1.5 seconds and fill another 3 seconds of data. 2341 // We shouldn't be able to write 6 seconds of data - that indicates stop continues 2342 // to drain beyond the frames written at the time of stop. 2343 int length = 0; 2344 while (length < soundData.length) { 2345 Thread.sleep(800 /* millis */); // assume larger than AF thread loop period 2346 final int delta = track.write(soundData, length, soundData.length - length); 2347 assertTrue("track write error: " + delta, delta >= 0); 2348 if (delta == 0) break; 2349 length += delta; 2350 } 2351 2352 // Check to see we limit the data drained (should be able to exactly fill the buffer). 2353 assertEquals("stop drain must be limited " + bufferSizeInBytes + " != " + length, 2354 bufferSizeInBytes, length); 2355 } finally { 2356 track.release(); 2357 } 2358 } 2359 2360 @Test 2361 public void testVariableSpeedPlayback() throws Exception { 2362 if (!hasAudioOutput()) { 2363 Log.w(TAG,"AUDIO_OUTPUT feature not found. This system might not have a valid " 2364 + "audio output HAL"); 2365 return; 2366 } 2367 2368 final String TEST_NAME = "testVariableSpeedPlayback"; 2369 final int TEST_FORMAT = AudioFormat.ENCODING_PCM_FLOAT; // required for test 2370 final int TEST_MODE = AudioTrack.MODE_STATIC; // required for test 2371 final int TEST_SR = 48000; 2372 2373 AudioFormat format = new AudioFormat.Builder() 2374 //.setChannelIndexMask((1 << 0)) // output to first channel, FL 2375 .setChannelMask(AudioFormat.CHANNEL_OUT_MONO) 2376 .setEncoding(TEST_FORMAT) 2377 .setSampleRate(TEST_SR) 2378 .build(); 2379 2380 // create track 2381 final int frameCount = AudioHelper.frameCountFromMsec(100 /*ms*/, format); 2382 final int frameSize = AudioHelper.frameSizeFromFormat(format); 2383 AudioTrack track = new AudioTrack.Builder() 2384 .setAudioFormat(format) 2385 .setBufferSizeInBytes(frameCount * frameSize) 2386 .setTransferMode(TEST_MODE) 2387 .build(); 2388 2389 // create float array and write it 2390 final int sampleCount = frameCount * format.getChannelCount(); 2391 float[] vaf = AudioHelper.createSoundDataInFloatArray( 2392 sampleCount, TEST_SR, 600 /* frequency */, 0 /* sweep */); 2393 assertEquals(vaf.length, track.write(vaf, 0 /* offsetInFloats */, vaf.length, 2394 AudioTrack.WRITE_NON_BLOCKING)); 2395 2396 // sweep speed and pitch 2397 final float[][][] speedAndPitch = { 2398 // { {speedStart, pitchStart} {speedEnd, pitchEnd} } 2399 { {0.5f, 0.5f}, {2.0f, 2.0f} }, // speed by SR conversion (chirp) 2400 { {0.5f, 1.0f}, {2.0f, 1.0f} }, // speed by time stretch (constant pitch) 2401 { {1.0f, 0.5f}, {1.0f, 2.0f} }, // pitch by SR conversion (chirp) 2402 }; 2403 2404 // sanity test that playback params works as expected 2405 PlaybackParams params = new PlaybackParams().allowDefaults(); 2406 assertEquals("default speed not correct", 1.0f, params.getSpeed(), 0.f /* delta */); 2407 assertEquals("default pitch not correct", 1.0f, params.getPitch(), 0.f /* delta */); 2408 assertEquals(TEST_NAME, 2409 params.AUDIO_FALLBACK_MODE_DEFAULT, 2410 params.getAudioFallbackMode()); 2411 track.setPlaybackParams(params); // OK 2412 params.setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_FAIL); 2413 assertEquals(TEST_NAME, 2414 params.AUDIO_FALLBACK_MODE_FAIL, params.getAudioFallbackMode()); 2415 params.setPitch(0.0f); 2416 try { 2417 track.setPlaybackParams(params); 2418 fail("IllegalArgumentException should be thrown on out of range data"); 2419 } catch (IllegalArgumentException e) { 2420 ; // expect this is invalid 2421 } 2422 // on failure, the AudioTrack params should not change. 2423 PlaybackParams paramCheck = track.getPlaybackParams(); 2424 assertEquals(TEST_NAME, 2425 paramCheck.AUDIO_FALLBACK_MODE_DEFAULT, paramCheck.getAudioFallbackMode()); 2426 assertEquals("pitch should be unchanged on failure", 2427 1.0f, paramCheck.getPitch(), 0. /* delta */); 2428 2429 // now try to see if we can do extreme pitch correction that should probably be muted. 2430 params.setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_MUTE); 2431 assertEquals(TEST_NAME, 2432 params.AUDIO_FALLBACK_MODE_MUTE, params.getAudioFallbackMode()); 2433 params.setPitch(0.1f); 2434 track.setPlaybackParams(params); // OK 2435 2436 // now do our actual playback 2437 final int TEST_TIME_MS = 2000; 2438 final int TEST_DELTA_MS = 100; 2439 final int testSteps = TEST_TIME_MS / TEST_DELTA_MS; 2440 2441 for (int i = 0; i < speedAndPitch.length; ++i) { 2442 final float speedStart = speedAndPitch[i][0][0]; 2443 final float pitchStart = speedAndPitch[i][0][1]; 2444 final float speedEnd = speedAndPitch[i][1][0]; 2445 final float pitchEnd = speedAndPitch[i][1][1]; 2446 final float speedInc = (speedEnd - speedStart) / testSteps; 2447 final float pitchInc = (pitchEnd - pitchStart) / testSteps; 2448 2449 PlaybackParams playbackParams = new PlaybackParams() 2450 .setPitch(pitchStart) 2451 .setSpeed(speedStart) 2452 .allowDefaults(); 2453 2454 // set track in infinite loop to be a sine generator 2455 track.setLoopPoints(0, frameCount, -1 /* loopCount */); // cleared by stop() 2456 track.play(); 2457 2458 Thread.sleep(300 /* millis */); // warm up track 2459 2460 int anticipatedPosition = track.getPlaybackHeadPosition(); 2461 for (int j = 0; j < testSteps; ++j) { 2462 // set playback settings 2463 final float pitch = playbackParams.getPitch(); 2464 final float speed = playbackParams.getSpeed(); 2465 2466 track.setPlaybackParams(playbackParams); 2467 2468 // verify that settings have changed 2469 PlaybackParams checkParams = track.getPlaybackParams(); 2470 assertEquals("pitch not changed correctly", 2471 pitch, checkParams.getPitch(), 0. /* delta */); 2472 assertEquals("speed not changed correctly", 2473 speed, checkParams.getSpeed(), 0. /* delta */); 2474 2475 // sleep for playback 2476 Thread.sleep(TEST_DELTA_MS); 2477 // Log.d(TAG, "position[" + j + "] " + track.getPlaybackHeadPosition()); 2478 anticipatedPosition += 2479 playbackParams.getSpeed() * TEST_DELTA_MS * TEST_SR / 1000; 2480 playbackParams.setPitch(playbackParams.getPitch() + pitchInc); 2481 playbackParams.setSpeed(playbackParams.getSpeed() + speedInc); 2482 } 2483 final int endPosition = track.getPlaybackHeadPosition(); 2484 final int tolerance100MsInFrames = 100 * TEST_SR / 1000; 2485 assertEquals(TAG, anticipatedPosition, endPosition, tolerance100MsInFrames); 2486 track.stop(); 2487 2488 Thread.sleep(100 /* millis */); // distinct pause between each test 2489 } 2490 track.release(); 2491 } 2492 2493 // Test AudioTrack to ensure we can build after a failure. 2494 @Test 2495 public void testAudioTrackBufferSize() throws Exception { 2496 // constants for test 2497 final String TEST_NAME = "testAudioTrackBufferSize"; 2498 2499 // use builder with parameters that should fail 2500 final int superBigBufferSize = 1 << 28; 2501 try { 2502 final AudioTrack track = new AudioTrack.Builder() 2503 .setBufferSizeInBytes(superBigBufferSize) 2504 .build(); 2505 track.release(); 2506 fail(TEST_NAME + ": should throw exception on failure"); 2507 } catch (UnsupportedOperationException e) { 2508 ; 2509 } 2510 2511 // we should be able to create again with minimum buffer size 2512 final int verySmallBufferSize = 2 * 3 * 4; // frame size multiples 2513 final AudioTrack track2 = new AudioTrack.Builder() 2514 .setBufferSizeInBytes(verySmallBufferSize) 2515 .build(); 2516 2517 final int observedState2 = track2.getState(); 2518 final int observedBufferSize2 = track2.getBufferSizeInFrames(); 2519 track2.release(); 2520 2521 // succeeds for minimum buffer size 2522 assertEquals(TEST_NAME + ": state", AudioTrack.STATE_INITIALIZED, observedState2); 2523 // should force the minimum size buffer which is > 0 2524 assertTrue(TEST_NAME + ": buffer frame count", observedBufferSize2 > 0); 2525 } 2526 2527 // Test AudioTrack to see if there are any problems with large frame counts. 2528 @Test 2529 public void testAudioTrackLargeFrameCount() throws Exception { 2530 // constants for test 2531 final String TEST_NAME = "testAudioTrackLargeFrameCount"; 2532 final int[] BUFFER_SIZES = { 4294968, 42949680, 429496800, Integer.MAX_VALUE }; 2533 final int[] MODES = { AudioTrack.MODE_STATIC, AudioTrack.MODE_STREAM }; 2534 2535 for (int mode : MODES) { 2536 for (int bufferSizeInBytes : BUFFER_SIZES) { 2537 try { 2538 final AudioTrack track = new AudioTrack.Builder() 2539 .setAudioFormat(new AudioFormat.Builder() 2540 .setEncoding(AudioFormat.ENCODING_PCM_8BIT) 2541 .setSampleRate(44100) 2542 .setChannelMask(AudioFormat.CHANNEL_OUT_MONO) 2543 .build()) 2544 .setTransferMode(mode) 2545 .setBufferSizeInBytes(bufferSizeInBytes) // 1 byte == 1 frame 2546 .build(); 2547 track.release(); // OK to successfully complete 2548 } catch (UnsupportedOperationException e) { 2549 ; // OK to throw unsupported exception 2550 } 2551 } 2552 } 2553 } 2554 2555 @Test 2556 public void testSetNullPresentation() throws Exception { 2557 final AudioTrack track = new AudioTrack.Builder().build(); 2558 assertThrows(IllegalArgumentException.class, () -> { 2559 track.setPresentation(null); 2560 }); 2561 } 2562 2563 @Test 2564 public void testSetPresentationDefaultTrack() throws Exception { 2565 final AudioTrack track = new AudioTrack.Builder().build(); 2566 assertEquals(AudioTrack.ERROR, track.setPresentation(createAudioPresentation())); 2567 } 2568 2569 @Test 2570 public void testIsDirectPlaybackSupported() throws Exception { 2571 // constants for test 2572 final String TEST_NAME = "testIsDirectPlaybackSupported"; 2573 // Default format leaves everything unspecified 2574 assertFalse(AudioTrack.isDirectPlaybackSupported( 2575 new AudioFormat.Builder().build(), 2576 new AudioAttributes.Builder().build())); 2577 // There is no requirement to support direct playback for this format, 2578 // so it's not possible to assert on the result, but at least the method 2579 // must execute with no exceptions. 2580 boolean isPcmStereo48kSupported = AudioTrack.isDirectPlaybackSupported( 2581 new AudioFormat.Builder() 2582 .setEncoding(AudioFormat.ENCODING_PCM_16BIT) 2583 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 2584 .setSampleRate(48000) 2585 .build(), 2586 new AudioAttributes.Builder().build()); 2587 log(TEST_NAME, "PCM Stereo 48 kHz: " + isPcmStereo48kSupported); 2588 } 2589 2590 @Test 2591 public void testMediaMetrics() throws Exception { 2592 if (!hasAudioOutput()) { 2593 return; 2594 } 2595 2596 AudioTrack track = null; 2597 try { 2598 final int TEST_SAMPLE_RATE = 44100; 2599 final int TEST_CHANNEL_MASK = AudioFormat.CHANNEL_OUT_STEREO; 2600 final int TEST_ENCODING = AudioFormat.ENCODING_PCM_16BIT; 2601 final AudioFormat format = new AudioFormat.Builder() 2602 .setSampleRate(TEST_SAMPLE_RATE) 2603 .setChannelMask(TEST_CHANNEL_MASK) 2604 .setEncoding(TEST_ENCODING) 2605 .build(); 2606 2607 final int TEST_USAGE = AudioAttributes.USAGE_MEDIA; 2608 final int TEST_CONTENT_TYPE = AudioAttributes.CONTENT_TYPE_MUSIC; 2609 final AudioAttributes attributes = new AudioAttributes.Builder() 2610 .setUsage(TEST_USAGE) 2611 .setContentType(TEST_CONTENT_TYPE) 2612 .build(); 2613 2614 // Setup a new audio track 2615 track = new AudioTrack.Builder() 2616 .setAudioFormat(format) 2617 .setAudioAttributes(attributes) 2618 .build(); 2619 2620 final PersistableBundle metrics = track.getMetrics(); 2621 assertNotNull("null metrics", metrics); 2622 2623 // The STREAMTYPE constant was generally not present in P, and if so 2624 // was incorrectly exposed as an integer. 2625 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.STREAMTYPE, 2626 new String("AUDIO_STREAM_MUSIC")); 2627 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.CONTENTTYPE, 2628 new String("AUDIO_CONTENT_TYPE_MUSIC")); 2629 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.USAGE, 2630 new String("AUDIO_USAGE_MEDIA")); 2631 2632 // AudioTrack.MetricsConstants.SAMPLERATE, metrics doesn't exit 2633 // AudioTrack.MetricsConstants.CHANNELMASK, metrics doesn't exist 2634 2635 // TestApi: 2636 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.SAMPLE_RATE, 2637 new Integer(track.getSampleRate())); 2638 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.CHANNEL_MASK, 2639 new Long(TEST_CHANNEL_MASK >> 2)); 2640 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.ENCODING, 2641 new String("AUDIO_FORMAT_PCM_16_BIT")); 2642 AudioHelper.assertMetricsKeyEquals(metrics, AudioTrack.MetricsConstants.FRAME_COUNT, 2643 new Integer(track.getBufferSizeInFrames())); 2644 2645 // TestApi: no particular value checking. 2646 AudioHelper.assertMetricsKey(metrics, AudioTrack.MetricsConstants.PORT_ID); 2647 AudioHelper.assertMetricsKey(metrics, AudioTrack.MetricsConstants.ATTRIBUTES); 2648 } finally { 2649 if (track != null) { 2650 track.release(); 2651 } 2652 } 2653 } 2654 2655 /* Do not run in JB-MR1. will be re-opened in the next platform release. 2656 public void testResourceLeakage() throws Exception { 2657 final int BUFFER_SIZE = 600 * 1024; 2658 ByteBuffer data = ByteBuffer.allocate(BUFFER_SIZE); 2659 for (int i = 0; i < 10; i++) { 2660 Log.i(TAG, "testResourceLeakage round " + i); 2661 data.rewind(); 2662 AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 2663 44100, 2664 AudioFormat.CHANNEL_OUT_STEREO, 2665 AudioFormat.ENCODING_PCM_16BIT, 2666 data.capacity(), 2667 AudioTrack.MODE_STREAM); 2668 assertTrue(track != null); 2669 track.write(data.array(), 0, data.capacity()); 2670 track.play(); 2671 Thread.sleep(100); 2672 track.stop(); 2673 track.release(); 2674 } 2675 } 2676 */ 2677 2678 /* MockAudioTrack allows testing of protected getNativeFrameCount() and setState(). */ 2679 private class MockAudioTrack extends AudioTrack { 2680 2681 public MockAudioTrack(int streamType, int sampleRateInHz, int channelConfig, 2682 int audioFormat, int bufferSizeInBytes, int mode) throws IllegalArgumentException { 2683 super(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mode); 2684 } 2685 2686 public void setState(int state) { 2687 super.setState(state); 2688 } 2689 2690 public int getNativeFrameCount() { 2691 return super.getNativeFrameCount(); 2692 } 2693 } 2694 2695 private static AudioPresentation createAudioPresentation() { 2696 return (new AudioPresentation.Builder(42 /*presentationId*/)).build(); 2697 } 2698 2699 private static Context getContext() { 2700 return InstrumentationRegistry.getInstrumentation().getTargetContext(); 2701 } 2702 } 2703