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