Sound.cpp
1// Copyright 2019 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4
5#include <AL/al.h>
6#include <AL/alc.h>
7
8#include <iostream>
9#include <smk/Audio.hpp>
10#include <smk/Sound.hpp>
11
12namespace smk {
13
14void Sound::EnsureSourceIsCreated() {
15 if (source_) {
16 return;
17 }
18
19 if (!Audio::Initialized()) {
20 static bool once = true;
21 if (once) {
22 std::cerr
23 << "Error: smk::Audio has not been initialized. Please create a "
24 "smk::Audio instance in the main() function before creating a "
25 "smk::Sound"
26 << std::endl;
27 once = false;
28 }
29 }
30
31 alGenSources(1, &source_);
32}
33
34/// @brief Create a null Sound.
35Sound::Sound() = default;
36
37/// @brief Create a sound reading data from a SoundBuffer
38/// @param buffer The SoundBuffer to read the data from.
39Sound::Sound(const SoundBuffer& buffer) : buffer_(&buffer) {}
40
41Sound::~Sound() {
42 Stop();
43 if (source_) {
44 alDeleteSources(1, &source_);
45 }
46}
47
48/// @brief Start playing the sound.
50 if (!buffer_ || !buffer_->buffer()) {
51 return;
52 }
53 if (is_playing_) {
54 Stop();
55 }
56 EnsureSourceIsCreated();
57 alSourcei(source_, AL_BUFFER, ALint(buffer_->buffer()));
58 alSourcePlay(source_);
59 is_playing_ = true;
60}
61
62/// @brief Stop playing the sound.
64 if (!source_ || !buffer_ || !is_playing_) {
65 return;
66 }
67 alSourceStop(source_);
68 alSourcei(source_, AL_BUFFER, 0);
69 is_playing_ = false;
70}
71
72/// @brief Specify whether the sound must restart when it has reached the end.
73/// @param looping whether the sound must restart when it has reached the end.
74void Sound::SetLoop(bool looping) {
75 EnsureSourceIsCreated();
76 alSourcei(source_, AL_LOOPING, looping);
77}
78
79/// @return return whether the sound is currently playing something or not.
80bool Sound::IsPlaying() const {
81 if (!source_) {
82 return false;
83 }
84 ALint state = {};
85 alGetSourcei(source_, AL_SOURCE_STATE, &state);
86 return (state == AL_PLAYING);
87}
88
89Sound::Sound(Sound&& o) noexcept {
90 operator=(std::move(o));
91}
92
93Sound& Sound::operator=(Sound&& o) noexcept {
94 std::swap(buffer_, o.buffer_);
95 std::swap(source_, o.source_);
96 std::swap(is_playing_, o.is_playing_);
97 return *this;
98}
99
100void Sound::SetVolume(float volume) {
101 if (!source_) {
102 return;
103 }
104 EnsureSourceIsCreated();
105 alSourcef(source_, AL_GAIN, volume);
106}
107
108} // namespace smk
static bool Initialized()
Definition: Audio.cpp:91
A sound file loaded in memory.
Definition: SoundBuffer.hpp:33
Represent a sound being played.
Definition: Sound.hpp:31
void Stop()
Stop playing the sound.
Definition: Sound.cpp:63
bool IsPlaying() const
Definition: Sound.cpp:80
void SetLoop(bool looping)
Specify whether the sound must restart when it has reached the end.
Definition: Sound.cpp:74
void Play()
Start playing the sound.
Definition: Sound.cpp:49
Sound()
Create a null Sound.