1 /**
2  * Copyright (c) 2006-2019 LOVE Development Team
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  **/
20 
21 #ifndef LOVE_AUDIO_OPENAL_SOURCE_H
22 #define LOVE_AUDIO_OPENAL_SOURCE_H
23 
24 // LOVE
25 #include "common/config.h"
26 #include "common/Object.h"
27 #include "audio/Source.h"
28 #include "audio/Filter.h"
29 #include "sound/SoundData.h"
30 #include "sound/Decoder.h"
31 #include "Audio.h"
32 #include "Filter.h"
33 
34 // STL
35 #include <vector>
36 #include <stack>
37 
38 // C
39 #include <float.h>
40 
41 // OpenAL
42 #ifdef LOVE_APPLE_USE_FRAMEWORKS
43 #ifdef LOVE_IOS
44 #include <OpenAL/alc.h>
45 #include <OpenAL/al.h>
46 #else
47 #include <OpenAL-Soft/alc.h>
48 #include <OpenAL-Soft/al.h>
49 #endif
50 #else
51 #include <AL/alc.h>
52 #include <AL/al.h>
53 #endif
54 
55 namespace love
56 {
57 namespace audio
58 {
59 namespace openal
60 {
61 
62 #ifdef LOVE_IOS
63 // OpenAL on iOS barfs if the max distance is +inf.
64 static const float MAX_ATTENUATION_DISTANCE = 1000000.0f;
65 #else
66 static const float MAX_ATTENUATION_DISTANCE = FLT_MAX;
67 #endif
68 
69 class Audio;
70 class Pool;
71 
72 // Basically just a reference-counted non-streaming OpenAL buffer object.
73 class StaticDataBuffer : public love::Object
74 {
75 public:
76 
77 	StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
78 	virtual ~StaticDataBuffer();
79 
getBuffer()80 	inline ALuint getBuffer() const
81 	{
82 		return buffer;
83 	}
84 
getSize()85 	inline ALsizei getSize() const
86 	{
87 		return size;
88 	}
89 
90 private:
91 
92 	ALuint buffer;
93 	ALsizei size;
94 
95 }; // StaticDataBuffer
96 
97 class Source : public love::audio::Source
98 {
99 public:
100 
101 	Source(Pool *pool, love::sound::SoundData *soundData);
102 	Source(Pool *pool, love::sound::Decoder *decoder);
103 	Source(Pool *pool, int sampleRate, int bitDepth, int channels, int buffers);
104 	Source(const Source &s);
105 	virtual ~Source();
106 
107 	virtual love::audio::Source *clone();
108 	virtual bool play();
109 	virtual void stop();
110 	virtual void pause();
111 	virtual bool isPlaying() const;
112 	virtual bool isFinished() const;
113 	virtual bool update();
114 	virtual void setPitch(float pitch);
115 	virtual float getPitch() const;
116 	virtual void setVolume(float volume);
117 	virtual float getVolume() const;
118 	virtual void seek(double offset, Unit unit);
119 	virtual double tell(Unit unit);
120 	virtual double getDuration(Unit unit);
121 	virtual void setPosition(float *v);
122 	virtual void getPosition(float *v) const;
123 	virtual void setVelocity(float *v);
124 	virtual void getVelocity(float *v) const;
125 	virtual void setDirection(float *v);
126 	virtual void getDirection(float *v) const;
127 	virtual void setCone(float innerAngle, float outerAngle, float outerVolume, float outerHighGain);
128 	virtual void getCone(float &innerAngle, float &outerAngle, float &outerVolume, float &outerHighGain) const;
129 	virtual void setRelative(bool enable);
130 	virtual bool isRelative() const;
131 	void setLooping(bool looping);
132 	bool isLooping() const;
133 	virtual void setMinVolume(float volume);
134 	virtual float getMinVolume() const;
135 	virtual void setMaxVolume(float volume);
136 	virtual float getMaxVolume() const;
137 	virtual void setReferenceDistance(float distance);
138 	virtual float getReferenceDistance() const;
139 	virtual void setRolloffFactor(float factor);
140 	virtual float getRolloffFactor() const;
141 	virtual void setMaxDistance(float distance);
142 	virtual float getMaxDistance() const;
143 	virtual void setAirAbsorptionFactor(float factor);
144 	virtual float getAirAbsorptionFactor() const;
145 	virtual int getChannelCount() const;
146 
147 	virtual bool setFilter(const std::map<Filter::Parameter, float> &params);
148 	virtual bool setFilter();
149 	virtual bool getFilter(std::map<Filter::Parameter, float> &params);
150 
151 	virtual bool setEffect(const char *effect);
152 	virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params);
153 	virtual bool unsetEffect(const char *effect);
154 	virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params);
155 	virtual bool getActiveEffects(std::vector<std::string> &list) const;
156 
157 	virtual int getFreeBufferCount() const;
158 	virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels);
159 
160 	void prepareAtomic();
161 	void teardownAtomic();
162 
163 	bool playAtomic(ALuint source);
164 	void stopAtomic();
165 	void pauseAtomic();
166 	void resumeAtomic();
167 
168 	static bool play(const std::vector<love::audio::Source*> &sources);
169 	static void stop(const std::vector<love::audio::Source*> &sources);
170 	static void pause(const std::vector<love::audio::Source*> &sources);
171 
172 	static std::vector<love::audio::Source*> pause(Pool *pool);
173 	static void stop(Pool *pool);
174 
175 private:
176 
177 	void reset();
178 
179 	void setFloatv(float *dst, const float *src) const;
180 
181 	int streamAtomic(ALuint buffer, love::sound::Decoder *d);
182 
183 	Pool *pool = nullptr;
184 	ALuint source = 0;
185 	bool valid = false;
186 
187 	const static int DEFAULT_BUFFERS = 8;
188 	const static int MAX_BUFFERS = 64;
189 	std::queue<ALuint> streamBuffers;
190 	std::stack<ALuint> unusedBuffers;
191 
192 	StrongRef<StaticDataBuffer> staticBuffer;
193 
194 	float pitch = 1.0f;
195 	float volume = 1.0f;
196 	float position[3];
197 	float velocity[3];
198 	float direction[3];
199 	bool relative = false;
200 	bool looping = false;
201 	float minVolume = 0.0f;
202 	float maxVolume = 1.0f;
203 	float referenceDistance = 1.0f;
204 	float rolloffFactor = 1.0f;
205 	float absorptionFactor = 0.0f;
206 	float maxDistance = MAX_ATTENUATION_DISTANCE;
207 
208 	struct Cone
209 	{
210 		int innerAngle = 360; // degrees
211 		int outerAngle = 360; // degrees
212 		float outerVolume = 0.0f;
213 		float outerHighGain = 1.0f;
214 	} cone;
215 
216 	int offsetSamples = 0;
217 
218 	int sampleRate = 0;
219 	int channels = 0;
220 	int bitDepth = 0;
221 
222 	StrongRef<love::sound::Decoder> decoder;
223 
224 	unsigned int toLoop = 0;
225 	ALsizei bufferedBytes = 0;
226 	int buffers = 0;
227 
228 	Filter *directfilter = nullptr;
229 
230 	struct EffectMapStorage
231 	{
232 		Filter *filter;
233 		ALuint slot, target;
234 	};
235 	std::map<std::string, EffectMapStorage> effectmap;
236 	std::stack<ALuint> slotlist;
237 }; // Source
238 
239 } // openal
240 } // audio
241 } // love
242 
243 #endif // LOVE_AUDIO_OPENAL_SOURCE_H
244