73 glm::vec3 listenerPos = glm::vec3(0.0f);
77 log(LogLevel::ERROR,
"No valid camera entity found");
83 comp.autoPlay =
false;
86 if (comp.getAudioClip() ==
nullptr && !comp.audioFilePath.empty()) {
88 auto newClip = std::make_unique<AudioClip>(comp.audioFilePath, vfs);
90 clipCache[comp.audioFilePath] = std::move(newClip);
93 comp.stateDirty =
false;
97 comp.setAudioClip(
clipCache[comp.audioFilePath].get());
100 if (comp.stateDirty) {
101 SDL_AudioStream* stream =
streamMap[entity];
103 if (comp.getState() == AudioState::PLAYING) {
104 if (comp.getAudioClip() && comp.getAudioClip()->valid) {
105 if (stream) SDL_DestroyAudioStream(stream);
107 stream = SDL_CreateAudioStream(&comp.getAudioClip()->spec, NULL);
108 SDL_BindAudioStream(deviceID, stream);
109 SDL_PutAudioStreamData(stream, comp.getAudioClip()->buffer, comp.getAudioClip()->length);
114 else if (comp.getState() == AudioState::STOPPED) {
116 SDL_DestroyAudioStream(stream);
121 else if (comp.getState() == AudioState::PAUSED) {
122 if (stream) SDL_UnbindAudioStream(stream);
125 comp.stateDirty =
false;
131 SDL_AudioStream* stream =
streamMap[entity];
137 if (comp.loop && SDL_GetAudioStreamAvailable(stream) < comp.getAudioClip()->length / 2) {
138 SDL_PutAudioStreamData(stream, comp.getAudioClip()->buffer, comp.getAudioClip()->length);
141 if (!comp.loop && SDL_GetAudioStreamAvailable(stream) == 0) {
142 SDL_DestroyAudioStream(stream);
145 comp.stateDirty =
false;
149 float finalVolume = comp.volume;
153 float dist = glm::distance(listenerPos, transform.getWorldPosition());
155 if (dist > comp.distance) {
158 finalVolume = comp.volume * (1.0f - (dist / comp.distance));
163 SDL_SetAudioStreamGain(stream, finalVolume);
164 SDL_SetAudioStreamFrequencyRatio(stream, comp.pitch);
167 for (
auto it = standaloneStreams.begin(); it != standaloneStreams.end(); ) {
168 SDL_AudioStream* stream = it->stream;
170 if (it->loop && SDL_GetAudioStreamAvailable(stream) < it->clip->length / 2) {
171 SDL_PutAudioStreamData(stream, it->clip->buffer, it->clip->length);
174 else if (!it->loop && SDL_GetAudioStreamAvailable(stream) == 0) {
175 SDL_DestroyAudioStream(stream);
176 it = standaloneStreams.erase(it);
209 auto newClip = std::make_unique<AudioClip>(filePath, vfs);
210 if (newClip->valid) {
211 clipCache[filePath] = std::move(newClip);
213 log(LogLevel::ERROR,
"PlaySound2D: Failed to load audio clip - %s", filePath.c_str());
220 SDL_AudioStream* stream = SDL_CreateAudioStream(&clip->spec, NULL);
223 SDL_SetAudioStreamGain(stream, volume);
224 SDL_SetAudioStreamFrequencyRatio(stream, pitch);
226 SDL_BindAudioStream(deviceID, stream);
227 SDL_PutAudioStreamData(stream, clip->buffer, clip->length);
229 standaloneStreams.push_back({stream, clip, loop});
230 }
catch (
const std::exception& e) {
231 log(LogLevel::ERROR,
"PlaySound2D: Failed to play sound - %s", e.what());
void PlaySound2D(const std::string &filePath, float volume=1.0f, float pitch=1.0f, bool loop=false)
Quickly plays a 2D sound without requiring an entity or AudioSourceComponent.