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