blob: 9d7410305c2c85c2ace13c83928573f6ea6adced [file] [log] [blame]
Marco Nelissen372be892014-12-04 08:59:22 -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>
25#include <binder/MemoryHeapBase.h>
26#include <binder/MemoryBase.h>
27
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:
Chih-Hung Hsiehae1aadc2016-08-29 14:53:50 -070040 explicit SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
Marco Nelissen372be892014-12-04 08:59:22 -080041 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, int fd, int64_t offset, int64_t length);
56 ~Sample();
57 int sampleID() { return mSampleID; }
58 int numChannels() { return mNumChannels; }
59 int sampleRate() { return mSampleRate; }
60 audio_format_t format() { return mFormat; }
jiabina0129612018-12-09 13:07:40 -080061 audio_channel_mask_t channelMask() { return mChannelMask; }
Marco Nelissen372be892014-12-04 08:59:22 -080062 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
69private:
70 void init();
71
jiabina0129612018-12-09 13:07:40 -080072 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;
Marco Nelissen372be892014-12-04 08:59:22 -080085};
86
87// stores pending events for stolen channels
88class SoundEvent
89{
90public:
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);
95 sp<Sample> sample() { return mSample; }
96 int channelID() { return mChannelID; }
97 float leftVolume() { return mLeftVolume; }
98 float rightVolume() { return mRightVolume; }
99 int priority() { return mPriority; }
100 int loop() { return mLoop; }
101 float rate() { return mRate; }
102 void clear() { mChannelID = 0; mSample.clear(); }
103
104protected:
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
115class SoundChannel : public SoundEvent {
116public:
117 enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
118 SoundChannel() : mState(IDLE), mNumChannels(1),
Jean-Michel Trivi8e48c692016-10-19 11:52:08 -0700119 mPos(0), mToggle(0), mAutoPaused(false), mMuted(false) {}
Marco Nelissen372be892014-12-04 08:59:22 -0800120 ~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);
Jean-Michel Trivi8e48c692016-10-19 11:52:08 -0700126 void mute(bool muting);
Marco Nelissen372be892014-12-04 08:59:22 -0800127 void stop_l();
128 void stop();
129 void pause();
130 void autoPause();
131 void resume();
132 void autoResume();
133 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();
Andy Hung0c4b81b2015-03-17 23:02:00 +0000142 int getPrevSampleID(void) { return mPrevSampleID; }
Marco Nelissen372be892014-12-04 08:59:22 -0800143
144private:
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;
Andy Hung0c4b81b2015-03-17 23:02:00 +0000159 int mPrevSampleID;
Jean-Michel Trivi8e48c692016-10-19 11:52:08 -0700160 bool mMuted;
Marco Nelissen372be892014-12-04 08:59:22 -0800161};
162
163// application object for managing a pool of sounds
164class SoundPool {
165 friend class SoundPoolThread;
166 friend class SoundChannel;
167public:
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);
Jean-Michel Trivi8e48c692016-10-19 11:52:08 -0700175 void mute(bool muting);
Marco Nelissen372be892014-12-04 08:59:22 -0800176 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);
184 const audio_attributes_t* attributes() { return &mAttributes; }
185
186 // called from SoundPoolThread
187 void sampleLoaded(int sampleID);
Andy Hung0a887bc2015-11-30 16:09:55 -0800188 sp<Sample> findSample(int sampleID);
Marco Nelissen372be892014-12-04 08:59:22 -0800189
190 // called from AudioTrack thread
191 void done_l(SoundChannel* channel);
192
193 // callback function
194 void setCallback(SoundPoolCallback* callback, void* user);
195 void* getUserData() { return mUserData; }
196
197private:
198 SoundPool() {} // no default constructor
199 bool startThreads();
Andy Hung0a887bc2015-11-30 16:09:55 -0800200 sp<Sample> findSample_l(int sampleID);
Marco Nelissen372be892014-12-04 08:59:22 -0800201 SoundChannel* findChannel (int channelID);
202 SoundChannel* findNextChannel (int channelID);
Andy Hung0c4b81b2015-03-17 23:02:00 +0000203 SoundChannel* allocateChannel_l(int priority, int sampleID);
Marco Nelissen372be892014-12-04 08:59:22 -0800204 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;
Jean-Michel Trivi8e48c692016-10-19 11:52:08 -0700230 bool mMuted;
Marco Nelissen372be892014-12-04 08:59:22 -0800231
232 // callback
233 Mutex mCallbackLock;
234 SoundPoolCallback* mCallback;
235 void* mUserData;
236};
237
238} // end namespace android
239
240#endif /*SOUNDPOOL_H_*/