SoundPool.cpp revision d24b8183b93e781080b2c16c487e60d51c12da31
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// XXX needed for timing latency 24#include <utils/Timers.h> 25 26#include <sys/resource.h> 27#include <media/AudioTrack.h> 28#include <media/mediaplayer.h> 29 30#include "SoundPool.h" 31#include "SoundPoolThread.h" 32 33namespace android 34{ 35 36int kDefaultBufferCount = 4; 37uint32_t kMaxSampleRate = 48000; 38uint32_t kDefaultSampleRate = 44100; 39uint32_t kDefaultFrameCount = 1200; 40 41SoundPool::SoundPool(jobject soundPoolRef, int maxChannels, int streamType, int srcQuality) 42{ 43 LOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d", 44 maxChannels, streamType, srcQuality); 45 46 if (maxChannels > 32) { 47 LOGW("App requested %d channels, capped at 32", maxChannels); 48 maxChannels = 32; 49 } 50 51 mQuit = false; 52 mSoundPoolRef = soundPoolRef; 53 mDecodeThread = 0; 54 mMaxChannels = maxChannels; 55 mStreamType = streamType; 56 mSrcQuality = srcQuality; 57 mAllocated = 0; 58 mNextSampleID = 0; 59 mNextChannelID = 0; 60 61 mChannelPool = new SoundChannel[maxChannels]; 62 for (int i = 0; i < maxChannels; ++i) { 63 mChannelPool[i].init(this); 64 mChannels.push_back(&mChannelPool[i]); 65 } 66 67 // start decode thread 68 startThreads(); 69} 70 71SoundPool::~SoundPool() 72{ 73 LOGV("SoundPool destructor"); 74 mDecodeThread->quit(); 75 quit(); 76 77 Mutex::Autolock lock(&mLock); 78 mChannels.clear(); 79 if (mChannelPool) 80 delete [] mChannelPool; 81 82 // clean up samples 83 LOGV("clear samples"); 84 mSamples.clear(); 85 86 if (mDecodeThread) 87 delete mDecodeThread; 88} 89 90void SoundPool::addToRestartList(SoundChannel* channel) 91{ 92 Mutex::Autolock lock(&mLock); 93 mRestart.push_back(channel); 94 mCondition.signal(); 95} 96 97int SoundPool::beginThread(void* arg) 98{ 99 SoundPool* p = (SoundPool*)arg; 100 return p->run(); 101} 102 103int SoundPool::run() 104{ 105 mLock.lock(); 106 while (!mQuit) { 107 mCondition.wait(mLock); 108 LOGV("awake"); 109 if (mQuit) break; 110 111 while (!mRestart.empty()) { 112 SoundChannel* channel; 113 LOGV("Getting channel from list"); 114 List<SoundChannel*>::iterator iter = mRestart.begin(); 115 channel = *iter; 116 mRestart.erase(iter); 117 if (channel) channel->nextEvent(); 118 if (mQuit) break; 119 } 120 } 121 122 mRestart.clear(); 123 mCondition.signal(); 124 mLock.unlock(); 125 LOGV("goodbye"); 126 return 0; 127} 128 129void SoundPool::quit() 130{ 131 mLock.lock(); 132 mQuit = true; 133 mCondition.signal(); 134 mCondition.wait(mLock); 135 LOGV("return from quit"); 136 mLock.unlock(); 137} 138 139bool SoundPool::startThreads() 140{ 141 createThread(beginThread, this); 142 if (mDecodeThread == NULL) 143 mDecodeThread = new SoundPoolThread(this); 144 return mDecodeThread != NULL; 145} 146 147SoundChannel* SoundPool::findChannel(int channelID) 148{ 149 for (int i = 0; i < mMaxChannels; ++i) { 150 if (mChannelPool[i].channelID() == channelID) { 151 return &mChannelPool[i]; 152 } 153 } 154 return NULL; 155} 156 157SoundChannel* SoundPool::findNextChannel(int channelID) 158{ 159 for (int i = 0; i < mMaxChannels; ++i) { 160 if (mChannelPool[i].nextChannelID() == channelID) { 161 return &mChannelPool[i]; 162 } 163 } 164 return NULL; 165} 166 167int SoundPool::load(const char* path, int priority) 168{ 169 LOGV("load: path=%s, priority=%d", path, priority); 170 Mutex::Autolock lock(&mLock); 171 sp<Sample> sample = new Sample(++mNextSampleID, path); 172 mSamples.add(sample->sampleID(), sample); 173 doLoad(sample); 174 return sample->sampleID(); 175} 176 177int SoundPool::load(int fd, int64_t offset, int64_t length, int priority) 178{ 179 LOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d", 180 fd, offset, length, priority); 181 Mutex::Autolock lock(&mLock); 182 sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length); 183 mSamples.add(sample->sampleID(), sample); 184 doLoad(sample); 185 return sample->sampleID(); 186} 187 188void SoundPool::doLoad(sp<Sample>& sample) 189{ 190 LOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); 191 sample->startLoad(); 192 mDecodeThread->loadSample(sample->sampleID()); 193} 194 195bool SoundPool::unload(int sampleID) 196{ 197 LOGV("unload: sampleID=%d", sampleID); 198 Mutex::Autolock lock(&mLock); 199 return mSamples.removeItem(sampleID); 200} 201 202int SoundPool::play(int sampleID, float leftVolume, float rightVolume, 203 int priority, int loop, float rate) 204{ 205 LOGV("sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", 206 sampleID, leftVolume, rightVolume, priority, loop, rate); 207 sp<Sample> sample; 208 SoundChannel* channel; 209 int channelID; 210 211 // scope for lock 212 { 213 Mutex::Autolock lock(&mLock); 214 215 // is sample ready? 216 sample = findSample(sampleID); 217 if ((sample == 0) || (sample->state() != Sample::READY)) { 218 LOGW(" sample %d not READY", sampleID); 219 return 0; 220 } 221 222 dump(); 223 224 // allocate a channel 225 channel = allocateChannel(priority); 226 227 // no channel allocated - return 0 228 if (!channel) { 229 LOGV("No channel allocated"); 230 return 0; 231 } 232 233 channelID = ++mNextChannelID; 234 } 235 236 LOGV("channel state = %d", channel->state()); 237 channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate); 238 return channelID; 239} 240 241SoundChannel* SoundPool::allocateChannel(int priority) 242{ 243 List<SoundChannel*>::iterator iter; 244 SoundChannel* channel = NULL; 245 246 // allocate a channel 247 if (!mChannels.empty()) { 248 iter = mChannels.begin(); 249 if (priority >= (*iter)->priority()) { 250 channel = *iter; 251 mChannels.erase(iter); 252 LOGV("Allocated active channel"); 253 } 254 } 255 256 // update priority and put it back in the list 257 if (channel) { 258 channel->setPriority(priority); 259 for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 260 if (priority < (*iter)->priority()) { 261 break; 262 } 263 } 264 mChannels.insert(iter, channel); 265 } 266 return channel; 267} 268 269// move a channel from its current position to the front of the list 270void SoundPool::moveToFront(SoundChannel* channel) 271{ 272 for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 273 if (*iter == channel) { 274 mChannels.erase(iter); 275 mChannels.push_front(channel); 276 break; 277 } 278 } 279} 280 281void SoundPool::pause(int channelID) 282{ 283 LOGV("pause(%d)", channelID); 284 Mutex::Autolock lock(&mLock); 285 SoundChannel* channel = findChannel(channelID); 286 if (channel) { 287 channel->pause(); 288 } 289} 290 291void SoundPool::resume(int channelID) 292{ 293 LOGV("resume(%d)", channelID); 294 Mutex::Autolock lock(&mLock); 295 SoundChannel* channel = findChannel(channelID); 296 if (channel) { 297 channel->resume(); 298 } 299} 300 301void SoundPool::stop(int channelID) 302{ 303 LOGV("stop(%d)", channelID); 304 Mutex::Autolock lock(&mLock); 305 SoundChannel* channel = findChannel(channelID); 306 if (channel) { 307 channel->stop(); 308 } else { 309 channel = findNextChannel(channelID); 310 if (channel) 311 channel->clearNextEvent(); 312 } 313} 314 315void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume) 316{ 317 Mutex::Autolock lock(&mLock); 318 SoundChannel* channel = findChannel(channelID); 319 if (channel) { 320 channel->setVolume(leftVolume, rightVolume); 321 } 322} 323 324void SoundPool::setPriority(int channelID, int priority) 325{ 326 LOGV("setPriority(%d, %d)", channelID, priority); 327 Mutex::Autolock lock(&mLock); 328 SoundChannel* channel = findChannel(channelID); 329 if (channel) { 330 channel->setPriority(priority); 331 } 332} 333 334void SoundPool::setLoop(int channelID, int loop) 335{ 336 LOGV("setLoop(%d, %d)", channelID, loop); 337 Mutex::Autolock lock(&mLock); 338 SoundChannel* channel = findChannel(channelID); 339 if (channel) { 340 channel->setLoop(loop); 341 } 342} 343 344void SoundPool::setRate(int channelID, float rate) 345{ 346 LOGV("setRate(%d, %f)", channelID, rate); 347 Mutex::Autolock lock(&mLock); 348 SoundChannel* channel = findChannel(channelID); 349 if (channel) { 350 channel->setRate(rate); 351 } 352} 353 354// call with lock held 355void SoundPool::done(SoundChannel* channel) 356{ 357 LOGV("done(%d)", channel->channelID()); 358 359 // if "stolen", play next event 360 if (channel->nextChannelID() != 0) { 361 LOGV("add to restart list"); 362 addToRestartList(channel); 363 } 364 365 // return to idle state 366 else { 367 LOGV("move to front"); 368 moveToFront(channel); 369 } 370} 371 372void SoundPool::dump() 373{ 374 for (int i = 0; i < mMaxChannels; ++i) { 375 mChannelPool[i].dump(); 376 } 377} 378 379 380Sample::Sample(int sampleID, const char* url) 381{ 382 init(); 383 mSampleID = sampleID; 384 mUrl = strdup(url); 385 LOGV("create sampleID=%d, url=%s", mSampleID, mUrl); 386} 387 388Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length) 389{ 390 init(); 391 mSampleID = sampleID; 392 mFd = dup(fd); 393 mOffset = offset; 394 mLength = length; 395 LOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset); 396} 397 398void Sample::init() 399{ 400 mData = 0; 401 mSize = 0; 402 mRefCount = 0; 403 mSampleID = 0; 404 mState = UNLOADED; 405 mFd = -1; 406 mOffset = 0; 407 mLength = 0; 408 mUrl = 0; 409} 410 411Sample::~Sample() 412{ 413 LOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd); 414 if (mFd > 0) { 415 LOGV("close(%d)", mFd); 416 ::close(mFd); 417 } 418 mData.clear(); 419 delete mUrl; 420} 421 422void Sample::doLoad() 423{ 424 uint32_t sampleRate; 425 int numChannels; 426 int format; 427 sp<IMemory> p; 428 LOGV("Start decode"); 429 if (mUrl) { 430 p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format); 431 } else { 432 p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format); 433 LOGV("close(%d)", mFd); 434 ::close(mFd); 435 mFd = -1; 436 } 437 if (p == 0) { 438 LOGE("Unable to load sample: %s", mUrl); 439 return; 440 } 441 LOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d", 442 p->pointer(), p->size(), sampleRate, numChannels); 443 444 if (sampleRate > kMaxSampleRate) { 445 LOGE("Sample rate (%u) out of range", sampleRate); 446 return; 447 } 448 449 if ((numChannels < 1) || (numChannels > 2)) { 450 LOGE("Sample channel count (%d) out of range", numChannels); 451 return; 452 } 453 454 //_dumpBuffer(p->pointer(), p->size()); 455 uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10; 456 //_dumpBuffer(q, 10, 10, false); 457 458 mData = p; 459 mSize = p->size(); 460 mSampleRate = sampleRate; 461 mNumChannels = numChannels; 462 mFormat = format; 463 mState = READY; 464} 465 466 467void SoundChannel::init(SoundPool* soundPool) 468{ 469 mSoundPool = soundPool; 470} 471 472void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, 473 float rightVolume, int priority, int loop, float rate) 474{ 475 AudioTrack* oldTrack; 476 477 LOGV("play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", 478 this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate); 479 480 // if not idle, this voice is being stolen 481 if (mState != IDLE) { 482 LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); 483 stop_l(); 484 mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 485#ifdef USE_SHARED_MEM_BUFFER 486 mSoundPool->done(this); 487#endif 488 return; 489 } 490 491 // initialize track 492 int afFrameCount; 493 int afSampleRate; 494 if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { 495 afFrameCount = kDefaultFrameCount; 496 } 497 if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) { 498 afSampleRate = kDefaultSampleRate; 499 } 500 int numChannels = sample->numChannels(); 501 uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 502 uint32_t bufferFrames = (afFrameCount * sampleRate) / afSampleRate; 503 uint32_t frameCount = 0; 504 505 if (loop) { 506 frameCount = sample->size()/numChannels/((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 507 } 508 509 // Ensure minimum audio buffer size in case of short looped sample 510 if(frameCount < kDefaultBufferCount * bufferFrames) { 511 frameCount = kDefaultBufferCount * bufferFrames; 512 } 513 514 AudioTrack* newTrack; 515 516 // mToggle toggles each time a track is started on a given channel. 517 // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 518 // as callback user data. This enables the detection of callbacks received from the old 519 // audio track while the new one is being started and avoids processing them with 520 // wrong audio audio buffer size (mAudioBufferSize) 521 unsigned long toggle = mToggle ^ 1; 522 void *userData = (void *)((unsigned long)this | toggle); 523 524#ifdef USE_SHARED_MEM_BUFFER 525 newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(), 526 numChannels, sample->getIMemory(), 0, callback, userData); 527#else 528 newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(), 529 numChannels, frameCount, 0, callback, userData, bufferFrames); 530#endif 531 if (newTrack->initCheck() != NO_ERROR) { 532 LOGE("Error creating AudioTrack"); 533 delete newTrack; 534 return; 535 } 536 LOGV("setVolume %p", newTrack); 537 newTrack->setVolume(leftVolume, rightVolume); 538 newTrack->setLoop(0, frameCount, loop); 539 540 { 541 Mutex::Autolock lock(&mLock); 542 // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored. 543 mToggle = toggle; 544 oldTrack = mAudioTrack; 545 mAudioTrack = newTrack; 546 mPos = 0; 547 mSample = sample; 548 mChannelID = nextChannelID; 549 mPriority = priority; 550 mLoop = loop; 551 mLeftVolume = leftVolume; 552 mRightVolume = rightVolume; 553 mNumChannels = numChannels; 554 mRate = rate; 555 clearNextEvent(); 556 mState = PLAYING; 557 mAudioTrack->start(); 558 mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 559 } 560 561 LOGV("delete oldTrack %p", oldTrack); 562 delete oldTrack; 563} 564 565void SoundChannel::nextEvent() 566{ 567 sp<Sample> sample; 568 int nextChannelID; 569 float leftVolume; 570 float rightVolume; 571 int priority; 572 int loop; 573 float rate; 574 575 // check for valid event 576 { 577 Mutex::Autolock lock(&mLock); 578 nextChannelID = mNextEvent.channelID(); 579 if (nextChannelID == 0) { 580 LOGV("stolen channel has no event"); 581 return; 582 } 583 584 sample = mNextEvent.sample(); 585 leftVolume = mNextEvent.leftVolume(); 586 rightVolume = mNextEvent.rightVolume(); 587 priority = mNextEvent.priority(); 588 loop = mNextEvent.loop(); 589 rate = mNextEvent.rate(); 590 } 591 592 LOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 593 play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 594} 595 596void SoundChannel::callback(int event, void* user, void *info) 597{ 598 unsigned long toggle = (unsigned long)user & 1; 599 SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 600 601 if (channel->mToggle != toggle) { 602 LOGV("callback with wrong toggle"); 603 return; 604 } 605 channel->process(event, info); 606} 607 608void SoundChannel::process(int event, void *info) 609{ 610 //LOGV("process(%d)", mChannelID); 611 sp<Sample> sample = mSample; 612 613// LOGV("SoundChannel::process event %d", event); 614 615 if (event == AudioTrack::EVENT_MORE_DATA) { 616 AudioTrack::Buffer* b = static_cast<AudioTrack::Buffer *>(info); 617 618 // check for stop state 619 if (b->size == 0) return; 620 621 if (sample != 0) { 622 // fill buffer 623 uint8_t* q = (uint8_t*) b->i8; 624 size_t count = 0; 625 626 if (mPos < (int)sample->size()) { 627 uint8_t* p = sample->data() + mPos; 628 count = sample->size() - mPos; 629 if (count > b->size) { 630 count = b->size; 631 } 632 memcpy(q, p, count); 633 LOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count); 634 } else if (mPos < mAudioBufferSize) { 635 count = mAudioBufferSize - mPos; 636 if (count > b->size) { 637 count = b->size; 638 } 639 memset(q, 0, count); 640 LOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 641 } 642 643 mPos += count; 644 b->size = count; 645 //LOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 646 } 647 } else if (event == AudioTrack::EVENT_UNDERRUN) { 648 LOGV("stopping track"); 649 stop(); 650 } else if (event == AudioTrack::EVENT_LOOP_END) { 651 LOGV("End loop: %d", *(int *)info); 652 } 653} 654 655 656// call with lock held 657void SoundChannel::stop_l() 658{ 659 if (mState != IDLE) { 660 setVolume_l(0, 0); 661 LOGV("stop"); 662 mAudioTrack->stop(); 663 mSample.clear(); 664 mState = IDLE; 665 mPriority = IDLE_PRIORITY; 666 } 667} 668 669void SoundChannel::stop() 670{ 671 { 672 Mutex::Autolock lock(&mLock); 673 stop_l(); 674 } 675 mSoundPool->done(this); 676} 677 678//FIXME: Pause is a little broken right now 679void SoundChannel::pause() 680{ 681 Mutex::Autolock lock(&mLock); 682 if (mState == PLAYING) { 683 LOGV("pause track"); 684 mState = PAUSED; 685 mAudioTrack->pause(); 686 } 687} 688 689void SoundChannel::resume() 690{ 691 Mutex::Autolock lock(&mLock); 692 if (mState == PAUSED) { 693 LOGV("resume track"); 694 mState = PLAYING; 695 mAudioTrack->start(); 696 } 697} 698 699void SoundChannel::setRate(float rate) 700{ 701 Mutex::Autolock lock(&mLock); 702 if (mAudioTrack != 0 && mSample.get() != 0) { 703 uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 704 mAudioTrack->setSampleRate(sampleRate); 705 mRate = rate; 706 } 707} 708 709// call with lock held 710void SoundChannel::setVolume_l(float leftVolume, float rightVolume) 711{ 712 mLeftVolume = leftVolume; 713 mRightVolume = rightVolume; 714 if (mAudioTrack != 0) mAudioTrack->setVolume(leftVolume, rightVolume); 715} 716 717void SoundChannel::setVolume(float leftVolume, float rightVolume) 718{ 719 Mutex::Autolock lock(&mLock); 720 setVolume_l(leftVolume, rightVolume); 721} 722 723void SoundChannel::setLoop(int loop) 724{ 725 Mutex::Autolock lock(&mLock); 726 if (mAudioTrack != 0 && mSample.get() != 0) { 727 mAudioTrack->setLoop(0, mSample->size()/mNumChannels/((mSample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)), loop); 728 mLoop = loop; 729 } 730} 731 732SoundChannel::~SoundChannel() 733{ 734 LOGV("SoundChannel destructor"); 735 if (mAudioTrack) { 736 LOGV("stop track"); 737 mAudioTrack->stop(); 738 delete mAudioTrack; 739 } 740 clearNextEvent(); 741 mSample.clear(); 742} 743 744void SoundChannel::dump() 745{ 746 LOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 747 mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 748} 749 750void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 751 float rightVolume, int priority, int loop, float rate) 752{ 753 mSample =sample; 754 mChannelID = channelID; 755 mLeftVolume = leftVolume; 756 mRightVolume = rightVolume; 757 mPriority = priority; 758 mLoop = loop; 759 mRate =rate; 760} 761 762} // end namespace android 763 764