AudioManager.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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 <boost/algorithm/string.hpp>
  19. #include <boost/algorithm/string/split.hpp>
  20. #include "core/AudioManager.h"
  21. #include "core/Event.h"
  22. #include "core/XmlMusicsFile.h"
  23. #include "core/XmlSoundsFile.h"
  24. #include "core/Logger.h"
  25. /**
  26. * Audio manager singleton.
  27. */
  28. template<>AudioManager *Ogre::Singleton<AudioManager>::msSingleton = nullptr;
  29. ALsizei AudioManager::channel_buffer_number_ = 2;
  30. int AudioManager::channel_buffer_size_ = 96 * 1024;
  31. AudioManager::AudioManager():
  32. initialized_(false), thread_continue_(true), update_mutex_(), music_(&update_mutex_),
  33. battle_music_(&update_mutex_), fx_(&update_mutex_)
  34. {
  35. al_device_ = alcOpenDevice(nullptr);
  36. if (al_device_ != nullptr){
  37. al_context_ = alcCreateContext(al_device_, nullptr);
  38. if (al_context_ != nullptr){
  39. alcMakeContextCurrent(al_context_);
  40. // Listeners
  41. ALfloat position[3] = {0.0f, 0.0f, 0.0f};
  42. ALfloat velocity[3] = {0.0f, 0.0f, 0.0f};
  43. ALfloat orientation[6] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f};
  44. alListenerfv(AL_POSITION, position);
  45. alListenerfv(AL_VELOCITY, velocity);
  46. alListenerfv(AL_ORIENTATION, orientation);
  47. initialized_ = true;
  48. buffer_ = new char[channel_buffer_size_];
  49. update_thread_ = new boost::thread(boost::ref(*this));
  50. LOG_TRIVIAL("AudioManager initialised.");
  51. }
  52. else{
  53. LOG_ERROR(
  54. "AudioManager failed to initialised. Could not create context for sound device."
  55. );
  56. }
  57. }
  58. else LOG_ERROR("AudioManager failed to initialised. There's no default sound device.");
  59. // Load musics.
  60. XmlMusicsFile musics("./data/audio/musics/_musics.xml");
  61. musics.LoadMusics();
  62. // Load sounds.
  63. XmlSoundsFile sounds("./data/audio/sounds/_sounds.xml");
  64. sounds.LoadSounds();
  65. }
  66. AudioManager::~AudioManager(){
  67. MusicStop();
  68. if (initialized_){
  69. thread_continue_ = false;
  70. update_thread_->join();
  71. delete update_thread_;
  72. delete[] buffer_;
  73. alcMakeContextCurrent(nullptr);
  74. alcDestroyContext(al_context_);
  75. alcCloseDevice(al_device_);
  76. LOG_TRIVIAL("AudioManager destroyed.");
  77. }
  78. }
  79. void AudioManager::operator()(){
  80. while(thread_continue_){
  81. Update();
  82. boost::xtime xt;
  83. boost::xtime_get(&xt, boost::TIME_UTC_);
  84. xt.nsec += 250000000; // sleep for 250 ms
  85. boost::thread::sleep(xt);
  86. update_thread_->yield();
  87. }
  88. }
  89. void AudioManager::Input(const VGears::Event& event){}
  90. void AudioManager::UpdateDebug(){}
  91. void AudioManager::OnResize(){}
  92. void AudioManager::ClearField(){tracks_.clear();}
  93. void AudioManager::ClearBattle(){battle_track_ = -1;}
  94. void AudioManager::ClearWorld(){tracks_.clear();}
  95. void AudioManager::MusicPause(){
  96. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  97. if (module_ == Module::BATTLE) battle_music_.Pause();
  98. else music_.Pause();
  99. }
  100. void AudioManager::MusicResume(){
  101. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  102. if (module_ == Module::BATTLE) battle_music_.Resume();
  103. else music_.Resume();
  104. }
  105. void AudioManager::ScriptPlayMusic(const char* name){
  106. const Ogre::String name_str = Ogre::String(name);
  107. MusicPlay(name_str);
  108. }
  109. void AudioManager::MusicPlay(const Ogre::String& name){
  110. if (initialized_){
  111. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  112. AudioManager::Music* music = GetMusic(name);
  113. if (music == nullptr){
  114. LOG_ERROR("No music found with name \"" + name + "\".");
  115. return;
  116. }
  117. if (module_ == Module::BATTLE){
  118. music_.Pause();
  119. battle_music_.SetLoop(music->loop);
  120. battle_music_.Play(music->file);
  121. }
  122. else{
  123. battle_music_.Stop();
  124. music_.SetLoop(music->loop);
  125. music_.Play(music->file);
  126. }
  127. }
  128. }
  129. void AudioManager::SoundPlay(const Ogre::String& name){
  130. if (initialized_){
  131. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  132. AudioManager::Sound* fx = GetSound(name);
  133. if (fx == nullptr){
  134. LOG_ERROR("No sound found with name \"" + name + "\".");
  135. return;
  136. }
  137. fx_.SetLoop(-1);
  138. fx_.Play(fx->file);
  139. }
  140. }
  141. void AudioManager::ScriptPlaySound(const char* name){
  142. const Ogre::String name_str = Ogre::String(name);
  143. SoundPlay(name_str);
  144. }
  145. void AudioManager::ScriptPlaySound(const char* name, const int channel){ScriptPlaySound(name);}
  146. void AudioManager::ScriptPlaySounds(
  147. const char* name1, const char* name2, const char* name3, const char* name4
  148. ){
  149. // TODO: Playing only name1, implement the rest.
  150. ScriptPlaySound(name1);
  151. }
  152. void AudioManager::MusicStop(){
  153. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  154. music_.Stop();
  155. }
  156. void AudioManager::AddMusic(const AudioManager::Music& music){
  157. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  158. for (
  159. std::list<AudioManager::Music>::iterator it = music_list_.begin();
  160. it != music_list_.end();
  161. ++ it
  162. ){
  163. if (it->name == music.name){
  164. LOG_ERROR("Music with name '" + music.name + "' already exists.");
  165. return;
  166. }
  167. }
  168. music_list_.push_back(music);
  169. }
  170. void AudioManager::AddSound(const AudioManager::Sound& sound){
  171. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  172. for (
  173. std::list<AudioManager::Sound>::iterator it = sound_list_.begin();
  174. it != sound_list_.end();
  175. ++ it
  176. ){
  177. if (it->name == sound.name){
  178. LOG_ERROR("Sound with name '" + sound.name + "' already exists.");
  179. return;
  180. }
  181. }
  182. sound_list_.push_back(sound);
  183. }
  184. AudioManager::Music* AudioManager::GetMusic(const Ogre::String& name){
  185. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  186. for (auto it = music_list_.begin(); it != music_list_.end(); ++ it)
  187. if (it->name == name) return &(*it);
  188. return nullptr;
  189. }
  190. AudioManager::Sound* AudioManager::GetSound(const Ogre::String& name){
  191. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  192. for (auto it = sound_list_.begin(); it != sound_list_.end(); ++ it){
  193. if (boost::algorithm::to_lower_copy(it->name) == boost::algorithm::to_lower_copy(name))
  194. return &(*it);
  195. if (it->name.find("|") != std::string::npos){
  196. std::vector<std::string> names;
  197. boost::split(
  198. names, boost::algorithm::to_lower_copy(it->name),
  199. boost::is_any_of("|"), boost::token_compress_on
  200. );
  201. for (int n = 0; n < names.size(); n ++)
  202. if (names[n] == boost::algorithm::to_lower_copy(name)) return &(*it);
  203. }
  204. }
  205. return nullptr;
  206. }
  207. void AudioManager::AddTrack(const int id, const int track_id){
  208. if (id >= 0 && id < 255) tracks_[id] = track_id;
  209. }
  210. int AudioManager::ScriptGetTrack(int id){
  211. if (tracks_.count(id) == 0) return -1;
  212. else return tracks_[id];
  213. }
  214. int AudioManager::ScriptGetBattleTrack(){return battle_track_;}
  215. void AudioManager::ScriptSetBattleTrack(int track){battle_track_ = track;}
  216. void AudioManager::UpdateField(){
  217. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  218. music_.Update();
  219. fx_.Update();
  220. }
  221. void AudioManager::UpdateBattle(){
  222. boost::recursive_mutex::scoped_lock lock(update_mutex_);
  223. battle_music_.Update();
  224. fx_.Update();
  225. }
  226. void AudioManager::UpdateWorld(){UpdateField();}
  227. const char* AudioManager::ALError(){
  228. //ALenum error_code = alGetError();
  229. //if (error_code == AL_NO_ERROR)
  230. return nullptr;
  231. //else return alGetString(error_code);
  232. }
  233. const char* AudioManager::ALCError(const ALCdevice* device){
  234. //const ALCdevice *alc_device =
  235. // ((device == nullptr) ? const_cast< ALCdevice* >(al_device_) :
  236. // const_cast< ALCdevice* >(device));
  237. //ALCenum error_code = alcGetError(const_cast< ALCdevice* >(alc_device));
  238. //if (error_code == ALC_NO_ERROR)
  239. return nullptr;
  240. //else return alcGetString(const_cast< ALCdevice* >(device), error_code);
  241. }
  242. AudioManager::Player::Player(boost::recursive_mutex* mutex):
  243. loop_(-1.0), vorbis_info_(nullptr), vorbis_section_(0),
  244. stream_finished_(false), update_mutex_(mutex)
  245. {buffer_ = new char[1024 * 96];}
  246. AudioManager::Player::~Player(){Stop();}
  247. void AudioManager::Player::Pause(){
  248. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  249. alSourcePause(source_);
  250. }
  251. void AudioManager::Player::Resume(){
  252. if (!alIsSource(source_)){
  253. LOG_WARNING("AudioManager::Player: Resume called but no track was paused.");
  254. return;
  255. }
  256. alSourcePlay(source_);
  257. }
  258. void AudioManager::Player::Play(const Ogre::String &file){
  259. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  260. // If the same track is already playing, don't restart.
  261. if (file_ == file) return;
  262. // Open vorbis file.
  263. if (ov_fopen(const_cast<char*>(file.c_str()), &vorbis_file_)){
  264. LOG_ERROR("Can't play file \"" + file + "\".");
  265. return;
  266. }
  267. file_ = file;
  268. // Get file info.
  269. vorbis_info_ = ov_info(&vorbis_file_, -1.0f);
  270. // Create sound source
  271. alGenSources(1, &source_);
  272. // Create buffers
  273. ALuint buffers[channel_buffer_number_];
  274. alGenBuffers(channel_buffer_number_, buffers);
  275. // Set source parameters
  276. alSourcei(source_, AL_LOOPING, AL_FALSE);
  277. // Fill buffers
  278. for (int i = 0; i < channel_buffer_number_; ++ i){
  279. ALsizei buffer_size = FillBuffer();
  280. if (buffer_size){
  281. alBufferData(
  282. buffers[i], vorbis_info_->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
  283. //static_cast<const ALvoid*>(AudioManager::getSingleton().buffer_),
  284. static_cast<const ALvoid*>(buffer_),
  285. static_cast<ALsizei>(buffer_size), static_cast<ALsizei>(vorbis_info_->rate)
  286. );
  287. alSourceQueueBuffers(source_, 1, &buffers[i]);
  288. }
  289. else{
  290. stream_finished_ = true;
  291. alDeleteBuffers(1, &buffers[i]);
  292. }
  293. }
  294. // Start playback
  295. alSourcePlay(source_);
  296. }
  297. void AudioManager::Player::Stop(){
  298. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  299. if (!alIsSource(source_)) return;
  300. // Stop source
  301. alSourceStop(source_);
  302. // Get source buffers
  303. int queued_count = 0;
  304. alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued_count);
  305. // Dequeue and delete buffers
  306. for(int i = 0; i < queued_count; ++ i){
  307. ALuint buffer_id;
  308. alSourceUnqueueBuffers(source_, 1, &buffer_id);
  309. alDeleteBuffers(1, &buffer_id);
  310. }
  311. // Delete source
  312. alDeleteSources(1, &source_);
  313. // Cleanup
  314. ov_clear(&vorbis_file_);
  315. stream_finished_ = false;
  316. file_ = "";
  317. }
  318. void AudioManager::Player::SetLoop(const float loop){
  319. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  320. loop_ = loop;
  321. }
  322. void AudioManager::Player::Update(){
  323. // Try to fill processed buffers
  324. int processed;
  325. alGetSourcei(source_, AL_BUFFERS_PROCESSED, &processed);
  326. for(int i = 0; i < processed; ++i){
  327. // Try to fill buffer
  328. ALsizei buffer_size = FillBuffer();
  329. if (buffer_size){
  330. ALuint buffer_id;
  331. alSourceUnqueueBuffers(source_, 1, &buffer_id);
  332. alBufferData(
  333. buffer_id, vorbis_info_->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
  334. //static_cast<const ALvoid*>(AudioManager::getSingleton().buffer_),
  335. static_cast<const ALvoid*>(buffer_),
  336. static_cast<ALsizei>(buffer_size), static_cast<ALsizei>(vorbis_info_->rate)
  337. );
  338. alSourceQueueBuffers(source_, 1, &buffer_id);
  339. }
  340. // Finished reading stream
  341. else{
  342. stream_finished_ = true;
  343. break;
  344. }
  345. }
  346. if (stream_finished_ && loop_ < 0){
  347. Stop();
  348. }
  349. // Manage source state
  350. alGetSourcei(source_, AL_BUFFERS_PROCESSED, &processed);
  351. int queued;
  352. alGetSourcei(source_, AL_BUFFERS_QUEUED, &queued);
  353. if (stream_finished_ && processed == queued) Stop();
  354. else{
  355. ALenum source_state;
  356. alGetSourcei(source_, AL_SOURCE_STATE, &source_state);
  357. if (source_state == AL_STOPPED) alSourcePlay(source_);
  358. }
  359. }
  360. ALsizei AudioManager::Player::FillBuffer(){
  361. ALsizei read = 0;
  362. if (stream_finished_) return read;
  363. //char *&buffer = AudioManager::getSingleton().buffer_;
  364. char *&buffer = buffer_;
  365. bool finished = false;
  366. do{
  367. long result = ov_read(
  368. &vorbis_file_, buffer + read, channel_buffer_size_ - read, 0, 2, 1, &vorbis_section_
  369. );
  370. switch(result){
  371. // Error
  372. case OV_HOLE:
  373. case OV_EBADLINK:
  374. case OV_EINVAL:
  375. finished = true;
  376. break;
  377. // End of stream
  378. case 0:
  379. // If there isn't loop point or can't seek
  380. if (loop_ < 0.0f || ov_time_seek(&vorbis_file_, loop_)) finished = true;
  381. break;
  382. // Readed "result" bytes
  383. default:
  384. read += result;
  385. if (read == channel_buffer_size_) finished = true;
  386. }
  387. }
  388. while (finished == false);
  389. return read;
  390. }
  391. float AudioManager::Player::GetPosition(){
  392. boost::recursive_mutex::scoped_lock lock(*update_mutex_);
  393. int play_offset;
  394. alGetSourcei(source_, AL_SAMPLE_OFFSET, &play_offset);
  395. return (
  396. ov_pcm_tell(&vorbis_file_)
  397. - (
  398. channel_buffer_number_ * channel_buffer_size_ / vorbis_info_->channels / sizeof(int16_t)
  399. - play_offset
  400. )
  401. ) * 1000 / vorbis_info_->rate;
  402. }