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; } size()61 size_t size() { return mSize; } state()62 int state() { return mState; } data()63 uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); } 64 status_t doLoad(); startLoad()65 void startLoad() { mState = LOADING; } getIMemory()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: SoundEvent()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); sample()93 sp<Sample> sample() { return mSample; } channelID()94 int channelID() { return mChannelID; } leftVolume()95 float leftVolume() { return mLeftVolume; } rightVolume()96 float rightVolume() { return mRightVolume; } priority()97 int priority() { return mPriority; } loop()98 int loop() { return mLoop; } rate()99 float rate() { return mRate; } clear()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 }; SoundChannel()116 SoundChannel() : mState(IDLE), mNumChannels(1), 117 mPos(0), mToggle(0), mAutoPaused(false), mMuted(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 mute(bool muting); 125 void stop_l(); 126 void stop(); 127 void pause(); 128 void autoPause(); 129 void resume(); 130 void autoResume(); 131 void setRate(float rate); state()132 int state() { return mState; } setPriority(int priority)133 void setPriority(int priority) { mPriority = priority; } 134 void setLoop(int loop); numChannels()135 int numChannels() { return mNumChannels; } clearNextEvent()136 void clearNextEvent() { mNextEvent.clear(); } 137 void nextEvent(); nextChannelID()138 int nextChannelID() { return mNextEvent.channelID(); } 139 void dump(); getPrevSampleID(void)140 int getPrevSampleID(void) { return mPrevSampleID; } 141 142 private: 143 static void callback(int event, void* user, void *info); 144 void process(int event, void *info, unsigned long toggle); 145 bool doStop_l(); 146 147 SoundPool* mSoundPool; 148 sp<AudioTrack> mAudioTrack; 149 SoundEvent mNextEvent; 150 Mutex mLock; 151 int mState; 152 int mNumChannels; 153 int mPos; 154 int mAudioBufferSize; 155 unsigned long mToggle; 156 bool mAutoPaused; 157 int mPrevSampleID; 158 bool mMuted; 159 }; 160 161 // application object for managing a pool of sounds 162 class SoundPool { 163 friend class SoundPoolThread; 164 friend class SoundChannel; 165 public: 166 SoundPool(int maxChannels, const audio_attributes_t* pAttributes); 167 ~SoundPool(); 168 int load(int fd, int64_t offset, int64_t length, int priority); 169 bool unload(int sampleID); 170 int play(int sampleID, float leftVolume, float rightVolume, int priority, 171 int loop, float rate); 172 void pause(int channelID); 173 void mute(bool muting); 174 void autoPause(); 175 void resume(int channelID); 176 void autoResume(); 177 void stop(int channelID); 178 void setVolume(int channelID, float leftVolume, float rightVolume); 179 void setPriority(int channelID, int priority); 180 void setLoop(int channelID, int loop); 181 void setRate(int channelID, float rate); attributes()182 const audio_attributes_t* attributes() { return &mAttributes; } 183 184 // called from SoundPoolThread 185 void sampleLoaded(int sampleID); 186 sp<Sample> findSample(int sampleID); 187 188 // called from AudioTrack thread 189 void done_l(SoundChannel* channel); 190 191 // callback function 192 void setCallback(SoundPoolCallback* callback, void* user); getUserData()193 void* getUserData() { return mUserData; } 194 195 private: SoundPool()196 SoundPool() {} // no default constructor 197 bool startThreads(); 198 sp<Sample> findSample_l(int sampleID); 199 SoundChannel* findChannel (int channelID); 200 SoundChannel* findNextChannel (int channelID); 201 SoundChannel* allocateChannel_l(int priority, int sampleID); 202 void moveToFront_l(SoundChannel* channel); 203 void notify(SoundPoolEvent event); 204 void dump(); 205 206 // restart thread 207 void addToRestartList(SoundChannel* channel); 208 void addToStopList(SoundChannel* channel); 209 static int beginThread(void* arg); 210 int run(); 211 void quit(); 212 213 Mutex mLock; 214 Mutex mRestartLock; 215 Condition mCondition; 216 SoundPoolThread* mDecodeThread; 217 SoundChannel* mChannelPool; 218 List<SoundChannel*> mChannels; 219 List<SoundChannel*> mRestart; 220 List<SoundChannel*> mStop; 221 DefaultKeyedVector< int, sp<Sample> > mSamples; 222 int mMaxChannels; 223 audio_attributes_t mAttributes; 224 int mAllocated; 225 int mNextSampleID; 226 int mNextChannelID; 227 bool mQuit; 228 bool mMuted; 229 230 // callback 231 Mutex mCallbackLock; 232 SoundPoolCallback* mCallback; 233 void* mUserData; 234 }; 235 236 } // end namespace android 237 238 #endif /*SOUNDPOOL_H_*/ 239