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