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