SoundPool.h revision 3d00aa6de95fb46e36f2bab4e3facdf0b96acf06
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
28namespace android {
29
30static const int IDLE_PRIORITY = -1;
31
32// forward declarations
33class SoundEvent;
34class SoundPoolThread;
35class SoundPool;
36
37// for queued events
38class SoundPoolEvent {
39public:
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
49typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
50
51// tracks samples used by application
52class Sample  : public RefBase {
53public:
54    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
55    Sample(int sampleID, const char* url);
56    Sample(int sampleID, int fd, int64_t offset, int64_t length);
57    ~Sample();
58    int sampleID() { return mSampleID; }
59    int numChannels() { return mNumChannels; }
60    int sampleRate() { return mSampleRate; }
61    audio_format_t format() { return mFormat; }
62    size_t size() { return mSize; }
63    int state() { return mState; }
64    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
65    status_t doLoad();
66    void startLoad() { mState = LOADING; }
67    sp<IMemory> getIMemory() { return mData; }
68
69    // hack
70    void init(int numChannels, int sampleRate, audio_format_t format, size_t size,
71            sp<IMemory> data ) {
72        mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size;
73            mData = data; }
74
75private:
76    void init();
77
78    size_t              mSize;
79    volatile int32_t    mRefCount;
80    uint16_t            mSampleID;
81    uint16_t            mSampleRate;
82    uint8_t             mState : 3;
83    uint8_t             mNumChannels : 2;
84    audio_format_t      mFormat;
85    int                 mFd;
86    int64_t             mOffset;
87    int64_t             mLength;
88    char*               mUrl;
89    sp<IMemory>         mData;
90    sp<MemoryHeapBase>  mHeap;
91};
92
93// stores pending events for stolen channels
94class SoundEvent
95{
96public:
97    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
98            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
99    void set(const sp<Sample>& sample, int channelID, float leftVolume,
100            float rightVolume, int priority, int loop, float rate);
101    sp<Sample>      sample() { return mSample; }
102    int             channelID() { return mChannelID; }
103    float           leftVolume() { return mLeftVolume; }
104    float           rightVolume() { return mRightVolume; }
105    int             priority() { return mPriority; }
106    int             loop() { return mLoop; }
107    float           rate() { return mRate; }
108    void            clear() { mChannelID = 0; mSample.clear(); }
109
110protected:
111    sp<Sample>      mSample;
112    int             mChannelID;
113    float           mLeftVolume;
114    float           mRightVolume;
115    int             mPriority;
116    int             mLoop;
117    float           mRate;
118};
119
120// for channels aka AudioTracks
121class SoundChannel : public SoundEvent {
122public:
123    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
124    SoundChannel() : mState(IDLE), mNumChannels(1),
125            mPos(0), mToggle(0), mAutoPaused(false) {}
126    ~SoundChannel();
127    void init(SoundPool* soundPool);
128    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
129            int priority, int loop, float rate);
130    void setVolume_l(float leftVolume, float rightVolume);
131    void setVolume(float leftVolume, float rightVolume);
132    void stop_l();
133    void stop();
134    void pause();
135    void autoPause();
136    void resume();
137    void autoResume();
138    void setRate(float rate);
139    int state() { return mState; }
140    void setPriority(int priority) { mPriority = priority; }
141    void setLoop(int loop);
142    int numChannels() { return mNumChannels; }
143    void clearNextEvent() { mNextEvent.clear(); }
144    void nextEvent();
145    int nextChannelID() { return mNextEvent.channelID(); }
146    void dump();
147
148private:
149    static void callback(int event, void* user, void *info);
150    void process(int event, void *info, unsigned long toggle);
151    bool doStop_l();
152
153    SoundPool*          mSoundPool;
154    sp<AudioTrack>      mAudioTrack;
155    SoundEvent          mNextEvent;
156    Mutex               mLock;
157    int                 mState;
158    int                 mNumChannels;
159    int                 mPos;
160    int                 mAudioBufferSize;
161    unsigned long       mToggle;
162    bool                mAutoPaused;
163};
164
165// application object for managing a pool of sounds
166class SoundPool {
167    friend class SoundPoolThread;
168    friend class SoundChannel;
169public:
170    SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality);
171    ~SoundPool();
172    int load(const char* url, int priority);
173    int load(int fd, int64_t offset, int64_t length, int priority);
174    bool unload(int sampleID);
175    int play(int sampleID, float leftVolume, float rightVolume, int priority,
176            int loop, float rate);
177    void pause(int channelID);
178    void autoPause();
179    void resume(int channelID);
180    void autoResume();
181    void stop(int channelID);
182    void setVolume(int channelID, float leftVolume, float rightVolume);
183    void setPriority(int channelID, int priority);
184    void setLoop(int channelID, int loop);
185    void setRate(int channelID, float rate);
186    audio_stream_type_t streamType() const { return mStreamType; }
187    int srcQuality() const { return mSrcQuality; }
188
189    // called from SoundPoolThread
190    void sampleLoaded(int sampleID);
191
192    // called from AudioTrack thread
193    void done_l(SoundChannel* channel);
194
195    // callback function
196    void setCallback(SoundPoolCallback* callback, void* user);
197    void* getUserData() { return mUserData; }
198
199private:
200    SoundPool() {} // no default constructor
201    bool startThreads();
202    void doLoad(sp<Sample>& sample);
203    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
204    SoundChannel* findChannel (int channelID);
205    SoundChannel* findNextChannel (int channelID);
206    SoundChannel* allocateChannel_l(int priority);
207    void moveToFront_l(SoundChannel* channel);
208    void notify(SoundPoolEvent event);
209    void dump();
210
211    // restart thread
212    void addToRestartList(SoundChannel* channel);
213    void addToStopList(SoundChannel* channel);
214    static int beginThread(void* arg);
215    int run();
216    void quit();
217
218    Mutex                   mLock;
219    Mutex                   mRestartLock;
220    Condition               mCondition;
221    SoundPoolThread*        mDecodeThread;
222    SoundChannel*           mChannelPool;
223    List<SoundChannel*>     mChannels;
224    List<SoundChannel*>     mRestart;
225    List<SoundChannel*>     mStop;
226    DefaultKeyedVector< int, sp<Sample> >   mSamples;
227    int                     mMaxChannels;
228    audio_stream_type_t     mStreamType;
229    int                     mSrcQuality;
230    int                     mAllocated;
231    int                     mNextSampleID;
232    int                     mNextChannelID;
233    bool                    mQuit;
234
235    // callback
236    Mutex                   mCallbackLock;
237    SoundPoolCallback*      mCallback;
238    void*                   mUserData;
239};
240
241} // end namespace android
242
243#endif /*SOUNDPOOL_H_*/
244