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