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