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; } channelMask()61 audio_channel_mask_t channelMask() { return mChannelMask; } 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 private: 70 void init(); 71 72 size_t mSize; 73 volatile int32_t mRefCount; 74 uint16_t mSampleID; 75 uint16_t mSampleRate; 76 uint8_t mState; 77 uint8_t mNumChannels; 78 audio_format_t mFormat; 79 audio_channel_mask_t mChannelMask; 80 int mFd; 81 int64_t mOffset; 82 int64_t mLength; 83 sp<IMemory> mData; 84 sp<MemoryHeapBase> mHeap; 85 }; 86 87 // stores pending events for stolen channels 88 class SoundEvent 89 { 90 public: SoundEvent()91 SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0), 92 mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {} 93 void set(const sp<Sample>& sample, int channelID, float leftVolume, 94 float rightVolume, int priority, int loop, float rate); sample()95 sp<Sample> sample() { return mSample; } channelID()96 int channelID() { return mChannelID; } leftVolume()97 float leftVolume() { return mLeftVolume; } rightVolume()98 float rightVolume() { return mRightVolume; } priority()99 int priority() { return mPriority; } loop()100 int loop() { return mLoop; } rate()101 float rate() { return mRate; } clear()102 void clear() { mChannelID = 0; mSample.clear(); } 103 104 protected: 105 sp<Sample> mSample; 106 int mChannelID; 107 float mLeftVolume; 108 float mRightVolume; 109 int mPriority; 110 int mLoop; 111 float mRate; 112 }; 113 114 // for channels aka AudioTracks 115 class SoundChannel : public SoundEvent { 116 public: 117 enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING }; SoundChannel()118 SoundChannel() : mState(IDLE), mNumChannels(1), 119 mPos(0), mToggle(0), mAutoPaused(false), mMuted(false) {} 120 ~SoundChannel(); 121 void init(SoundPool* soundPool); 122 void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume, 123 int priority, int loop, float rate); 124 void setVolume_l(float leftVolume, float rightVolume); 125 void setVolume(float leftVolume, float rightVolume); 126 void mute(bool muting); 127 void stop_l(); 128 void stop(); 129 void pause(); 130 void autoPause(); 131 void resume(); 132 void autoResume(); 133 void setRate(float rate); state()134 int state() { return mState; } setPriority(int priority)135 void setPriority(int priority) { mPriority = priority; } 136 void setLoop(int loop); numChannels()137 int numChannels() { return mNumChannels; } clearNextEvent()138 void clearNextEvent() { mNextEvent.clear(); } 139 void nextEvent(); nextChannelID()140 int nextChannelID() { return mNextEvent.channelID(); } 141 void dump(); getPrevSampleID(void)142 int getPrevSampleID(void) { return mPrevSampleID; } 143 144 private: 145 static void callback(int event, void* user, void *info); 146 void process(int event, void *info, unsigned long toggle); 147 bool doStop_l(); 148 149 SoundPool* mSoundPool; 150 sp<AudioTrack> mAudioTrack; 151 SoundEvent mNextEvent; 152 Mutex mLock; 153 int mState; 154 int mNumChannels; 155 int mPos; 156 int mAudioBufferSize; 157 unsigned long mToggle; 158 bool mAutoPaused; 159 int mPrevSampleID; 160 bool mMuted; 161 }; 162 163 // application object for managing a pool of sounds 164 class SoundPool { 165 friend class SoundPoolThread; 166 friend class SoundChannel; 167 public: 168 SoundPool(int maxChannels, const audio_attributes_t* pAttributes); 169 ~SoundPool(); 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 mute(bool muting); 176 void autoPause(); 177 void resume(int channelID); 178 void autoResume(); 179 void stop(int channelID); 180 void setVolume(int channelID, float leftVolume, float rightVolume); 181 void setPriority(int channelID, int priority); 182 void setLoop(int channelID, int loop); 183 void setRate(int channelID, float rate); attributes()184 const audio_attributes_t* attributes() { return &mAttributes; } 185 186 // called from SoundPoolThread 187 void sampleLoaded(int sampleID); 188 sp<Sample> findSample(int sampleID); 189 190 // called from AudioTrack thread 191 void done_l(SoundChannel* channel); 192 193 // callback function 194 void setCallback(SoundPoolCallback* callback, void* user); getUserData()195 void* getUserData() { return mUserData; } 196 197 private: SoundPool()198 SoundPool() {} // no default constructor 199 bool startThreads(); 200 sp<Sample> findSample_l(int sampleID); 201 SoundChannel* findChannel (int channelID); 202 SoundChannel* findNextChannel (int channelID); 203 SoundChannel* allocateChannel_l(int priority, int sampleID); 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_attributes_t mAttributes; 226 int mAllocated; 227 int mNextSampleID; 228 int mNextChannelID; 229 bool mQuit; 230 bool mMuted; 231 232 // callback 233 Mutex mCallbackLock; 234 SoundPoolCallback* mCallback; 235 void* mUserData; 236 }; 237 238 } // end namespace android 239 240 #endif /*SOUNDPOOL_H_*/ 241