SoundPool.cpp revision e2773bb17bc5d01e05a77b8913539575ebd04500
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// call with sound pool lock held 541void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, 542 float rightVolume, int priority, int loop, float rate) 543{ 544 sp<AudioTrack> oldTrack; 545 sp<AudioTrack> newTrack; 546 status_t status; 547 548 { // scope for the lock 549 Mutex::Autolock lock(&mLock); 550 551 ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f," 552 " priority=%d, loop=%d, rate=%f", 553 this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, 554 priority, loop, rate); 555 556 // if not idle, this voice is being stolen 557 if (mState != IDLE) { 558 ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); 559 mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 560 stop_l(); 561 return; 562 } 563 564 // initialize track 565 size_t afFrameCount; 566 uint32_t afSampleRate; 567 audio_stream_type_t streamType = mSoundPool->streamType(); 568 if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { 569 afFrameCount = kDefaultFrameCount; 570 } 571 if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { 572 afSampleRate = kDefaultSampleRate; 573 } 574 int numChannels = sample->numChannels(); 575 uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 576 uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; 577 uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; 578 uint32_t frameCount = 0; 579 580 if (loop) { 581 frameCount = sample->size()/numChannels/ 582 ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 583 } 584 585#ifndef USE_SHARED_MEM_BUFFER 586 // Ensure minimum audio buffer size in case of short looped sample 587 if(frameCount < totalFrames) { 588 frameCount = totalFrames; 589 } 590#endif 591 592 // mToggle toggles each time a track is started on a given channel. 593 // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 594 // as callback user data. This enables the detection of callbacks received from the old 595 // audio track while the new one is being started and avoids processing them with 596 // wrong audio audio buffer size (mAudioBufferSize) 597 unsigned long toggle = mToggle ^ 1; 598 void *userData = (void *)((unsigned long)this | toggle); 599 uint32_t channels = (numChannels == 2) ? 600 AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO; 601 602 // do not create a new audio track if current track is compatible with sample parameters 603#ifdef USE_SHARED_MEM_BUFFER 604 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 605 channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData); 606#else 607 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 608 channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, 609 bufferFrames); 610#endif 611 oldTrack = mAudioTrack; 612 status = newTrack->initCheck(); 613 if (status != NO_ERROR) { 614 ALOGE("Error creating AudioTrack"); 615 goto exit; 616 } 617 ALOGV("setVolume %p", newTrack.get()); 618 newTrack->setVolume(leftVolume, rightVolume); 619 newTrack->setLoop(0, frameCount, loop); 620 621 // From now on, AudioTrack callbacks received with previous toggle value will be ignored. 622 mToggle = toggle; 623 mAudioTrack = newTrack; 624 mPos = 0; 625 mSample = sample; 626 mChannelID = nextChannelID; 627 mPriority = priority; 628 mLoop = loop; 629 mLeftVolume = leftVolume; 630 mRightVolume = rightVolume; 631 mNumChannels = numChannels; 632 mRate = rate; 633 clearNextEvent(); 634 mState = PLAYING; 635 mAudioTrack->start(); 636 mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 637 } 638 639exit: 640 ALOGV("delete oldTrack %p", oldTrack.get()); 641 if (status != NO_ERROR) { 642 mAudioTrack.clear(); 643 } 644} 645 646void SoundChannel::nextEvent() 647{ 648 sp<Sample> sample; 649 int nextChannelID; 650 float leftVolume; 651 float rightVolume; 652 int priority; 653 int loop; 654 float rate; 655 656 // check for valid event 657 { 658 Mutex::Autolock lock(&mLock); 659 nextChannelID = mNextEvent.channelID(); 660 if (nextChannelID == 0) { 661 ALOGV("stolen channel has no event"); 662 return; 663 } 664 665 sample = mNextEvent.sample(); 666 leftVolume = mNextEvent.leftVolume(); 667 rightVolume = mNextEvent.rightVolume(); 668 priority = mNextEvent.priority(); 669 loop = mNextEvent.loop(); 670 rate = mNextEvent.rate(); 671 } 672 673 ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 674 play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 675} 676 677void SoundChannel::callback(int event, void* user, void *info) 678{ 679 SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 680 681 channel->process(event, info, (unsigned long)user & 1); 682} 683 684void SoundChannel::process(int event, void *info, unsigned long toggle) 685{ 686 //ALOGV("process(%d)", mChannelID); 687 688 Mutex::Autolock lock(&mLock); 689 690 AudioTrack::Buffer* b = NULL; 691 if (event == AudioTrack::EVENT_MORE_DATA) { 692 b = static_cast<AudioTrack::Buffer *>(info); 693 } 694 695 if (mToggle != toggle) { 696 ALOGV("process wrong toggle %p channel %d", this, mChannelID); 697 if (b != NULL) { 698 b->size = 0; 699 } 700 return; 701 } 702 703 sp<Sample> sample = mSample; 704 705// ALOGV("SoundChannel::process event %d", event); 706 707 if (event == AudioTrack::EVENT_MORE_DATA) { 708 709 // check for stop state 710 if (b->size == 0) return; 711 712 if (mState == IDLE) { 713 b->size = 0; 714 return; 715 } 716 717 if (sample != 0) { 718 // fill buffer 719 uint8_t* q = (uint8_t*) b->i8; 720 size_t count = 0; 721 722 if (mPos < (int)sample->size()) { 723 uint8_t* p = sample->data() + mPos; 724 count = sample->size() - mPos; 725 if (count > b->size) { 726 count = b->size; 727 } 728 memcpy(q, p, count); 729// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count); 730 } else if (mPos < mAudioBufferSize) { 731 count = mAudioBufferSize - mPos; 732 if (count > b->size) { 733 count = b->size; 734 } 735 memset(q, 0, count); 736// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 737 } 738 739 mPos += count; 740 b->size = count; 741 //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 742 } 743 } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { 744 ALOGV("process %p channel %d EVENT_UNDERRUN or EVENT_BUFFER_END", this, mChannelID); 745 mSoundPool->addToStopList(this); 746 } else if (event == AudioTrack::EVENT_LOOP_END) { 747 ALOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info); 748 } 749} 750 751 752// call with lock held 753bool SoundChannel::doStop_l() 754{ 755 if (mState != IDLE) { 756 setVolume_l(0, 0); 757 ALOGV("stop"); 758 mAudioTrack->stop(); 759 mSample.clear(); 760 mState = IDLE; 761 mPriority = IDLE_PRIORITY; 762 return true; 763 } 764 return false; 765} 766 767// call with lock held and sound pool lock held 768void SoundChannel::stop_l() 769{ 770 if (doStop_l()) { 771 mSoundPool->done_l(this); 772 } 773} 774 775// call with sound pool lock held 776void SoundChannel::stop() 777{ 778 bool stopped; 779 { 780 Mutex::Autolock lock(&mLock); 781 stopped = doStop_l(); 782 } 783 784 if (stopped) { 785 mSoundPool->done_l(this); 786 } 787} 788 789//FIXME: Pause is a little broken right now 790void SoundChannel::pause() 791{ 792 Mutex::Autolock lock(&mLock); 793 if (mState == PLAYING) { 794 ALOGV("pause track"); 795 mState = PAUSED; 796 mAudioTrack->pause(); 797 } 798} 799 800void SoundChannel::autoPause() 801{ 802 Mutex::Autolock lock(&mLock); 803 if (mState == PLAYING) { 804 ALOGV("pause track"); 805 mState = PAUSED; 806 mAutoPaused = true; 807 mAudioTrack->pause(); 808 } 809} 810 811void SoundChannel::resume() 812{ 813 Mutex::Autolock lock(&mLock); 814 if (mState == PAUSED) { 815 ALOGV("resume track"); 816 mState = PLAYING; 817 mAutoPaused = false; 818 mAudioTrack->start(); 819 } 820} 821 822void SoundChannel::autoResume() 823{ 824 Mutex::Autolock lock(&mLock); 825 if (mAutoPaused && (mState == PAUSED)) { 826 ALOGV("resume track"); 827 mState = PLAYING; 828 mAutoPaused = false; 829 mAudioTrack->start(); 830 } 831} 832 833void SoundChannel::setRate(float rate) 834{ 835 Mutex::Autolock lock(&mLock); 836 if (mAudioTrack != NULL && mSample != 0) { 837 uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 838 mAudioTrack->setSampleRate(sampleRate); 839 mRate = rate; 840 } 841} 842 843// call with lock held 844void SoundChannel::setVolume_l(float leftVolume, float rightVolume) 845{ 846 mLeftVolume = leftVolume; 847 mRightVolume = rightVolume; 848 if (mAudioTrack != NULL) 849 mAudioTrack->setVolume(leftVolume, rightVolume); 850} 851 852void SoundChannel::setVolume(float leftVolume, float rightVolume) 853{ 854 Mutex::Autolock lock(&mLock); 855 setVolume_l(leftVolume, rightVolume); 856} 857 858void SoundChannel::setLoop(int loop) 859{ 860 Mutex::Autolock lock(&mLock); 861 if (mAudioTrack != NULL && mSample != 0) { 862 uint32_t loopEnd = mSample->size()/mNumChannels/ 863 ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 864 mAudioTrack->setLoop(0, loopEnd, loop); 865 mLoop = loop; 866 } 867} 868 869SoundChannel::~SoundChannel() 870{ 871 ALOGV("SoundChannel destructor %p", this); 872 { 873 Mutex::Autolock lock(&mLock); 874 clearNextEvent(); 875 doStop_l(); 876 } 877 // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack 878 // callback thread to exit which may need to execute process() and acquire the mLock. 879 mAudioTrack.clear(); 880} 881 882void SoundChannel::dump() 883{ 884 ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 885 mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 886} 887 888void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 889 float rightVolume, int priority, int loop, float rate) 890{ 891 mSample = sample; 892 mChannelID = channelID; 893 mLeftVolume = leftVolume; 894 mRightVolume = rightVolume; 895 mPriority = priority; 896 mLoop = loop; 897 mRate =rate; 898} 899 900} // end namespace android 901