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