Source.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /**
  2. * Copyright (c) 2006-2011 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 "Source.h"
  21. #include "Pool.h"
  22. // STD
  23. #include <iostream>
  24. namespace love
  25. {
  26. namespace audio
  27. {
  28. namespace openal
  29. {
  30. Source::Source(Pool * pool, love::sound::SoundData * soundData)
  31. : love::audio::Source(Source::TYPE_STATIC), pool(pool), valid(false),
  32. pitch(1.0f), volume(1.0f), looping(false), paused(false), offsetSamples(0),
  33. offsetSeconds(0), decoder(0), toLoop(0)
  34. {
  35. alGenBuffers(1, buffers);
  36. ALenum fmt = getFormat(soundData->getChannels(), soundData->getBits());
  37. alBufferData(buffers[0], fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate());
  38. static float z[3] = {0, 0, 0};
  39. setFloatv(position, z);
  40. setFloatv(velocity, z);
  41. setFloatv(direction, z);
  42. }
  43. Source::Source(Pool * pool, love::sound::Decoder * decoder)
  44. : love::audio::Source(Source::TYPE_STREAM), pool(pool), valid(false),
  45. pitch(1.0f), volume(1.0f), looping(false), paused(false), offsetSamples(0),
  46. offsetSeconds(0), decoder(decoder), toLoop(0)
  47. {
  48. decoder->retain();
  49. alGenBuffers(MAX_BUFFERS, buffers);
  50. static float z[3] = {0, 0, 0};
  51. setFloatv(position, z);
  52. setFloatv(velocity, z);
  53. setFloatv(direction, z);
  54. }
  55. Source::~Source()
  56. {
  57. pool->stop(this);
  58. alDeleteBuffers((type == TYPE_STATIC) ? 1 : MAX_BUFFERS, buffers);
  59. if (decoder)
  60. decoder->release();
  61. }
  62. love::audio::Source * Source::copy()
  63. {
  64. return 0;
  65. }
  66. void Source::play()
  67. {
  68. if (valid && paused)
  69. {
  70. pool->resume(this);
  71. return;
  72. }
  73. valid = pool->play(this, source);
  74. if(valid)
  75. reset(source);
  76. }
  77. void Source::stop()
  78. {
  79. if (!isStopped())
  80. {
  81. pool->stop(this);
  82. rewind();
  83. }
  84. }
  85. void Source::pause()
  86. {
  87. pool->pause(this);
  88. }
  89. void Source::resume()
  90. {
  91. pool->resume(this);
  92. }
  93. void Source::rewind()
  94. {
  95. pool->rewind(this);
  96. }
  97. bool Source::isStopped() const
  98. {
  99. if(valid)
  100. {
  101. ALenum state;
  102. alGetSourcei(source, AL_SOURCE_STATE, &state);
  103. return (state == AL_STOPPED);
  104. }
  105. return true;
  106. }
  107. bool Source::isPaused() const
  108. {
  109. if(valid)
  110. {
  111. ALenum state;
  112. alGetSourcei(source, AL_SOURCE_STATE, &state);
  113. return (state == AL_PAUSED);
  114. }
  115. return false;
  116. }
  117. bool Source::isFinished() const
  118. {
  119. return type == TYPE_STATIC ? isStopped() : isStopped() && !isLooping() && decoder->isFinished();
  120. }
  121. void Source::update()
  122. {
  123. if(valid && type == TYPE_STATIC)
  124. {
  125. // Looping mode could have changed.
  126. alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
  127. }
  128. else if(valid && type == TYPE_STREAM && !(!isLooping() && isFinished()))
  129. {
  130. // Number of processed buffers.
  131. ALint processed;
  132. alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
  133. while(processed--)
  134. {
  135. ALuint buffer;
  136. float curOffsetSamples, curOffsetSecs;
  137. alGetSourcef(source, AL_SAMPLE_OFFSET, &curOffsetSamples);
  138. ALint b;
  139. alGetSourcei(source, AL_BUFFER, &b);
  140. int freq;
  141. alGetBufferi(b, AL_FREQUENCY, &freq);
  142. curOffsetSecs = curOffsetSamples / freq;
  143. // Get a free buffer.
  144. alSourceUnqueueBuffers(source, 1, &buffer);
  145. float newOffsetSamples, newOffsetSecs;
  146. alGetSourcef(source, AL_SAMPLE_OFFSET, &newOffsetSamples);
  147. newOffsetSecs = newOffsetSamples / freq;
  148. offsetSamples += (curOffsetSamples - newOffsetSamples);
  149. offsetSeconds += (curOffsetSecs - newOffsetSecs);
  150. streamAtomic(buffer, decoder);
  151. alSourceQueueBuffers(source, 1, &buffer);
  152. }
  153. }
  154. }
  155. void Source::setPitch(float pitch)
  156. {
  157. if(valid)
  158. alSourcef(source, AL_PITCH, pitch);
  159. this->pitch = pitch;
  160. }
  161. float Source::getPitch() const
  162. {
  163. if(valid)
  164. {
  165. ALfloat f;
  166. alGetSourcef(source, AL_PITCH, &f);
  167. return f;
  168. }
  169. // In case the Source isn't playing.
  170. return pitch;
  171. }
  172. void Source::setVolume(float volume)
  173. {
  174. if(valid)
  175. {
  176. alSourcef(source, AL_GAIN, volume);
  177. }
  178. this->volume = volume;
  179. }
  180. float Source::getVolume() const
  181. {
  182. if(valid)
  183. {
  184. ALfloat f;
  185. alGetSourcef(source, AL_GAIN, &f);
  186. return f;
  187. }
  188. // In case the Source isn't playing.
  189. return volume;
  190. }
  191. void Source::seekAtomic(float offset, void * unit)
  192. {
  193. if (valid)
  194. {
  195. switch (*((Source::Unit*) unit)) {
  196. case Source::UNIT_SAMPLES:
  197. if (type == TYPE_STREAM) {
  198. offsetSamples = offset;
  199. ALint buffer;
  200. alGetSourcei(source, AL_BUFFER, &buffer);
  201. int freq;
  202. alGetBufferi(buffer, AL_FREQUENCY, &freq);
  203. offset /= freq;
  204. offsetSeconds = offset;
  205. decoder->seek(offset);
  206. } else {
  207. alSourcef(source, AL_SAMPLE_OFFSET, offset);
  208. }
  209. break;
  210. case Source::UNIT_SECONDS:
  211. default:
  212. if (type == TYPE_STREAM) {
  213. offsetSeconds = offset;
  214. decoder->seek(offset);
  215. ALint buffer;
  216. alGetSourcei(source, AL_BUFFER, &buffer);
  217. int freq;
  218. alGetBufferi(buffer, AL_FREQUENCY, &freq);
  219. offsetSamples = offset*freq;
  220. } else {
  221. alSourcef(source, AL_SEC_OFFSET, offset);
  222. }
  223. break;
  224. }
  225. if (type == TYPE_STREAM)
  226. {
  227. bool waspaused = paused;
  228. // Because we still have old data
  229. // from before the seek in the buffers
  230. // let's empty them.
  231. stopAtomic();
  232. playAtomic();
  233. if (waspaused)
  234. pauseAtomic();
  235. }
  236. }
  237. }
  238. void Source::seek(float offset, Source::Unit unit)
  239. {
  240. return pool->seek(this, offset, &unit);
  241. }
  242. float Source::tellAtomic(void * unit) const
  243. {
  244. if (valid)
  245. {
  246. float offset;
  247. switch (*((Source::Unit*) unit)) {
  248. case Source::UNIT_SAMPLES:
  249. alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
  250. if (type == TYPE_STREAM) offset += offsetSamples;
  251. break;
  252. case Source::UNIT_SECONDS:
  253. default:
  254. alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
  255. ALint buffer;
  256. alGetSourcei(source, AL_BUFFER, &buffer);
  257. int freq;
  258. alGetBufferi(buffer, AL_FREQUENCY, &freq);
  259. offset /= freq;
  260. if (type == TYPE_STREAM) offset += offsetSeconds;
  261. break;
  262. }
  263. return offset;
  264. }
  265. return 0.0f;
  266. }
  267. float Source::tell(Source::Unit unit)
  268. {
  269. return pool->tell(this, &unit);
  270. }
  271. void Source::setPosition(float * v)
  272. {
  273. if(valid)
  274. alSourcefv(source, AL_POSITION, v);
  275. setFloatv(position, v);
  276. }
  277. void Source::getPosition(float * v) const
  278. {
  279. if(valid)
  280. alGetSourcefv(source, AL_POSITION, v);
  281. else
  282. setFloatv(v, position);
  283. }
  284. void Source::setVelocity(float * v)
  285. {
  286. if(valid)
  287. alSourcefv(source, AL_VELOCITY, v);
  288. setFloatv(velocity, v);
  289. }
  290. void Source::getVelocity(float * v) const
  291. {
  292. if(valid)
  293. alGetSourcefv(source, AL_VELOCITY, v);
  294. else
  295. setFloatv(v, velocity);
  296. }
  297. void Source::setDirection(float * v)
  298. {
  299. if(valid)
  300. alSourcefv(source, AL_DIRECTION, v);
  301. else
  302. setFloatv(direction, v);
  303. }
  304. void Source::getDirection(float * v) const
  305. {
  306. if(valid)
  307. alGetSourcefv(source, AL_DIRECTION, v);
  308. else
  309. setFloatv(v, direction);
  310. }
  311. void Source::setLooping(bool looping)
  312. {
  313. if(valid && type == TYPE_STATIC)
  314. alSourcei(source, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
  315. this->looping = looping;
  316. }
  317. bool Source::isLooping() const
  318. {
  319. return looping;
  320. }
  321. void Source::playAtomic()
  322. {
  323. if(type == TYPE_STATIC)
  324. {
  325. alSourcei(source, AL_BUFFER, buffers[0]);
  326. }
  327. else if(type == TYPE_STREAM)
  328. {
  329. int usedBuffers = 0;
  330. for(unsigned int i = 0; i < MAX_BUFFERS; i++)
  331. {
  332. int decoded = streamAtomic(buffers[i], decoder);
  333. ++usedBuffers;
  334. if(decoder->isFinished())
  335. break;
  336. }
  337. if(usedBuffers > 0)
  338. alSourceQueueBuffers(source, usedBuffers, buffers);
  339. }
  340. // Set these properties. These may have changed while we've
  341. // been without an AL source.
  342. alSourcef(source, AL_PITCH, pitch);
  343. alSourcef(source, AL_GAIN, volume);
  344. alSourcePlay(source);
  345. valid = true; //if it fails it will be set to false again
  346. //but this prevents a horrible, horrible bug
  347. }
  348. void Source::stopAtomic()
  349. {
  350. if(valid)
  351. {
  352. if(type == TYPE_STATIC)
  353. {
  354. alSourceStop(source);
  355. }
  356. else if(type == TYPE_STREAM)
  357. {
  358. alSourceStop(source);
  359. int queued = 0;
  360. alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
  361. while (queued--)
  362. {
  363. ALuint buffer;
  364. alSourceUnqueueBuffers(source, 1, &buffer);
  365. }
  366. }
  367. alSourcei(source, AL_BUFFER, AL_NONE);
  368. }
  369. toLoop = 0;
  370. valid = false;
  371. }
  372. void Source::pauseAtomic()
  373. {
  374. if(valid)
  375. {
  376. alSourcePause(source);
  377. paused = true;
  378. }
  379. }
  380. void Source::resumeAtomic()
  381. {
  382. if(valid && paused)
  383. {
  384. alSourcePlay(source);
  385. paused = false;
  386. }
  387. }
  388. void Source::rewindAtomic()
  389. {
  390. if(valid && type == TYPE_STATIC)
  391. {
  392. alSourceRewind(source);
  393. if (!paused)
  394. alSourcePlay(source);
  395. }
  396. else if(valid && type == TYPE_STREAM)
  397. {
  398. bool waspaused = paused;
  399. decoder->rewind();
  400. // Because we still have old data
  401. // from before the seek in the buffers
  402. // let's empty them.
  403. stopAtomic();
  404. playAtomic();
  405. if (waspaused)
  406. pauseAtomic();
  407. offsetSamples = 0;
  408. offsetSeconds = 0;
  409. }
  410. }
  411. void Source::reset(ALenum source)
  412. {
  413. alSourcefv(source, AL_POSITION, position);
  414. alSourcefv(source, AL_VELOCITY, velocity);
  415. alSourcefv(source, AL_DIRECTION, direction);
  416. alSourcef(source, AL_PITCH, pitch);
  417. alSourcef(source, AL_GAIN, volume);
  418. }
  419. void Source::setFloatv(float * dst, const float * src) const
  420. {
  421. dst[0] = src[0];
  422. dst[1] = src[1];
  423. dst[2] = src[2];
  424. }
  425. ALenum Source::getFormat(int channels, int bits) const
  426. {
  427. if(channels == 1 && bits == 8)
  428. return AL_FORMAT_MONO8;
  429. else if(channels == 1 && bits == 16)
  430. return AL_FORMAT_MONO16;
  431. else if(channels == 2 && bits == 8)
  432. return AL_FORMAT_STEREO8;
  433. else if(channels == 2 && bits == 16)
  434. return AL_FORMAT_STEREO16;
  435. else
  436. return 0;
  437. }
  438. int Source::streamAtomic(ALuint buffer, love::sound::Decoder * d)
  439. {
  440. // Get more sound data.
  441. int decoded = d->decode();
  442. int fmt = getFormat(d->getChannels(), d->getBits());
  443. if(fmt != 0)
  444. alBufferData(buffer, fmt, d->getBuffer(), decoded, d->getSampleRate());
  445. if(decoder->isFinished() && isLooping()) {
  446. int queued, processed;
  447. alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
  448. alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
  449. if (queued > processed)
  450. toLoop = queued-processed;
  451. else
  452. toLoop = MAX_BUFFERS-processed;
  453. d->rewind();
  454. }
  455. if (toLoop > 0)
  456. {
  457. if (--toLoop == 0)
  458. {
  459. offsetSamples = 0;
  460. offsetSeconds = 0;
  461. }
  462. }
  463. return decoded;
  464. }
  465. bool Source::isStatic() const
  466. {
  467. return (type == TYPE_STATIC);
  468. }
  469. } // openal
  470. } // audio
  471. } // love