Leviathan  0.8.0.0
Leviathan game engine
Leviathan::SoundDevice Class Reference

Manages loading the audio library and provides some helpers. More...

#include <SoundDevice.h>

Public Member Functions

DLLEXPORT SoundDevice ()
 
DLLEXPORT ~SoundDevice ()
 
DLLEXPORT bool Init (bool simulatesound=false, bool noconsolelog=false)
 
DLLEXPORT void Release ()
 
DLLEXPORT void Tick (int PassedMs)
 
DLLEXPORT void SetSoundListenerPosition (const Float3 &pos, const Float4 &orientation)
 Loads the file and plays the sound. More...
 
DLLEXPORT void SetGlobalVolume (float vol)
 
DLLEXPORT void Play2DSoundEffect (const std::string &filename)
 Plays a 2d sound without possibility of interrupting. More...
 
DLLEXPORT AudioSource::pointer Play2DSound (const std::string &filename, bool looping, bool startpaused)
 Plays a 2d sound with options. More...
 
DLLEXPORT AudioSource::pointer CreateProceduralSound (ProceduralSoundData::pointer data, const char *soundname)
 Opens an audio source from a procedural data stream. More...
 
DLLEXPORT void BabysitAudio (AudioSource::pointer audio)
 This class holds the audio source until it has finished playing and then releases the reference. More...
 
DLLEXPORT cAudio::IAudioManager * GetAudioManager ()
 

Static Public Member Functions

static DLLEXPORT std::vector< std::string > GetAudioDevices (size_t *indexofdefault=nullptr)
 Returns a list of audio playback devices. More...
 

Detailed Description

Manages loading the audio library and provides some helpers.

Definition at line 20 of file SoundDevice.h.

Constructor & Destructor Documentation

◆ SoundDevice()

SoundDevice::SoundDevice ( )

Definition at line 20 of file SoundDevice.cpp.

20 {}

◆ ~SoundDevice()

SoundDevice::~SoundDevice ( )

Definition at line 21 of file SoundDevice.cpp.

22 {
23  Release();
24 }
DLLEXPORT void Release()
Definition: SoundDevice.cpp:99

Member Function Documentation

◆ BabysitAudio()

DLLEXPORT void SoundDevice::BabysitAudio ( AudioSource::pointer  audio)

This class holds the audio source until it has finished playing and then releases the reference.

Definition at line 210 of file SoundDevice.cpp.

211 {
213 
214  HandledAudioSources.push_back(audio);
215 }
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85
DLLEXPORT void AssertIfNotMainThread() const
Asserts if not called on the main thread.
Definition: Engine.h:105

◆ CreateProceduralSound()

DLLEXPORT AudioSource::pointer SoundDevice::CreateProceduralSound ( ProceduralSoundData::pointer  data,
const char *  soundname 
)

Opens an audio source from a procedural data stream.

Parameters
soundnameName for this audio source. Should be at least somewhat unique

Definition at line 198 of file SoundDevice.cpp.

200 {
201  if(!AudioManager || !data)
202  return nullptr;
203 
204  return AudioSource::MakeShared<AudioSource>(
205  AudioManager->createFromAudioDecoder(soundname, data->Properties.SourceName.c_str(),
206  CAUDIO_NEW ProceduralSoundStream(data)),
207  this);
208 }
Used to feed data retrieved from a callback to cAudio::IAudioSource.

◆ GetAudioDevices()

DLLEXPORT std::vector< std::string > SoundDevice::GetAudioDevices ( size_t *  indexofdefault = nullptr)
static

Returns a list of audio playback devices.

Parameters
indexofdefaultReturns the index of the default device (if not null)

Definition at line 217 of file SoundDevice.cpp.

219 {
220  std::vector<std::string> result;
221 
222  cAudio::IAudioDeviceList* devices = cAudio::createAudioDeviceList();
223 
224  if(!devices) {
225  LOG_ERROR("SoundDevice: GetAudioDevices: failed to get audio device list");
226  return {};
227  }
228 
229  const auto deviceCount = devices->getDeviceCount();
230  result.reserve(deviceCount);
231 
232  const auto defaultDeviceName = devices->getDefaultDeviceName();
233 
234  for(unsigned int i = 0; i < deviceCount; ++i) {
235 
236  const auto deviceName = devices->getDeviceName(i);
237 
238  if(deviceName.compare(defaultDeviceName) == 0 && indexofdefault) {
239 
240  *indexofdefault = i;
241  }
242 
243  result.push_back(deviceName);
244  }
245 
246  CAUDIO_DELETE devices;
247 
248  return result;
249 }
#define LOG_ERROR(x)
Definition: Define.h:90

◆ GetAudioManager()

DLLEXPORT cAudio::IAudioManager* Leviathan::SoundDevice::GetAudioManager ( )
inline

Definition at line 73 of file SoundDevice.h.

74  {
75  return AudioManager;
76  }

◆ Init()

bool SoundDevice::Init ( bool  simulatesound = false,
bool  noconsolelog = false 
)
Parameters
simulatenosoundIf true the sound device isn't initialized to simulate not having a valid audio device (or if the user just doesn't want sound)

Definition at line 26 of file SoundDevice.cpp.

27 {
28  AudioLogPath = StringOperations::RemoveExtension(Logger::Get()->GetLogFile(), false) +
29  "cAudioLog.html";
30 
31  AudioManager = cAudio::createAudioManager(
32  // No default init, we want to select the device
33  false,
34  // And write to a program specific log file
35  AudioLogPath.c_str(), noconsolelog);
36 
37  LEVIATHAN_ASSERT(AudioManager, "Failed to create cAudio manager");
38 
39  size_t defaultDevice = 0;
40  const auto devices = GetAudioDevices(&defaultDevice);
41 
42  if(simulatesound == true) {
43 
44  LOG_WARNING("SoundDevice: simulating not having a playing device");
45  return true;
46  }
47 
48  if(devices.empty() || defaultDevice >= devices.size()) {
49 
50  LOG_ERROR("SoundDevice: no sound devices detected");
51  return false;
52  }
53 
54  if(std::find(devices.begin(), devices.end(), devices[defaultDevice]) == devices.end()) {
55  // I have no clue how it would ever get here, but you never know
56  LOG_ERROR("SoundDevice: Default device doesn't exist. The code should not have "
57  "been able to get here.");
58  }
59 
60  LOG_INFO("Detected audio devices: ");
61 
62  for(const auto& dev : devices)
63  LOG_INFO("> " + dev);
64 
65  LOG_INFO("End of devices");
66 
67  std::string selectedDevice;
68  // There's no print error here if missing to make tests run
69  ObjectFileProcessor::LoadValueFromNamedVars<std::string>(
70  Engine::Get()->GetDefinition()->GetValues(), "AudioDevice", selectedDevice, "default");
71 
72  if(selectedDevice == "default") {
73 
74  selectedDevice = devices[defaultDevice];
75 
76  } else if(std::find(devices.begin(), devices.end(), selectedDevice) == devices.end()) {
77  LOG_ERROR("SoundDevice: selected audio device \"" + selectedDevice +
78  "\" doesn't exists. Using default");
79  selectedDevice = devices[defaultDevice];
80  }
81 
82  LOG_INFO("SoundDevice: Initializing sound with device: " + selectedDevice);
83 
84  if(!AudioManager->initialize(selectedDevice.c_str())) {
85 
86  LOG_ERROR("SoundDevice: initializing failed");
87  return false;
88  }
89 
90  ListeningPosition = AudioManager->getListener();
91 
92  // setup global volume //
93  SetGlobalVolume(1.f);
94 
95  ListeningPosition->setUpVector(cAudio::cVector3(0, 1, 0));
96 
97  return true;
98 }
#define LOG_INFO(x)
Definition: Define.h:88
#define LOG_ERROR(x)
Definition: Define.h:90
DLLEXPORT void SetGlobalVolume(float vol)
static const StringTypeN RemoveExtension(const StringTypeN &filepath, bool delpath=true)
#define LOG_WARNING(x)
Definition: Define.h:89
DLLEXPORT NamedVars * GetValues()
Definition: AppDefine.cpp:40
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:98
static DLLEXPORT std::vector< std::string > GetAudioDevices(size_t *indexofdefault=nullptr)
Returns a list of audio playback devices.
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
AppDef * GetDefinition()
Definition: Engine.h:205
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85

◆ Play2DSound()

DLLEXPORT AudioSource::pointer SoundDevice::Play2DSound ( const std::string &  filename,
bool  looping,
bool  startpaused 
)

Plays a 2d sound with options.

Note
If both looping and startpaused are false then this is the same as Play2DSoundEffect and returns null
Returns
The audio source that is playing the sound (this must be held onto until it is done playing, can be passed to BabysitAudio if not manually wanted to be managed or use the SoundEffect variant of this method) is null if looping and startpaused are false

Definition at line 171 of file SoundDevice.cpp.

173 {
174  if(!AudioManager)
175  return nullptr;
176 
177  if(!looping && !startpaused)
178  LOG_WARNING("SoundDevice: Play2DSound: called with same settings that "
179  "Play2DSoundEffect uses. looping or startpaused must be true to return an "
180  "AudioSource.");
181 
182  cAudio::IAudioSource* source =
183  AudioManager->play2D(filename.c_str(), looping, startpaused);
184 
185  if(!source) {
186  LOG_ERROR(
187  "SoundDevice: Play2DSound: failed to create IAudioSource from file: " + filename);
188 
189  if(!boost::filesystem::is_regular(filename))
190  LOG_INFO("SoundDevice: file '" + filename + "' doesn't exist");
191 
192  return nullptr;
193  }
194 
195  return AudioSource::MakeShared<AudioSource>(source, this);
196 }
#define LOG_INFO(x)
Definition: Define.h:88
#define LOG_ERROR(x)
Definition: Define.h:90
#define LOG_WARNING(x)
Definition: Define.h:89

◆ Play2DSoundEffect()

DLLEXPORT void SoundDevice::Play2DSoundEffect ( const std::string &  filename)

Plays a 2d sound without possibility of interrupting.

Definition at line 154 of file SoundDevice.cpp.

155 {
156  if(!AudioManager)
157  return;
158 
159  cAudio::IAudioSource* source = AudioManager->play2D(filename.c_str(), false, false);
160 
161  if(source) {
162 
163  LOG_ERROR("SoundDevice: Play2DSoundEffect: shouldn't return a source but it did. "
164  "Babysitting it");
165 
167  [=]() { this->BabysitAudio(AudioSource::MakeShared<AudioSource>(source, this)); });
168  }
169 }
#define LOG_ERROR(x)
Definition: Define.h:90
DLLEXPORT void RunOnMainThread(const std::function< void()> &function)
Runs the function now if on the main thread otherwise calls Invoke.
Definition: Engine.cpp:1185
DLLEXPORT void BabysitAudio(AudioSource::pointer audio)
This class holds the audio source until it has finished playing and then releases the reference...
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85

◆ Release()

void SoundDevice::Release ( )

Definition at line 99 of file SoundDevice.cpp.

100 {
101  HandledAudioSources.clear();
102 
103  if(AudioManager) {
104 
105  cAudio::destroyAudioManager(AudioManager);
106  AudioManager = nullptr;
107  }
108 }

◆ SetGlobalVolume()

DLLEXPORT void SoundDevice::SetGlobalVolume ( float  vol)
Parameters
volThe volume [0.f, 1.f]

Definition at line 144 of file SoundDevice.cpp.

145 {
146  if(!AudioManager)
147  return;
148 
149  vol = std::clamp(vol, 0.f, 1.f);
150 
151  AudioManager->setMasterVolume(vol);
152 }

◆ SetSoundListenerPosition()

DLLEXPORT void SoundDevice::SetSoundListenerPosition ( const Float3 pos,
const Float4 orientation 
)

Loads the file and plays the sound.

This creates a temporary SoundEffect on a background thread that is loaded from the file and destroyed once it finishes

Returns
False if the file doesn't exist or the sound couldn't be played for some other reason

Definition at line 121 of file SoundDevice.cpp.

123 {
124  // we need to create a vector from the angles //
125  // Float3 vec = Float3(-sin(pitchyawroll.X*DEGREES_TO_RADIANS),
126  // sin(pitchyawroll.Y*DEGREES_TO_RADIANS), -cos(pitchyawroll.X*DEGREES_TO_RADIANS));
127 
128  if(!ListeningPosition)
129  return;
130 
131  ListeningPosition->move(cAudio::cVector3(pos.X, pos.Y, pos.Z));
132 
133  bs::Quaternion quaternion(orientation);
134 
135  bs::Radian angle;
136  bs::Vector3 direction;
137 
138  // TODO: does this do the right thing?
139  quaternion.toAxisAngle(direction, angle); // toAngleAxis(angle, direction);
140 
141  ListeningPosition->setDirection(cAudio::cVector3(direction.x, direction.y, direction.z));
142 }

◆ Tick()

void SoundDevice::Tick ( int  PassedMs)

Definition at line 110 of file SoundDevice.cpp.

111 {
112  for(auto iter = HandledAudioSources.begin(); iter != HandledAudioSources.end(); ++iter) {
113 
114  if(!(*iter)->Get()->isPlaying()) {
115 
116  iter = HandledAudioSources.erase(iter);
117  }
118  }
119 }

The documentation for this class was generated from the following files: