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