AudioManager.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <iostream>
  16. #include <list>
  17. #include <boost/thread.hpp>
  18. #include "core/AudioManager.h"
  19. #include "core/XmlMusicsFile.h"
  20. #include "core/XmlSoundsFile.h"
  21. #include "core/Logger.h"
  22. /**
  23. * Audio manager singleton.
  24. */
  25. template<>AudioManager *Ogre::Singleton<AudioManager>::msSingleton = nullptr;
  26. ALsizei AudioManager::channel_buffer_number_ = 2;
  27. int AudioManager::channel_buffer_size_ = 96 * 1024;
  28. AudioManager::AudioManager():
  29. initialized_(false), thread_continue_(true), update_mutex_(), music_(&update_mutex_),
  30. fx_(&update_mutex_)
  31. {
  32. al_device_ = alcOpenDevice(nullptr);
  33. if (al_device_ != nullptr){
  34. al_context_ = alcCreateContext(al_device_, nullptr);
  35. if (al_context_ != nullptr){
  36. alcMakeContextCurrent(al_context_);
  37. // Listeners
  38. ALfloat position[3] = {0.0f, 0.0f, 0.0f};
  39. ALfloat velocity[3] = {0.0f, 0.0f, 0.0f};
  40. ALfloat orientation[6] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f};
  41. alListenerfv(AL_POSITION, position);
  42. alListenerfv(AL_VELOCITY, velocity);
  43. alListenerfv(AL_ORIENTATION, orientation);
  44. initialized_ = true;
  45. buffer_ = new char[channel_buffer_size_];
  46. update_thread_ = new boost::thread(boost::ref(*this));
  47. LOG_TRIVIAL("AudioManager initialised.");
  48. }
  49. else{
  50. LOG_ERROR(
  51. "AudioManager failed to initialised. Could not create context for sound device."
  52. );
  53. }
  54. }
  55. else LOG_ERROR("AudioManager failed to initialised. There's no default sound device.");
  56. // Load musics.
  57. XmlMusicsFile musics("./data/musics.xml");
  58. musics.LoadMusics();
  59. // Load sounds.
  60. XmlSoundsFile sounds("./data/sounds.xml");
  61. sounds.LoadSounds();
  62. }
  63. AudioManager::~AudioManager(){
  64. MusicStop();
  65. if (initialized_){
  66. thread_continue_ = false;
  67. update_thread_->join();
  68. delete update_thread_;
  69. delete[] buffer_;
  70. alcMakeContextCurrent(nullptr);
  71. alcDestroyContext(al_context_);
  72. alcCloseDevice(al_device_);
  73. LOG_TRIVIAL("AudioManager destroyed.");
  74. }
  75. }
  76. void AudioManager::operator()(){
  77. while(thread_continue_){
  78. Update();
  79. boost::xtime xt;
  80. boost::xtime_get(&xt, boost::TIME_UTC_);
  81. xt.nsec += 250000000; // sleep for 250 ms
  82. boost::thread::sleep(xt);
  83. update_thread_->yield();
  84. }
  85. }
  86. void AudioManager::Update(){
  87. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  88. music_.Update();
  89. fx_.Update();
  90. }
  91. void AudioManager::MusicPause(){
  92. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  93. music_.Pause();
  94. }
  95. void AudioManager::ScriptPlayMusic(const char* name){
  96. const Ogre::String name_str = Ogre::String(name);
  97. MusicPlay(name_str);
  98. }
  99. void AudioManager::MusicPlay(const Ogre::String& name){
  100. if (initialized_){
  101. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  102. AudioManager::Music* music = GetMusic(name);
  103. if (music == nullptr){
  104. LOG_ERROR("No music found with name \"" + name + "\".");
  105. return;
  106. }
  107. music_.SetLoop(music->loop);
  108. music_.Play(music->file);
  109. }
  110. }
  111. void AudioManager::SoundPlay(const Ogre::String& name){
  112. if (initialized_){
  113. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  114. AudioManager::Sound* fx = GetSound(name);
  115. if (fx == nullptr){
  116. LOG_ERROR("No sound found with name \"" + name + "\".");
  117. return;
  118. }
  119. fx_.SetLoop(-1);
  120. fx_.Play(fx->file);
  121. }
  122. }
  123. void AudioManager::ScriptPlaySound(const char* name){
  124. const Ogre::String name_str = Ogre::String(name);
  125. SoundPlay(name_str);
  126. }
  127. void AudioManager::ScriptPlaySound(const char* name, const int channel){ScriptPlaySound(name);}
  128. void AudioManager::ScriptPlaySounds(
  129. const char* name1, const char* name2, const char* name3, const char* name4
  130. ){
  131. // TODO: Playing only name1, implement the rest.
  132. ScriptPlaySound(name1);
  133. }
  134. void AudioManager::MusicStop(){
  135. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  136. music_.Stop();
  137. }
  138. void AudioManager::AddMusic(const AudioManager::Music& music){
  139. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  140. for (
  141. std::list<AudioManager::Music>::iterator it = music_list_.begin();
  142. it != music_list_.end();
  143. ++ it
  144. ){
  145. if (it->name == music.name){
  146. LOG_ERROR("Music with name '" + music.name + "' already exists.");
  147. return;
  148. }
  149. }
  150. music_list_.push_back(music);
  151. }
  152. void AudioManager::AddSound(const AudioManager::Sound& sound){
  153. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  154. for (
  155. std::list<AudioManager::Sound>::iterator it = sound_list_.begin();
  156. it != sound_list_.end();
  157. ++ it
  158. ){
  159. if (it->name == sound.name){
  160. LOG_ERROR("Sound with name '" + sound.name + "' already exists.");
  161. return;
  162. }
  163. }
  164. sound_list_.push_back(sound);
  165. }
  166. AudioManager::Music* AudioManager::GetMusic(const Ogre::String& name){
  167. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  168. for (auto it = music_list_.begin(); it != music_list_.end(); ++ it)
  169. if (it->name == name) return &(*it);
  170. return nullptr;
  171. }
  172. AudioManager::Sound* AudioManager::GetSound(const Ogre::String& name){
  173. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  174. for (auto it = sound_list_.begin(); it != sound_list_.end(); ++ it)
  175. if (it->name == name) return &(*it);
  176. return nullptr;
  177. }
  178. const char* AudioManager::ALError(){
  179. //ALenum error_code = alGetError();
  180. //if (error_code == AL_NO_ERROR)
  181. return nullptr;
  182. //else return alGetString(error_code);
  183. }
  184. const char* AudioManager::ALCError(const ALCdevice* device){
  185. //const ALCdevice *alc_device =
  186. // ((device == nullptr) ? const_cast< ALCdevice* >(al_device_) :
  187. // const_cast< ALCdevice* >(device));
  188. //ALCenum error_code = alcGetError(const_cast< ALCdevice* >(alc_device));
  189. //if (error_code == ALC_NO_ERROR)
  190. return nullptr;
  191. //else return alcGetString(const_cast< ALCdevice* >(device), error_code);
  192. }
  193. AudioManager::Player::Player(boost::recursive_mutex* mutex):
  194. loop_(-1.0), vorbis_info_(nullptr), vorbis_section_(0),
  195. stream_finished_(false), update_mutex_(mutex)
  196. {
  197. buffer_ = new char[1024 * 96];
  198. }
  199. AudioManager::Player::~Player(){Stop();}
  200. void AudioManager::Player::Pause(){
  201. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  202. alSourcePause(source_);
  203. }
  204. void AudioManager::Player::Play(const Ogre::String &file){
  205. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  206. // If the same track is already playing, don't restart.
  207. if (file_ == file) return;
  208. // Open vorbis file.
  209. if (ov_fopen(const_cast<char*>(file.c_str()), &vorbis_file_)){
  210. LOG_ERROR("Can't play file \"" + file + "\".");
  211. return;
  212. }
  213. file_ = file;
  214. // Get file info.
  215. vorbis_info_ = ov_info(&vorbis_file_, -1.0f);
  216. // Create sound source
  217. alGenSources(1, &source_);
  218. // Create buffers
  219. ALuint buffers[channel_buffer_number_];
  220. alGenBuffers(channel_buffer_number_, buffers);
  221. // Set source parameters
  222. alSourcei(source_, AL_LOOPING, AL_FALSE);
  223. // Fill buffers
  224. for (int i = 0; i < channel_buffer_number_; ++ i){
  225. ALsizei buffer_size = FillBuffer();
  226. if (buffer_size){
  227. alBufferData(
  228. buffers[i], vorbis_info_->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
  229. //static_cast<const ALvoid*>(AudioManager::getSingleton().buffer_),
  230. static_cast<const ALvoid*>(buffer_),
  231. static_cast<ALsizei>(buffer_size), static_cast<ALsizei>(vorbis_info_->rate)
  232. );
  233. alSourceQueueBuffers(source_, 1, &buffers[i]);
  234. }
  235. else{
  236. stream_finished_ = true;
  237. alDeleteBuffers(1, &buffers[i]);
  238. }
  239. }
  240. // Start playback
  241. alSourcePlay(source_);
  242. }
  243. void AudioManager::Player::Stop(){
  244. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  245. // Stop source
  246. alSourceStop(source_);
  247. // Get source buffers
  248. int queued_count = 0;
  249. alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued_count);
  250. // Dequeue and delete buffers
  251. for(int i = 0; i < queued_count; ++ i){
  252. ALuint buffer_id;
  253. alSourceUnqueueBuffers(source_, 1, &buffer_id);
  254. alDeleteBuffers(1, &buffer_id);
  255. }
  256. // Delete source
  257. alDeleteSources(1, &source_);
  258. // Cleanup
  259. ov_clear(&vorbis_file_);
  260. stream_finished_ = false;
  261. file_ = "";
  262. }
  263. void AudioManager::Player::SetLoop(const float loop){
  264. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  265. loop_ = loop;
  266. }
  267. void AudioManager::Player::Update(){
  268. // Try to fill processed buffers
  269. int processed;
  270. alGetSourcei(source_, AL_BUFFERS_PROCESSED, &processed);
  271. for(int i = 0; i < processed; ++i){
  272. // Try to fill buffer
  273. ALsizei buffer_size = FillBuffer();
  274. if (buffer_size){
  275. ALuint buffer_id;
  276. alSourceUnqueueBuffers(source_, 1, &buffer_id);
  277. alBufferData(
  278. buffer_id, vorbis_info_->channels == 1 ?
  279. AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
  280. //static_cast<const ALvoid*>(AudioManager::getSingleton().buffer_),
  281. static_cast<const ALvoid*>(buffer_),
  282. static_cast<ALsizei>(buffer_size), static_cast<ALsizei>(vorbis_info_->rate)
  283. );
  284. alSourceQueueBuffers(source_, 1, &buffer_id);
  285. }
  286. // Finished reading stream
  287. else{
  288. stream_finished_ = true;
  289. break;
  290. }
  291. }
  292. if (stream_finished_ && loop_ < 0){
  293. Stop();
  294. }
  295. // Manage source state
  296. alGetSourcei(source_, AL_BUFFERS_PROCESSED, &processed);
  297. int queued;
  298. alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued);
  299. if (stream_finished_ && processed == queued) Stop();
  300. else{
  301. ALenum source_state;
  302. alGetSourcei(source_, AL_SOURCE_STATE, &source_state);
  303. if (source_state == AL_STOPPED) alSourcePlay(source_);
  304. }
  305. }
  306. ALsizei AudioManager::Player::FillBuffer(){
  307. ALsizei read = 0;
  308. if (stream_finished_) return read;
  309. //char *&buffer = AudioManager::getSingleton().buffer_;
  310. char *&buffer = buffer_;
  311. bool finished = false;
  312. do{
  313. long result = ov_read(
  314. &vorbis_file_, buffer + read, channel_buffer_size_ - read, 0, 2, 1, &vorbis_section_
  315. );
  316. switch(result){
  317. // Error
  318. case OV_HOLE:
  319. case OV_EBADLINK:
  320. case OV_EINVAL:
  321. finished = true;
  322. break;
  323. // End of stream
  324. case 0:
  325. // If there isn't loop point or can't seek
  326. if (loop_ < 0.0f || ov_time_seek(&vorbis_file_, loop_)) finished = true;
  327. break;
  328. // Readed "result" bytes
  329. default:
  330. read += result;
  331. if (read == channel_buffer_size_) finished = true;
  332. }
  333. }
  334. while (finished == false);
  335. return read;
  336. }
  337. float AudioManager::Player::GetPosition(){
  338. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  339. int play_offset;
  340. alGetSourcei(source_, AL_SAMPLE_OFFSET, &play_offset);
  341. return (
  342. ov_pcm_tell(&vorbis_file_)
  343. - (
  344. channel_buffer_number_ * channel_buffer_size_ / vorbis_info_->channels / sizeof(int16_t)
  345. - play_offset
  346. )
  347. ) * 1000 / vorbis_info_->rate;
  348. }