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