12e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent/*
22e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * Copyright (C) 2007 The Android Open Source Project
32e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent *
42e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
52e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * you may not use this file except in compliance with the License.
62e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * You may obtain a copy of the License at
72e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent *
82e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
92e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent *
102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * Unless required by applicable law or agreed to in writing, software
112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * See the License for the specific language governing permissions and
142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent * limitations under the License.
152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent */
162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent//#define LOG_NDEBUG 0
182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#define LOG_TAG "SoundPool"
192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include <utils/Log.h>
202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent//#define USE_SHARED_MEM_BUFFER
222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent// XXX needed for timing latency
242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include <utils/Timers.h>
252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include <media/AudioTrack.h>
272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include <media/mediaplayer.h>
282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include <system/audio.h>
302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
31559bf2836f5da25b75bfb229fec0d20d540ee426James Dong#include <media/SoundPool.h>
322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#include "SoundPoolThread.h"
332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentnamespace android
352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint kDefaultBufferCount = 4;
382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentuint32_t kMaxSampleRate = 48000;
392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentuint32_t kDefaultSampleRate = 44100;
402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentuint32_t kDefaultFrameCount = 1200;
412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality)
432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d",
452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            maxChannels, streamType, srcQuality);
462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // check limits
482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mMaxChannels = maxChannels;
492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mMaxChannels < 1) {
502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mMaxChannels = 1;
512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    else if (mMaxChannels > 32) {
532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mMaxChannels = 32;
542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mQuit = false;
582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mDecodeThread = 0;
592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mStreamType = streamType;
602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSrcQuality = srcQuality;
612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mAllocated = 0;
622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mNextSampleID = 0;
632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mNextChannelID = 0;
642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mCallback = 0;
662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mUserData = 0;
672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mChannelPool = new SoundChannel[mMaxChannels];
692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mChannelPool[i].init(this);
712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mChannels.push_back(&mChannelPool[i]);
722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // start decode thread
752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    startThreads();
762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSoundPool::~SoundPool()
792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("SoundPool destructor");
812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mDecodeThread->quit();
822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    quit();
832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mChannels.clear();
872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mChannelPool)
882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        delete [] mChannelPool;
892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // clean up samples
902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("clear samples");
912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSamples.clear();
922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mDecodeThread)
942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        delete mDecodeThread;
952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::addToRestartList(SoundChannel* channel)
982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mRestartLock);
1002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (!mQuit) {
1012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mRestart.push_back(channel);
1022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mCondition.signal();
1032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
1042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::addToStopList(SoundChannel* channel)
1072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mRestartLock);
1092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (!mQuit) {
1102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mStop.push_back(channel);
1112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mCondition.signal();
1122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
1132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint SoundPool::beginThread(void* arg)
1162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundPool* p = (SoundPool*)arg;
1182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return p->run();
1192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint SoundPool::run()
1222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRestartLock.lock();
1242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    while (!mQuit) {
1252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mCondition.wait(mRestartLock);
1262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("awake");
1272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (mQuit) break;
1282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        while (!mStop.empty()) {
1302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            SoundChannel* channel;
1312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGV("Getting channel from stop list");
1322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            List<SoundChannel* >::iterator iter = mStop.begin();
1332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            channel = *iter;
1342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mStop.erase(iter);
1352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mRestartLock.unlock();
1362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (channel != 0) {
1372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                Mutex::Autolock lock(&mLock);
1382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                channel->stop();
1392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            }
1402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mRestartLock.lock();
1412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (mQuit) break;
1422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
1432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        while (!mRestart.empty()) {
1452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            SoundChannel* channel;
1462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGV("Getting channel from list");
1472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            List<SoundChannel*>::iterator iter = mRestart.begin();
1482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            channel = *iter;
1492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mRestart.erase(iter);
1502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mRestartLock.unlock();
1512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (channel != 0) {
1522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                Mutex::Autolock lock(&mLock);
1532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                channel->nextEvent();
1542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            }
1552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mRestartLock.lock();
1562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (mQuit) break;
1572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
1582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
1592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mStop.clear();
1612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRestart.clear();
1622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mCondition.signal();
1632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRestartLock.unlock();
1642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("goodbye");
1652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return 0;
1662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::quit()
1692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRestartLock.lock();
1712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mQuit = true;
1722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mCondition.signal();
1732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mCondition.wait(mRestartLock);
1742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("return from quit");
1752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRestartLock.unlock();
1762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentbool SoundPool::startThreads()
1792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    createThreadEtc(beginThread, this, "SoundPool");
1812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mDecodeThread == NULL)
1822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mDecodeThread = new SoundPoolThread(this);
1832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return mDecodeThread != NULL;
1842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSoundChannel* SoundPool::findChannel(int channelID)
1872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
1892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (mChannelPool[i].channelID() == channelID) {
1902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            return &mChannelPool[i];
1912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
1922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
1932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return NULL;
1942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
1952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
1962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSoundChannel* SoundPool::findNextChannel(int channelID)
1972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
1982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
1992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (mChannelPool[i].nextChannelID() == channelID) {
2002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            return &mChannelPool[i];
2012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
2022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
2032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return NULL;
2042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint SoundPool::load(const char* path, int priority)
2072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("load: path=%s, priority=%d", path, priority);
2092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
2102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<Sample> sample = new Sample(++mNextSampleID, path);
2112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSamples.add(sample->sampleID(), sample);
2122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    doLoad(sample);
2132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return sample->sampleID();
2142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint SoundPool::load(int fd, int64_t offset, int64_t length, int priority)
2172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d",
2192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            fd, offset, length, priority);
2202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
2212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
2222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSamples.add(sample->sampleID(), sample);
2232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    doLoad(sample);
2242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return sample->sampleID();
2252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::doLoad(sp<Sample>& sample)
2282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
2302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sample->startLoad();
2312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mDecodeThread->loadSample(sample->sampleID());
2322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentbool SoundPool::unload(int sampleID)
2352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("unload: sampleID=%d", sampleID);
2372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
2382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return mSamples.removeItem(sampleID);
2392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentint SoundPool::play(int sampleID, float leftVolume, float rightVolume,
2422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        int priority, int loop, float rate)
2432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
2452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            sampleID, leftVolume, rightVolume, priority, loop, rate);
2462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<Sample> sample;
2472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel;
2482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    int channelID;
2492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
2512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mQuit) {
2532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return 0;
2542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
2552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // is sample ready?
2562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sample = findSample(sampleID);
2572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if ((sample == 0) || (sample->state() != Sample::READY)) {
2582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGW("  sample %d not READY", sampleID);
2592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return 0;
2602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
2612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    dump();
2632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // allocate a channel
2652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    channel = allocateChannel_l(priority);
2662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // no channel allocated - return 0
2682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (!channel) {
2692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("No channel allocated");
2702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return 0;
2712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
2722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    channelID = ++mNextChannelID;
2742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("play channel %p state = %d", channel, channel->state());
2762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
2772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return channelID;
2782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
2792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSoundChannel* SoundPool::allocateChannel_l(int priority)
2812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
2822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    List<SoundChannel*>::iterator iter;
2832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = NULL;
2842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // allocate a channel
2862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (!mChannels.empty()) {
2872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        iter = mChannels.begin();
2882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (priority >= (*iter)->priority()) {
2892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            channel = *iter;
2902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mChannels.erase(iter);
2912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGV("Allocated active channel");
2922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
2932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
2942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
2952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // update priority and put it back in the list
2962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
2972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->setPriority(priority);
2982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
2992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (priority < (*iter)->priority()) {
3002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                break;
3012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            }
3022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
3032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mChannels.insert(iter, channel);
3042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return channel;
3062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent// move a channel from its current position to the front of the list
3092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::moveToFront_l(SoundChannel* channel)
3102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
3122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (*iter == channel) {
3132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mChannels.erase(iter);
3142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mChannels.push_front(channel);
3152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            break;
3162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
3172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::pause(int channelID)
3212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("pause(%d)", channelID);
3232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->pause();
3272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::autoPause()
3312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("autoPause()");
3332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
3352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        SoundChannel* channel = &mChannelPool[i];
3362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->autoPause();
3372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::resume(int channelID)
3412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("resume(%d)", channelID);
3432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->resume();
3472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::autoResume()
3512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("autoResume()");
3532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
3552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        SoundChannel* channel = &mChannelPool[i];
3562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->autoResume();
3572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::stop(int channelID)
3612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("stop(%d)", channelID);
3632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->stop();
3672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    } else {
3682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel = findNextChannel(channelID);
3692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (channel)
3702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            channel->clearNextEvent();
3712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
3752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->setVolume(leftVolume, rightVolume);
3802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::setPriority(int channelID, int priority)
3842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("setPriority(%d, %d)", channelID, priority);
3862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->setPriority(priority);
3902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
3912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
3922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
3932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::setLoop(int channelID, int loop)
3942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
3952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("setLoop(%d, %d)", channelID, loop);
3962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
3972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
3982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
3992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->setLoop(loop);
4002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::setRate(int channelID, float rate)
4042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("setRate(%d, %f)", channelID, rate);
4062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
4072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = findChannel(channelID);
4082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel) {
4092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        channel->setRate(rate);
4102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent// call with lock held
4142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::done_l(SoundChannel* channel)
4152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("done_l(%d)", channel->channelID());
4172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // if "stolen", play next event
4182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (channel->nextChannelID() != 0) {
4192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("add to restart list");
4202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        addToRestartList(channel);
4212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // return to idle state
4242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    else {
4252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("move to front");
4262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        moveToFront_l(channel);
4272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::setCallback(SoundPoolCallback* callback, void* user)
4312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mCallbackLock);
4332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mCallback = callback;
4342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mUserData = user;
4352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::notify(SoundPoolEvent event)
4382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mCallbackLock);
4402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mCallback != NULL) {
4412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mCallback(event, this, mUserData);
4422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundPool::dump()
4462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    for (int i = 0; i < mMaxChannels; ++i) {
4482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mChannelPool[i].dump();
4492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSample::Sample(int sampleID, const char* url)
4542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    init();
4562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSampleID = sampleID;
4572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mUrl = strdup(url);
4582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
4592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
4622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    init();
4642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSampleID = sampleID;
4652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mFd = dup(fd);
4662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mOffset = offset;
4672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mLength = length;
4682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset);
4692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid Sample::init()
4722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mData = 0;
4742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSize = 0;
4752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mRefCount = 0;
4762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSampleID = 0;
4772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mState = UNLOADED;
4782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mFd = -1;
4792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mOffset = 0;
4802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mLength = 0;
4812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mUrl = 0;
4822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric LaurentSample::~Sample()
4852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
4872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mFd > 0) {
4882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("close(%d)", mFd);
4892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ::close(mFd);
4902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
4912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mData.clear();
4922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    delete mUrl;
4932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
4942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
4952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentstatus_t Sample::doLoad()
4962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
4972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    uint32_t sampleRate;
4982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    int numChannels;
4992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    audio_format_t format;
5002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<IMemory> p;
5012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("Start decode");
5022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mUrl) {
5032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format);
5042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    } else {
5052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format);
5062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("close(%d)", mFd);
5072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ::close(mFd);
5082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mFd = -1;
5092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
5102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (p == 0) {
5112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGE("Unable to load sample: %s", mUrl);
5122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return -1;
5132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
5142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d",
5152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            p->pointer(), p->size(), sampleRate, numChannels);
5162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (sampleRate > kMaxSampleRate) {
5182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent       ALOGE("Sample rate (%u) out of range", sampleRate);
5192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent       return - 1;
5202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
5212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if ((numChannels < 1) || (numChannels > 2)) {
5232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGE("Sample channel count (%d) out of range", numChannels);
5242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return - 1;
5252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
5262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    //_dumpBuffer(p->pointer(), p->size());
5282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10;
5292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    //_dumpBuffer(q, 10, 10, false);
5302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mData = p;
5322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSize = p->size();
5332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSampleRate = sampleRate;
5342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mNumChannels = numChannels;
5352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mFormat = format;
5362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mState = READY;
5372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    return 0;
5382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
5392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundChannel::init(SoundPool* soundPool)
5422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
5432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    mSoundPool = soundPool;
5442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
5452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent// call with sound pool lock held
5472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
5482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        float rightVolume, int priority, int loop, float rate)
5492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
5502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    AudioTrack* oldTrack;
5512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    AudioTrack* newTrack;
5522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    status_t status;
5532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    { // scope for the lock
5552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        Mutex::Autolock lock(&mLock);
5562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
5582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                " priority=%d, loop=%d, rate=%f",
5592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
5602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                priority, loop, rate);
5612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // if not idle, this voice is being stolen
5632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (mState != IDLE) {
5642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
5652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
5662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            stop_l();
5672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            return;
5682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
5692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // initialize track
5712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        int afFrameCount;
5722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        int afSampleRate;
5732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        audio_stream_type_t streamType = mSoundPool->streamType();
5742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
5752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            afFrameCount = kDefaultFrameCount;
5762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
5772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
5782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            afSampleRate = kDefaultSampleRate;
5792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
5802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        int numChannels = sample->numChannels();
5812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
5822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
5832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
5842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        uint32_t frameCount = 0;
5852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (loop) {
5872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            frameCount = sample->size()/numChannels/
5882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
5892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
5902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#ifndef USE_SHARED_MEM_BUFFER
5922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // Ensure minimum audio buffer size in case of short looped sample
5932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if(frameCount < totalFrames) {
5942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            frameCount = totalFrames;
5952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
5962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#endif
5972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
5982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // mToggle toggles each time a track is started on a given channel.
5992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
6002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // as callback user data. This enables the detection of callbacks received from the old
6012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // audio track while the new one is being started and avoids processing them with
6022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // wrong audio audio buffer size  (mAudioBufferSize)
6032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        unsigned long toggle = mToggle ^ 1;
6042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        void *userData = (void *)((unsigned long)this | toggle);
6052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        uint32_t channels = (numChannels == 2) ?
6062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO;
6072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // do not create a new audio track if current track is compatible with sample parameters
6092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#ifdef USE_SHARED_MEM_BUFFER
6102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
6110ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent                channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_NONE, callback, userData);
6122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#else
6132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
6141477e92867a950016579a644e74f803ed1d90cbbGlenn Kasten                channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
6152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                bufferFrames);
6162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent#endif
6172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        oldTrack = mAudioTrack;
6182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        status = newTrack->initCheck();
6192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (status != NO_ERROR) {
6202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGE("Error creating AudioTrack");
6212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            goto exit;
6222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
6232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("setVolume %p", newTrack);
6242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        newTrack->setVolume(leftVolume, rightVolume);
6252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        newTrack->setLoop(0, frameCount, loop);
6262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
6282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mToggle = toggle;
6292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mAudioTrack = newTrack;
6302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mPos = 0;
6312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mSample = sample;
6322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mChannelID = nextChannelID;
6332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mPriority = priority;
6342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mLoop = loop;
6352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mLeftVolume = leftVolume;
6362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mRightVolume = rightVolume;
6372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mNumChannels = numChannels;
6382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mRate = rate;
6392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        clearNextEvent();
6402e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mState = PLAYING;
6412e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mAudioTrack->start();
6422e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
6432e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
6442e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6452e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentexit:
6462e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("delete oldTrack %p", oldTrack);
6472e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    delete oldTrack;
6482e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (status != NO_ERROR) {
6492e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        delete newTrack;
6502e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        mAudioTrack = NULL;
6512e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
6522e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
6532e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6542e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundChannel::nextEvent()
6552e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
6562e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<Sample> sample;
6572e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    int nextChannelID;
6582e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    float leftVolume;
6592e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    float rightVolume;
6602e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    int priority;
6612e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    int loop;
6622e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    float rate;
6632e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6642e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    // check for valid event
6652e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    {
6662e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        Mutex::Autolock lock(&mLock);
6672e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        nextChannelID = mNextEvent.channelID();
6682e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (nextChannelID  == 0) {
6692e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            ALOGV("stolen channel has no event");
6702e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            return;
6712e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
6722e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6732e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        sample = mNextEvent.sample();
6742e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        leftVolume = mNextEvent.leftVolume();
6752e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        rightVolume = mNextEvent.rightVolume();
6762e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        priority = mNextEvent.priority();
6772e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        loop = mNextEvent.loop();
6782e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        rate = mNextEvent.rate();
6792e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
6802e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6812e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
6822e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
6832e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
6842e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6852e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundChannel::callback(int event, void* user, void *info)
6862e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
6872e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
6882e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6892e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    channel->process(event, info, (unsigned long)user & 1);
6902e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent}
6912e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6922e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurentvoid SoundChannel::process(int event, void *info, unsigned long toggle)
6932e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent{
6942e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    //ALOGV("process(%d)", mChannelID);
6952e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6962e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    Mutex::Autolock lock(&mLock);
6972e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
6982e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    AudioTrack::Buffer* b = NULL;
6992e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (event == AudioTrack::EVENT_MORE_DATA) {
7002e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent       b = static_cast<AudioTrack::Buffer *>(info);
7012e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
7022e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7032e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (mToggle != toggle) {
7042e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        ALOGV("process wrong toggle %p channel %d", this, mChannelID);
7052e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (b != NULL) {
7062e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            b->size = 0;
7072e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
7082e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        return;
7092e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    }
7102e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7112e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    sp<Sample> sample = mSample;
7122e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7132e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent//    ALOGV("SoundChannel::process event %d", event);
7142e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7152e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent    if (event == AudioTrack::EVENT_MORE_DATA) {
7162e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7172e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        // check for stop state
7182e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (b->size == 0) return;
7192e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7202e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (mState == IDLE) {
7212e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            b->size = 0;
7222e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            return;
7232e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        }
7242e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7252e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent        if (sample != 0) {
7262e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            // fill buffer
7272e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            uint8_t* q = (uint8_t*) b->i8;
7282e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            size_t count = 0;
7292e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent
7302e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            if (mPos < (int)sample->size()) {
7312e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                uint8_t* p = sample->data() + mPos;
7322e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                count = sample->size() - mPos;
7332e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                if (count > b->size) {
7342e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                    count = b->size;
7352e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                }
7362e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent                memcpy(q, p, count);
7372e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent//              ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count);
7382e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent            } else if (mPos < mAudioBufferSize) {
7392e66a7896c9a9da3a15fc6cff9be28b4174d8719Eric Laurent