• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) :
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, const char* url);
56     Sample(int sampleID, int fd, int64_t offset, int64_t length);
57     ~Sample();
sampleID()58     int sampleID() { return mSampleID; }
numChannels()59     int numChannels() { return mNumChannels; }
sampleRate()60     int sampleRate() { return mSampleRate; }
format()61     audio_format_t format() { return mFormat; }
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     // hack
init(int numChannels,int sampleRate,audio_format_t format,size_t size,sp<IMemory> data)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 
75 private:
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
94 class SoundEvent
95 {
96 public:
SoundEvent()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);
sample()101     sp<Sample>      sample() { return mSample; }
channelID()102     int             channelID() { return mChannelID; }
leftVolume()103     float           leftVolume() { return mLeftVolume; }
rightVolume()104     float           rightVolume() { return mRightVolume; }
priority()105     int             priority() { return mPriority; }
loop()106     int             loop() { return mLoop; }
rate()107     float           rate() { return mRate; }
clear()108     void            clear() { mChannelID = 0; mSample.clear(); }
109 
110 protected:
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
121 class SoundChannel : public SoundEvent {
122 public:
123     enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
SoundChannel()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);
state()139     int state() { return mState; }
setPriority(int priority)140     void setPriority(int priority) { mPriority = priority; }
141     void setLoop(int loop);
numChannels()142     int numChannels() { return mNumChannels; }
clearNextEvent()143     void clearNextEvent() { mNextEvent.clear(); }
144     void nextEvent();
nextChannelID()145     int nextChannelID() { return mNextEvent.channelID(); }
146     void dump();
147 
148 private:
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
166 class SoundPool {
167     friend class SoundPoolThread;
168     friend class SoundChannel;
169 public:
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);
streamType()186     audio_stream_type_t streamType() const { return mStreamType; }
srcQuality()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);
getUserData()197     void* getUserData() { return mUserData; }
198 
199 private:
SoundPool()200     SoundPool() {} // no default constructor
201     bool startThreads();
202     void doLoad(sp<Sample>& sample);
findSample(int sampleID)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