blob: 7bf306901b2f2b93653d0731fd9064e79859cd7d [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>
25
26namespace android {
27
28static const int IDLE_PRIORITY = -1;
29
30// forward declarations
31class SoundEvent;
32class SoundPoolThread;
33class SoundPool;
34
35// for queued events
36class SoundPoolEvent {
37public:
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
47typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
48
49// tracks samples used by application
50class Sample : public RefBase {
51public:
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
Glenn Kasten8af901c2012-11-01 11:11:38 -070068 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; }
Eric Laurent2e66a782012-03-26 10:47:22 -070072
73private:
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
91class SoundEvent
92{
93public:
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
107protected:
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
118class SoundChannel : public SoundEvent {
119public:
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
145private:
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
163class SoundPool {
164 friend class SoundPoolThread;
165 friend class SoundChannel;
166public:
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
196private:
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_*/