Skip to content

Commit

Permalink
Merge pull request #5959 from WickedSmoke/sound_cleanup
Browse files Browse the repository at this point in the history
Sound Cleanup
  • Loading branch information
Webster Sheets authored Nov 23, 2024
2 parents e2bf87f + 678d46e commit 9949946
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 144 deletions.
3 changes: 1 addition & 2 deletions src/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ void Player::StaticUpdate(const float timeStep)
m_creakSound.VolumeAnimate(creakVol, creakVol, 0.3f, 0.3f);
}
} else if (m_creakSound.IsPlaying()) {
m_creakSound.VolumeAnimate(0.0f, 0.0f, 1.5f, 1.5f);
m_creakSound.SetOp(Sound::OP_STOP_AT_TARGET_VOLUME);
m_creakSound.FadeOut(1.5f);
}
m_atmosAccel = current_atmosAccel;

Expand Down
45 changes: 9 additions & 36 deletions src/sound/AmbientSounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,15 @@ void AmbientSounds::Update()

if (Pi::player->GetFlightState() == Ship::DOCKED) {
if (s_starNoise.IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_starNoise.VolumeAnimate(target, dv_dt);
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_starNoise.FadeOut(1.0f, Sound::OP_REPEAT);
}
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
if (s_atmosphereNoises[i].IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_atmosphereNoises[i].FadeOut(1.0f, Sound::OP_REPEAT);
}
}
if (s_planetSurfaceNoise.IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_planetSurfaceNoise.VolumeAnimate(target, dv_dt);
s_planetSurfaceNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_planetSurfaceNoise.FadeOut(1.0f, Sound::OP_REPEAT);
}

if (!s_stationNoise.IsPlaying()) {
Expand All @@ -109,24 +100,15 @@ void AmbientSounds::Update()
} else if (Pi::player->GetFlightState() == Ship::LANDED) {
/* Planet surface noise on rough-landing */
if (s_starNoise.IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_starNoise.VolumeAnimate(target, dv_dt);
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_starNoise.FadeOut(1.0f, Sound::OP_REPEAT);
}
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
if (s_atmosphereNoises[i].IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_atmosphereNoises[i].FadeOut(1.0f, Sound::OP_REPEAT);
}
}
if (s_stationNoise.IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_stationNoise.VolumeAnimate(target, dv_dt);
s_stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_stationNoise.FadeOut(1.0f, Sound::OP_REPEAT);
}

// lets try something random for the time being
Expand Down Expand Up @@ -166,20 +148,14 @@ void AmbientSounds::Update()
}
} else {
if (s_stationNoise.IsPlaying()) {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
s_stationNoise.VolumeAnimate(target, dv_dt);
s_stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_stationNoise.FadeOut(1.0f, Sound::OP_REPEAT);
}
if (Pi::game->IsNormalSpace()) {
StarSystem *s = Pi::game->GetSpace()->GetStarSystem().Get();
if (astroNoiseSeed != s->GetSeed()) {
// change sound!
astroNoiseSeed = s->GetSeed();
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 0.1f, 0.1f };
s_starNoise.VolumeAnimate(target, dv_dt);
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_starNoise.FadeOut(0.1f, Sound::OP_REPEAT);
// XXX the way Sound::Event works isn't totally obvious.
// to destroy the object doesn't stop the sound. it is
// really just a sound event reference
Expand Down Expand Up @@ -255,11 +231,8 @@ void AmbientSounds::Update()
}
}
} else {
const float target[2] = { 0.0f, 0.0f };
const float dv_dt[2] = { 1.0f, 1.0f };
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
s_atmosphereNoises[i].FadeOut(1.0f, Sound::OP_REPEAT);
}
}
}
Expand Down
100 changes: 72 additions & 28 deletions src/sound/Sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,21 +172,33 @@ namespace Sound {
(*volRightOut) = Clamp((*volRightOut), 0.0f, 1.0f);
}

eventid BodyMakeNoise(const Body *b, const char *sfx, float vol)
void BodyMakeNoise(const Body *b, const char *sfx, float vol)
{
float vl, vr;
CalculateStereo(b, vol, &vl, &vr);
return Sound::PlaySfx(sfx, vl, vr, 0);
Sound::PlaySfx(sfx, vl, vr, 0);
}

struct Sample {
uint16_t *buf;
uint32_t buf_len;
uint32_t channels;
int upsample; // 1 = 44100, 2=22050
/* if buf is null, this will be path to an ogg we must stream */
std::string path;
bool isMusic;
};

typedef uint32_t eventid;

struct SoundEvent {
const Sample *sample;
OggVorbis_File *oggv; // if sample->buf = 0 then stream this
OggFileDataStream ogg_data_stream;
Uint32 buf_pos;
uint32_t buf_pos;
float volume[2]; // left and right channels
eventid identifier;
Uint32 op;
uint32_t op;

float targetVolume[2];
float rateOfChange[2]; // per sample
Expand Down Expand Up @@ -215,20 +227,6 @@ namespace Sound {
return nullptr;
}

bool SetOp(eventid id, Op op)
{
if (id == 0) return false;
bool ret = false;
SDL_LockAudioDevice(m_audioDevice);
SoundEvent *se = GetEvent(id);
if (se) {
se->op = op;
ret = true;
}
SDL_UnlockAudioDevice(m_audioDevice);
return ret;
}

static void DestroyEvent(SoundEvent *ev)
{
if (ev->oggv) {
Expand All @@ -244,12 +242,12 @@ namespace Sound {
/*
* Volume should be 0-65535
*/
static Uint32 identifier = 1;
eventid PlaySfx(const char *fx, const float volume_left, const float volume_right, const Op op)
static uint32_t identifier = 1;
static eventid PlaySfxSample(Sample *sample, const float volume_left, const float volume_right, const Op op)
{
SDL_LockAudioDevice(m_audioDevice);
unsigned int idx;
Uint32 age;
uint32_t age;
/* find free wavstream (first two reserved for music) */
for (idx = 2; idx < MAX_WAVSTREAMS; idx++) {
if (!wavstream[idx].sample) break;
Expand All @@ -266,7 +264,7 @@ namespace Sound {
}
DestroyEvent(&wavstream[idx]);
}
wavstream[idx].sample = GetSample(fx);
wavstream[idx].sample = sample;
wavstream[idx].oggv = 0;
wavstream[idx].buf_pos = 0;
wavstream[idx].volume[0] = volume_left * GetSfxVolume();
Expand All @@ -280,17 +278,25 @@ namespace Sound {
return identifier++;
}

//unlike PlaySfx, we want uninterrupted play and do not care about age
void PlaySfx(const char *fx, const float volume_left, const float volume_right, const Op op)
{
Sample* sample = GetSample(fx);
if (sample) {
PlaySfxSample(sample, volume_left, volume_right, op);
}
}

//unlike PlaySfxSample, we want uninterrupted play and do not care about age
//alternate between two streams for crossfade
static int nextMusicStream = 0;
eventid PlayMusic(const char *fx, const float volume_left, const float volume_right, const Op op)
static eventid PlayMusicSample(Sample *sample, const float volume_left, const float volume_right, const Op op)
{
const int idx = nextMusicStream;
nextMusicStream ^= 1;
SDL_LockAudioDevice(m_audioDevice);
if (wavstream[idx].sample)
DestroyEvent(&wavstream[idx]);
wavstream[idx].sample = GetSample(fx);
wavstream[idx].sample = sample;
wavstream[idx].oggv = nullptr;
wavstream[idx].buf_pos = 0;
wavstream[idx].volume[0] = volume_left;
Expand Down Expand Up @@ -690,7 +696,30 @@ namespace Sound {
void Event::Play(const char *fx, float volume_left, float volume_right, Op op)
{
Stop();
eid = PlaySfx(fx, volume_left, volume_right, op);
Sample* sample = GetSample(fx);
if (sample) {
eid = PlaySfxSample(sample, volume_left, volume_right, op);
}
}

void Event::PlayMusic(const char *fx, float volume, float fadeDelta, bool repeat, Event* fadeOut)
{
// The FadeOut, Stop, PlayMusicSample & VolumeAnimate calls perform
// five mutex lock operations. These could be reduced to a single
// lock/unlock if this were re-written.

if (fadeOut) {
fadeOut->FadeOut(fadeDelta);
}
Stop();
Sample* sample = GetSample(fx);
if (sample) {
float start = fadeDelta ? 0.0f : volume;
eid = PlayMusicSample(sample, start, start, repeat ? Sound::OP_REPEAT : 0);
if (fadeDelta) {
VolumeAnimate(volume, volume, fadeDelta, fadeDelta);
}
}
}

bool Event::Stop()
Expand Down Expand Up @@ -762,9 +791,24 @@ namespace Sound {
return status;
}

const std::map<std::string, Sample> &GetSamples()
bool Event::FadeOut(float dv_dt, Op op)
{
bool found = VolumeAnimate(0.0f, 0.0f, dv_dt, dv_dt);
if (found)
SetOp(op | Sound::OP_STOP_AT_TARGET_VOLUME);
return found;
}

const std::vector<std::string> GetMusicFiles()
{
return sfx_samples;
std::vector<std::string> songs;
songs.reserve(sfx_samples.size());
for (std::map<std::string, Sample>::const_iterator it = sfx_samples.begin();
it != sfx_samples.end(); ++it) {
if (it->second.isMusic)
songs.emplace_back(it->first.c_str());
}
return songs;
}

} /* namespace Sound */
41 changes: 14 additions & 27 deletions src/sound/Sound.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

#ifndef __OGGMIX_H
#define __OGGMIX_H
#ifndef __SOUND_H
#define __SOUND_H

#include <SDL_stdinc.h>
#include <cstdint>
#include <map>
#include <string>
#include <vector>
Expand All @@ -17,29 +17,17 @@ namespace Sound {
OP_REPEAT = (1 << 0),
OP_STOP_AT_TARGET_VOLUME = (1 << 1)
};
typedef Uint32 Op;

struct Sample {
Uint16 *buf;
Uint32 buf_len;
Uint32 channels;
int upsample; // 1 = 44100, 2=22050
/* if buf is null, this will be path to an ogg we must stream */
std::string path;
bool isMusic;
};
typedef uint32_t Op;

class Event {
public:
Event() :
eid(0) {}
Event(Uint32 id) :
eid(id) {}
virtual void Play(const char *fx, const float volume_left, const float volume_right, Op op);
void Play(const char *fx, const float volume_left, const float volume_right, Op op);
void Play(const char *fx) { Play(fx, 1.0f, 1.0f, 0); }
void PlayMusic(const char *fx, float volume, float fadeDelta, bool repeat, Event* fadeOut = nullptr);
bool Stop();
bool IsPlaying() const;
Uint32 EventId() { return eid; }
bool SetOp(Op op);
bool VolumeAnimate(const float targetVol1, const float targetVol2, const float dv_dt1, const float dv_dt2);
bool VolumeAnimate(const float targetVols[2], const float dv_dt[2])
Expand All @@ -52,11 +40,11 @@ namespace Sound {
{
return SetVolume(vol, vol);
}
bool FadeOut(float dv_dt, Op op = 0);

protected:
Uint32 eid;
private:
uint32_t eid;
};
typedef Uint32 eventid;

bool Init(bool automaticallyOpenDevice = true);
bool InitDevice(std::string &name);
Expand All @@ -69,17 +57,16 @@ namespace Sound {
void DestroyAllEvents();
void DestroyAllEventsExceptMusic();
void Pause(int on);
eventid PlaySfx(const char *fx, const float volume_left, const float volume_right, const Op op);
eventid PlayMusic(const char *fx, const float volume_left, const float volume_right, const Op op);
inline static eventid PlaySfx(const char *fx) { return PlaySfx(fx, 1.0f, 1.0f, 0); }
void PlaySfx(const char *fx, const float volume_left, const float volume_right, const Op op);
inline static void PlaySfx(const char *fx) { PlaySfx(fx, 1.0f, 1.0f, 0); }
void CalculateStereo(const Body *b, float vol, float *volLeftOut, float *volRightOut);
eventid BodyMakeNoise(const Body *b, const char *fx, float vol);
void BodyMakeNoise(const Body *b, const char *fx, float vol);
void SetMasterVolume(const float vol);
float GetMasterVolume();
void SetSfxVolume(const float vol);
float GetSfxVolume();
const std::map<std::string, Sample> &GetSamples();
const std::vector<std::string> GetMusicFiles();

} /* namespace Sound */

#endif /* __OGGMIX_H */
#endif /* __SOUND_H */
Loading

0 comments on commit 9949946

Please sign in to comment.