1372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen/* 2372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * Copyright (C) 2007 The Android Open Source Project 3372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * 4372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 5372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * you may not use this file except in compliance with the License. 6372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * You may obtain a copy of the License at 7372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * 8372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 9372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * 10372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * Unless required by applicable law or agreed to in writing, software 11372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 12372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * See the License for the specific language governing permissions and 14372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen * limitations under the License. 15372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen */ 16372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 17372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen//#define LOG_NDEBUG 0 18372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#define LOG_TAG "SoundPool" 19372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 20372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <inttypes.h> 21372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 22372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <utils/Log.h> 23372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 24372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#define USE_SHARED_MEM_BUFFER 25372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 26372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <media/AudioTrack.h> 27372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <media/IMediaHTTPService.h> 28372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <media/mediaplayer.h> 29372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <media/stagefright/MediaExtractor.h> 30372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include "SoundPool.h" 31372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include "SoundPoolThread.h" 32372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <media/AudioPolicyHelper.h> 33372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <ndk/NdkMediaCodec.h> 34372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <ndk/NdkMediaExtractor.h> 35372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#include <ndk/NdkMediaFormat.h> 36372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 37372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissennamespace android 38372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 39372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 40372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint kDefaultBufferCount = 4; 41372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenuint32_t kMaxSampleRate = 48000; 42372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenuint32_t kDefaultSampleRate = 44100; 43372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenuint32_t kDefaultFrameCount = 1200; 44372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissensize_t kDefaultHeapSize = 1024 * 1024; // 1MB 45372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 46372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 47372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes) 48372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 49372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s", 50372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags); 51372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 52372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // check limits 53372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mMaxChannels = maxChannels; 54372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mMaxChannels < 1) { 55372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mMaxChannels = 1; 56372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 57372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen else if (mMaxChannels > 32) { 58372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mMaxChannels = 32; 59372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 60372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); 61372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 62372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mQuit = false; 63372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mDecodeThread = 0; 64372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); 65372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAllocated = 0; 66372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNextSampleID = 0; 67372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNextChannelID = 0; 68372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 69372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCallback = 0; 70372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mUserData = 0; 71372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 72372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelPool = new SoundChannel[mMaxChannels]; 73372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 74372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelPool[i].init(this); 75372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.push_back(&mChannelPool[i]); 76372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 77372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 78372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // start decode thread 79372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen startThreads(); 80372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 81372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 82372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundPool::~SoundPool() 83372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 84372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundPool destructor"); 85372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mDecodeThread->quit(); 86372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen quit(); 87372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 88372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 89372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 90372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.clear(); 91372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mChannelPool) 92372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen delete [] mChannelPool; 93372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // clean up samples 94372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("clear samples"); 95372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSamples.clear(); 96372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 97372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mDecodeThread) 98372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen delete mDecodeThread; 99372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 100372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 101372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::addToRestartList(SoundChannel* channel) 102372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 103372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mRestartLock); 104372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!mQuit) { 105372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestart.push_back(channel); 106372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.signal(); 107372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 108372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 109372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 110372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::addToStopList(SoundChannel* channel) 111372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 112372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mRestartLock); 113372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!mQuit) { 114372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mStop.push_back(channel); 115372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.signal(); 116372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 117372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 118372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 119372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::beginThread(void* arg) 120372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 121372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundPool* p = (SoundPool*)arg; 122372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return p->run(); 123372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 124372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 125372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::run() 126372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 127372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.lock(); 128372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen while (!mQuit) { 129372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.wait(mRestartLock); 130372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("awake"); 131372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mQuit) break; 132372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 133372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen while (!mStop.empty()) { 134372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel; 135372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Getting channel from stop list"); 136372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen List<SoundChannel* >::iterator iter = mStop.begin(); 137372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = *iter; 138372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mStop.erase(iter); 139372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.unlock(); 140372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel != 0) { 141372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 142372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->stop(); 143372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 144372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.lock(); 145372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mQuit) break; 146372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 147372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 148372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen while (!mRestart.empty()) { 149372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel; 150372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Getting channel from list"); 151372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen List<SoundChannel*>::iterator iter = mRestart.begin(); 152372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = *iter; 153372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestart.erase(iter); 154372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.unlock(); 155372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel != 0) { 156372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 157372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->nextEvent(); 158372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 159372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.lock(); 160372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mQuit) break; 161372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 162372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 163372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 164372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mStop.clear(); 165372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestart.clear(); 166372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.signal(); 167372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.unlock(); 168372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("goodbye"); 169372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 170372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 171372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 172372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::quit() 173372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 174372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.lock(); 175372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mQuit = true; 176372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.signal(); 177372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCondition.wait(mRestartLock); 178372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("return from quit"); 179372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRestartLock.unlock(); 180372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 181372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 182372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenbool SoundPool::startThreads() 183372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 184372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen createThreadEtc(beginThread, this, "SoundPool"); 185372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mDecodeThread == NULL) 186372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mDecodeThread = new SoundPoolThread(this); 187372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return mDecodeThread != NULL; 188372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 189372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 190372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel* SoundPool::findChannel(int channelID) 191372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 192372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 193372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mChannelPool[i].channelID() == channelID) { 194372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return &mChannelPool[i]; 195372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 196372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 197372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NULL; 198372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 199372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 200372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel* SoundPool::findNextChannel(int channelID) 201372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 202372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 203372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mChannelPool[i].nextChannelID() == channelID) { 204372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return &mChannelPool[i]; 205372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 206372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 207372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NULL; 208372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 209372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 210372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) 211372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 212372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", 213372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen fd, offset, length, priority); 214372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 215372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length); 216372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSamples.add(sample->sampleID(), sample); 217372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen doLoad(sample); 218372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return sample->sampleID(); 219372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 220372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 221372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::doLoad(sp<Sample>& sample) 222372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 223372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID()); 224372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sample->startLoad(); 225372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mDecodeThread->loadSample(sample->sampleID()); 226372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 227372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 228372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenbool SoundPool::unload(int sampleID) 229372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 230372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("unload: sampleID=%d", sampleID); 231372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 232a6238ef3891bbbdb1c42d3e7954c4cd55527cef6Andy Hung return mSamples.removeItem(sampleID) >= 0; // removeItem() returns index or BAD_VALUE 233372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 234372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 235372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::play(int sampleID, float leftVolume, float rightVolume, 236372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int priority, int loop, float rate) 237372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 238372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", 239372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sampleID, leftVolume, rightVolume, priority, loop, rate); 240372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample; 241372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel; 242372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int channelID; 243372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 244372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 245372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 246372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mQuit) { 247372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 248372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 249372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // is sample ready? 250372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sample = findSample(sampleID); 251372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if ((sample == 0) || (sample->state() != Sample::READY)) { 252372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGW(" sample %d not READY", sampleID); 253372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 254372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 255372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 256372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen dump(); 257372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 258372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // allocate a channel 2590c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channel = allocateChannel_l(priority, sampleID); 260372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 261372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // no channel allocated - return 0 262372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!channel) { 263372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("No channel allocated"); 264372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 265372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 266372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 267372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channelID = ++mNextChannelID; 268372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 269372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("play channel %p state = %d", channel, channel->state()); 270372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate); 271372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return channelID; 272372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 273372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 2740c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy HungSoundChannel* SoundPool::allocateChannel_l(int priority, int sampleID) 275372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 276372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen List<SoundChannel*>::iterator iter; 277372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = NULL; 278372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 2790c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // check if channel for given sampleID still available 280372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!mChannels.empty()) { 2810c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 2820c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (sampleID == (*iter)->getPrevSampleID() && (*iter)->state() == SoundChannel::IDLE) { 2830c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channel = *iter; 2840c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mChannels.erase(iter); 2850c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung ALOGV("Allocated recycled channel for same sampleID"); 2860c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung break; 2870c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 2880c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 2890c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 2900c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung 2910c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // allocate any channel 2920c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (!channel && !mChannels.empty()) { 293372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen iter = mChannels.begin(); 294372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (priority >= (*iter)->priority()) { 295372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = *iter; 296372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.erase(iter); 297372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Allocated active channel"); 298372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 299372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 300372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 301372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // update priority and put it back in the list 302372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 303372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setPriority(priority); 304372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 305372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (priority < (*iter)->priority()) { 306372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen break; 307372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 308372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 309372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.insert(iter, channel); 310372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 311372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return channel; 312372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 313372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 314372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// move a channel from its current position to the front of the list 315372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::moveToFront_l(SoundChannel* channel) 316372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 317372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 318372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (*iter == channel) { 319372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.erase(iter); 320372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.push_front(channel); 321372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen break; 322372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 323372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 324372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 325372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 326372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::pause(int channelID) 327372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 328372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause(%d)", channelID); 329372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 330372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 331372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 332372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->pause(); 333372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 334372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 335372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 336372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::autoPause() 337372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 338372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("autoPause()"); 339372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 340372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 341372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = &mChannelPool[i]; 342372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->autoPause(); 343372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 344372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 345372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 346372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::resume(int channelID) 347372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 348372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume(%d)", channelID); 349372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 350372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 351372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 352372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->resume(); 353372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 354372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 355372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 356372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::autoResume() 357372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 358372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("autoResume()"); 359372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 360372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 361372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = &mChannelPool[i]; 362372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->autoResume(); 363372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 364372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 365372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 366372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::stop(int channelID) 367372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 368372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stop(%d)", channelID); 369372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 370372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 371372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 372372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->stop(); 373372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 374372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = findNextChannel(channelID); 375372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) 376372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->clearNextEvent(); 377372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 378372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 379372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 380372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setVolume(int channelID, float leftVolume, float rightVolume) 381372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 382372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 383372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 384372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 385372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setVolume(leftVolume, rightVolume); 386372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 387372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 388372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 389372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setPriority(int channelID, int priority) 390372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 391372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setPriority(%d, %d)", channelID, priority); 392372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 393372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 394372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 395372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setPriority(priority); 396372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 397372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 398372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 399372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setLoop(int channelID, int loop) 400372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 401372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setLoop(%d, %d)", channelID, loop); 402372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 403372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 404372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 405372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setLoop(loop); 406372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 407372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 408372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 409372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setRate(int channelID, float rate) 410372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 411372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setRate(%d, %f)", channelID, rate); 412372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 413372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 414372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 415372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setRate(rate); 416372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 417372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 418372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 419372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 420372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::done_l(SoundChannel* channel) 421372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 422372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("done_l(%d)", channel->channelID()); 423372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // if "stolen", play next event 424372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel->nextChannelID() != 0) { 425372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("add to restart list"); 426372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen addToRestartList(channel); 427372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 428372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 429372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // return to idle state 430372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen else { 431372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("move to front"); 432372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen moveToFront_l(channel); 433372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 434372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 435372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 436372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setCallback(SoundPoolCallback* callback, void* user) 437372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 438372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mCallbackLock); 439372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCallback = callback; 440372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mUserData = user; 441372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 442372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 443372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::notify(SoundPoolEvent event) 444372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 445372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mCallbackLock); 446372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mCallback != NULL) { 447372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCallback(event, this, mUserData); 448372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 449372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 450372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 451372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::dump() 452372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 453372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 454372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelPool[i].dump(); 455372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 456372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 457372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 458372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 459372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSample::Sample(int sampleID, int fd, int64_t offset, int64_t length) 460372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 461372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen init(); 462372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID = sampleID; 463372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = dup(fd); 464372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mOffset = offset; 465372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLength = length; 466372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64, 467372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID, mFd, mLength, mOffset); 468372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 469372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 470372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid Sample::init() 471372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 472372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSize = 0; 473372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRefCount = 0; 474372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID = 0; 475372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = UNLOADED; 476372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = -1; 477372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mOffset = 0; 478372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLength = 0; 479372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 480372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 481372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSample::~Sample() 482372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 483372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd); 484372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mFd > 0) { 485372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("close(%d)", mFd); 486372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ::close(mFd); 487372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 488372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 489372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 490372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenstatic status_t decode(int fd, int64_t offset, int64_t length, 491372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t *rate, int *numChannels, audio_format_t *audioFormat, 492372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<MemoryHeapBase> heap, size_t *memsize) { 493372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 4946cd6110773bf83638f21a76d388dc2b7037df0d8Marco Nelissen ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length); 495372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor *ex = AMediaExtractor_new(); 496372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length); 497372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 498372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (err != AMEDIA_OK) { 49906524dccbc35cdeed92d0b5ec96b42d43518d7edMarco Nelissen AMediaExtractor_delete(ex); 500372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return err; 501372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 502372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 503372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen *audioFormat = AUDIO_FORMAT_PCM_16_BIT; 504372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 505372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t numTracks = AMediaExtractor_getTrackCount(ex); 506372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (size_t i = 0; i < numTracks; i++) { 507372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 508372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen const char *mime; 509372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 510372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 511372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 512372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 513372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 514372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (strncmp(mime, "audio/", 6) == 0) { 515372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 516372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec *codec = AMediaCodec_createDecoderByType(mime); 51726eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung if (codec == NULL 51826eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaCodec_configure(codec, format, 51926eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK 52026eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaCodec_start(codec) != AMEDIA_OK 52126eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) { 522372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 523372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_delete(codec); 524372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 525372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 526372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 527372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 528372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool sawInputEOS = false; 529372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool sawOutputEOS = false; 530372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* writePos = static_cast<uint8_t*>(heap->getBase()); 531372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t available = heap->getSize(); 532372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t written = 0; 533372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 534372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 535372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen format = AMediaCodec_getOutputFormat(codec); 536372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 537372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen while (!sawOutputEOS) { 538372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!sawInputEOS) { 539372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000); 5406cd6110773bf83638f21a76d388dc2b7037df0d8Marco Nelissen ALOGV("input buffer %zd", bufidx); 541372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (bufidx >= 0) { 542372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t bufsize; 543372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize); 544372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize); 545372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("read %d", sampleSize); 546372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sampleSize < 0) { 547372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sampleSize = 0; 548372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawInputEOS = true; 549372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("EOS"); 550372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 551372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex); 552372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 553372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_queueInputBuffer(codec, bufidx, 554372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 0 /* offset */, sampleSize, presentationTimeUs, 555372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0); 556372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_advance(ex); 557372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 558372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 559372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 560372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodecBufferInfo info; 561372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1); 562372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("dequeueoutput returned: %d", status); 563372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status >= 0) { 564372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { 565372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("output EOS"); 566372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawOutputEOS = true; 567372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 568372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("got decoded buffer size %d", info.size); 569372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 570372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */); 571372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t dataSize = info.size; 572372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (dataSize > available) { 573372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen dataSize = available; 574372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 575372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memcpy(writePos, buf + info.offset, dataSize); 576372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen writePos += dataSize; 577372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen written += dataSize; 578372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen available -= dataSize; 579372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_releaseOutputBuffer(codec, status, false /* render */); 580372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (available == 0) { 581372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // there might be more data, but there's no space for it 582372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawOutputEOS = true; 583372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 584372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) { 585372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("output buffers changed"); 586372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { 587372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 588372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen format = AMediaCodec_getOutputFormat(codec); 589372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("format changed to: %s", AMediaFormat_toString(format)); 590372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { 591372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("no output buffer right now"); 592372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 593372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("unexpected info code: %d", status); 594372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 595372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 596372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 597372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_stop(codec); 598372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_delete(codec); 599372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 600372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) || 601372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) { 602372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 603372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 604372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 605372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 606372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen *memsize = written; 607372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return OK; 608372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 609372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 610372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 611372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 612372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 613372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 614372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 615372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenstatus_t Sample::doLoad() 616372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 617372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate; 618372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int numChannels; 619372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen audio_format_t format; 620372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status_t status; 621372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap = new MemoryHeapBase(kDefaultHeapSize); 622372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 623372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Start decode"); 624372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format, 625372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap, &mSize); 626372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("close(%d)", mFd); 627372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ::close(mFd); 628372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = -1; 629372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status != NO_ERROR) { 630372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Unable to load sample"); 631372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 632372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 633372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d", 634372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap->getBase(), mSize, sampleRate, numChannels); 635372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 636372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sampleRate > kMaxSampleRate) { 637372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Sample rate (%u) out of range", sampleRate); 638372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = BAD_VALUE; 639372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 640372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 641372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 642a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung if ((numChannels < 1) || (numChannels > 8)) { 643372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Sample channel count (%d) out of range", numChannels); 644372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = BAD_VALUE; 645372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 646372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 647372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 648372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mData = new MemoryBase(mHeap, 0, mSize); 649372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleRate = sampleRate; 650372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNumChannels = numChannels; 651372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFormat = format; 652372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = READY; 653372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NO_ERROR; 654372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 655372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenerror: 656372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap.clear(); 657372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return status; 658372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 659372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 660372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 661372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::init(SoundPool* soundPool) 662372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 663372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool = soundPool; 6640c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mPrevSampleID = -1; 665372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 666372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 667372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with sound pool lock held 668372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, 669372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume, int priority, int loop, float rate) 670372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 671372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<AudioTrack> oldTrack; 672372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<AudioTrack> newTrack; 6730c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung status_t status = NO_ERROR; 674372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 675372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { // scope for the lock 676372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 677372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 678372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f," 679372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen " priority=%d, loop=%d, rate=%f", 680372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, 681372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen priority, loop, rate); 682372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 683372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // if not idle, this voice is being stolen 684372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState != IDLE) { 685372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); 686372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 687372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen stop_l(); 688372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 689372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 690372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 691372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // initialize track 692372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t afFrameCount; 693372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t afSampleRate; 694372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes()); 695372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { 696372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen afFrameCount = kDefaultFrameCount; 697372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 698372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { 699372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen afSampleRate = kDefaultSampleRate; 700372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 701372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int numChannels = sample->numChannels(); 702372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 703372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t frameCount = 0; 704372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 705372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (loop) { 706a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung const audio_format_t format = sample->format(); 707a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung const size_t frameSize = audio_is_linear_pcm(format) 708a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung ? numChannels * audio_bytes_per_sample(format) : 1; 709a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung frameCount = sample->size() / frameSize; 710372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 711372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 712372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#ifndef USE_SHARED_MEM_BUFFER 713372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; 714372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // Ensure minimum audio buffer size in case of short looped sample 715372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if(frameCount < totalFrames) { 716372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen frameCount = totalFrames; 717372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 718372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#endif 719372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 72032ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung // check if the existing track has the same sample id. 72132ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (mAudioTrack != 0 && mPrevSampleID == sample->sampleID()) { 72232ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung // the sample rate may fail to change if the audio track is a fast track. 72332ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) { 72432ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung newTrack = mAudioTrack; 72532ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID()); 72632ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung } 72732ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung } 72832ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (newTrack == 0) { 7290c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // mToggle toggles each time a track is started on a given channel. 7300c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 7310c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // as callback user data. This enables the detection of callbacks received from the old 7320c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // audio track while the new one is being started and avoids processing them with 7330c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // wrong audio audio buffer size (mAudioBufferSize) 7340c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung unsigned long toggle = mToggle ^ 1; 7350c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung void *userData = (void *)((unsigned long)this | toggle); 7360c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels); 7370c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung 7380c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // do not create a new audio track if current track is compatible with sample parameters 7390c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #ifdef USE_SHARED_MEM_BUFFER 7400c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 7416c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData, 7426c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi 0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE, 7436c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi AudioTrack::TRANSFER_DEFAULT, 7446c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes()); 7450c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #else 7460c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; 7470c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 7480c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, 7496c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi bufferFrames, AUDIO_SESSION_ALLOCATE, AudioTrack::TRANSFER_DEFAULT, 7506c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes()); 7510c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #endif 7520c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung oldTrack = mAudioTrack; 7530c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung status = newTrack->initCheck(); 7540c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (status != NO_ERROR) { 7550c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung ALOGE("Error creating AudioTrack"); 75614d226a2cd7b39e17a3f0bfdab79e645f7146f53Glenn Kasten // newTrack goes out of scope, so reference count drops to zero 7570c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung goto exit; 7580c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 7590c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // From now on, AudioTrack callbacks received with previous toggle value will be ignored. 7600c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mToggle = toggle; 7610c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mAudioTrack = newTrack; 762bc4537393b02b39433e07fed4ed57186d8e5959fAndy Hung ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID()); 763372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 764372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen newTrack->setVolume(leftVolume, rightVolume); 765372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen newTrack->setLoop(0, frameCount, loop); 766372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPos = 0; 767372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample = sample; 768372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelID = nextChannelID; 769372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = priority; 770372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 771372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 772372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 773372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNumChannels = numChannels; 774372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate = rate; 775372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen clearNextEvent(); 776372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 777372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 778372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 779372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 780372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 781372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenexit: 782372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("delete oldTrack %p", oldTrack.get()); 783372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status != NO_ERROR) { 784372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack.clear(); 785372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 786372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 787372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 788372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::nextEvent() 789372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 790372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample; 791372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int nextChannelID; 792372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float leftVolume; 793372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume; 794372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int priority; 795372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int loop; 796372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rate; 797372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 798372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // check for valid event 799372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 800372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 801372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen nextChannelID = mNextEvent.channelID(); 802372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (nextChannelID == 0) { 803372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stolen channel has no event"); 804372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 805372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 806372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 807372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sample = mNextEvent.sample(); 808372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen leftVolume = mNextEvent.leftVolume(); 809372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen rightVolume = mNextEvent.rightVolume(); 810372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen priority = mNextEvent.priority(); 811372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen loop = mNextEvent.loop(); 812372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen rate = mNextEvent.rate(); 813372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 814372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 815372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 816372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 817372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 818372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 819372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::callback(int event, void* user, void *info) 820372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 821372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 822372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 823372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->process(event, info, (unsigned long)user & 1); 824372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 825372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 826372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::process(int event, void *info, unsigned long toggle) 827372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 828372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen //ALOGV("process(%d)", mChannelID); 829372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 830372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 831372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 832372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AudioTrack::Buffer* b = NULL; 833372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (event == AudioTrack::EVENT_MORE_DATA) { 834372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b = static_cast<AudioTrack::Buffer *>(info); 835372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 836372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 837372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mToggle != toggle) { 838372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process wrong toggle %p channel %d", this, mChannelID); 839372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (b != NULL) { 840372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = 0; 841372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 842372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 843372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 844372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 845372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample = mSample; 846372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 847372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("SoundChannel::process event %d", event); 848372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 849372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (event == AudioTrack::EVENT_MORE_DATA) { 850372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 851372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // check for stop state 852372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (b->size == 0) return; 853372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 854372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == IDLE) { 855372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = 0; 856372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 857372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 858372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 859372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sample != 0) { 860372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // fill buffer 861372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* q = (uint8_t*) b->i8; 862372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t count = 0; 863372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 864372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mPos < (int)sample->size()) { 865372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* p = sample->data() + mPos; 866372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = sample->size() - mPos; 867372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (count > b->size) { 868372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = b->size; 869372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 870372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memcpy(q, p, count); 871372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, 872372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// count); 873372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (mPos < mAudioBufferSize) { 874372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = mAudioBufferSize - mPos; 875372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (count > b->size) { 876372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = b->size; 877372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 878372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memset(q, 0, count); 879372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 880372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 881372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 882372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPos += count; 883372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = count; 884372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 885372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 886372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { 887372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process %p channel %d event %s", 888372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" : 889372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen "BUFFER_END"); 890372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->addToStopList(this); 891372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_LOOP_END) { 892372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("End loop %p channel %d", this, mChannelID); 893372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) { 894372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID); 895372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 896372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGW("SoundChannel::process unexpected event %d", event); 897372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 898372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 899372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 900372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 901372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 902372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenbool SoundChannel::doStop_l() 903372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 904372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState != IDLE) { 905372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen setVolume_l(0, 0); 906372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stop"); 907372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->stop(); 9080c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mPrevSampleID = mSample->sampleID(); 909372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample.clear(); 910372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = IDLE; 911372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = IDLE_PRIORITY; 912372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return true; 913372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 914372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return false; 915372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 916372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 917372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held and sound pool lock held 918372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::stop_l() 919372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 920372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (doStop_l()) { 921372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->done_l(this); 922372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 923372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 924372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 925372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with sound pool lock held 926372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::stop() 927372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 928372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool stopped; 929372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 930372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 931372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen stopped = doStop_l(); 932372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 933372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 934372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (stopped) { 935372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->done_l(this); 936372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 937372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 938372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 939372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen//FIXME: Pause is a little broken right now 940372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::pause() 941372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 942372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 943372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PLAYING) { 944372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause track"); 945372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PAUSED; 946372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->pause(); 947372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 948372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 949372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 950372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::autoPause() 951372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 952372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 953372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PLAYING) { 954372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause track"); 955372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PAUSED; 956372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = true; 957372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->pause(); 958372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 959372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 960372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 961372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::resume() 962372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 963372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 964372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PAUSED) { 965372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume track"); 966372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 967372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = false; 968372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 969372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 970372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 971372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 972372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::autoResume() 973372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 974372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 975372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAutoPaused && (mState == PAUSED)) { 976372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume track"); 977372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 978372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = false; 979372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 980372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 981372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 982372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 983372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setRate(float rate) 984372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 985372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 986372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL && mSample != 0) { 987372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 988372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setSampleRate(sampleRate); 989372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate = rate; 990372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 991372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 992372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 993372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 994372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setVolume_l(float leftVolume, float rightVolume) 995372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 996372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 997372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 998372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL) 999372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setVolume(leftVolume, rightVolume); 1000372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1001372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1002372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setVolume(float leftVolume, float rightVolume) 1003372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1004372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1005372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen setVolume_l(leftVolume, rightVolume); 1006372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1007372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1008372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setLoop(int loop) 1009372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1010372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1011372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL && mSample != 0) { 1012372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t loopEnd = mSample->size()/mNumChannels/ 1013372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 1014372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setLoop(0, loopEnd, loop); 1015372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 1016372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1017372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1018372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1019372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel::~SoundChannel() 1020372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1021372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundChannel destructor %p", this); 1022372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 1023372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1024372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen clearNextEvent(); 1025372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen doStop_l(); 1026372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1027372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack 1028372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // callback thread to exit which may need to execute process() and acquire the mLock. 1029372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack.clear(); 1030372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1031372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1032372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::dump() 1033372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1034372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 1035372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 1036372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1037372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1038372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 1039372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume, int priority, int loop, float rate) 1040372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1041372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample = sample; 1042372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelID = channelID; 1043372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 1044372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 1045372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = priority; 1046372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 1047372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate =rate; 1048372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1049372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1050372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} // end namespace android 1051