SoundPool.cpp revision da996f390e17e16f2dfa60e972e7ebc4f868f37e
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 int streamType = mSoundPool->streamType(); 495 if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { 496 afFrameCount = kDefaultFrameCount; 497 } 498 if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { 499 afSampleRate = kDefaultSampleRate; 500 } 501 int numChannels = sample->numChannels(); 502 uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 503 uint32_t bufferFrames = (afFrameCount * sampleRate) / afSampleRate; 504 uint32_t frameCount = 0; 505 506 if (loop) { 507 frameCount = sample->size()/numChannels/((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 508 } 509 510 // Ensure minimum audio buffer size in case of short looped sample 511 if(frameCount < kDefaultBufferCount * bufferFrames) { 512 frameCount = kDefaultBufferCount * bufferFrames; 513 } 514 515 AudioTrack* newTrack; 516 517 // mToggle toggles each time a track is started on a given channel. 518 // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 519 // as callback user data. This enables the detection of callbacks received from the old 520 // audio track while the new one is being started and avoids processing them with 521 // wrong audio audio buffer size (mAudioBufferSize) 522 unsigned long toggle = mToggle ^ 1; 523 void *userData = (void *)((unsigned long)this | toggle); 524 525#ifdef USE_SHARED_MEM_BUFFER 526 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 527 numChannels, sample->getIMemory(), 0, callback, userData); 528#else 529 newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 530 numChannels, frameCount, 0, callback, userData, bufferFrames); 531#endif 532 if (newTrack->initCheck() != NO_ERROR) { 533 LOGE("Error creating AudioTrack"); 534 delete newTrack; 535 return; 536 } 537 LOGV("setVolume %p", newTrack); 538 newTrack->setVolume(leftVolume, rightVolume); 539 newTrack->setLoop(0, frameCount, loop); 540 541 { 542 Mutex::Autolock lock(&mLock); 543 // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored. 544 mToggle = toggle; 545 oldTrack = mAudioTrack; 546 mAudioTrack = newTrack; 547 mPos = 0; 548 mSample = sample; 549 mChannelID = nextChannelID; 550 mPriority = priority; 551 mLoop = loop; 552 mLeftVolume = leftVolume; 553 mRightVolume = rightVolume; 554 mNumChannels = numChannels; 555 mRate = rate; 556 clearNextEvent(); 557 mState = PLAYING; 558 mAudioTrack->start(); 559 mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 560 } 561 562 LOGV("delete oldTrack %p", oldTrack); 563 delete oldTrack; 564} 565 566void SoundChannel::nextEvent() 567{ 568 sp<Sample> sample; 569 int nextChannelID; 570 float leftVolume; 571 float rightVolume; 572 int priority; 573 int loop; 574 float rate; 575 576 // check for valid event 577 { 578 Mutex::Autolock lock(&mLock); 579 nextChannelID = mNextEvent.channelID(); 580 if (nextChannelID == 0) { 581 LOGV("stolen channel has no event"); 582 return; 583 } 584 585 sample = mNextEvent.sample(); 586 leftVolume = mNextEvent.leftVolume(); 587 rightVolume = mNextEvent.rightVolume(); 588 priority = mNextEvent.priority(); 589 loop = mNextEvent.loop(); 590 rate = mNextEvent.rate(); 591 } 592 593 LOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 594 play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 595} 596 597void SoundChannel::callback(int event, void* user, void *info) 598{ 599 unsigned long toggle = (unsigned long)user & 1; 600 SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 601 602 if (channel->mToggle != toggle) { 603 LOGV("callback with wrong toggle"); 604 return; 605 } 606 channel->process(event, info); 607} 608 609void SoundChannel::process(int event, void *info) 610{ 611 //LOGV("process(%d)", mChannelID); 612 sp<Sample> sample = mSample; 613 614// LOGV("SoundChannel::process event %d", event); 615 616 if (event == AudioTrack::EVENT_MORE_DATA) { 617 AudioTrack::Buffer* b = static_cast<AudioTrack::Buffer *>(info); 618 619 // check for stop state 620 if (b->size == 0) return; 621 622 if (sample != 0) { 623 // fill buffer 624 uint8_t* q = (uint8_t*) b->i8; 625 size_t count = 0; 626 627 if (mPos < (int)sample->size()) { 628 uint8_t* p = sample->data() + mPos; 629 count = sample->size() - mPos; 630 if (count > b->size) { 631 count = b->size; 632 } 633 memcpy(q, p, count); 634 LOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count); 635 } else if (mPos < mAudioBufferSize) { 636 count = mAudioBufferSize - mPos; 637 if (count > b->size) { 638 count = b->size; 639 } 640 memset(q, 0, count); 641 LOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 642 } 643 644 mPos += count; 645 b->size = count; 646 //LOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 647 } 648 } else if (event == AudioTrack::EVENT_UNDERRUN) { 649 LOGV("stopping track"); 650 stop(); 651 } else if (event == AudioTrack::EVENT_LOOP_END) { 652 LOGV("End loop: %d", *(int *)info); 653 } 654} 655 656 657// call with lock held 658void SoundChannel::stop_l() 659{ 660 if (mState != IDLE) { 661 setVolume_l(0, 0); 662 LOGV("stop"); 663 mAudioTrack->stop(); 664 mSample.clear(); 665 mState = IDLE; 666 mPriority = IDLE_PRIORITY; 667 } 668} 669 670void SoundChannel::stop() 671{ 672 { 673 Mutex::Autolock lock(&mLock); 674 stop_l(); 675 } 676 mSoundPool->done(this); 677} 678 679//FIXME: Pause is a little broken right now 680void SoundChannel::pause() 681{ 682 Mutex::Autolock lock(&mLock); 683 if (mState == PLAYING) { 684 LOGV("pause track"); 685 mState = PAUSED; 686 mAudioTrack->pause(); 687 } 688} 689 690void SoundChannel::resume() 691{ 692 Mutex::Autolock lock(&mLock); 693 if (mState == PAUSED) { 694 LOGV("resume track"); 695 mState = PLAYING; 696 mAudioTrack->start(); 697 } 698} 699 700void SoundChannel::setRate(float rate) 701{ 702 Mutex::Autolock lock(&mLock); 703 if (mAudioTrack != 0 && mSample.get() != 0) { 704 uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 705 mAudioTrack->setSampleRate(sampleRate); 706 mRate = rate; 707 } 708} 709 710// call with lock held 711void SoundChannel::setVolume_l(float leftVolume, float rightVolume) 712{ 713 mLeftVolume = leftVolume; 714 mRightVolume = rightVolume; 715 if (mAudioTrack != 0) mAudioTrack->setVolume(leftVolume, rightVolume); 716} 717 718void SoundChannel::setVolume(float leftVolume, float rightVolume) 719{ 720 Mutex::Autolock lock(&mLock); 721 setVolume_l(leftVolume, rightVolume); 722} 723 724void SoundChannel::setLoop(int loop) 725{ 726 Mutex::Autolock lock(&mLock); 727 if (mAudioTrack != 0 && mSample.get() != 0) { 728 mAudioTrack->setLoop(0, mSample->size()/mNumChannels/((mSample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)), loop); 729 mLoop = loop; 730 } 731} 732 733SoundChannel::~SoundChannel() 734{ 735 LOGV("SoundChannel destructor"); 736 if (mAudioTrack) { 737 LOGV("stop track"); 738 mAudioTrack->stop(); 739 delete mAudioTrack; 740 } 741 clearNextEvent(); 742 mSample.clear(); 743} 744 745void SoundChannel::dump() 746{ 747 LOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 748 mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 749} 750 751void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 752 float rightVolume, int priority, int loop, float rate) 753{ 754 mSample =sample; 755 mChannelID = channelID; 756 mLeftVolume = leftVolume; 757 mRightVolume = rightVolume; 758 mPriority = priority; 759 mLoop = loop; 760 mRate =rate; 761} 762 763} // end namespace android 764 765