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