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