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