1 // This file is part of Dust Racing 2D.
2 // Copyright (C) 2013 Jussi Lind <jussi.lind@iki.fi>
3 //
4 // Dust Racing 2D is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 // Dust Racing 2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Dust Racing 2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "openalsource.hpp"
17 #include "openaldata.hpp"
18 
19 #include <AL/alc.h>
20 
21 #include <memory>
22 #include <stdexcept>
23 
checkError()24 static bool checkError()
25 {
26     ALCenum error = alGetError();
27     return error == AL_NO_ERROR;
28 }
29 
OpenALSource(STFH::DataPtr data)30 OpenALSource::OpenALSource(STFH::DataPtr data)
31   : m_handle(0)
32 {
33     alGenSources((ALuint)1, &m_handle);
34 
35     alSourcef(m_handle, AL_PITCH, pitch());
36     alSourcef(m_handle, AL_GAIN, volume());
37     alSource3f(m_handle, AL_POSITION, 0, 0, 0);
38     alSource3f(m_handle, AL_VELOCITY, 0, 0, 0);
39     alSourcei(m_handle, AL_LOOPING, AL_FALSE);
40 
41     setData(data);
42 }
43 
setData(STFH::DataPtr data)44 void OpenALSource::setData(STFH::DataPtr data)
45 {
46     alGetError();
47 
48     if (auto soundData = std::dynamic_pointer_cast<OpenALData>(data))
49     {
50         Source::setData(data);
51         alSourcei(m_handle, AL_BUFFER, soundData->buffer());
52 
53         if (!checkError())
54         {
55             throw std::runtime_error("Failed to bind '" + data->path() + "'");
56         }
57     }
58     else
59     {
60         throw std::runtime_error("Incompatible sound data container for '" + data->path() + "'");
61     }
62 }
63 
play(bool loop)64 void OpenALSource::play(bool loop)
65 {
66     alSourcei(m_handle, AL_LOOPING, loop);
67     alSourcePlay(m_handle);
68 }
69 
stop()70 void OpenALSource::stop()
71 {
72     alSourceStop(m_handle);
73 }
74 
setVolume(float volume)75 void OpenALSource::setVolume(float volume)
76 {
77     STFH::Source::setVolume(volume);
78     alSourcef(m_handle, AL_GAIN, volume);
79 }
80 
setPitch(float pitch)81 void OpenALSource::setPitch(float pitch)
82 {
83     STFH::Source::setPitch(pitch);
84     alSourcef(m_handle, AL_PITCH, STFH::Source::pitch());
85 }
86 
setLocation(const STFH::Location & location)87 void OpenALSource::setLocation(const STFH::Location & location)
88 {
89     STFH::Source::setLocation(location);
90     alSource3f(m_handle, AL_POSITION, location.x(), location.y(), 0);
91 }
92 
setMaxDist(float maxDist)93 void OpenALSource::setMaxDist(float maxDist)
94 {
95     Source::setMaxDist(maxDist);
96     alSourcef(m_handle, AL_MAX_DISTANCE, maxDist);
97 }
98 
setReferenceDist(float refDist)99 void OpenALSource::setReferenceDist(float refDist)
100 {
101     Source::setReferenceDist(refDist);
102     alSourcef(m_handle, AL_REFERENCE_DISTANCE, refDist);
103 }
104 
~OpenALSource()105 OpenALSource::~OpenALSource()
106 {
107     alDeleteSources(1, &m_handle);
108 }
109