8 #include <glm/gtc/type_ptr.hpp>
9 #include <glm/gtx/io.hpp>
14 const char *al_error_string(ALenum num) {
19 return "invalid name";
21 return "invalid enum";
22 case AL_INVALID_VALUE:
23 return "invalid value";
24 case AL_INVALID_OPERATION:
25 return "invalid operation";
26 case AL_OUT_OF_MEMORY:
27 return "out of memory";
29 return "unknown AL error";
32 std::string al_error_append(ALenum num, std::string msg) {
33 return msg + ": " + al_error_string(num);
40 ALError::ALError(ALenum num)
41 : std::runtime_error(al_error_string(num)) {
45 ALError::ALError(ALenum num, const std::string &msg)
46 : std::runtime_error(al_error_append(num, msg)) {
52 alGenSources(NUM_SRC, source);
53 ALenum err = alGetError();
54 if (err != AL_NO_ERROR) {
55 throw ALError(err, "alGenSources");
57 for (std::size_t i = 0; i < NUM_SRC; ++i) {
58 alSourcef(source[i], AL_REFERENCE_DISTANCE, 2.0f);
59 alSourcef(source[i], AL_ROLLOFF_FACTOR, 1.0f);
64 alDeleteSources(NUM_SRC, source);
65 ALenum err = alGetError();
66 if (err != AL_NO_ERROR) {
67 std::cerr << "warning: alDeleteSources failed with " << al_error_string(err) << std::endl;
68 //throw ALError(err, "alDeleteSources");
72 void Audio::Position(const glm::vec3 &pos) noexcept {
73 alListenerfv(AL_POSITION, glm::value_ptr(pos));
74 //std::cout << "listener at " << pos << std::endl;
77 void Audio::Velocity(const glm::vec3 &vel) noexcept {
78 alListenerfv(AL_VELOCITY, glm::value_ptr(vel));
81 void Audio::Orientation(const glm::vec3 &dir, const glm::vec3 &up) noexcept {
86 alListenerfv(AL_ORIENTATION, orient);
97 std::cerr << "unable to find free audio source" << std::endl;
101 ALuint src = source[i];
102 IntervalTimer &t = timer[i];
105 alSourcefv(src, AL_POSITION, glm::value_ptr(pos));
106 alSourcefv(src, AL_VELOCITY, glm::value_ptr(vel));
107 alSourcefv(src, AL_DIRECTION, glm::value_ptr(dir));
110 t = IntervalTimer(sound.Duration());
114 void Audio::StopAll() noexcept {
115 alSourceStopv(NUM_SRC, source);
116 for (std::size_t i = 0; i < NUM_SRC; ++i) {
117 alSourcei(source[i], AL_BUFFER, AL_NONE);
121 void Audio::Update(int dt) noexcept {
122 for (std::size_t i = 0; i < NUM_SRC; ++i) {
124 if (timer[i].HitOnce()) {
126 alSourceStop(source[i]);
127 alSourcei(source[i], AL_BUFFER, AL_NONE);
133 int Audio::NextFree() noexcept {
134 if (!timer[last_free].Running()) {
137 for (int i = (last_free + 1) % NUM_SRC; i != last_free; i = (i + 1) % NUM_SRC) {
138 if (!timer[i].Running()) {
150 alGenBuffers(1, &handle);
151 ALenum err = alGetError();
152 if (err != AL_NO_ERROR) {
153 throw ALError(err, "alGenBuffers");
157 Sound::Sound(const char *file)
158 : handle(alutCreateBufferFromFile(file)) {
159 if (handle == AL_NONE) {
160 throw ALError(alGetError(), "alutCreateBufferFromFile");
163 ALint size, channels, bits, freq;
164 alGetBufferi(handle, AL_SIZE, &size);
165 alGetBufferi(handle, AL_CHANNELS, &channels);
166 alGetBufferi(handle, AL_BITS, &bits);
167 alGetBufferi(handle, AL_FREQUENCY, &freq);
169 duration = size * 8 * 1000 / (channels * bits * freq);
173 if (handle != AL_NONE) {
174 alDeleteBuffers(1, &handle);
175 ALenum err = alGetError();
176 if (err != AL_NO_ERROR) {
177 std::cerr << "warning: alDeleteBuffers failed with " << al_error_string(err) << std::endl;
178 //throw ALError(err, "alDeleteBuffers");
183 Sound::Sound(Sound &&other)
184 : handle(other.handle) {
185 other.handle = AL_NONE;
188 Sound &Sound::operator =(Sound &&other) {
189 std::swap(handle, other.handle);
193 void Sound::Bind(ALuint src) const {
194 alSourcei(src, AL_BUFFER, handle);