Home | History | Annotate | Download | only in soundpool
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef SOUNDPOOL_H_
     18 #define SOUNDPOOL_H_
     19 
     20 #include <utils/threads.h>
     21 #include <utils/List.h>
     22 #include <utils/Vector.h>
     23 #include <utils/KeyedVector.h>
     24 #include <media/AudioTrack.h>
     25 #include <binder/MemoryHeapBase.h>
     26 #include <binder/MemoryBase.h>
     27 
     28 namespace android {
     29 
     30 static const int IDLE_PRIORITY = -1;
     31 
     32 // forward declarations
     33 class SoundEvent;
     34 class SoundPoolThread;
     35 class SoundPool;
     36 
     37 // for queued events
     38 class SoundPoolEvent {
     39 public:
     40     SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
     41         mMsg(msg), mArg1(arg1), mArg2(arg2) {}
     42     int         mMsg;
     43     int         mArg1;
     44     int         mArg2;
     45     enum MessageType { INVALID, SAMPLE_LOADED };
     46 };
     47 
     48 // callback function prototype
     49 typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
     50 
     51 // tracks samples used by application
     52 class Sample  : public RefBase {
     53 public:
     54     enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
     55     Sample(int sampleID, int fd, int64_t offset, int64_t length);
     56     ~Sample();
     57     int sampleID() { return mSampleID; }
     58     int numChannels() { return mNumChannels; }
     59     int sampleRate() { return mSampleRate; }
     60     audio_format_t format() { return mFormat; }
     61     size_t size() { return mSize; }
     62     int state() { return mState; }
     63     uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
     64     status_t doLoad();
     65     void startLoad() { mState = LOADING; }
     66     sp<IMemory> getIMemory() { return mData; }
     67 
     68 private:
     69     void init();
     70 
     71     size_t              mSize;
     72     volatile int32_t    mRefCount;
     73     uint16_t            mSampleID;
     74     uint16_t            mSampleRate;
     75     uint8_t             mState;
     76     uint8_t             mNumChannels;
     77     audio_format_t      mFormat;
     78     int                 mFd;
     79     int64_t             mOffset;
     80     int64_t             mLength;
     81     sp<IMemory>         mData;
     82     sp<MemoryHeapBase>  mHeap;
     83 };
     84 
     85 // stores pending events for stolen channels
     86 class SoundEvent
     87 {
     88 public:
     89     SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
     90             mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
     91     void set(const sp<Sample>& sample, int channelID, float leftVolume,
     92             float rightVolume, int priority, int loop, float rate);
     93     sp<Sample>      sample() { return mSample; }
     94     int             channelID() { return mChannelID; }
     95     float           leftVolume() { return mLeftVolume; }
     96     float           rightVolume() { return mRightVolume; }
     97     int             priority() { return mPriority; }
     98     int             loop() { return mLoop; }
     99     float           rate() { return mRate; }
    100     void            clear() { mChannelID = 0; mSample.clear(); }
    101 
    102 protected:
    103     sp<Sample>      mSample;
    104     int             mChannelID;
    105     float           mLeftVolume;
    106     float           mRightVolume;
    107     int             mPriority;
    108     int             mLoop;
    109     float           mRate;
    110 };
    111 
    112 // for channels aka AudioTracks
    113 class SoundChannel : public SoundEvent {
    114 public:
    115     enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
    116     SoundChannel() : mState(IDLE), mNumChannels(1),
    117             mPos(0), mToggle(0), mAutoPaused(false) {}
    118     ~SoundChannel();
    119     void init(SoundPool* soundPool);
    120     void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
    121             int priority, int loop, float rate);
    122     void setVolume_l(float leftVolume, float rightVolume);
    123     void setVolume(float leftVolume, float rightVolume);
    124     void stop_l();
    125     void stop();
    126     void pause();
    127     void autoPause();
    128     void resume();
    129     void autoResume();
    130     void setRate(float rate);
    131     int state() { return mState; }
    132     void setPriority(int priority) { mPriority = priority; }
    133     void setLoop(int loop);
    134     int numChannels() { return mNumChannels; }
    135     void clearNextEvent() { mNextEvent.clear(); }
    136     void nextEvent();
    137     int nextChannelID() { return mNextEvent.channelID(); }
    138     void dump();
    139     int getPrevSampleID(void) { return mPrevSampleID; }
    140 
    141 private:
    142     static void callback(int event, void* user, void *info);
    143     void process(int event, void *info, unsigned long toggle);
    144     bool doStop_l();
    145 
    146     SoundPool*          mSoundPool;
    147     sp<AudioTrack>      mAudioTrack;
    148     SoundEvent          mNextEvent;
    149     Mutex               mLock;
    150     int                 mState;
    151     int                 mNumChannels;
    152     int                 mPos;
    153     int                 mAudioBufferSize;
    154     unsigned long       mToggle;
    155     bool                mAutoPaused;
    156     int                 mPrevSampleID;
    157 };
    158 
    159 // application object for managing a pool of sounds
    160 class SoundPool {
    161     friend class SoundPoolThread;
    162     friend class SoundChannel;
    163 public:
    164     SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
    165     ~SoundPool();
    166     int load(int fd, int64_t offset, int64_t length, int priority);
    167     bool unload(int sampleID);
    168     int play(int sampleID, float leftVolume, float rightVolume, int priority,
    169             int loop, float rate);
    170     void pause(int channelID);
    171     void autoPause();
    172     void resume(int channelID);
    173     void autoResume();
    174     void stop(int channelID);
    175     void setVolume(int channelID, float leftVolume, float rightVolume);
    176     void setPriority(int channelID, int priority);
    177     void setLoop(int channelID, int loop);
    178     void setRate(int channelID, float rate);
    179     const audio_attributes_t* attributes() { return &mAttributes; }
    180 
    181     // called from SoundPoolThread
    182     void sampleLoaded(int sampleID);
    183     sp<Sample> findSample(int sampleID);
    184 
    185     // called from AudioTrack thread
    186     void done_l(SoundChannel* channel);
    187 
    188     // callback function
    189     void setCallback(SoundPoolCallback* callback, void* user);
    190     void* getUserData() { return mUserData; }
    191 
    192 private:
    193     SoundPool() {} // no default constructor
    194     bool startThreads();
    195     sp<Sample> findSample_l(int sampleID);
    196     SoundChannel* findChannel (int channelID);
    197     SoundChannel* findNextChannel (int channelID);
    198     SoundChannel* allocateChannel_l(int priority, int sampleID);
    199     void moveToFront_l(SoundChannel* channel);
    200     void notify(SoundPoolEvent event);
    201     void dump();
    202 
    203     // restart thread
    204     void addToRestartList(SoundChannel* channel);
    205     void addToStopList(SoundChannel* channel);
    206     static int beginThread(void* arg);
    207     int run();
    208     void quit();
    209 
    210     Mutex                   mLock;
    211     Mutex                   mRestartLock;
    212     Condition               mCondition;
    213     SoundPoolThread*        mDecodeThread;
    214     SoundChannel*           mChannelPool;
    215     List<SoundChannel*>     mChannels;
    216     List<SoundChannel*>     mRestart;
    217     List<SoundChannel*>     mStop;
    218     DefaultKeyedVector< int, sp<Sample> >   mSamples;
    219     int                     mMaxChannels;
    220     audio_attributes_t      mAttributes;
    221     int                     mAllocated;
    222     int                     mNextSampleID;
    223     int                     mNextChannelID;
    224     bool                    mQuit;
    225 
    226     // callback
    227     Mutex                   mCallbackLock;
    228     SoundPoolCallback*      mCallback;
    229     void*                   mUserData;
    230 };
    231 
    232 } // end namespace android
    233 
    234 #endif /*SOUNDPOOL_H_*/
    235