]> camargo.eng.br - camargo/neiasound.git/blob - src/nSoundSource.cpp
Added shared lib project.
[camargo/neiasound.git] / src / nSoundSource.cpp
1 // Copyright (C) 2015 Lucas Pires Camargo
2 // 
3 // This file is part of neiasound - Qt-style OpenAL wrapper for games.
4 // 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 // 
9 // 1. Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // 
12 // 2. Redistributions in binary form must reproduce the above copyright notice,
13 // this list of conditions and the following disclaimer in the documentation
14 // and/or other materials provided with the distribution.
15 // 
16 // THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS
17 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 // NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "nSoundSource.h"
27 #include "nSoundSystem.h"
28 #include "nSoundBuffer.h"
29
30 #include "AL/al.h"
31
32
33 nSoundSource::nSoundSource(QString name, nSoundSourceRole role, nSoundSystem * parent) :
34     QObject(parent)
35 {
36     setObjectName(name);
37     m_role = role;
38     m_gainMirror = _roleGainVolume(role);
39     m_fading = false;
40     m_fadeTarget = 0.0f;
41     m_fadeDeltaPerSecond = 0.0f;
42     m_destroyAfterStopped = false;
43
44     alGetError(); //reset error state
45
46     unsigned int hnd;
47     alGenSources(1, &hnd);
48     m_handle = hnd;
49
50     ALenum error = alGetError();
51     if(error!=AL_NO_ERROR)
52     {
53         throw QString("nSoundSource: alGenSources() failed.");
54     }
55
56     alSourcef(m_handle, AL_GAIN, m_gainMirror);
57     alSource3f(m_handle, AL_POSITION, 0.0f ,0.0f ,0.0f);
58     alSource3f(m_handle, AL_VELOCITY, 0.0f ,0.0f ,0.0f);
59     alSource3f(m_handle, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
60     if(error!=AL_NO_ERROR)
61         throw QString("nSoundSource: Setting of source properties failed.");
62
63 }
64
65 nSoundSource::~nSoundSource()
66 {
67     alDeleteSources(1, &m_handle);
68 }
69
70 // PROPERTIES
71
72 nSoundSource::nSoundSourceState nSoundSource::state()
73 {
74     alGetError();
75
76     int state;
77     alGetSourcei(m_handle, AL_SOURCE_STATE, &state);
78
79     switch (state)
80     {
81     case AL_INITIAL:
82         return SSS_INITIAL;
83
84     case AL_PLAYING:
85         return SSS_PLAYING;
86
87     case AL_PAUSED:
88         return SSS_PAUSED;
89
90     case AL_STOPPED:
91         return SSS_STOPPED;
92     }
93
94     return SSS_UNKNOWN;
95
96 }
97
98 qreal nSoundSource::gain()
99 {
100     return m_gainMirror;
101 }
102
103 void nSoundSource::setGain(qreal f)
104 {
105     if(f<0.0f)
106         f=0.0f;
107     alSourcef(m_handle, AL_GAIN, f);    
108     m_gainMirror = f;
109 }
110
111
112 qreal nSoundSource::pitch()
113 {
114     ALfloat pitch;
115     alGetSourcef(m_handle, AL_PITCH, &pitch);
116     return pitch;
117 }
118
119 void nSoundSource::setPitch(qreal f)
120 {
121     if(f<0.0f)
122         f=0.0f;
123     alSourcef(m_handle, AL_PITCH, f);
124 }
125
126
127 qreal nSoundSource::rolloffFactor()
128 {
129     ALfloat rolloff;
130     alGetSourcef(m_handle, AL_ROLLOFF_FACTOR, &rolloff);
131     return rolloff;
132 }
133
134 void nSoundSource::setRolloffFactor(qreal f)
135 {
136     if(f<0.0f)
137         f=0.0f;
138     alSourcef(m_handle, AL_ROLLOFF_FACTOR, f);
139 }
140
141
142 bool nSoundSource::loop()
143 {
144     ALint loop;
145     alGetSourcei(m_handle, AL_LOOPING, &loop);
146     return (loop?true:false);
147 }
148
149 void nSoundSource::setLoop(bool b)
150 {
151     alSourcei(m_handle, AL_LOOPING, (b?AL_TRUE:AL_FALSE));
152 }
153
154 QVector3D nSoundSource::position()
155 {
156     ALfloat x,y,z;
157     alGetSource3f(m_handle, AL_POSITION, &x, &y, &z);
158     return QVector3D(x,y,z);
159 }
160
161 void nSoundSource::setPosition(QVector3D pos)
162 {
163     alSource3f(m_handle, AL_POSITION, pos.x(), pos.y(), pos.z() );
164 }
165
166
167 // METHODS
168
169 bool nSoundSource::update(qreal frameTime)
170 {
171     if(m_fading)
172     {
173         qreal newGain = m_gainMirror + frameTime*m_fadeDeltaPerSecond;
174         if( ((m_fadeDeltaPerSecond < 0.0f)&&(newGain<m_fadeTarget)) ||
175             ((m_fadeDeltaPerSecond > 0.0f)&&(newGain>m_fadeTarget)) )
176         {
177             newGain = m_fadeTarget;
178             m_fading = false;
179         }
180         setGain(newGain);
181     }if(destroyAfterStopped() && state() == SSS_STOPPED)
182     {
183         return false;
184     }
185
186     return true;
187 }
188
189 void nSoundSource::fade(qreal to, qreal duration, qreal from)
190 {
191     if(to==from)
192     {
193         setGain(to);
194         m_fading = false;
195         return;
196     }
197
198     qreal newGain;
199     if(from >= 0.0f)
200     {
201         setGain(from);
202         newGain = from;
203     }else newGain = gain();
204
205     m_fadeTarget = to;
206     m_fadeDeltaPerSecond = (to - newGain)/duration;
207     m_fading = true;
208
209 }
210
211 void nSoundSource::attachBuffer(nSoundBuffer * buffer)
212 {
213     if(!buffer) return;
214     alGetError();
215
216     ALint sourceType;
217     alGetSourcei(m_handle, AL_SOURCE_TYPE, &sourceType);
218     if(sourceType == AL_STREAMING)
219         throw QString("nSoundSource: Tried to play a single buffer on a streaming source.");
220
221     alSourcei(m_handle, AL_BUFFER, buffer->openalHandle());
222
223     ALenum err = alGetError();
224     if(err!=AL_NO_ERROR)
225         throw QString("nSoundSource: failed to bind buffer \"")+buffer->objectName()+
226                 QString("\" to source \"")+objectName()+QString("\".");
227 }
228
229 void nSoundSource::play()
230 {
231     alGetError();
232     alSourcePlay(m_handle);
233     if(alGetError()!=AL_NO_ERROR)
234         throw QString("nSoundSource: Failed to play source.");
235 }
236
237 void nSoundSource::pause()
238 {
239     alGetError();
240     alSourcePause(m_handle);
241     if(alGetError()!=AL_NO_ERROR)
242         throw QString("nSoundSource: Failed to pause source.");
243 }
244
245 void nSoundSource::stop()
246 {
247     alGetError();
248     alSourceStop(m_handle);
249     if(alGetError()!=AL_NO_ERROR)
250         throw QString("nSoundSource: Failed to stop source.");
251 }
252
253 void nSoundSource::rewind()
254 {
255     alGetError();
256     alSourceRewind(m_handle);
257     if(alGetError()!=AL_NO_ERROR)
258         throw QString("nSoundSource: Failed to rewind source.");
259 }
260
261 // GAIN CFG SUPPORT
262
263 bool nSoundSource::_m_gainsInitialized = false;
264 qreal nSoundSource::_m_musicGain = 0.0f;
265 qreal nSoundSource::_m_sfxGain = 0.0f;
266 qreal nSoundSource::_m_voiceGain = 0.0f;
267 qreal nSoundSource::_m_ambienceGain = 0.0f;
268
269 #include <QSettings>
270
271 void nSoundSource::_resetRoleGains()
272 {
273     QSettings settings;
274     settings.beginGroup("Audio");
275     _m_musicGain = settings.value("MusicGain", 60).toFloat()/100.0f;
276     _m_sfxGain = settings.value("SfxGain", 90).toFloat()/100.0f;
277     _m_voiceGain = settings.value("VoiceGain", 70).toFloat()/100.0f;
278     _m_ambienceGain = settings.value("AmbienceGain", 60).toFloat()/100.0f;
279     _m_gainsInitialized = true;
280     settings.endGroup();
281
282     _m_gainsInitialized = true;
283 }
284
285 qreal nSoundSource::_roleGainVolume(nSoundSourceRole role)
286 {
287     if(!_m_gainsInitialized)
288         nSoundSource::_resetRoleGains();
289
290     switch(role)
291     {
292     case SSR_MUSIC:
293         return _m_musicGain;
294     case SSR_SFX:
295         return _m_sfxGain;
296     case SSR_AMBIENCE:
297         return _m_ambienceGain;
298     case SSR_VOICE:
299         return _m_voiceGain;
300     default:
301         return 1.0f;
302     }
303
304 }
305