SoundPool.cpp revision 8bbbd7da02fac3de40139af19f7cf7a7cc3cc824
1/* 2 * Copyright (C) 2007 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//#define LOG_NDEBUG 0 18#define LOG_TAG "SoundPool" 19#include <utils/Log.h> 20 21#define USE_SHARED_MEM_BUFFER 22 23#include <media/AudioTrack.h> 24#include <media/mediaplayer.h> 25#include <media/SoundPool.h> 26#include "SoundPoolThread.h" 27 28namespace android 29{ 30 31int kDefaultBufferCount = 4; 32uint32_t kMaxSampleRate = 48000; 33uint32_t kDefaultSampleRate = 44100; 34uint32_t kDefaultFrameCount = 1200; 35 36SoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality) 37{ 38 ALOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d", 39 maxChannels, streamType, srcQuality); 40 41 // check limits 42 mMaxChannels = maxChannels; 43 if (mMaxChannels < 1) { 44 mMaxChannels = 1; 45 } 46 else if (mMaxChannels > 32) { 47 mMaxChannels = 32; 48 } 49 ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); 50 51 mQuit = false; 52 mDecodeThread = 0; 53 mStreamType = streamType; 54 mSrcQuality = srcQuality; 55 mAllocated = 0; 56 mNextSampleID = 0; 57 mNextChannelID = 0; 58 59 mCallback = 0; 60 mUserData = 0; 61 62 mChannelPool = new SoundChannel[mMaxChannels]; 63 for (int i = 0; i < mMaxChannels; ++i) { 64 mChannelPool[i].init(this); 65 mChannels.push_back(&mChannelPool[i]); 66 } 67 68 // start decode thread 69 startThreads(); 70} 71 72SoundPool::~SoundPool() 73{ 74 ALOGV("SoundPool destructor"); 75 mDecodeThread->quit(); 76 quit(); 77 78 Mutex::Autolock lock(&mLock); 79 80 mChannels.clear(); 81 if (mChannelPool) 82 delete [] mChannelPool; 83 // clean up samples 84 ALOGV("clear samples"); 85 mSamples.clear(); 86 87 if (mDecodeThread) 88 delete mDecodeThread; 89} 90 91void SoundPool::addToRestartList(SoundChannel* channel) 92{ 93 Mutex::Autolock lock(&mRestartLock); 94 if (!mQuit) { 95 mRestart.push_back(channel); 96 mCondition.signal(); 97 } 98} 99 100void SoundPool::addToStopList(SoundChannel* channel) 101{ 102 Mutex::Autolock lock(&mRestartLock); 103 if (!mQuit) { 104 mStop.push_back(channel); 105 mCondition.signal(); 106 } 107} 108 109int SoundPool::beginThread(void* arg) 110{ 111 SoundPool* p = (SoundPool*)arg; 112 return p->run(); 113} 114 115int SoundPool::run() 116{ 117 mRestartLock.lock(); 118 while (!mQuit) { 119 mCondition.wait(mRestartLock); 120 ALOGV("awake"); 121 if (mQuit) break; 122 123 while (!mStop.empty()) { 124 SoundChannel* channel; 125 ALOGV("Getting channel from stop list"); 126 List<SoundChannel* >::iterator iter = mStop.begin(); 127 channel = *iter; 128 mStop.erase(iter); 129 mRestartLock.unlock(); 130 if (channel != 0) { 131 Mutex::Autolock lock(&mLock); 132 channel->stop(); 133 } 134 mRestartLock.lock(); 135 if (mQuit) break; 136 } 137 138 while (!mRestart.empty()) { 139 SoundChannel* channel; 140 ALOGV("Getting channel from list"); 141 List<SoundChannel*>::iterator iter = mRestart.begin(); 142 channel = *iter; 143 mRestart.erase(iter); 144 mRestartLock.unlock(); 145 if (channel != 0) { 146 Mutex::Autolock lock(&mLock); 147 channel->nextEvent(); 148 } 149 mRestartLock.lock(); 150 if (mQuit) break; 151 } 152 } 153 154 mStop.clear(); 155 mRestart.clear(); 156 mCondition.signal(); 157 mRestartLock.unlock(); 158 ALOGV("goodbye"); 159 return 0; 160} 161 162void SoundPool::quit() 163{ 164 mRestartLock.lock(); 165 mQuit = true; 166 mCondition.signal(); 167 mCondition.wait(mRestartLock); 168 ALOGV("return from quit"); 169 mRestartLock.unlock(); 170} 171 172bool SoundPool::startThreads() 173{ 174 createThreadEtc(beginThread, this, "SoundPool"); 175 if (mDecodeThread == NULL) 176 mDecodeThread = new SoundPoolThread(this); 177 return mDecodeThread != NULL; 178} 179 180SoundChannel* SoundPool::findChannel(int channelID) 181{ 182 for (int i = 0; i < mMaxChannels; ++i) { 183 if (mChannelPool[i].channelID() == channelID) { 184 return &mChannelPool[i]; 185 } 186 } 187 return NULL; 188} 189 190SoundChannel* SoundPool::findNextChannel(int channelID) 191{ 192 for (int i = 0; i < mMaxChannels; ++i) { 193 if (mChannelPool[i].nextChannelID() == channelID) { 194 return &mChannelPool[i]; 195 } 196 } 197 return NULL; 198} 199 200int SoundPool::load(const char* path, int priority) 201{ 202 ALOGV("load: path=%s, priority=%d", path, priority); 203 Mutex::Autolock lock(&mLock); 204 sp<Sample> sample = new Sample(++mNextSampleID, path); 205 mSamples.add(sample->sampleID(), sample); 206 doLoad(sample); 207 return sample->sampleID(); 208} 209 210int SoundPool::load(int fd, int64_t offset, int64_t length, int priority) 211{ 212 ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d", 213 fd, offset, length, priority); 214 Mutex::Autolock lock(&mLock); 215 sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length); 216 mSamples.add(sample->sampleID(), sample); 217 doLoad(sample); 218 return sample->sampleID(); 219} 220 221void SoundPool::doLoad(sp<Sample>& sample) 222{ 223 ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); 224 sample->startLoad(); 225 mDecodeThread->loadSample(sample->sampleID()); 226} 227 228bool SoundPool::unload(int sampleID) 229{ 230 ALOGV("unload: sampleID=%d", sampleID); 231 Mutex::Autolock lock(&mLock); 232 return mSamples.removeItem(sampleID); 233} 234 235int SoundPool::play(int sampleID, float leftVolume, float rightVolume, 236 int priority, int loop, float rate) 237{ 238 ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", 239 sampleID, leftVolume, rightVolume, priority, loop, rate); 240 sp<Sample> sample; 241 SoundChannel* channel; 242 int channelID; 243 244 Mutex::Autolock lock(&mLock); 245 246 if (mQuit) { 247 return 0; 248 } 249 // is sample ready? 250 sample = findSample(sampleID); 251 if ((sample == 0) || (sample->state() != Sample::READY)) { 252 ALOGW(" sample %d not READY", sampleID); 253 return 0; 254 } 255 256 dump(); 257 258 // allocate a channel 259 channel = allocateChannel_l(priority); 260 261 // no channel allocated - return 0 262 if (!channel) { 263 ALOGV("No channel allocated"); 264 return 0; 265 } 266 267 channelID = ++mNextChannelID; 268 269 ALOGV("play channel %p state = %d", channel, channel->state()); 270 channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate); 271 return channelID; 272} 273 274SoundChannel* SoundPool::allocateChannel_l(int priority) 275{ 276 List<SoundChannel*>::iterator iter; 277 SoundChannel* channel = NULL; 278 279 // allocate a channel 280 if (!mChannels.empty()) { 281 iter = mChannels.begin(); 282 if (priority >= (*iter)->priority()) { 283 channel = *iter; 284 mChannels.erase(iter); 285 ALOGV("Allocated active channel"); 286 } 287 } 288 289 // update priority and put it back in the list 290 if (channel) { 291 channel->setPriority(priority); 292 for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 293 if (priority < (*iter)->priority()) { 294 break; 295 } 296 } 297 mChannels.insert(iter, channel); 298 } 299 return channel; 300} 301 302// move a channel from its current position to the front of the list 303void SoundPool::moveToFront_l(SoundChannel* channel) 304{ 305 for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 306 if (*iter == channel) { 307 mChannels.erase(iter); 308 mChannels.push_front(channel); 309 break; 310 } 311 } 312} 313 314void SoundPool::pause(int channelID) 315{ 316 ALOGV("pause(%d)", channelID); 317 Mutex::Autolock lock(&mLock); 318 SoundChannel* channel = findChannel(channelID); 319 if (channel) { 320 channel->pause(); 321 } 322} 323 324void SoundPool::autoPause() 325{ 326 ALOGV("autoPause()"); 327 Mutex::Autolock lock(&mLock); 328 for (int i = 0; i < mMaxChannels; ++i) { 329 SoundChannel* channel = &mChannelPool[i]; 330 channel->autoPause(); 331 } 332} 333 334void SoundPool::resume(int channelID) 335{ 336 ALOGV("resume(%d)", channelID); 337 Mutex::Autolock lock(&mLock); 338 SoundChannel* channel = findChannel(channelID); 339 if (channel) { 340 channel->resume(); 341 } 342} 343 344void SoundPool::autoResume() 345{ 346 ALOGV("autoResume()"); 347 Mutex::Autolock lock(&mLock); 348 for (int i = 0; i < mMaxChannels; ++i) { 349 SoundChannel* channel = &mChannelPool[i]; 350 channel->autoResume(); 351 } 352} 353 354void SoundPool::stop(int channelID) 355{ 356 ALOGV("stop(%d)", channelID); 357 Mutex::Autolock lock(&mLock); 358 SoundChannel* channel = findChannel(channelID); 359 if (channel) { 360 channel->stop(); 361 } else { 362 channel = findNextChannel(channelID); 363 if (channel) 364 channel->clearNextEvent(); 365 } 366} 367 368void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume) 369{ 370 Mutex::Autolock lock(&mLock); 371 SoundChannel* channel = findChannel(channelID); 372 if (channel) { 373 channel->setVolume(leftVolume, rightVolume); 374 } 375} 376 377void SoundPool::setPriority(int channelID, int priority) 378{ 379 ALOGV("setPriority(%d, %d)", channelID, priority); 380 Mutex::Autolock lock(&mLock); 381 SoundChannel* channel = findChannel(channelID); 382 if (channel) { 383 channel->setPriority(priority); 384 } 385} 386 387void SoundPool::setLoop(int channelID, int loop) 388{ 389 ALOGV("setLoop(%d, %d)", channelID, loop); 390 Mutex::Autolock lock(&mLock); 391 SoundChannel* channel = findChannel(channelID); 392 if (channel) { 393 channel->setLoop(loop); 394 } 395} 396 397void SoundPool::setRate(int channelID, float rate) 398{ 399 ALOGV("setRate(%d, %f)", channelID, rate); 400 Mutex::Autolock lock(&mLock); 401 SoundChannel* channel = findChannel(channelID); 402 if (channel) { 403 channel->setRate(rate); 404 } 405} 406 407// call with lock held 408void SoundPool::done_l(SoundChannel* channel) 409{ 410 ALOGV("done_l(%d)", channel->channelID()); 411 // if "stolen", play next event 412 if (channel->nextChannelID() != 0) { 413 ALOGV("add to restart list"); 414 addToRestartList(channel); 415 } 416 417 // return to idle state 418 else { 419 ALOGV("move to front"); 420 moveToFront_l(channel); 421 } 422} 423 424void SoundPool::setCallback(SoundPoolCallback* callback, void* user) 425{ 426 Mutex::Autolock lock(&mCallbackLock); 427 mCallback = callback; 428 mUserData = user; 429} 430 431void SoundPool::notify(SoundPoolEvent event) 432{ 433 Mutex::Autolock lock(&mCallbackLock); 434 if (mCallback != NULL) { 435 mCallback(event, this, mUserData); 436 } 437} 438 439void SoundPool::dump() 440{ 441 for (int i = 0; i < mMaxChannels; ++i) { 442 mChannelPool[i].dump(); 443 } 444} 445 446 447Sample::Sample(int sampleID, const char* url) 448{ 449 init(); 450 mSampleID = sampleID; 451 mUrl = strdup(url); 452 ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl); 453} 454 455Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length) 456{ 457 init(); 458 mSampleID = sampleID; 459 mFd = dup(fd); 460 mOffset = offset; 461 mLength = length; 462 ALOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset); 463} 464 465void Sample::init() 466{ 467 mData = 0; 468 mSize = 0; 469 mRefCount = 0; 470 mSampleID = 0; 471 mState = UNLOADED; 472 mFd = -1; 473 mOffset = 0; 474 mLength = 0; 475 mUrl = 0; 476} 477 478Sample::~Sample() 479{ 480 ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd); 481 if (mFd > 0) { 482 ALOGV("close(%d)", mFd); 483 ::close(mFd); 484 } 485 mData.clear(); 486 free(mUrl); 487} 488 489status_t Sample::doLoad() 490{ 491 uint32_t sampleRate; 492 int numChannels; 493 audio_format_t format; 494 sp<IMemory> p; 495 ALOGV("Start decode"); 496 if (mUrl) { 497 p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format); 498 } else { 499 p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format); 500 ALOGV("close(%d)", mFd); 501 ::close(mFd); 502 mFd = -1; 503 } 504 if (p == 0) { 505 ALOGE("Unable to load sample: %s", mUrl); 506 return -1; 507 } 508 ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d", 509 p->pointer(), p->size(), sampleRate, numChannels); 510 511 if (sampleRate > kMaxSampleRate) { 512 ALOGE("Sample rate (%u) out of range", sampleRate); 513 return - 1; 514 } 515 516 if ((numChannels < 1) || (numChannels > 2)) { 517 ALOGE("Sample channel count (%d) out of range", numChannels); 518 return - 1; 519 } 520 521 //_dumpBuffer(p->pointer(), p->size()); 522 uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10; 523 //_dumpBuffer(q, 10, 10, false); 524 525 mData = p; 526 mSize = p->size(); 527 mSampleRate = sampleRate; 528 mNumChannels = numChannels; 529 mFormat = format; 530 mState = READY; 531 return 0; 532} 533 534 535void SoundChannel::init(SoundPool* soundPool) 536{ 537 mSoundPool = soundPool; 538} 539 540// This class is used to destroy a RefBase asynchronously 541class AsyncDestructThread : public Thread 542{ 543public: 544 AsyncDestructThread(sp<RefBase> refBase) : mRefBase(refBase) { } 545protected: 546 virtual ~AsyncDestructThread() { } 547private: 548 virtual bool threadLoop() { return false; } 549 const sp<RefBase> mRefBase; 550}; 551 552// call with sound pool lock held 553void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, 554 float rightVolume, int priority, int loop, float rate) 555{ 556 sp<AudioTrack> oldTrack; 557 sp<AudioTrack> newTrack; 558 status_t status; 559 560 { // scope for the lock 561 Mutex::Autolock lock(&mLock); 562 563 ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f," 564 " priority=%d, loop=%d, rate=%f", 565 this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, 566 priority, loop, rate); 567 568 // if not idle, this voice is being stolen 569 if (mState != IDLE) { 570 ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); 571 mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 572 stop_l(); 573 return; 574 } 575 576 // initialize track 577 size_t afFrameCount; 578 uint32_t afSampleRate; 579 audio_stream_type_t streamType = mSoundPool->streamType(); 580 if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { 581 afFrameCount = kDefaultFrameCount; 582 } 583 if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { 584 afSampleRate = kDefaultSampleRate; 585 } 586 int numChannels = sample->numChannels(); 587 uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 588 uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; 589 uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; 590 uint32_t frameCount = 0; 591 592 if (loop) { 593 frameCount = sample->size()/numChannels/ 594 ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 595 } 596 597#ifndef USE_SHARED_MEM_BUFFER 598 // Ensure minimum audio buffer size in case of short looped sample 599 if(frameCount < totalFrames) { 600 frameCount = totalFrames; 601 } 602#endif 603 604 // mToggle toggles each time a track is started on a given channel. 605 // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 606 // as callback user data. This enables the detection of callbacks received from the old 607 // audio track while the new one is being started and avoids processing them with 608 // wrong audio audio buffer size (mAudioBufferSize) 609 unsigned long toggle = mToggle ^ 1; 610 void *userData = (void *)((unsigned long)this | toggle); 611 uint32_t channels = (numChannels == 2) ? 612 AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO; 613 614 // do not create a new audio track if current track is compatible with sample parameters 615#ifdef USE_SHARED_MEM_BUFFER 616 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 617 channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); 618#else 619 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 620 channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, 621 bufferFrames); 622#endif 623 oldTrack = mAudioTrack; 624 status = newTrack->initCheck(); 625 if (status != NO_ERROR) { 626 ALOGE("Error creating AudioTrack"); 627 goto exit; 628 } 629 ALOGV("setVolume %p", newTrack.get()); 630 newTrack->setVolume(leftVolume, rightVolume); 631 newTrack->setLoop(0, frameCount, loop); 632 633 // From now on, AudioTrack callbacks received with previous toggle value will be ignored. 634 mToggle = toggle; 635 mAudioTrack = newTrack; 636 mPos = 0; 637 mSample = sample; 638 mChannelID = nextChannelID; 639 mPriority = priority; 640 mLoop = loop; 641 mLeftVolume = leftVolume; 642 mRightVolume = rightVolume; 643 mNumChannels = numChannels; 644 mRate = rate; 645 clearNextEvent(); 646 mState = PLAYING; 647 mAudioTrack->start(); 648 mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 649 } 650 651exit: 652 ALOGV("delete oldTrack %p", oldTrack.get()); 653 if (status != NO_ERROR) { 654 mAudioTrack.clear(); 655 } 656 // FIXME AudioTrack destruction should not be slow 657 if (oldTrack != 0) { 658 // must be a raw reference to avoid a race after run() 659 AsyncDestructThread *adt = new AsyncDestructThread(oldTrack); 660 // guaranteed to not run destructor 661 oldTrack.clear(); 662 // after the run(), adt thread will hold a strong reference to oldTrack, 663 // and the only strong reference to itself 664 adt->run("AsyncDestruct"); 665 // do not delete adt here: adt thread destroys itself, and oldTrack if needed 666 } 667} 668 669void SoundChannel::nextEvent() 670{ 671 sp<Sample> sample; 672 int nextChannelID; 673 float leftVolume; 674 float rightVolume; 675 int priority; 676 int loop; 677 float rate; 678 679 // check for valid event 680 { 681 Mutex::Autolock lock(&mLock); 682 nextChannelID = mNextEvent.channelID(); 683 if (nextChannelID == 0) { 684 ALOGV("stolen channel has no event"); 685 return; 686 } 687 688 sample = mNextEvent.sample(); 689 leftVolume = mNextEvent.leftVolume(); 690 rightVolume = mNextEvent.rightVolume(); 691 priority = mNextEvent.priority(); 692 loop = mNextEvent.loop(); 693 rate = mNextEvent.rate(); 694 } 695 696 ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 697 play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 698} 699 700void SoundChannel::callback(int event, void* user, void *info) 701{ 702 SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 703 704 channel->process(event, info, (unsigned long)user & 1); 705} 706 707void SoundChannel::process(int event, void *info, unsigned long toggle) 708{ 709 //ALOGV("process(%d)", mChannelID); 710 711 Mutex::Autolock lock(&mLock); 712 713 AudioTrack::Buffer* b = NULL; 714 if (event == AudioTrack::EVENT_MORE_DATA) { 715 b = static_cast<AudioTrack::Buffer *>(info); 716 } 717 718 if (mToggle != toggle) { 719 ALOGV("process wrong toggle %p channel %d", this, mChannelID); 720 if (b != NULL) { 721 b->size = 0; 722 } 723 return; 724 } 725 726 sp<Sample> sample = mSample; 727 728// ALOGV("SoundChannel::process event %d", event); 729 730 if (event == AudioTrack::EVENT_MORE_DATA) { 731 732 // check for stop state 733 if (b->size == 0) return; 734 735 if (mState == IDLE) { 736 b->size = 0; 737 return; 738 } 739 740 if (sample != 0) { 741 // fill buffer 742 uint8_t* q = (uint8_t*) b->i8; 743 size_t count = 0; 744 745 if (mPos < (int)sample->size()) { 746 uint8_t* p = sample->data() + mPos; 747 count = sample->size() - mPos; 748 if (count > b->size) { 749 count = b->size; 750 } 751 memcpy(q, p, count); 752// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count); 753 } else if (mPos < mAudioBufferSize) { 754 count = mAudioBufferSize - mPos; 755 if (count > b->size) { 756 count = b->size; 757 } 758 memset(q, 0, count); 759// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 760 } 761 762 mPos += count; 763 b->size = count; 764 //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 765 } 766 } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { 767 ALOGV("process %p channel %d EVENT_UNDERRUN or EVENT_BUFFER_END", this, mChannelID); 768 mSoundPool->addToStopList(this); 769 } else if (event == AudioTrack::EVENT_LOOP_END) { 770 ALOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info); 771 } 772} 773 774 775// call with lock held 776bool SoundChannel::doStop_l() 777{ 778 if (mState != IDLE) { 779 setVolume_l(0, 0); 780 ALOGV("stop"); 781 mAudioTrack->stop(); 782 mSample.clear(); 783 mState = IDLE; 784 mPriority = IDLE_PRIORITY; 785 return true; 786 } 787 return false; 788} 789 790// call with lock held and sound pool lock held 791void SoundChannel::stop_l() 792{ 793 if (doStop_l()) { 794 mSoundPool->done_l(this); 795 } 796} 797 798// call with sound pool lock held 799void SoundChannel::stop() 800{ 801 bool stopped; 802 { 803 Mutex::Autolock lock(&mLock); 804 stopped = doStop_l(); 805 } 806 807 if (stopped) { 808 mSoundPool->done_l(this); 809 } 810} 811 812//FIXME: Pause is a little broken right now 813void SoundChannel::pause() 814{ 815 Mutex::Autolock lock(&mLock); 816 if (mState == PLAYING) { 817 ALOGV("pause track"); 818 mState = PAUSED; 819 mAudioTrack->pause(); 820 } 821} 822 823void SoundChannel::autoPause() 824{ 825 Mutex::Autolock lock(&mLock); 826 if (mState == PLAYING) { 827 ALOGV("pause track"); 828 mState = PAUSED; 829 mAutoPaused = true; 830 mAudioTrack->pause(); 831 } 832} 833 834void SoundChannel::resume() 835{ 836 Mutex::Autolock lock(&mLock); 837 if (mState == PAUSED) { 838 ALOGV("resume track"); 839 mState = PLAYING; 840 mAutoPaused = false; 841 mAudioTrack->start(); 842 } 843} 844 845void SoundChannel::autoResume() 846{ 847 Mutex::Autolock lock(&mLock); 848 if (mAutoPaused && (mState == PAUSED)) { 849 ALOGV("resume track"); 850 mState = PLAYING; 851 mAutoPaused = false; 852 mAudioTrack->start(); 853 } 854} 855 856void SoundChannel::setRate(float rate) 857{ 858 Mutex::Autolock lock(&mLock); 859 if (mAudioTrack != NULL && mSample != 0) { 860 uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 861 mAudioTrack->setSampleRate(sampleRate); 862 mRate = rate; 863 } 864} 865 866// call with lock held 867void SoundChannel::setVolume_l(float leftVolume, float rightVolume) 868{ 869 mLeftVolume = leftVolume; 870 mRightVolume = rightVolume; 871 if (mAudioTrack != NULL) 872 mAudioTrack->setVolume(leftVolume, rightVolume); 873} 874 875void SoundChannel::setVolume(float leftVolume, float rightVolume) 876{ 877 Mutex::Autolock lock(&mLock); 878 setVolume_l(leftVolume, rightVolume); 879} 880 881void SoundChannel::setLoop(int loop) 882{ 883 Mutex::Autolock lock(&mLock); 884 if (mAudioTrack != NULL && mSample != 0) { 885 uint32_t loopEnd = mSample->size()/mNumChannels/ 886 ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 887 mAudioTrack->setLoop(0, loopEnd, loop); 888 mLoop = loop; 889 } 890} 891 892SoundChannel::~SoundChannel() 893{ 894 ALOGV("SoundChannel destructor %p", this); 895 { 896 Mutex::Autolock lock(&mLock); 897 clearNextEvent(); 898 doStop_l(); 899 } 900 // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack 901 // callback thread to exit which may need to execute process() and acquire the mLock. 902 mAudioTrack.clear(); 903} 904 905void SoundChannel::dump() 906{ 907 ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 908 mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 909} 910 911void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 912 float rightVolume, int priority, int loop, float rate) 913{ 914 mSample = sample; 915 mChannelID = channelID; 916 mLeftVolume = leftVolume; 917 mRightVolume = rightVolume; 918 mPriority = priority; 919 mLoop = loop; 920 mRate =rate; 921} 922 923} // end namespace android 924