No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

olcPGEX_Sound.h 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. olcPGEX_Sound.h
  3. +-------------------------------------------------------------+
  4. | OneLoneCoder Pixel Game Engine Extension |
  5. | Sound - v0.3 |
  6. +-------------------------------------------------------------+
  7. What is this?
  8. ~~~~~~~~~~~~~
  9. This is an extension to the olcPixelGameEngine, which provides
  10. sound generation and wave playing routines.
  11. Special Thanks:
  12. ~~~~~~~~~~~~~~~
  13. Slavka - For entire non-windows system back end!
  14. Gorbit99 - Testing, Bug Fixes
  15. Cyberdroid - Testing, Bug Fixes
  16. Dragoneye - Testing
  17. Puol - Testing
  18. License (OLC-3)
  19. ~~~~~~~~~~~~~~~
  20. Copyright 2018 - 2019 OneLoneCoder.com
  21. Redistribution and use in source and binary forms, with or without
  22. modification, are permitted provided that the following conditions
  23. are met:
  24. 1. Redistributions or derivations of source code must retain the above
  25. copyright notice, this list of conditions and the following disclaimer.
  26. 2. Redistributions or derivative works in binary form must reproduce
  27. the above copyright notice. This list of conditions and the following
  28. disclaimer must be reproduced in the documentation and/or other
  29. materials provided with the distribution.
  30. 3. Neither the name of the copyright holder nor the names of its
  31. contributors may be used to endorse or promote products derived
  32. from this software without specific prior written permission.
  33. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  34. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  35. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  36. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  37. HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  39. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  40. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  41. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  43. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. Links
  45. ~~~~~
  46. YouTube: https://www.youtube.com/javidx9
  47. Discord: https://discord.gg/WhwHUMV
  48. Twitter: https://www.twitter.com/javidx9
  49. Twitch: https://www.twitch.tv/javidx9
  50. GitHub: https://www.github.com/onelonecoder
  51. Homepage: https://www.onelonecoder.com
  52. Patreon: https://www.patreon.com/javidx9
  53. Author
  54. ~~~~~~
  55. David Barr, aka javidx9, �OneLoneCoder 2019
  56. */
  57. #ifndef OLC_PGEX_SOUND_H
  58. #define OLC_PGEX_SOUND_H
  59. #include "olcPixelGameEngine.h"
  60. #include <istream>
  61. #include <cstring>
  62. #include <climits>
  63. #include <algorithm>
  64. #undef min
  65. #undef max
  66. // Choose a default sound backend
  67. #if !defined(USE_ALSA) && !defined(USE_OPENAL) && !defined(USE_WINDOWS)
  68. #ifdef __linux__
  69. #define USE_ALSA
  70. #endif
  71. #ifdef __EMSCRIPTEN__
  72. #define USE_OPENAL
  73. #endif
  74. #ifdef _WIN32
  75. #define USE_WINDOWS
  76. #endif
  77. #endif
  78. #ifdef USE_ALSA
  79. #define ALSA_PCM_NEW_HW_PARAMS_API
  80. #include <alsa/asoundlib.h>
  81. #endif
  82. #ifdef USE_OPENAL
  83. #include <AL/al.h>
  84. #include <AL/alc.h>
  85. #include <queue>
  86. #endif
  87. #pragma pack(push, 1)
  88. typedef struct {
  89. uint16_t wFormatTag;
  90. uint16_t nChannels;
  91. uint32_t nSamplesPerSec;
  92. uint32_t nAvgBytesPerSec;
  93. uint16_t nBlockAlign;
  94. uint16_t wBitsPerSample;
  95. uint16_t cbSize;
  96. } OLC_WAVEFORMATEX;
  97. #pragma pack(pop)
  98. namespace olc
  99. {
  100. // Container class for Advanced 2D Drawing functions
  101. class SOUND : public olc::PGEX
  102. {
  103. // A representation of an affine transform, used to rotate, scale, offset & shear space
  104. public:
  105. class AudioSample
  106. {
  107. public:
  108. AudioSample();
  109. AudioSample(std::string sWavFile, olc::ResourcePack *pack = nullptr);
  110. olc::rcode LoadFromFile(std::string sWavFile, olc::ResourcePack *pack = nullptr);
  111. public:
  112. OLC_WAVEFORMATEX wavHeader;
  113. float *fSample = nullptr;
  114. long nSamples = 0;
  115. int nChannels = 0;
  116. bool bSampleValid = false;
  117. };
  118. struct sCurrentlyPlayingSample
  119. {
  120. int nAudioSampleID = 0;
  121. long nSamplePosition = 0;
  122. bool bFinished = false;
  123. bool bLoop = false;
  124. bool bFlagForStop = false;
  125. };
  126. static std::list<sCurrentlyPlayingSample> listActiveSamples;
  127. public:
  128. static bool InitialiseAudio(unsigned int nSampleRate = 44100, unsigned int nChannels = 1, unsigned int nBlocks = 8, unsigned int nBlockSamples = 512);
  129. static bool DestroyAudio();
  130. static void SetUserSynthFunction(std::function<float(int, float, float)> func);
  131. static void SetUserFilterFunction(std::function<float(int, float, float)> func);
  132. public:
  133. static int LoadAudioSample(std::string sWavFile, olc::ResourcePack *pack = nullptr);
  134. static void PlaySample(int id, bool bLoop = false);
  135. static void StopSample(int id);
  136. static void StopAll();
  137. static float GetMixerOutput(int nChannel, float fGlobalTime, float fTimeStep);
  138. private:
  139. #ifdef USE_WINDOWS // Windows specific sound management
  140. static void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD_PTR dwInstance, DWORD dwParam1, DWORD dwParam2);
  141. static unsigned int m_nSampleRate;
  142. static unsigned int m_nChannels;
  143. static unsigned int m_nBlockCount;
  144. static unsigned int m_nBlockSamples;
  145. static unsigned int m_nBlockCurrent;
  146. static short* m_pBlockMemory;
  147. static WAVEHDR *m_pWaveHeaders;
  148. static HWAVEOUT m_hwDevice;
  149. static std::atomic<unsigned int> m_nBlockFree;
  150. static std::condition_variable m_cvBlockNotZero;
  151. static std::mutex m_muxBlockNotZero;
  152. #endif
  153. #ifdef USE_ALSA
  154. static snd_pcm_t *m_pPCM;
  155. static unsigned int m_nSampleRate;
  156. static unsigned int m_nChannels;
  157. static unsigned int m_nBlockSamples;
  158. static short* m_pBlockMemory;
  159. #endif
  160. #ifdef USE_OPENAL
  161. static std::queue<ALuint> m_qAvailableBuffers;
  162. static ALuint *m_pBuffers;
  163. static ALuint m_nSource;
  164. static ALCdevice *m_pDevice;
  165. static ALCcontext *m_pContext;
  166. static unsigned int m_nSampleRate;
  167. static unsigned int m_nChannels;
  168. static unsigned int m_nBlockCount;
  169. static unsigned int m_nBlockSamples;
  170. static short* m_pBlockMemory;
  171. #endif
  172. static void AudioThread();
  173. static std::thread m_AudioThread;
  174. static std::atomic<bool> m_bAudioThreadActive;
  175. static std::atomic<float> m_fGlobalTime;
  176. static std::function<float(int, float, float)> funcUserSynth;
  177. static std::function<float(int, float, float)> funcUserFilter;
  178. };
  179. }
  180. #endif // OLC_PGEX_SOUND