blob: 2dd78cc07f7119c6f36b15a5603d6c31d431ecc8 [file] [log] [blame]
Eric Laurent2e66a782012-03-26 10:47:22 -07001/*
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>
Eric Laurent3d00aa62013-09-24 09:53:27 -070025#include <binder/MemoryHeapBase.h>
26#include <binder/MemoryBase.h>
Eric Laurent2e66a782012-03-26 10:47:22 -070027
28namespace android {
29
30static const int IDLE_PRIORITY = -1;
31
32// forward declarations
33class SoundEvent;
34class SoundPoolThread;
35class SoundPool;
36
37// for queued events
38class SoundPoolEvent {
39public:
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
49typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
50
51// tracks samples used by application
52class Sample : public RefBase {
53public:
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();
58 int sampleID() { return mSampleID; }
59 int numChannels() { return mNumChannels; }
60 int sampleRate() { return mSampleRate; }
61 audio_format_t format() { return mFormat; }
62 size_t size() { return mSize; }
63 int state() { return mState; }
64 uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
65 status_t doLoad();
66 void startLoad() { mState = LOADING; }
67 sp<IMemory> getIMemory() { return mData; }
68
69 // hack
Glenn Kasten85ab62c2012-11-01 11:11:38 -070070 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; }
Eric Laurent2e66a782012-03-26 10:47:22 -070074
75private:
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;
Eric Laurent3d00aa62013-09-24 09:53:27 -070090 sp<MemoryHeapBase> mHeap;
Eric Laurent2e66a782012-03-26 10:47:22 -070091};
92
93// stores pending events for stolen channels
94class SoundEvent
95{
96public:
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);
101 sp<Sample> sample() { return mSample; }
102 int channelID() { return mChannelID; }
103 float leftVolume() { return mLeftVolume; }
104 float rightVolume() { return mRightVolume; }
105 int priority() { return mPriority; }
106 int loop() { return mLoop; }
107 float rate() { return mRate; }
108 void clear() { mChannelID = 0; mSample.clear(); }
109
110protected:
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
121class SoundChannel : public SoundEvent {
122public:
123 enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
Glenn Kasten2799d742013-05-30 14:33:29 -0700124 SoundChannel() : mState(IDLE), mNumChannels(1),
Eric Laurent2e66a782012-03-26 10:47:22 -0700125 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);
139 int state() { return mState; }
140 void setPriority(int priority) { mPriority = priority; }
141 void setLoop(int loop);
142 int numChannels() { return mNumChannels; }
143 void clearNextEvent() { mNextEvent.clear(); }
144 void nextEvent();
145 int nextChannelID() { return mNextEvent.channelID(); }
146 void dump();
147
148private:
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;
Glenn Kasten2799d742013-05-30 14:33:29 -0700154 sp<AudioTrack> mAudioTrack;
Eric Laurent2e66a782012-03-26 10:47:22 -0700155 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
166class SoundPool {
167 friend class SoundPoolThread;
168 friend class SoundChannel;
169public:
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);
186 audio_stream_type_t streamType() const { return mStreamType; }
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);
197 void* getUserData() { return mUserData; }
198
199private:
200 SoundPool() {} // no default constructor
201 bool startThreads();
202 void doLoad(sp<Sample>& sample);
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_*/