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 1900275a982abecee683f16c827d405eafe51fb67aeAndy Hungsp<Sample> SoundPool::findSample(int sampleID) 1910275a982abecee683f16c827d405eafe51fb67aeAndy Hung{ 1920275a982abecee683f16c827d405eafe51fb67aeAndy Hung Mutex::Autolock lock(&mLock); 1930275a982abecee683f16c827d405eafe51fb67aeAndy Hung return findSample_l(sampleID); 1940275a982abecee683f16c827d405eafe51fb67aeAndy Hung} 1950275a982abecee683f16c827d405eafe51fb67aeAndy Hung 1960275a982abecee683f16c827d405eafe51fb67aeAndy Hungsp<Sample> SoundPool::findSample_l(int sampleID) 1970275a982abecee683f16c827d405eafe51fb67aeAndy Hung{ 1980275a982abecee683f16c827d405eafe51fb67aeAndy Hung return mSamples.valueFor(sampleID); 1990275a982abecee683f16c827d405eafe51fb67aeAndy Hung} 2000275a982abecee683f16c827d405eafe51fb67aeAndy Hung 201372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel* SoundPool::findChannel(int channelID) 202372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 203372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 204372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mChannelPool[i].channelID() == channelID) { 205372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return &mChannelPool[i]; 206372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 207372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 208372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NULL; 209372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 210372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 211372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel* SoundPool::findNextChannel(int channelID) 212372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 213372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 214372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mChannelPool[i].nextChannelID() == channelID) { 215372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return &mChannelPool[i]; 216372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 217372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 218372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NULL; 219372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 220372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 221372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused) 222372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 223372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d", 224372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen fd, offset, length, priority); 2250275a982abecee683f16c827d405eafe51fb67aeAndy Hung int sampleID; 2260275a982abecee683f16c827d405eafe51fb67aeAndy Hung { 2270275a982abecee683f16c827d405eafe51fb67aeAndy Hung Mutex::Autolock lock(&mLock); 2280275a982abecee683f16c827d405eafe51fb67aeAndy Hung sampleID = ++mNextSampleID; 2290275a982abecee683f16c827d405eafe51fb67aeAndy Hung sp<Sample> sample = new Sample(sampleID, fd, offset, length); 2300275a982abecee683f16c827d405eafe51fb67aeAndy Hung mSamples.add(sampleID, sample); 2310275a982abecee683f16c827d405eafe51fb67aeAndy Hung sample->startLoad(); 2320275a982abecee683f16c827d405eafe51fb67aeAndy Hung } 2330275a982abecee683f16c827d405eafe51fb67aeAndy Hung // mDecodeThread->loadSample() must be called outside of mLock. 2340275a982abecee683f16c827d405eafe51fb67aeAndy Hung // mDecodeThread->loadSample() may block on mDecodeThread message queue space; 2350275a982abecee683f16c827d405eafe51fb67aeAndy Hung // the message queue emptying may block on SoundPool::findSample(). 2360275a982abecee683f16c827d405eafe51fb67aeAndy Hung // 2370275a982abecee683f16c827d405eafe51fb67aeAndy Hung // It theoretically possible that sample loads might decode out-of-order. 2380275a982abecee683f16c827d405eafe51fb67aeAndy Hung mDecodeThread->loadSample(sampleID); 2390275a982abecee683f16c827d405eafe51fb67aeAndy Hung return sampleID; 240372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 241372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 242372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenbool SoundPool::unload(int sampleID) 243372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 244372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("unload: sampleID=%d", sampleID); 245372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 246a6238ef3891bbbdb1c42d3e7954c4cd55527cef6Andy Hung return mSamples.removeItem(sampleID) >= 0; // removeItem() returns index or BAD_VALUE 247372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 248372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 249372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenint SoundPool::play(int sampleID, float leftVolume, float rightVolume, 250372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int priority, int loop, float rate) 251372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 252372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f", 253372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sampleID, leftVolume, rightVolume, priority, loop, rate); 254372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel; 255372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int channelID; 256372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 257372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 258372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 259372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mQuit) { 260372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 261372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 262372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // is sample ready? 2630275a982abecee683f16c827d405eafe51fb67aeAndy Hung sp<Sample> sample(findSample_l(sampleID)); 264372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if ((sample == 0) || (sample->state() != Sample::READY)) { 265372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGW(" sample %d not READY", sampleID); 266372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 267372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 268372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 269372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen dump(); 270372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 271372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // allocate a channel 2720c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channel = allocateChannel_l(priority, sampleID); 273372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 274372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // no channel allocated - return 0 275372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!channel) { 276372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("No channel allocated"); 277372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return 0; 278372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 279372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 280372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channelID = ++mNextChannelID; 281372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 282372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("play channel %p state = %d", channel, channel->state()); 283372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate); 284372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return channelID; 285372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 286372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 2870c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy HungSoundChannel* SoundPool::allocateChannel_l(int priority, int sampleID) 288372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 289372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen List<SoundChannel*>::iterator iter; 290372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = NULL; 291372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 2920c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // check if channel for given sampleID still available 293372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!mChannels.empty()) { 2940c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 2950c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (sampleID == (*iter)->getPrevSampleID() && (*iter)->state() == SoundChannel::IDLE) { 2960c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channel = *iter; 2970c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mChannels.erase(iter); 2980c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung ALOGV("Allocated recycled channel for same sampleID"); 2990c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung break; 3000c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 3010c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 3020c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 3030c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung 3040c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // allocate any channel 3050c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (!channel && !mChannels.empty()) { 306372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen iter = mChannels.begin(); 307372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (priority >= (*iter)->priority()) { 308372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = *iter; 309372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.erase(iter); 310372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Allocated active channel"); 311372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 312372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 313372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 314372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // update priority and put it back in the list 315372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 316372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setPriority(priority); 317372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 318372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (priority < (*iter)->priority()) { 319372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen break; 320372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 321372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 322372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.insert(iter, channel); 323372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 324372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return channel; 325372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 326372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 327372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// move a channel from its current position to the front of the list 328372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::moveToFront_l(SoundChannel* channel) 329372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 330372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { 331372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (*iter == channel) { 332372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.erase(iter); 333372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannels.push_front(channel); 334372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen break; 335372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 336372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 337372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 338372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 339372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::pause(int channelID) 340372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 341372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause(%d)", channelID); 342372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 343372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 344372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 345372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->pause(); 346372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 347372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 348372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 349372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::autoPause() 350372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 351372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("autoPause()"); 352372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 353372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 354372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = &mChannelPool[i]; 355372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->autoPause(); 356372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 357372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 358372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 359372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::resume(int channelID) 360372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 361372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume(%d)", channelID); 362372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 363372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 364372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 365372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->resume(); 366372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 367372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 368372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 369372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::autoResume() 370372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 371372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("autoResume()"); 372372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 373372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 374372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = &mChannelPool[i]; 375372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->autoResume(); 376372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 377372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 378372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 379372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::stop(int channelID) 380372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 381372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stop(%d)", channelID); 382372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 383372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 384372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 385372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->stop(); 386372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 387372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel = findNextChannel(channelID); 388372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) 389372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->clearNextEvent(); 390372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 391372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 392372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 393372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setVolume(int channelID, float leftVolume, float rightVolume) 394372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 395372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 396372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 397372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 398372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setVolume(leftVolume, rightVolume); 399372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 400372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 401372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 402372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setPriority(int channelID, int priority) 403372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 404372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setPriority(%d, %d)", channelID, priority); 405372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 406372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 407372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 408372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setPriority(priority); 409372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 410372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 411372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 412372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setLoop(int channelID, int loop) 413372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 414372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setLoop(%d, %d)", channelID, loop); 415372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 416372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 417372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 418372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setLoop(loop); 419372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 420372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 421372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 422372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setRate(int channelID, float rate) 423372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 424372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("setRate(%d, %f)", channelID, rate); 425372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 426372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = findChannel(channelID); 427372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel) { 428372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->setRate(rate); 429372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 430372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 431372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 432372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 433372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::done_l(SoundChannel* channel) 434372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 435372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("done_l(%d)", channel->channelID()); 436372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // if "stolen", play next event 437372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (channel->nextChannelID() != 0) { 438372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("add to restart list"); 439372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen addToRestartList(channel); 440372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 441372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 442372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // return to idle state 443372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen else { 444372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("move to front"); 445372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen moveToFront_l(channel); 446372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 447372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 448372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 449372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::setCallback(SoundPoolCallback* callback, void* user) 450372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 451372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mCallbackLock); 452372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCallback = callback; 453372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mUserData = user; 454372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 455372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 456372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::notify(SoundPoolEvent event) 457372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 458372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mCallbackLock); 459372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mCallback != NULL) { 460372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mCallback(event, this, mUserData); 461372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 462372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 463372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 464372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundPool::dump() 465372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 466372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (int i = 0; i < mMaxChannels; ++i) { 467372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelPool[i].dump(); 468372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 469372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 470372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 471372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 472372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSample::Sample(int sampleID, int fd, int64_t offset, int64_t length) 473372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 474372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen init(); 475372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID = sampleID; 476372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = dup(fd); 477372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mOffset = offset; 478372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLength = length; 479372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64, 480372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID, mFd, mLength, mOffset); 481372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 482372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 483372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid Sample::init() 484372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 485372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSize = 0; 486372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRefCount = 0; 487372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleID = 0; 488372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = UNLOADED; 489372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = -1; 490372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mOffset = 0; 491372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLength = 0; 492372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 493372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 494372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSample::~Sample() 495372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 496372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd); 497372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mFd > 0) { 498372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("close(%d)", mFd); 499372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ::close(mFd); 500372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 501372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 502372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 503372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenstatic status_t decode(int fd, int64_t offset, int64_t length, 504372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t *rate, int *numChannels, audio_format_t *audioFormat, 505372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<MemoryHeapBase> heap, size_t *memsize) { 506372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 5076cd6110773bf83638f21a76d388dc2b7037df0d8Marco Nelissen ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length); 508372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor *ex = AMediaExtractor_new(); 509372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length); 510372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 511372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (err != AMEDIA_OK) { 51206524dccbc35cdeed92d0b5ec96b42d43518d7edMarco Nelissen AMediaExtractor_delete(ex); 513372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return err; 514372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 515372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 516372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen *audioFormat = AUDIO_FORMAT_PCM_16_BIT; 517372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 518372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t numTracks = AMediaExtractor_getTrackCount(ex); 519372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen for (size_t i = 0; i < numTracks; i++) { 520372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i); 521372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen const char *mime; 522372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) { 523372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 524372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 525372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 526372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 527372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (strncmp(mime, "audio/", 6) == 0) { 528372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 529372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec *codec = AMediaCodec_createDecoderByType(mime); 53026eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung if (codec == NULL 53126eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaCodec_configure(codec, format, 53226eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK 53326eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaCodec_start(codec) != AMEDIA_OK 53426eca01c490f643fc2558be4c5477a1d433a8a07Andy Hung || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) { 535372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaExtractor_delete(ex); 536372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodec_delete(codec); 537372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 538372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 539372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 540372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 541372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool sawInputEOS = false; 542372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool sawOutputEOS = false; 543372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* writePos = static_cast<uint8_t*>(heap->getBase()); 544372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t available = heap->getSize(); 545372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t written = 0; 546372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 547372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 548372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen format = AMediaCodec_getOutputFormat(codec); 549372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 550372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen while (!sawOutputEOS) { 551372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!sawInputEOS) { 552372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000); 5536cd6110773bf83638f21a76d388dc2b7037df0d8Marco Nelissen ALOGV("input buffer %zd", bufidx); 554372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (bufidx >= 0) { 555372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t bufsize; 556372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize); 5570474773aab24594f4f4d395bf058d6f5b16db958Andy Hung if (buf == nullptr) { 5580474773aab24594f4f4d395bf058d6f5b16db958Andy Hung ALOGE("AMediaCodec_getInputBuffer returned nullptr, short decode"); 5590474773aab24594f4f4d395bf058d6f5b16db958Andy Hung break; 5600474773aab24594f4f4d395bf058d6f5b16db958Andy Hung } 561372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize); 562372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("read %d", sampleSize); 563372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sampleSize < 0) { 564372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sampleSize = 0; 565372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawInputEOS = true; 566372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("EOS"); 567372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 568372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex); 569372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 5700474773aab24594f4f4d395bf058d6f5b16db958Andy Hung media_status_t mstatus = AMediaCodec_queueInputBuffer(codec, bufidx, 571372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 0 /* offset */, sampleSize, presentationTimeUs, 572372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0); 5730474773aab24594f4f4d395bf058d6f5b16db958Andy Hung if (mstatus != AMEDIA_OK) { 5740474773aab24594f4f4d395bf058d6f5b16db958Andy Hung // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES } 5750474773aab24594f4f4d395bf058d6f5b16db958Andy Hung ALOGE("AMediaCodec_queueInputBuffer returned status %d, short decode", 5760474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (int)mstatus); 5770474773aab24594f4f4d395bf058d6f5b16db958Andy Hung break; 5780474773aab24594f4f4d395bf058d6f5b16db958Andy Hung } 5790474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaExtractor_advance(ex); 580372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 581372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 582372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 583372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaCodecBufferInfo info; 584372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1); 585372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("dequeueoutput returned: %d", status); 586372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status >= 0) { 587372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) { 588372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("output EOS"); 589372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawOutputEOS = true; 590372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 591372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("got decoded buffer size %d", info.size); 592372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 593372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */); 5940474773aab24594f4f4d395bf058d6f5b16db958Andy Hung if (buf == nullptr) { 5950474773aab24594f4f4d395bf058d6f5b16db958Andy Hung ALOGE("AMediaCodec_getOutputBuffer returned nullptr, short decode"); 5960474773aab24594f4f4d395bf058d6f5b16db958Andy Hung break; 5970474773aab24594f4f4d395bf058d6f5b16db958Andy Hung } 598372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t dataSize = info.size; 599372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (dataSize > available) { 600372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen dataSize = available; 601372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 602372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memcpy(writePos, buf + info.offset, dataSize); 603372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen writePos += dataSize; 604372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen written += dataSize; 605372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen available -= dataSize; 6060474773aab24594f4f4d395bf058d6f5b16db958Andy Hung media_status_t mstatus = AMediaCodec_releaseOutputBuffer( 6070474773aab24594f4f4d395bf058d6f5b16db958Andy Hung codec, status, false /* render */); 6080474773aab24594f4f4d395bf058d6f5b16db958Andy Hung if (mstatus != AMEDIA_OK) { 6090474773aab24594f4f4d395bf058d6f5b16db958Andy Hung // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES } 6100474773aab24594f4f4d395bf058d6f5b16db958Andy Hung ALOGE("AMediaCodec_releaseOutputBuffer returned status %d, short decode", 6110474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (int)mstatus); 6120474773aab24594f4f4d395bf058d6f5b16db958Andy Hung break; 6130474773aab24594f4f4d395bf058d6f5b16db958Andy Hung } 614372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (available == 0) { 615372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // there might be more data, but there's no space for it 616372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sawOutputEOS = true; 617372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 618372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) { 619372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("output buffers changed"); 620372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) { 621372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AMediaFormat_delete(format); 622372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen format = AMediaCodec_getOutputFormat(codec); 623372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("format changed to: %s", AMediaFormat_toString(format)); 624372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) { 625372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("no output buffer right now"); 6262f01c806e06632f8b9db8ea127d704e13811cb8eMarco Nelissen } else if (status <= AMEDIA_ERROR_BASE) { 6272f01c806e06632f8b9db8ea127d704e13811cb8eMarco Nelissen ALOGE("decode error: %d", status); 6282f01c806e06632f8b9db8ea127d704e13811cb8eMarco Nelissen break; 629372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 630372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("unexpected info code: %d", status); 631372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 632372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 633372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 6340474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaCodec_stop(codec); 6350474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaCodec_delete(codec); 6360474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaExtractor_delete(ex); 637372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) || 638372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) { 6390474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaFormat_delete(format); 640372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 641372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 6420474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaFormat_delete(format); 643372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen *memsize = written; 644372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return OK; 645372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 6460474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaFormat_delete(format); 647372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 6480474773aab24594f4f4d395bf058d6f5b16db958Andy Hung (void)AMediaExtractor_delete(ex); 649372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return UNKNOWN_ERROR; 650372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 651372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 652372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenstatus_t Sample::doLoad() 653372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 654372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate; 655372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int numChannels; 656372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen audio_format_t format; 657372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status_t status; 658372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap = new MemoryHeapBase(kDefaultHeapSize); 659372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 660372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Start decode"); 661372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format, 662372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap, &mSize); 663372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("close(%d)", mFd); 664372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ::close(mFd); 665372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFd = -1; 666372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status != NO_ERROR) { 667372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Unable to load sample"); 668372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 669372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 670372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d", 671372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap->getBase(), mSize, sampleRate, numChannels); 672372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 673372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sampleRate > kMaxSampleRate) { 674372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Sample rate (%u) out of range", sampleRate); 675372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = BAD_VALUE; 676372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 677372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 678372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 679bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten if ((numChannels < 1) || (numChannels > FCC_8)) { 680372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGE("Sample channel count (%d) out of range", numChannels); 681372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen status = BAD_VALUE; 682372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen goto error; 683372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 684372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 685372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mData = new MemoryBase(mHeap, 0, mSize); 686372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSampleRate = sampleRate; 687372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNumChannels = numChannels; 688372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mFormat = format; 689372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = READY; 690372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return NO_ERROR; 691372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 692372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenerror: 693372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mHeap.clear(); 694372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return status; 695372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 696372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 697372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 698372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::init(SoundPool* soundPool) 699372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 700372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool = soundPool; 7010c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mPrevSampleID = -1; 702372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 703372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 704372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with sound pool lock held 705372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume, 706372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume, int priority, int loop, float rate) 707372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 708372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<AudioTrack> oldTrack; 709372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<AudioTrack> newTrack; 7100c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung status_t status = NO_ERROR; 711372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 712372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { // scope for the lock 713372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 714372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 715372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f," 716372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen " priority=%d, loop=%d, rate=%f", 717372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, 718372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen priority, loop, rate); 719372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 720372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // if not idle, this voice is being stolen 721372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState != IDLE) { 722372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID); 723372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 724372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen stop_l(); 725372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 726372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 727372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 728372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // initialize track 729372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t afFrameCount; 730372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t afSampleRate; 731372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes()); 732372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { 733372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen afFrameCount = kDefaultFrameCount; 734372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 735372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { 736372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen afSampleRate = kDefaultSampleRate; 737372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 738372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int numChannels = sample->numChannels(); 739372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5); 740372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t frameCount = 0; 741372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 742372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (loop) { 743a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung const audio_format_t format = sample->format(); 744a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung const size_t frameSize = audio_is_linear_pcm(format) 745a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung ? numChannels * audio_bytes_per_sample(format) : 1; 746a1c3516a243d00428ff2b470409d47cc9f5c9523Andy Hung frameCount = sample->size() / frameSize; 747372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 748372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 749372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#ifndef USE_SHARED_MEM_BUFFER 750372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate; 751372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // Ensure minimum audio buffer size in case of short looped sample 752372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if(frameCount < totalFrames) { 753372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen frameCount = totalFrames; 754372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 755372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen#endif 756372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 75732ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung // check if the existing track has the same sample id. 75832ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (mAudioTrack != 0 && mPrevSampleID == sample->sampleID()) { 75932ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung // the sample rate may fail to change if the audio track is a fast track. 76032ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) { 76132ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung newTrack = mAudioTrack; 76232ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID()); 76332ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung } 76432ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung } 76532ccb69fdeeeb236d9c5f2a4335b44d1d0c4b042Andy Hung if (newTrack == 0) { 7660c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // mToggle toggles each time a track is started on a given channel. 7670c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // The toggle is concatenated with the SoundChannel address and passed to AudioTrack 7680c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // as callback user data. This enables the detection of callbacks received from the old 7690c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // audio track while the new one is being started and avoids processing them with 7700c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // wrong audio audio buffer size (mAudioBufferSize) 7710c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung unsigned long toggle = mToggle ^ 1; 7720c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung void *userData = (void *)((unsigned long)this | toggle); 7730c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels); 7740c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung 7750c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // do not create a new audio track if current track is compatible with sample parameters 7760c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #ifdef USE_SHARED_MEM_BUFFER 7770c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 7786c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData, 7796c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi 0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE, 7806c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi AudioTrack::TRANSFER_DEFAULT, 7816c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes()); 7820c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #else 7830c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount; 7840c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung newTrack = new AudioTrack(streamType, sampleRate, sample->format(), 7850c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData, 7866c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi bufferFrames, AUDIO_SESSION_ALLOCATE, AudioTrack::TRANSFER_DEFAULT, 7876c307879b75f3eac2179b23ac309df0e4ce9ceddJean-Michel Trivi NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes()); 7880c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung #endif 7890c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung oldTrack = mAudioTrack; 7900c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung status = newTrack->initCheck(); 7910c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung if (status != NO_ERROR) { 7920c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung ALOGE("Error creating AudioTrack"); 79314d226a2cd7b39e17a3f0bfdab79e645f7146f53Glenn Kasten // newTrack goes out of scope, so reference count drops to zero 7940c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung goto exit; 7950c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung } 7960c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung // From now on, AudioTrack callbacks received with previous toggle value will be ignored. 7970c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mToggle = toggle; 7980c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mAudioTrack = newTrack; 799bc4537393b02b39433e07fed4ed57186d8e5959fAndy Hung ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID()); 800372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 801372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen newTrack->setVolume(leftVolume, rightVolume); 802372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen newTrack->setLoop(0, frameCount, loop); 803372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPos = 0; 804372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample = sample; 805372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelID = nextChannelID; 806372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = priority; 807372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 808372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 809372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 810372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mNumChannels = numChannels; 811372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate = rate; 812372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen clearNextEvent(); 813372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 814372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 815372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize(); 816372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 817372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 818372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenexit: 819372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("delete oldTrack %p", oldTrack.get()); 820372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (status != NO_ERROR) { 821372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack.clear(); 822372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 823372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 824372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 825372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::nextEvent() 826372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 827372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample; 828372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int nextChannelID; 829372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float leftVolume; 830372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume; 831372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int priority; 832372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen int loop; 833372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rate; 834372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 835372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // check for valid event 836372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 837372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 838372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen nextChannelID = mNextEvent.channelID(); 839372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (nextChannelID == 0) { 840372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stolen channel has no event"); 841372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 842372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 843372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 844372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sample = mNextEvent.sample(); 845372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen leftVolume = mNextEvent.leftVolume(); 846372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen rightVolume = mNextEvent.rightVolume(); 847372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen priority = mNextEvent.priority(); 848372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen loop = mNextEvent.loop(); 849372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen rate = mNextEvent.rate(); 850372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 851372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 852372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID); 853372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate); 854372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 855372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 856372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::callback(int event, void* user, void *info) 857372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 858372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1)); 859372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 860372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen channel->process(event, info, (unsigned long)user & 1); 861372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 862372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 863372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::process(int event, void *info, unsigned long toggle) 864372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 865372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen //ALOGV("process(%d)", mChannelID); 866372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 867372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 868372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 869372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen AudioTrack::Buffer* b = NULL; 870372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (event == AudioTrack::EVENT_MORE_DATA) { 871372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b = static_cast<AudioTrack::Buffer *>(info); 872372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 873372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 874372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mToggle != toggle) { 875372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process wrong toggle %p channel %d", this, mChannelID); 876372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (b != NULL) { 877372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = 0; 878372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 879372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 880372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 881372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 882372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen sp<Sample> sample = mSample; 883372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 884372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("SoundChannel::process event %d", event); 885372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 886372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (event == AudioTrack::EVENT_MORE_DATA) { 887372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 888372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // check for stop state 889372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (b->size == 0) return; 890372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 891372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == IDLE) { 892372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = 0; 893372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return; 894372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 895372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 896372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (sample != 0) { 897372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // fill buffer 898372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* q = (uint8_t*) b->i8; 899372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen size_t count = 0; 900372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 901372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mPos < (int)sample->size()) { 902372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint8_t* p = sample->data() + mPos; 903372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = sample->size() - mPos; 904372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (count > b->size) { 905372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = b->size; 906372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 907372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memcpy(q, p, count); 908372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, 909372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// count); 910372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (mPos < mAudioBufferSize) { 911372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = mAudioBufferSize - mPos; 912372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (count > b->size) { 913372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen count = b->size; 914372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 915372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen memset(q, 0, count); 916372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count); 917372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 918372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 919372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPos += count; 920372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen b->size = count; 921372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]); 922372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 923372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) { 924372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process %p channel %d event %s", 925372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" : 926372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen "BUFFER_END"); 927372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->addToStopList(this); 928372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_LOOP_END) { 929372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("End loop %p channel %d", this, mChannelID); 930372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) { 931372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID); 932372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } else { 933372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGW("SoundChannel::process unexpected event %d", event); 934372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 935372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 936372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 937372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 938372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 939372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenbool SoundChannel::doStop_l() 940372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 941372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState != IDLE) { 942372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen setVolume_l(0, 0); 943372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("stop"); 944372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->stop(); 9450c4b81bd3ef3fd5eb0f7d1b8e2c6168b95020134Andy Hung mPrevSampleID = mSample->sampleID(); 946372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample.clear(); 947372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = IDLE; 948372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = IDLE_PRIORITY; 949372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return true; 950372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 951372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen return false; 952372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 953372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 954372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held and sound pool lock held 955372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::stop_l() 956372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 957372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (doStop_l()) { 958372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->done_l(this); 959372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 960372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 961372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 962372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with sound pool lock held 963372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::stop() 964372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 965372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen bool stopped; 966372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 967372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 968372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen stopped = doStop_l(); 969372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 970372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 971372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (stopped) { 972372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSoundPool->done_l(this); 973372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 974372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 975372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 976372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen//FIXME: Pause is a little broken right now 977372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::pause() 978372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 979372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 980372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PLAYING) { 981372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause track"); 982372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PAUSED; 983372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->pause(); 984372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 985372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 986372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 987372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::autoPause() 988372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 989372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 990372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PLAYING) { 991372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("pause track"); 992372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PAUSED; 993372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = true; 994372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->pause(); 995372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 996372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 997372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 998372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::resume() 999372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1000372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1001372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mState == PAUSED) { 1002372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume track"); 1003372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 1004372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = false; 1005372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 1006372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1007372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1008372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1009372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::autoResume() 1010372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1011372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1012372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAutoPaused && (mState == PAUSED)) { 1013372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("resume track"); 1014372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState = PLAYING; 1015372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAutoPaused = false; 1016372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->start(); 1017372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1018372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1019372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1020372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setRate(float rate) 1021372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1022372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1023372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL && mSample != 0) { 1024372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5); 1025372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setSampleRate(sampleRate); 1026372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate = rate; 1027372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1028372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1029372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1030372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen// call with lock held 1031372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setVolume_l(float leftVolume, float rightVolume) 1032372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1033372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 1034372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 1035372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL) 1036372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setVolume(leftVolume, rightVolume); 1037372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1038372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1039372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setVolume(float leftVolume, float rightVolume) 1040372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1041372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1042372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen setVolume_l(leftVolume, rightVolume); 1043372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1044372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1045372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::setLoop(int loop) 1046372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1047372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1048372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen if (mAudioTrack != NULL && mSample != 0) { 1049372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen uint32_t loopEnd = mSample->size()/mNumChannels/ 1050372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)); 1051372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack->setLoop(0, loopEnd, loop); 1052372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 1053372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1054372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1055372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1056372be8970c6ab68c295fb74dbb878ab1d443d90eMarco NelissenSoundChannel::~SoundChannel() 1057372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1058372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("SoundChannel destructor %p", this); 1059372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen { 1060372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen Mutex::Autolock lock(&mLock); 1061372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen clearNextEvent(); 1062372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen doStop_l(); 1063372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen } 1064372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack 1065372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen // callback thread to exit which may need to execute process() and acquire the mLock. 1066372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mAudioTrack.clear(); 1067372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1068372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1069372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundChannel::dump() 1070372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1071372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d", 1072372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mState, mChannelID, mNumChannels, mPos, mPriority, mLoop); 1073372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1074372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1075372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissenvoid SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume, 1076372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen float rightVolume, int priority, int loop, float rate) 1077372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen{ 1078372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mSample = sample; 1079372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mChannelID = channelID; 1080372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLeftVolume = leftVolume; 1081372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRightVolume = rightVolume; 1082372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mPriority = priority; 1083372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mLoop = loop; 1084372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen mRate =rate; 1085372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} 1086372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen 1087372be8970c6ab68c295fb74dbb878ab1d443d90eMarco Nelissen} // end namespace android 1088