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)) {
53 alGenSources(NUM_SRC, source);
54 ALenum err = alGetError();
55 if (err != AL_NO_ERROR) {
56 throw ALError(err, "alGenSources");
58 for (std::size_t i = 0; i < NUM_SRC; ++i) {
59 alSourcef(source[i], AL_REFERENCE_DISTANCE, 2.0f);
60 alSourcef(source[i], AL_ROLLOFF_FACTOR, 1.0f);
65 alDeleteSources(NUM_SRC, source);
66 ALenum err = alGetError();
67 if (err != AL_NO_ERROR) {
68 std::cerr << "warning: alDeleteSources failed with " << al_error_string(err) << std::endl;
69 //throw ALError(err, "alDeleteSources");
73 void Audio::Position(const glm::vec3 &pos) noexcept {
74 alListenerfv(AL_POSITION, glm::value_ptr(pos));
75 //std::cout << "listener at " << pos << std::endl;
78 void Audio::Velocity(const glm::vec3 &vel) noexcept {
79 alListenerfv(AL_VELOCITY, glm::value_ptr(vel));
82 void Audio::Orientation(const glm::vec3 &dir, const glm::vec3 &up) noexcept {
87 alListenerfv(AL_ORIENTATION, orient);
98 std::cerr << "unable to find free audio source" << std::endl;
102 ALuint src = source[i];
103 IntervalTimer &t = timer[i];
106 alSourcefv(src, AL_POSITION, glm::value_ptr(pos));
107 alSourcefv(src, AL_VELOCITY, glm::value_ptr(vel));
108 alSourcefv(src, AL_DIRECTION, glm::value_ptr(dir));
111 t = IntervalTimer(sound.Duration());
115 void Audio::StopAll() noexcept {
116 alSourceStopv(NUM_SRC, source);
117 for (std::size_t i = 0; i < NUM_SRC; ++i) {
118 alSourcei(source[i], AL_BUFFER, AL_NONE);
122 void Audio::Update(int dt) noexcept {
123 for (std::size_t i = 0; i < NUM_SRC; ++i) {
125 if (timer[i].HitOnce()) {
127 alSourceStop(source[i]);
128 alSourcei(source[i], AL_BUFFER, AL_NONE);
134 int Audio::NextFree() noexcept {
135 if (!timer[last_free].Running()) {
138 for (int i = (last_free + 1) % NUM_SRC; i != last_free; i = (i + 1) % NUM_SRC) {
139 if (!timer[i].Running()) {
151 alGenBuffers(1, &handle);
152 ALenum err = alGetError();
153 if (err != AL_NO_ERROR) {
154 throw ALError(err, "alGenBuffers");
158 Sound::Sound(const char *file)
159 : handle(alutCreateBufferFromFile(file)) {
160 if (handle == AL_NONE) {
161 throw ALError(alGetError(), "alutCreateBufferFromFile");
164 ALint size, channels, bits, freq;
165 alGetBufferi(handle, AL_SIZE, &size);
166 alGetBufferi(handle, AL_CHANNELS, &channels);
167 alGetBufferi(handle, AL_BITS, &bits);
168 alGetBufferi(handle, AL_FREQUENCY, &freq);
170 duration = size * 8 * 1000 / (channels * bits * freq);
174 if (handle != AL_NONE) {
175 alDeleteBuffers(1, &handle);
176 ALenum err = alGetError();
177 if (err != AL_NO_ERROR) {
178 std::cerr << "warning: alDeleteBuffers failed with " << al_error_string(err) << std::endl;
179 //throw ALError(err, "alDeleteBuffers");
184 Sound::Sound(Sound &&other)
185 : handle(other.handle) {
186 other.handle = AL_NONE;
189 Sound &Sound::operator =(Sound &&other) {
190 std::swap(handle, other.handle);
194 void Sound::Bind(ALuint src) const {
195 alSourcei(src, AL_BUFFER, handle);