verus/Verus/src/Audio/Sound.h

142 lines
3.1 KiB
C++

#pragma once
namespace verus
{
namespace Audio
{
struct SoundFlags
{
enum
{
loaded = (ObjectFlags::user << 0),
is3D = (ObjectFlags::user << 1),
loop = (ObjectFlags::user << 2),
randOff = (ObjectFlags::user << 3),
user = (ObjectFlags::user << 4)
};
};
class Sound : public Object, public IO::AsyncCallback
{
Source _sources[8];
String _url;
ALuint _buffer = 0;
int _next = 0;
int _refCount = 0;
Range<float> _gain = 1;
Range<float> _pitch = 1;
float _length = 0;
float _referenceDistance = 4;
public:
struct Desc
{
CSZ _url = nullptr;
Range<float> _gain = 0.8f;
Range<float> _pitch = 1;
float _referenceDistance = 4;
bool _is3D = false;
bool _loop = false;
bool _randomOffset = false;
Desc(CSZ url) : _url(url) {}
Desc& Set3D(bool b = true) { _is3D = b; return *this; }
Desc& SetLoop(bool b = true) { _loop = b; return *this; }
Desc& SetGain(const Range<float>& gain) { _gain = gain; return *this; }
Desc& SetPitch(const Range<float>& pitch) { _pitch = pitch; return *this; }
Desc& SetRandomOffset(bool b = true) { _randomOffset = b; return *this; }
Desc& SetReferenceDistance(float rd) { _referenceDistance = rd; return *this; }
};
VERUS_TYPEDEFS(Desc);
Sound();
~Sound();
void Init(RcDesc desc);
bool Done();
virtual void Async_Run(CSZ url, RcBlob blob) override;
bool IsLoaded() const { return IsFlagSet(SoundFlags::loaded); }
void AddRef() { _refCount++; }
Str GetUrl() const { return _C(_url); }
void Update();
void UpdateHRTF();
SourcePtr NewSource(PSourcePtr pID = nullptr, Source::RcDesc desc = Source::Desc());
const Range<float>& GetGain() const { return _gain; }
const Range<float>& GetPitch() const { return _pitch; }
float GetLength() const { return _length; }
float GetRandomOffset() const;
void SetRandomOffset(bool b) { b ? SetFlag(SoundFlags::randOff) : ResetFlag(SoundFlags::randOff); }
bool HasRandomOffset() const { return IsFlagSet(SoundFlags::randOff); }
};
VERUS_TYPEDEFS(Sound);
class SoundPtr : public Ptr<Sound>
{
public:
void Init(Sound::RcDesc desc);
};
VERUS_TYPEDEFS(SoundPtr);
class SoundPwn : public SoundPtr
{
public:
~SoundPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(SoundPwn);
template<int NUM>
class SoundPwns
{
SoundPwn _sounds[NUM];
int _prev = 0;
public:
SoundPwns()
{
}
~SoundPwns()
{
Done();
}
void Init(Sound::RcDesc desc)
{
char buffer[200];
VERUS_FOR(i, NUM)
{
sprintf_s(buffer, desc._url, i);
Sound::Desc descs = desc;
descs._url = buffer;
_sounds[i].Init(descs);
}
}
void Done()
{
VERUS_FOR(i, NUM)
_sounds[i].Done();
}
RSoundPtr operator[](int i)
{
if (i < 0)
i = Utils::I().GetRandom().Next() & 0xFF; // Only positive.
i %= NUM;
if (i == _prev)
i = (i + 1) % NUM;
_prev = i;
return _sounds[i];
}
};
}
}