1/* 2 * Copyright (C) 2010 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// Play an audio file using buffer queue 18 19#include <assert.h> 20#include <math.h> 21#include <pthread.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <time.h> 26#include <unistd.h> 27 28#include <SLES/OpenSLES.h> 29#include <SLES/OpenSLES_Android.h> 30#include <system/audio.h> 31#include <audio_utils/fifo.h> 32#include <audio_utils/primitives.h> 33#include <audio_utils/sndfile.h> 34 35#define max(a, b) ((a) > (b) ? (a) : (b)) 36#define min(a, b) ((a) < (b) ? (a) : (b)) 37 38unsigned numBuffers = 2; 39int framesPerBuffer = 512; 40SNDFILE *sndfile; 41SF_INFO sfinfo; 42unsigned which; // which buffer to use next 43SLboolean eof; // whether we have hit EOF on input yet 44void *buffers; 45SLuint32 byteOrder; // desired to use for PCM buffers 46SLuint32 nativeByteOrder; // of platform 47audio_format_t transferFormat = AUDIO_FORMAT_DEFAULT; 48size_t sfframesize = 0; 49 50static audio_utils_fifo *fifo; 51static audio_utils_fifo_reader *fifoReader; 52static audio_utils_fifo_writer *fifoWriter; 53static unsigned underruns = 0; 54 55static SLuint32 squeeze(void *buffer, SLuint32 nbytes) 56{ 57 if (byteOrder != nativeByteOrder) { 58 // FIXME does not work for non 16-bit 59 swab(buffer, buffer, nbytes); 60 } 61 if (transferFormat == AUDIO_FORMAT_PCM_8_BIT) { 62 memcpy_to_u8_from_i16((uint8_t *) buffer, (const int16_t *) buffer, 63 nbytes / sizeof(int16_t)); 64 nbytes /= 2; 65 } else if (transferFormat == AUDIO_FORMAT_PCM_24_BIT_PACKED) { 66 memcpy_to_p24_from_i32((uint8_t *) buffer, (const int32_t *) buffer, 67 nbytes / sizeof(int32_t)); 68 nbytes = nbytes * 3 / 4; 69 } 70 return nbytes; 71} 72 73// This callback is called each time a buffer finishes playing 74 75static void callback(SLBufferQueueItf bufq, void *param) 76{ 77 assert(NULL == param); 78 if (!eof) { 79 void *buffer = (char *)buffers + framesPerBuffer * sfframesize * which; 80 ssize_t count = fifoReader->read(buffer, framesPerBuffer); 81 // on underrun from pipe, substitute silence 82 if (0 >= count) { 83 memset(buffer, 0, framesPerBuffer * sfframesize); 84 count = framesPerBuffer; 85 ++underruns; 86 } 87 if (count > 0) { 88 SLuint32 nbytes = count * sfframesize; 89 nbytes = squeeze(buffer, nbytes); 90 SLresult result = (*bufq)->Enqueue(bufq, buffer, nbytes); 91 assert(SL_RESULT_SUCCESS == result); 92 if (++which >= numBuffers) 93 which = 0; 94 } 95 } 96} 97 98// This thread reads from a (slow) filesystem with unpredictable latency and writes to pipe 99 100static void *file_reader_loop(void *arg __unused) 101{ 102#define READ_FRAMES 256 103 void *temp = malloc(READ_FRAMES * sfframesize); 104 sf_count_t total = 0; 105 sf_count_t count; 106 for (;;) { 107 switch (transferFormat) { 108 case AUDIO_FORMAT_PCM_FLOAT: 109 count = sf_readf_float(sndfile, (float *) temp, READ_FRAMES); 110 break; 111 case AUDIO_FORMAT_PCM_32_BIT: 112 case AUDIO_FORMAT_PCM_24_BIT_PACKED: 113 count = sf_readf_int(sndfile, (int *) temp, READ_FRAMES); 114 break; 115 case AUDIO_FORMAT_PCM_16_BIT: 116 case AUDIO_FORMAT_PCM_8_BIT: 117 count = sf_readf_short(sndfile, (short *) temp, READ_FRAMES); 118 break; 119 default: 120 count = 0; 121 break; 122 } 123 if (0 >= count) { 124 eof = SL_BOOLEAN_TRUE; 125 break; 126 } 127 const unsigned char *ptr = (unsigned char *) temp; 128 while (count > 0) { 129 ssize_t actual = fifoWriter->write(ptr, (size_t) count); 130 if (actual < 0) { 131 break; 132 } 133 if ((sf_count_t) actual < count) { 134 usleep(10000); 135 } 136 ptr += actual * sfframesize; 137 count -= actual; 138 total += actual; 139 } 140 // simulate occasional filesystem latency 141 if ((total & 0xFF00) == 0xFF00) { 142 usleep(100000); 143 } 144 } 145 free(temp); 146 return NULL; 147} 148 149// Main program 150 151int main(int argc, char **argv) 152{ 153 // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1) 154 union { 155 short s; 156 char c[2]; 157 } u; 158 u.s = 0x1234; 159 if (u.c[0] == 0x34) { 160 nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN; 161 } else if (u.c[0] == 0x12) { 162 nativeByteOrder = SL_BYTEORDER_BIGENDIAN; 163 } else { 164 fprintf(stderr, "Unable to determine native byte order\n"); 165 return EXIT_FAILURE; 166 } 167 byteOrder = nativeByteOrder; 168 169 SLboolean enableReverb = SL_BOOLEAN_FALSE; 170 SLboolean enablePlaybackRate = SL_BOOLEAN_FALSE; 171 SLpermille initialRate = 0; 172 SLpermille finalRate = 0; 173 SLpermille deltaRate = 1; 174 SLmillisecond deltaRateMs = 0; 175 176 // process command-line options 177 int i; 178 for (i = 1; i < argc; ++i) { 179 char *arg = argv[i]; 180 if (arg[0] != '-') { 181 break; 182 } 183 if (!strcmp(arg, "-b")) { 184 byteOrder = SL_BYTEORDER_BIGENDIAN; 185 } else if (!strcmp(arg, "-l")) { 186 byteOrder = SL_BYTEORDER_LITTLEENDIAN; 187 } else if (!strcmp(arg, "-8")) { 188 transferFormat = AUDIO_FORMAT_PCM_8_BIT; 189 } else if (!strcmp(arg, "-16")) { 190 transferFormat = AUDIO_FORMAT_PCM_16_BIT; 191 } else if (!strcmp(arg, "-24")) { 192 transferFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED; 193 } else if (!strcmp(arg, "-32")) { 194 transferFormat = AUDIO_FORMAT_PCM_32_BIT; 195 } else if (!strcmp(arg, "-32f")) { 196 transferFormat = AUDIO_FORMAT_PCM_FLOAT; 197 } else if (!strncmp(arg, "-f", 2)) { 198 framesPerBuffer = atoi(&arg[2]); 199 } else if (!strncmp(arg, "-n", 2)) { 200 numBuffers = atoi(&arg[2]); 201 } else if (!strncmp(arg, "-p", 2)) { 202 initialRate = atoi(&arg[2]); 203 enablePlaybackRate = SL_BOOLEAN_TRUE; 204 } else if (!strncmp(arg, "-P", 2)) { 205 finalRate = atoi(&arg[2]); 206 enablePlaybackRate = SL_BOOLEAN_TRUE; 207 } else if (!strncmp(arg, "-q", 2)) { 208 deltaRate = atoi(&arg[2]); 209 // deltaRate is a magnitude, so take absolute value 210 if (deltaRate < 0) { 211 deltaRate = -deltaRate; 212 } 213 enablePlaybackRate = SL_BOOLEAN_TRUE; 214 } else if (!strncmp(arg, "-Q", 2)) { 215 deltaRateMs = atoi(&arg[2]); 216 enablePlaybackRate = SL_BOOLEAN_TRUE; 217 } else if (!strcmp(arg, "-r")) { 218 enableReverb = SL_BOOLEAN_TRUE; 219 } else { 220 fprintf(stderr, "option %s ignored\n", arg); 221 } 222 } 223 224 if (argc - i != 1) { 225 fprintf(stderr, "usage: [-b/l] [-8 | | -16 | -24 | -32 | -32f] [-f#] [-n#] [-p#] [-r]" 226 " %s filename\n", argv[0]); 227 fprintf(stderr, " -b force big-endian byte order (default is native byte order)\n"); 228 fprintf(stderr, " -l force little-endian byte order (default is native byte order)\n"); 229 fprintf(stderr, " -8 output 8-bits per sample (default is that of input file)\n"); 230 fprintf(stderr, " -16 output 16-bits per sample\n"); 231 fprintf(stderr, " -24 output 24-bits per sample\n"); 232 fprintf(stderr, " -32 output 32-bits per sample\n"); 233 fprintf(stderr, " -32f output float 32-bits per sample\n"); 234 fprintf(stderr, " -f# frames per buffer (default 512)\n"); 235 fprintf(stderr, " -n# number of buffers (default 2)\n"); 236 fprintf(stderr, " -p# initial playback rate in per mille (default 1000)\n"); 237 fprintf(stderr, " -P# final playback rate in per mille (default same as -p#)\n"); 238 fprintf(stderr, " -q# magnitude of playback rate changes in per mille (default 1)\n"); 239 fprintf(stderr, " -Q# period between playback rate changes in ms (default 50)\n"); 240 fprintf(stderr, " -r enable reverb (default disabled)\n"); 241 return EXIT_FAILURE; 242 } 243 244 const char *filename = argv[i]; 245 //memset(&sfinfo, 0, sizeof(SF_INFO)); 246 sfinfo.format = 0; 247 sndfile = sf_open(filename, SFM_READ, &sfinfo); 248 if (NULL == sndfile) { 249 perror(filename); 250 return EXIT_FAILURE; 251 } 252 253 // verify the file format 254 switch (sfinfo.channels) { 255 case 1: 256 case 2: 257 break; 258 default: 259 fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels); 260 goto close_sndfile; 261 } 262 263 if (sfinfo.samplerate < 8000 || sfinfo.samplerate > 192000) { 264 fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate); 265 goto close_sndfile; 266 } 267 268 switch (sfinfo.format & SF_FORMAT_TYPEMASK) { 269 case SF_FORMAT_WAV: 270 break; 271 default: 272 fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK); 273 goto close_sndfile; 274 } 275 276 switch (sfinfo.format & SF_FORMAT_SUBMASK) { 277 case SF_FORMAT_FLOAT: 278 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 279 transferFormat = AUDIO_FORMAT_PCM_FLOAT; 280 } 281 break; 282 case SF_FORMAT_PCM_32: 283 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 284 transferFormat = AUDIO_FORMAT_PCM_32_BIT; 285 } 286 break; 287 case SF_FORMAT_PCM_16: 288 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 289 transferFormat = AUDIO_FORMAT_PCM_16_BIT; 290 } 291 break; 292 case SF_FORMAT_PCM_U8: 293 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 294 transferFormat = AUDIO_FORMAT_PCM_8_BIT; 295 } 296 break; 297 case SF_FORMAT_PCM_24: 298 if (transferFormat == AUDIO_FORMAT_DEFAULT) { 299 transferFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED; 300 } 301 break; 302 default: 303 fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK); 304 goto close_sndfile; 305 } 306 307 SLuint32 bitsPerSample; 308 switch (transferFormat) { 309 case AUDIO_FORMAT_PCM_FLOAT: 310 bitsPerSample = 32; 311 sfframesize = sfinfo.channels * sizeof(float); 312 break; 313 case AUDIO_FORMAT_PCM_32_BIT: 314 bitsPerSample = 32; 315 sfframesize = sfinfo.channels * sizeof(int); 316 break; 317 case AUDIO_FORMAT_PCM_24_BIT_PACKED: 318 bitsPerSample = 24; 319 sfframesize = sfinfo.channels * sizeof(int); // use int size 320 break; 321 case AUDIO_FORMAT_PCM_16_BIT: 322 bitsPerSample = 16; 323 sfframesize = sfinfo.channels * sizeof(short); 324 break; 325 case AUDIO_FORMAT_PCM_8_BIT: 326 bitsPerSample = 8; 327 sfframesize = sfinfo.channels * sizeof(short); // use short size 328 break; 329 default: 330 fprintf(stderr, "unsupported transfer format %#x\n", transferFormat); 331 goto close_sndfile; 332 } 333 334 { 335 buffers = malloc(framesPerBuffer * sfframesize * numBuffers); 336 337 // create engine 338 SLresult result; 339 SLObjectItf engineObject; 340 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 341 assert(SL_RESULT_SUCCESS == result); 342 SLEngineItf engineEngine; 343 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 344 assert(SL_RESULT_SUCCESS == result); 345 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 346 assert(SL_RESULT_SUCCESS == result); 347 348 // create output mix 349 SLObjectItf outputMixObject; 350 SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; 351 SLboolean req[1] = {SL_BOOLEAN_TRUE}; 352 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0, 353 ids, req); 354 assert(SL_RESULT_SUCCESS == result); 355 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 356 assert(SL_RESULT_SUCCESS == result); 357 358 // configure environmental reverb on output mix 359 SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL; 360 if (enableReverb) { 361 result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB, 362 &mixEnvironmentalReverb); 363 assert(SL_RESULT_SUCCESS == result); 364 SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR; 365 result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb, 366 &settings); 367 assert(SL_RESULT_SUCCESS == result); 368 } 369 370 // configure audio source 371 SLDataLocator_BufferQueue loc_bufq; 372 loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE; 373 loc_bufq.numBuffers = numBuffers; 374 SLAndroidDataFormat_PCM_EX format_pcm; 375 format_pcm.formatType = transferFormat == AUDIO_FORMAT_PCM_FLOAT 376 ? SL_ANDROID_DATAFORMAT_PCM_EX : SL_DATAFORMAT_PCM; 377 format_pcm.numChannels = sfinfo.channels; 378 format_pcm.sampleRate = sfinfo.samplerate * 1000; 379 format_pcm.bitsPerSample = bitsPerSample; 380 format_pcm.containerSize = format_pcm.bitsPerSample; 381 format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER : 382 SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 383 format_pcm.endianness = byteOrder; 384 format_pcm.representation = transferFormat == AUDIO_FORMAT_PCM_FLOAT 385 ? SL_ANDROID_PCM_REPRESENTATION_FLOAT : transferFormat == AUDIO_FORMAT_PCM_8_BIT 386 ? SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT 387 : SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; 388 SLDataSource audioSrc; 389 audioSrc.pLocator = &loc_bufq; 390 audioSrc.pFormat = &format_pcm; 391 392 // configure audio sink 393 SLDataLocator_OutputMix loc_outmix; 394 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 395 loc_outmix.outputMix = outputMixObject; 396 SLDataSink audioSnk; 397 audioSnk.pLocator = &loc_outmix; 398 audioSnk.pFormat = NULL; 399 400 // create audio player 401 SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND}; 402 SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 403 SLObjectItf playerObject; 404 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc, 405 &audioSnk, enableReverb ? 3 : (enablePlaybackRate ? 2 : 1), ids2, req2); 406 if (SL_RESULT_SUCCESS != result) { 407 fprintf(stderr, "can't create audio player\n"); 408 goto no_player; 409 } 410 411 { 412 413 // realize the player 414 result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE); 415 assert(SL_RESULT_SUCCESS == result); 416 417 // get the effect send interface and enable effect send reverb for this player 418 if (enableReverb) { 419 SLEffectSendItf playerEffectSend; 420 result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend); 421 assert(SL_RESULT_SUCCESS == result); 422 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb, 423 SL_BOOLEAN_TRUE, (SLmillibel) 0); 424 assert(SL_RESULT_SUCCESS == result); 425 } 426 427 // get the playback rate interface and configure the rate 428 SLPlaybackRateItf playerPlaybackRate; 429 SLpermille currentRate = 0; 430 if (enablePlaybackRate) { 431 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE, 432 &playerPlaybackRate); 433 assert(SL_RESULT_SUCCESS == result); 434 SLpermille defaultRate; 435 result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate); 436 assert(SL_RESULT_SUCCESS == result); 437 SLuint32 defaultProperties; 438 result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties); 439 assert(SL_RESULT_SUCCESS == result); 440 printf("default playback rate %d per mille, properties 0x%x\n", defaultRate, 441 defaultProperties); 442 if (initialRate <= 0) { 443 initialRate = defaultRate; 444 } 445 if (finalRate <= 0) { 446 finalRate = initialRate; 447 } 448 currentRate = defaultRate; 449 if (finalRate == initialRate) { 450 deltaRate = 0; 451 } else if (finalRate < initialRate) { 452 deltaRate = -deltaRate; 453 } 454 if (initialRate != defaultRate) { 455 result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate); 456 if (SL_RESULT_FEATURE_UNSUPPORTED == result) { 457 fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate); 458 deltaRate = 0; 459 } else if (SL_RESULT_PARAMETER_INVALID == result) { 460 fprintf(stderr, "initial playback rate %d is invalid\n", initialRate); 461 deltaRate = 0; 462 } else { 463 assert(SL_RESULT_SUCCESS == result); 464 currentRate = initialRate; 465 } 466 } 467 } 468 469 // get the play interface 470 SLPlayItf playerPlay; 471 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay); 472 assert(SL_RESULT_SUCCESS == result); 473 474 // get the buffer queue interface 475 SLBufferQueueItf playerBufferQueue; 476 result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE, 477 &playerBufferQueue); 478 assert(SL_RESULT_SUCCESS == result); 479 480 // loop until EOF or no more buffers 481 for (which = 0; which < numBuffers; ++which) { 482 void *buffer = (char *)buffers + framesPerBuffer * sfframesize * which; 483 sf_count_t frames = framesPerBuffer; 484 sf_count_t count; 485 switch (transferFormat) { 486 case AUDIO_FORMAT_PCM_FLOAT: 487 count = sf_readf_float(sndfile, (float *) buffer, frames); 488 break; 489 case AUDIO_FORMAT_PCM_32_BIT: 490 count = sf_readf_int(sndfile, (int *) buffer, frames); 491 break; 492 case AUDIO_FORMAT_PCM_24_BIT_PACKED: 493 count = sf_readf_int(sndfile, (int *) buffer, frames); 494 break; 495 case AUDIO_FORMAT_PCM_16_BIT: 496 case AUDIO_FORMAT_PCM_8_BIT: 497 count = sf_readf_short(sndfile, (short *) buffer, frames); 498 break; 499 default: 500 count = 0; 501 break; 502 } 503 if (0 >= count) { 504 eof = SL_BOOLEAN_TRUE; 505 break; 506 } 507 508 // enqueue a buffer 509 SLuint32 nbytes = count * sfframesize; 510 nbytes = squeeze(buffer, nbytes); 511 result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes); 512 assert(SL_RESULT_SUCCESS == result); 513 } 514 if (which >= numBuffers) { 515 which = 0; 516 } 517 518 // register a callback on the buffer queue 519 result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL); 520 assert(SL_RESULT_SUCCESS == result); 521 522#define FIFO_FRAMES 16384 523 void *fifoBuffer = malloc(FIFO_FRAMES * sfframesize); 524 fifo = new audio_utils_fifo(FIFO_FRAMES, sfframesize, fifoBuffer); 525 fifoReader = new audio_utils_fifo_reader(*fifo, true /*throttlesWriter*/); 526 fifoWriter = new audio_utils_fifo_writer(*fifo); 527 528 // create thread to read from file 529 pthread_t thread; 530 int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL); 531 assert(0 == ok); 532 533 // give thread a head start so that the pipe is initially filled 534 sleep(1); 535 536 // set the player's state to playing 537 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING); 538 assert(SL_RESULT_SUCCESS == result); 539 540 // get the initial time 541 struct timespec prevTs; 542 clock_gettime(CLOCK_MONOTONIC, &prevTs); 543 long elapsedNs = 0; 544 long deltaRateNs = deltaRateMs * 1000000; 545 546 // wait until the buffer queue is empty 547 SLBufferQueueState bufqstate; 548 for (;;) { 549 result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate); 550 assert(SL_RESULT_SUCCESS == result); 551 if (0 >= bufqstate.count) { 552 break; 553 } 554 if (!enablePlaybackRate || deltaRate == 0) { 555 sleep(1); 556 } else { 557 struct timespec curTs; 558 clock_gettime(CLOCK_MONOTONIC, &curTs); 559 elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 + 560 // this term can be negative 561 (curTs.tv_nsec - prevTs.tv_nsec); 562 prevTs = curTs; 563 if (elapsedNs < deltaRateNs) { 564 usleep((deltaRateNs - elapsedNs) / 1000); 565 continue; 566 } 567 elapsedNs -= deltaRateNs; 568 SLpermille nextRate = currentRate + deltaRate; 569 result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate); 570 if (SL_RESULT_SUCCESS != result) { 571 fprintf(stderr, "next playback rate %d is unsupported\n", nextRate); 572 } else if (SL_RESULT_PARAMETER_INVALID == result) { 573 fprintf(stderr, "next playback rate %d is invalid\n", nextRate); 574 } else { 575 assert(SL_RESULT_SUCCESS == result); 576 } 577 currentRate = nextRate; 578 if (currentRate >= max(initialRate, finalRate)) { 579 currentRate = max(initialRate, finalRate); 580 deltaRate = -abs(deltaRate); 581 } else if (currentRate <= min(initialRate, finalRate)) { 582 currentRate = min(initialRate, finalRate); 583 deltaRate = abs(deltaRate); 584 } 585 } 586 587 } 588 589 // wait for reader thread to exit 590 ok = pthread_join(thread, (void **) NULL); 591 assert(0 == ok); 592 593 // set the player's state to stopped 594 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED); 595 assert(SL_RESULT_SUCCESS == result); 596 597 // destroy audio player 598 (*playerObject)->Destroy(playerObject); 599 600 delete fifoWriter; 601 fifoWriter = NULL; 602 delete fifoReader; 603 fifoReader = NULL; 604 delete fifo; 605 fifo = NULL; 606 free(fifoBuffer); 607 fifoBuffer = NULL; 608 609 } 610 611no_player: 612 613 // destroy output mix 614 (*outputMixObject)->Destroy(outputMixObject); 615 616 // destroy engine 617 (*engineObject)->Destroy(engineObject); 618 619 } 620 621close_sndfile: 622 623 (void) sf_close(sndfile); 624 625 return EXIT_SUCCESS; 626} 627