blob: 6010aac77916066b0b0486873c113c49b568c5af [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026namespace 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;
Dave Sparksf6e43bf2009-12-08 08:10:42 -080043 enum MessageType { INVALID, SAMPLE_LOADED };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044};
45
Dave Sparksf6e43bf2009-12-08 08:10:42 -080046// callback function prototype
47typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
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 int 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()); }
Dave Sparksf6e43bf2009-12-08 08:10:42 -080063 status_t doLoad();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 void startLoad() { mState = LOADING; }
65 sp<IMemory> getIMemory() { return mData; }
66
67 // hack
68 void init(int numChannels, int sampleRate, int format, size_t size, sp<IMemory> data ) {
69 mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size; mData = data; }
70
71private:
72 void init();
73
74 size_t mSize;
75 volatile int32_t mRefCount;
76 uint16_t mSampleID;
77 uint16_t mSampleRate;
78 uint8_t mState : 3;
79 uint8_t mNumChannels : 2;
80 uint8_t mFormat : 2;
81 int mFd;
82 int64_t mOffset;
83 int64_t mLength;
84 char* mUrl;
85 sp<IMemory> mData;
86};
87
88// stores pending events for stolen channels
89class SoundEvent
90{
91public:
92 SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
93 mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
94 void set(const sp<Sample>& sample, int channelID, float leftVolume,
95 float rightVolume, int priority, int loop, float rate);
96 sp<Sample> sample() { return mSample; }
97 int channelID() { return mChannelID; }
98 float leftVolume() { return mLeftVolume; }
99 float rightVolume() { return mRightVolume; }
100 int priority() { return mPriority; }
101 int loop() { return mLoop; }
102 float rate() { return mRate; }
103 void clear() { mChannelID = 0; mSample.clear(); }
104
105protected:
106 sp<Sample> mSample;
107 int mChannelID;
108 float mLeftVolume;
109 float mRightVolume;
110 int mPriority;
111 int mLoop;
112 float mRate;
113};
114
115// for channels aka AudioTracks
116class SoundChannel : public SoundEvent {
117public:
118 enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
Dave Sparksf992cbb2010-02-09 13:00:09 -0800119 SoundChannel() : mAudioTrack(0), mState(IDLE), mNumChannels(1),
120 mPos(0), mToggle(0), mAutoPaused(false) {}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 ~SoundChannel();
122 void init(SoundPool* soundPool);
123 void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
124 int priority, int loop, float rate);
125 void setVolume_l(float leftVolume, float rightVolume);
126 void setVolume(float leftVolume, float rightVolume);
127 void stop_l();
128 void stop();
129 void pause();
Dave Sparksf992cbb2010-02-09 13:00:09 -0800130 void autoPause();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 void resume();
Dave Sparksf992cbb2010-02-09 13:00:09 -0800132 void autoResume();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 void setRate(float rate);
134 int state() { return mState; }
135 void setPriority(int priority) { mPriority = priority; }
136 void setLoop(int loop);
137 int numChannels() { return mNumChannels; }
138 void clearNextEvent() { mNextEvent.clear(); }
139 void nextEvent();
140 int nextChannelID() { return mNextEvent.channelID(); }
141 void dump();
142
143private:
Glenn Kastene46a86f2011-06-01 15:20:35 -0700144 static void callback(int event, void* user, void *info);
145 void process(int event, void *info, unsigned long toggle);
Eric Laurenta60e2122010-12-28 16:49:07 -0800146 bool doStop_l();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147
148 SoundPool* mSoundPool;
149 AudioTrack* mAudioTrack;
150 SoundEvent mNextEvent;
151 Mutex mLock;
152 int mState;
153 int mNumChannels;
154 int mPos;
155 int mAudioBufferSize;
156 unsigned long mToggle;
Dave Sparksf992cbb2010-02-09 13:00:09 -0800157 bool mAutoPaused;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158};
159
160// application object for managing a pool of sounds
161class SoundPool {
162 friend class SoundPoolThread;
163 friend class SoundChannel;
164public:
Dave Sparksc0e3ddf2009-12-07 12:36:20 -0800165 SoundPool(int maxChannels, int streamType, int srcQuality);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 ~SoundPool();
167 int load(const char* url, int priority);
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);
Dave Sparksf992cbb2010-02-09 13:00:09 -0800173 void autoPause();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 void resume(int channelID);
Dave Sparksf992cbb2010-02-09 13:00:09 -0800175 void autoResume();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 void stop(int channelID);
177 void setVolume(int channelID, float leftVolume, float rightVolume);
178 void setPriority(int channelID, int priority);
179 void setLoop(int channelID, int loop);
180 void setRate(int channelID, float rate);
181 int streamType() const { return mStreamType; }
182 int srcQuality() const { return mSrcQuality; }
183
184 // called from SoundPoolThread
185 void sampleLoaded(int sampleID);
186
187 // called from AudioTrack thread
Eric Laurenta60e2122010-12-28 16:49:07 -0800188 void done_l(SoundChannel* channel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
Dave Sparksf6e43bf2009-12-08 08:10:42 -0800190 // callback function
191 void setCallback(SoundPoolCallback* callback, void* user);
192 void* getUserData() { return mUserData; }
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194private:
195 SoundPool() {} // no default constructor
196 bool startThreads();
197 void doLoad(sp<Sample>& sample);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
199 SoundChannel* findChannel (int channelID);
200 SoundChannel* findNextChannel (int channelID);
Eric Laurenta60e2122010-12-28 16:49:07 -0800201 SoundChannel* allocateChannel_l(int priority);
202 void moveToFront_l(SoundChannel* channel);
Dave Sparksf6e43bf2009-12-08 08:10:42 -0800203 void notify(SoundPoolEvent event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 void dump();
205
206 // restart thread
207 void addToRestartList(SoundChannel* channel);
Eric Laurenta60e2122010-12-28 16:49:07 -0800208 void addToStopList(SoundChannel* channel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 static int beginThread(void* arg);
210 int run();
211 void quit();
212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 Mutex mLock;
Eric Laurentfd8c0e12009-07-31 06:29:13 -0700214 Mutex mRestartLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 Condition mCondition;
216 SoundPoolThread* mDecodeThread;
217 SoundChannel* mChannelPool;
218 List<SoundChannel*> mChannels;
219 List<SoundChannel*> mRestart;
Eric Laurenta60e2122010-12-28 16:49:07 -0800220 List<SoundChannel*> mStop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 DefaultKeyedVector< int, sp<Sample> > mSamples;
222 int mMaxChannels;
223 int mStreamType;
224 int mSrcQuality;
225 int mAllocated;
226 int mNextSampleID;
227 int mNextChannelID;
228 bool mQuit;
Dave Sparksf6e43bf2009-12-08 08:10:42 -0800229
230 // callback
231 Mutex mCallbackLock;
232 SoundPoolCallback* mCallback;
233 void* mUserData;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234};
235
236} // end namespace android
237
238#endif /*SOUNDPOOL_H_*/