Advertisement
Guest User

Untitled

a guest
Jan 25th, 2020
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.15 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <SDL.h>
  4. #include <cstdio>
  5. #include <iostream>
  6. #include <string>
  7. #include <cstring>
  8. #include <fstream>
  9. #include <ctime>
  10. #include <stdexcept>
  11. #include <vector>
  12.  
  13. #include <SDL2/SDL_mixer.h>
  14.  
  15. namespace Hx { namespace Audio {
  16.  
  17. template <typename T>
  18. T clamp(T val, T max, T min)
  19. {
  20. if (val > max)
  21. {
  22. return max;
  23. }
  24. else if (val < min)
  25. {
  26. return min;
  27. }
  28. else
  29. {
  30. return val;
  31. }
  32. }
  33.  
  34. class Music
  35. {
  36. private:
  37. FILE *file;
  38. const char* filename;
  39. Uint32 file_size;
  40.  
  41. public:
  42. Music(const char* filename)
  43. {
  44. this->filename = filename;
  45. this->file = fopen(this->filename, "rb");
  46. fseek(this->file, 0L, SEEK_END);
  47. this->file_size = ftell(this->file);
  48. rewind(this->file);
  49. }
  50.  
  51. ~Music() noexcept(false)
  52. {
  53. if (fclose(this->file) == 0)
  54. {
  55. throw std::runtime_error("Closing file error");
  56. }
  57. }
  58.  
  59. size_t stream(Uint16* buffer, int length)
  60. {
  61. return fread(buffer, 1, length, this->file);
  62. }
  63.  
  64. Uint32 size()
  65. {
  66. return this->file_size;
  67. }
  68. };
  69.  
  70. class MusicEngine
  71. {
  72. private:
  73. SDL_AudioSpec playback_spec_given;
  74. SDL_AudioDeviceID playback_device_id;
  75. int buffer_byte_position;
  76. static std::vector<Music*> musics;
  77.  
  78. public:
  79. MusicEngine();
  80. void start();
  81. void pauseDevice();
  82. void unpauseDevice();
  83. void lock();
  84. void unlock();
  85.  
  86. static void playback(void*, Uint8*, int);
  87. void add(Music*);
  88. static std::vector<Music*> getMusics();
  89. };
  90.  
  91. void MusicEngine::playback(void* user_data, Uint8* stream_real, int len)
  92. {
  93. Uint16* stream = (Uint16*) stream_real;
  94. std::memset(stream, 0, len);
  95.  
  96. std::vector<Music*> musics = MusicEngine::getMusics();
  97.  
  98. Uint16* buffer = new Uint16[len];
  99. for (auto it = musics.begin(); it != musics.end(); ++it)
  100. {
  101. (*it)->stream(buffer, len);
  102.  
  103. for (int i = 0; i < len / (sizeof(Uint16) / sizeof(Uint8)); ++i)
  104. {
  105. // http://www.vttoth.com/CMS/index.php/technical-notes/68
  106. // stream[i] = stream[i] + buffer[i];
  107. stream[i] = (Uint16) clamp((Uint32) stream[i] + (Uint32) buffer[i], 65536U, 0U);
  108. }
  109. }
  110.  
  111. delete[] buffer;
  112. }
  113.  
  114.  
  115. MusicEngine::MusicEngine()
  116. {
  117. }
  118.  
  119. std::vector<Music*> MusicEngine::musics;
  120.  
  121. void MusicEngine::start()
  122. {
  123. this->buffer_byte_position = 0;
  124. this->playback_device_id = 0;
  125.  
  126. // Open the audio device
  127. SDL_AudioSpec playback_spec_desired;
  128. SDL_zero(playback_spec_desired);
  129. playback_spec_desired.freq = 44100;
  130. playback_spec_desired.format = AUDIO_U16;
  131. playback_spec_desired.channels = 2;
  132. playback_spec_desired.samples = 4096;
  133. playback_spec_desired.callback = MusicEngine::playback;
  134.  
  135. this->playback_device_id = SDL_OpenAudioDevice(nullptr, SDL_FALSE,
  136. &playback_spec_desired, &this->playback_spec_given, SDL_AUDIO_ALLOW_FORMAT_CHANGE);
  137. if (this->playback_device_id == 0)
  138. {
  139. throw std::runtime_error(SDL_GetError());
  140. }
  141. }
  142.  
  143. void MusicEngine::add(Music* music)
  144. {
  145. MusicEngine::musics.push_back(music);
  146. }
  147.  
  148. std::vector<Music*> MusicEngine::getMusics()
  149. {
  150. return MusicEngine::musics;
  151. }
  152.  
  153. void MusicEngine::unpauseDevice()
  154. {
  155. SDL_PauseAudioDevice(this->playback_device_id, SDL_FALSE);
  156. }
  157.  
  158. void MusicEngine::pauseDevice()
  159. {
  160. SDL_PauseAudioDevice(this->playback_device_id, SDL_TRUE);
  161. }
  162.  
  163. void MusicEngine::unlock()
  164. {
  165. SDL_UnlockAudioDevice(this->playback_device_id);
  166. }
  167.  
  168. void MusicEngine::lock()
  169. {
  170. SDL_LockAudioDevice(this->playback_device_id);
  171. }
  172.  
  173. } }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement