audio.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #if defined(AUDIO_ALSA)
  2. #include <ruby/audio/alsa.cpp>
  3. #endif
  4. #if defined(AUDIO_AO)
  5. #include <ruby/audio/ao.cpp>
  6. #endif
  7. #if defined(AUDIO_ASIO)
  8. #include <ruby/audio/asio.cpp>
  9. #endif
  10. #if defined(AUDIO_DIRECTSOUND)
  11. #include <ruby/audio/directsound.cpp>
  12. #endif
  13. #if defined(AUDIO_OPENAL)
  14. #include <ruby/audio/openal.cpp>
  15. #endif
  16. #if defined(AUDIO_OSS)
  17. #include <ruby/audio/oss.cpp>
  18. #endif
  19. #if defined(AUDIO_PULSEAUDIO)
  20. #include <ruby/audio/pulseaudio.cpp>
  21. #endif
  22. #if defined(AUDIO_PULSEAUDIOSIMPLE)
  23. #include <ruby/audio/pulseaudio-simple.cpp>
  24. #endif
  25. #if defined(AUDIO_WASAPI)
  26. #include <ruby/audio/wasapi.cpp>
  27. #endif
  28. #if defined(AUDIO_WAVEOUT)
  29. #include <ruby/audio/waveout.cpp>
  30. #endif
  31. #if defined(AUDIO_XAUDIO2)
  32. #include <ruby/audio/xaudio2.cpp>
  33. #endif
  34. namespace ruby {
  35. auto Audio::setExclusive(bool exclusive) -> bool {
  36. if(instance->exclusive == exclusive) return true;
  37. if(!instance->hasExclusive()) return false;
  38. if(!instance->setExclusive(instance->exclusive = exclusive)) return false;
  39. return true;
  40. }
  41. auto Audio::setContext(uintptr context) -> bool {
  42. if(instance->context == context) return true;
  43. if(!instance->hasContext()) return false;
  44. if(!instance->setContext(instance->context = context)) return false;
  45. return true;
  46. }
  47. auto Audio::setDevice(string device) -> bool {
  48. if(instance->device == device) return true;
  49. if(!instance->hasDevice(device)) return false;
  50. if(!instance->setDevice(instance->device = device)) return false;
  51. return true;
  52. }
  53. auto Audio::setBlocking(bool blocking) -> bool {
  54. if(instance->blocking == blocking) return true;
  55. if(!instance->hasBlocking()) return false;
  56. if(!instance->setBlocking(instance->blocking = blocking)) return false;
  57. for(auto& resampler : resamplers) resampler.reset(instance->frequency);
  58. return true;
  59. }
  60. auto Audio::setDynamic(bool dynamic) -> bool {
  61. if(instance->dynamic == dynamic) return true;
  62. if(!instance->hasDynamic()) return false;
  63. if(!instance->setDynamic(instance->dynamic = dynamic)) return false;
  64. return true;
  65. }
  66. auto Audio::setChannels(uint channels) -> bool {
  67. if(resamplers.size() != channels) {
  68. resamplers.reset();
  69. resamplers.resize(channels);
  70. for(auto& resampler : resamplers) resampler.reset(instance->frequency);
  71. }
  72. if(instance->channels == channels) return true;
  73. if(!instance->hasChannels(channels)) return false;
  74. if(!instance->setChannels(instance->channels = channels)) return false;
  75. return true;
  76. }
  77. auto Audio::setFrequency(uint frequency) -> bool {
  78. if(instance->frequency == frequency) return true;
  79. if(!instance->hasFrequency(frequency)) return false;
  80. if(!instance->setFrequency(instance->frequency = frequency)) return false;
  81. for(auto& resampler : resamplers) resampler.reset(instance->frequency);
  82. return true;
  83. }
  84. auto Audio::setLatency(uint latency) -> bool {
  85. if(instance->latency == latency) return true;
  86. if(!instance->hasLatency(latency)) return false;
  87. if(!instance->setLatency(instance->latency = latency)) return false;
  88. return true;
  89. }
  90. //
  91. auto Audio::clear() -> void {
  92. for(auto& resampler : resamplers) resampler.reset(instance->frequency);
  93. return instance->clear();
  94. }
  95. auto Audio::level() -> double {
  96. return instance->level();
  97. }
  98. auto Audio::output(const double samples[]) -> void {
  99. if(!instance->dynamic) return instance->output(samples);
  100. auto maxDelta = 0.005;
  101. double fillLevel = instance->level();
  102. double dynamicFrequency = ((1.0 - maxDelta) + 2.0 * fillLevel * maxDelta) * instance->frequency;
  103. for(auto& resampler : resamplers) {
  104. resampler.setInputFrequency(dynamicFrequency);
  105. resampler.write(*samples++);
  106. }
  107. while(resamplers.first().pending()) {
  108. double samples[instance->channels];
  109. for(uint n : range(instance->channels)) samples[n] = resamplers[n].read();
  110. instance->output(samples);
  111. }
  112. }
  113. //
  114. auto Audio::create(string driver) -> bool {
  115. self.instance.reset();
  116. if(!driver) driver = optimalDriver();
  117. #if defined(AUDIO_ALSA)
  118. if(driver == "ALSA") self.instance = new AudioALSA(*this);
  119. #endif
  120. #if defined(AUDIO_AO)
  121. if(driver == "libao") self.instance = new AudioAO(*this);
  122. #endif
  123. #if defined(AUDIO_ASIO)
  124. if(driver == "ASIO") self.instance = new AudioASIO(*this);
  125. #endif
  126. #if defined(AUDIO_DIRECTSOUND)
  127. if(driver == "DirectSound 7.0") self.instance = new AudioDirectSound(*this);
  128. #endif
  129. #if defined(AUDIO_OPENAL)
  130. if(driver == "OpenAL") self.instance = new AudioOpenAL(*this);
  131. #endif
  132. #if defined(AUDIO_OSS)
  133. if(driver == "OSS") self.instance = new AudioOSS(*this);
  134. #endif
  135. #if defined(AUDIO_PULSEAUDIO)
  136. if(driver == "PulseAudio") self.instance = new AudioPulseAudio(*this);
  137. #endif
  138. #if defined(AUDIO_PULSEAUDIOSIMPLE)
  139. if(driver == "PulseAudio Simple") self.instance = new AudioPulseAudioSimple(*this);
  140. #endif
  141. #if defined(AUDIO_WASAPI)
  142. if(driver == "WASAPI") self.instance = new AudioWASAPI(*this);
  143. #endif
  144. #if defined(AUDIO_WAVEOUT)
  145. if(driver == "waveOut") self.instance = new AudioWaveOut(*this);
  146. #endif
  147. #if defined(AUDIO_XAUDIO2)
  148. if(driver == "XAudio 2.1") self.instance = new AudioXAudio2(*this);
  149. #endif
  150. if(!self.instance) self.instance = new AudioDriver(*this);
  151. return self.instance->create();
  152. }
  153. auto Audio::hasDrivers() -> vector<string> {
  154. return {
  155. #if defined(AUDIO_ASIO)
  156. "ASIO",
  157. #endif
  158. #if defined(AUDIO_WASAPI)
  159. "WASAPI",
  160. #endif
  161. #if defined(AUDIO_XAUDIO2)
  162. "XAudio 2.1",
  163. #endif
  164. #if defined(AUDIO_DIRECTSOUND)
  165. "DirectSound 7.0",
  166. #endif
  167. #if defined(AUDIO_WAVEOUT)
  168. "waveOut",
  169. #endif
  170. #if defined(AUDIO_ALSA)
  171. "ALSA",
  172. #endif
  173. #if defined(AUDIO_OSS)
  174. "OSS",
  175. #endif
  176. #if defined(AUDIO_OPENAL)
  177. "OpenAL",
  178. #endif
  179. #if defined(AUDIO_PULSEAUDIO)
  180. "PulseAudio",
  181. #endif
  182. #if defined(AUDIO_PULSEAUDIOSIMPLE)
  183. "PulseAudio Simple",
  184. #endif
  185. #if defined(AUDIO_AO)
  186. "libao",
  187. #endif
  188. "None"};
  189. }
  190. auto Audio::optimalDriver() -> string {
  191. #if defined(AUDIO_WASAPI)
  192. return "WASAPI";
  193. #elif defined(AUDIO_ASIO)
  194. return "ASIO";
  195. #elif defined(AUDIO_XAUDIO2)
  196. return "XAudio 2.1";
  197. #elif defined(AUDIO_DIRECTSOUND)
  198. return "DirectSound 7.0";
  199. #elif defined(AUDIO_WAVEOUT)
  200. return "waveOut";
  201. #elif defined(AUDIO_ALSA)
  202. return "ALSA";
  203. #elif defined(AUDIO_OSS)
  204. return "OSS";
  205. #elif defined(AUDIO_OPENAL)
  206. return "OpenAL";
  207. #elif defined(AUDIO_PULSEAUDIO)
  208. return "PulseAudio";
  209. #elif defined(AUDIO_PULSEAUDIOSIMPLE)
  210. return "PulseAudio Simple";
  211. #elif defined(AUDIO_AO)
  212. return "libao";
  213. #else
  214. return "None";
  215. #endif
  216. }
  217. auto Audio::safestDriver() -> string {
  218. #if defined(AUDIO_WAVEOUT)
  219. return "waveOut";
  220. #elif defined(AUDIO_DIRECTSOUND)
  221. return "DirectSound 7.0";
  222. #elif defined(AUDIO_WASAPI)
  223. return "WASAPI";
  224. #elif defined(AUDIO_XAUDIO2)
  225. return "XAudio 2.1";
  226. #elif defined(AUDIO_ALSA)
  227. return "ALSA";
  228. #elif defined(AUDIO_OSS)
  229. return "OSS";
  230. #elif defined(AUDIO_OPENAL)
  231. return "OpenAL";
  232. #elif defined(AUDIO_PULSEAUDIO)
  233. return "PulseAudio";
  234. #elif defined(AUDIO_PULSEAUDIOSIMPLE)
  235. return "PulseAudio Simple";
  236. #elif defined(AUDIO_AO)
  237. return "libao";
  238. #elif defined(AUDIO_ASIO)
  239. return "ASIO";
  240. #else
  241. return "None";
  242. #endif
  243. }
  244. }