Audio.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /**
  2. * Copyright (c) 2006-2014 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Audio.h"
  21. #include "common/delay.h"
  22. #include "sound/Decoder.h"
  23. #include <cstdlib>
  24. namespace love
  25. {
  26. namespace audio
  27. {
  28. namespace openal
  29. {
  30. Audio::PoolThread::PoolThread(Pool *pool)
  31. : pool(pool)
  32. , finish(false)
  33. {
  34. mutex = thread::newMutex();
  35. }
  36. Audio::PoolThread::~PoolThread()
  37. {
  38. delete mutex;
  39. }
  40. void Audio::PoolThread::threadFunction()
  41. {
  42. while (true)
  43. {
  44. {
  45. thread::Lock lock(mutex);
  46. if (finish)
  47. {
  48. return;
  49. }
  50. }
  51. pool->update();
  52. delay(5);
  53. }
  54. }
  55. void Audio::PoolThread::setFinish()
  56. {
  57. thread::Lock lock(mutex);
  58. finish = true;
  59. }
  60. Audio::Audio()
  61. : device(nullptr)
  62. , capture(nullptr)
  63. , context(nullptr)
  64. , pool(nullptr)
  65. , poolThread(nullptr)
  66. , distanceModel(DISTANCE_INVERSE_CLAMPED)
  67. {
  68. // Passing null for default device.
  69. device = alcOpenDevice(nullptr);
  70. if (device == nullptr)
  71. throw love::Exception("Could not open device.");
  72. context = alcCreateContext(device, nullptr);
  73. if (context == nullptr)
  74. throw love::Exception("Could not create context.");
  75. if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR)
  76. throw love::Exception("Could not make context current.");
  77. /*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
  78. const ALCchar * devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
  79. while (*devices)
  80. {
  81. std::string device(devices);
  82. devices += device.size() + 1;
  83. if (device.find("Mic") != std::string::npos || device.find("mic") != std::string::npos)
  84. {
  85. captureName = device;
  86. }
  87. }
  88. capture = alcCaptureOpenDevice(captureName.c_str(), 8000, AL_FORMAT_MONO16, 262144); // about 32 seconds
  89. if (!capture)
  90. {
  91. // We're not going to prevent LOVE from running without a microphone, but we should warn, at least
  92. std::cerr << "Warning, couldn't open capture device! No audio input!" << std::endl;
  93. }*/
  94. // pool must be allocated after AL context.
  95. try
  96. {
  97. pool = new Pool();
  98. }
  99. catch (love::Exception &)
  100. {
  101. alcMakeContextCurrent(nullptr);
  102. alcDestroyContext(context);
  103. //if (capture) alcCaptureCloseDevice(capture);
  104. alcCloseDevice(device);
  105. throw;
  106. }
  107. poolThread = new PoolThread(pool);
  108. poolThread->start();
  109. }
  110. Audio::~Audio()
  111. {
  112. poolThread->setFinish();
  113. poolThread->wait();
  114. delete poolThread;
  115. delete pool;
  116. alcMakeContextCurrent(nullptr);
  117. alcDestroyContext(context);
  118. //if (capture) alcCaptureCloseDevice(capture);
  119. alcCloseDevice(device);
  120. }
  121. const char *Audio::getName() const
  122. {
  123. return "love.audio.openal";
  124. }
  125. love::audio::Source *Audio::newSource(love::sound::Decoder *decoder)
  126. {
  127. return new Source(pool, decoder);
  128. }
  129. love::audio::Source *Audio::newSource(love::sound::SoundData *soundData)
  130. {
  131. return new Source(pool, soundData);
  132. }
  133. int Audio::getSourceCount() const
  134. {
  135. return pool->getSourceCount();
  136. }
  137. int Audio::getMaxSources() const
  138. {
  139. return pool->getMaxSources();
  140. }
  141. bool Audio::play(love::audio::Source *source)
  142. {
  143. return source->play();
  144. }
  145. void Audio::stop(love::audio::Source *source)
  146. {
  147. source->stop();
  148. }
  149. void Audio::stop()
  150. {
  151. pool->stop();
  152. }
  153. void Audio::pause(love::audio::Source *source)
  154. {
  155. source->pause();
  156. }
  157. void Audio::pause()
  158. {
  159. pool->pause();
  160. }
  161. void Audio::resume(love::audio::Source *source)
  162. {
  163. source->resume();
  164. }
  165. void Audio::resume()
  166. {
  167. pool->resume();
  168. }
  169. void Audio::rewind(love::audio::Source *source)
  170. {
  171. source->rewind();
  172. }
  173. void Audio::rewind()
  174. {
  175. pool->rewind();
  176. }
  177. void Audio::setVolume(float volume)
  178. {
  179. alListenerf(AL_GAIN, volume);
  180. }
  181. float Audio::getVolume() const
  182. {
  183. ALfloat volume;
  184. alGetListenerf(AL_GAIN, &volume);
  185. return volume;
  186. }
  187. void Audio::getPosition(float *v) const
  188. {
  189. alGetListenerfv(AL_POSITION, v);
  190. }
  191. void Audio::setPosition(float *v)
  192. {
  193. alListenerfv(AL_POSITION, v);
  194. }
  195. void Audio::getOrientation(float *v) const
  196. {
  197. alGetListenerfv(AL_ORIENTATION, v);
  198. }
  199. void Audio::setOrientation(float *v)
  200. {
  201. alListenerfv(AL_ORIENTATION, v);
  202. }
  203. void Audio::getVelocity(float *v) const
  204. {
  205. alGetListenerfv(AL_VELOCITY, v);
  206. }
  207. void Audio::setVelocity(float *v)
  208. {
  209. alListenerfv(AL_VELOCITY, v);
  210. }
  211. void Audio::record()
  212. {
  213. if (!canRecord()) return;
  214. alcCaptureStart(capture);
  215. }
  216. love::sound::SoundData *Audio::getRecordedData()
  217. {
  218. if (!canRecord())
  219. return NULL;
  220. int samplerate = 8000;
  221. ALCint samples;
  222. alcGetIntegerv(capture, ALC_CAPTURE_SAMPLES, 4, &samples);
  223. void *data = malloc(samples * (2/sizeof(char)));
  224. alcCaptureSamples(capture, data, samples);
  225. love::sound::SoundData *sd = new love::sound::SoundData(data, samples, samplerate, 16, 1);
  226. free(data);
  227. return sd;
  228. }
  229. love::sound::SoundData *Audio::stopRecording(bool returnData)
  230. {
  231. if (!canRecord())
  232. return NULL;
  233. love::sound::SoundData *sd = NULL;
  234. if (returnData)
  235. {
  236. sd = getRecordedData();
  237. }
  238. alcCaptureStop(capture);
  239. return sd;
  240. }
  241. bool Audio::canRecord()
  242. {
  243. return (capture != NULL);
  244. }
  245. Audio::DistanceModel Audio::getDistanceModel() const
  246. {
  247. return distanceModel;
  248. }
  249. void Audio::setDistanceModel(DistanceModel distanceModel)
  250. {
  251. this->distanceModel = distanceModel;
  252. switch (distanceModel)
  253. {
  254. case DISTANCE_NONE:
  255. alDistanceModel(AL_NONE);
  256. break;
  257. case DISTANCE_INVERSE:
  258. alDistanceModel(AL_INVERSE_DISTANCE);
  259. break;
  260. case DISTANCE_INVERSE_CLAMPED:
  261. alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
  262. break;
  263. case DISTANCE_LINEAR:
  264. alDistanceModel(AL_LINEAR_DISTANCE);
  265. break;
  266. case DISTANCE_LINEAR_CLAMPED:
  267. alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
  268. break;
  269. case DISTANCE_EXPONENT:
  270. alDistanceModel(AL_EXPONENT_DISTANCE);
  271. break;
  272. case DISTANCE_EXPONENT_CLAMPED:
  273. alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
  274. break;
  275. default:
  276. break;
  277. }
  278. }
  279. } // openal
  280. } // audio
  281. } // love