1/**
2 * Copyright (c) 2006-2023 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
55namespace love
56{
57namespace audio
58{
59namespace openal
60{
61
62#ifdef LOVE_IOS
63// OpenAL on iOS barfs if the max distance is +inf.
64static const float MAX_ATTENUATION_DISTANCE = 1000000.0f;
65#else
66static const float MAX_ATTENUATION_DISTANCE = FLT_MAX;
67#endif
68
69class Audio;
70class Pool;
71
72// Basically just a reference-counted non-streaming OpenAL buffer object.
73class StaticDataBuffer : public love::Object
74{
75public:
76
77 StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
78 virtual ~StaticDataBuffer();
79
80 inline ALuint getBuffer() const
81 {
82 return buffer;
83 }
84
85 inline ALsizei getSize() const
86 {
87 return size;
88 }
89
90private:
91
92 ALuint buffer;
93 ALsizei size;
94
95}; // StaticDataBuffer
96
97class Source : public love::audio::Source
98{
99public:
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
175private:
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