GEAudioBufferPlayInstance.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. * Copyright (c) 2011 Nokia Corporation.
  3. *
  4. * Part of the Qt GameEnabler.
  5. */
  6. #include "GEAudioBufferPlayInstance.h"
  7. #include "GEAudioBuffer.h"
  8. #include "trace.h"
  9. using namespace GE;
  10. // Constants
  11. const float GEMaxAudioSpeedValue(4096.0f);
  12. const float GEDefaultAudioVolume(1.0f); // 1.0 => 100 %
  13. const float GEDefaultAudioSpeed(1.0f); // 1.0 => 100 %
  14. /*!
  15. * \class AudioBufferPlayInstance
  16. * \brief An AudioSource instance capable of playing a single audio buffer.
  17. */
  18. /*!
  19. Constructor. If \a buffer is not NULL, it is set as the buffer to play.
  20. */
  21. AudioBufferPlayInstance::AudioBufferPlayInstance(AudioBuffer *buffer /* = 0 */,
  22. QObject *parent /* = 0 */)
  23. : AudioSource(parent),
  24. m_buffer(0),
  25. m_finished(false),
  26. m_destroyWhenFinished(true),
  27. m_fixedPos(0),
  28. m_fixedInc(0),
  29. m_fixedLeftVolume((int)GEMaxAudioVolumeValue),
  30. m_fixedRightVolume((int)GEMaxAudioVolumeValue),
  31. m_fixedCenter(0),
  32. m_loopCount(0)
  33. {
  34. if (buffer) {
  35. // Start playing the given buffer.
  36. playBuffer(buffer, GEDefaultAudioVolume, GEDefaultAudioSpeed);
  37. }
  38. }
  39. /*!
  40. Destructor.
  41. */
  42. AudioBufferPlayInstance::~AudioBufferPlayInstance()
  43. {
  44. }
  45. /*!
  46. Returns true if the buffer is set, false otherwise.
  47. */
  48. bool AudioBufferPlayInstance::isPlaying() const
  49. {
  50. if (m_buffer)
  51. return true;
  52. return false;
  53. }
  54. /*!
  55. From AudioSource.
  56. The framework will use this to know whether this AudioSource can be
  57. destroyed or not.
  58. */
  59. bool AudioBufferPlayInstance::canBeDestroyed()
  60. {
  61. if (m_finished && m_destroyWhenFinished)
  62. return true;
  63. return false;
  64. }
  65. /*!
  66. From AudioSource.
  67. Returns an audio stream from the current sample.
  68. */
  69. int AudioBufferPlayInstance::pullAudio(AUDIO_SAMPLE_TYPE *target,
  70. int bufferLength)
  71. {
  72. if (!m_buffer) {
  73. // No sample!
  74. return 0;
  75. }
  76. int divider(m_buffer->getNofChannels() * m_buffer->getBytesPerSample());
  77. int channelLength(0);
  78. // Check in case of division by zero.
  79. if (divider) {
  80. channelLength = m_buffer->getDataLength() / divider - 2;
  81. }
  82. else {
  83. DEBUG_INFO("Warning: Catched division by zero error!");
  84. }
  85. int samplesToWrite(bufferLength / 2);
  86. int amount(0);
  87. int totalMixed(0);
  88. while (samplesToWrite > 0) {
  89. int samplesLeft = channelLength - (m_fixedPos >> 12);
  90. if (m_fixedInc == 0) {
  91. // No speed set. Will lead to division by zero error if not set.
  92. setSpeed(GEDefaultAudioSpeed);
  93. }
  94. // This is how much we can mix at least.
  95. int maxMixAmount = (int)(((long long int)(samplesLeft) << 12) /
  96. m_fixedInc);
  97. if (maxMixAmount > samplesToWrite) {
  98. maxMixAmount = samplesToWrite;
  99. }
  100. if (maxMixAmount > 0) {
  101. amount = mixBlock(target+totalMixed * 2, maxMixAmount);
  102. if (amount == 0) {
  103. // Error!
  104. break;
  105. }
  106. totalMixed += amount;
  107. }
  108. else {
  109. amount = 0;
  110. m_fixedPos = channelLength<<12;
  111. }
  112. // The sample ended. Check the looping variables and see what to do.
  113. if ((m_fixedPos >> 12) >= channelLength) {
  114. m_fixedPos -= (channelLength << 12);
  115. if (m_loopCount > 0)
  116. m_loopCount--;
  117. if (m_loopCount == 0) {
  118. // No more loops, stop the sample and return the amount of
  119. // samples already mixed.
  120. stop();
  121. return totalMixed;
  122. }
  123. }
  124. samplesToWrite -= amount;
  125. if (samplesToWrite < 1)
  126. break;
  127. }
  128. return totalMixed * 2;
  129. }
  130. /*!
  131. Sets \a buffer as the audio buffer and will repeat the buffer according to
  132. \a loopCount. Note: If the given loop count is -1, the buffer will be
  133. repeated forever.
  134. */
  135. void AudioBufferPlayInstance::playBuffer(AudioBuffer *buffer,
  136. int loopCount /* = 0 */)
  137. {
  138. m_buffer = buffer;
  139. m_loopCount = loopCount;
  140. m_fixedPos = 0;
  141. }
  142. /*!
  143. For convenience.
  144. In addition to playBuffer(AudioBuffer*, int) method, will also set \a volume
  145. and \a speed.
  146. */
  147. void AudioBufferPlayInstance::playBuffer(AudioBuffer *buffer,
  148. float volume,
  149. float speed,
  150. int loopCount /* = 0 */)
  151. {
  152. setLeftVolume(volume);
  153. m_fixedRightVolume = m_fixedLeftVolume;
  154. setSpeed(speed);
  155. playBuffer(buffer, loopCount);
  156. }
  157. /*!
  158. Resets the local buffer i.e. gets rid of the set buffer.
  159. */
  160. void AudioBufferPlayInstance::stop()
  161. {
  162. m_buffer = 0;
  163. m_finished = true;
  164. emit finished();
  165. }
  166. /*!
  167. Sets the loop count to \a count. If the argument value is -1, the
  168. buffer is looped forever.
  169. */
  170. void AudioBufferPlayInstance::setLoopCount(int count)
  171. {
  172. DEBUG_INFO("Setting the loop count to " << count);
  173. m_loopCount = count;
  174. }
  175. /*!
  176. Sets \a speed as the speed of which the buffer is played in. The given
  177. argument value should be between 0.0 and 1.0 since 1.0 indicates 100 %.
  178. */
  179. void AudioBufferPlayInstance::setSpeed(float speed)
  180. {
  181. if (!m_buffer)
  182. return;
  183. m_fixedInc =
  184. (int)(((float)m_buffer->getSamplesPerSec() *
  185. GEMaxAudioSpeedValue * speed) /
  186. (float)AUDIO_FREQUENCY);
  187. }
  188. /*!
  189. Sets \a volume for the left channel. The given argument value should be
  190. between 0.0 and 1.0 since 1.0 indicates 100 %.
  191. */
  192. void AudioBufferPlayInstance::setLeftVolume(float volume)
  193. {
  194. m_fixedLeftVolume = (int)(GEMaxAudioVolumeValue * volume);
  195. }
  196. /*!
  197. Sets \a volume for the right channel. The given argument value should be
  198. between 0.0 and 1.0 since 1.0 indicates 100 %.
  199. */
  200. void AudioBufferPlayInstance::setRightVolume(float volume)
  201. {
  202. m_fixedRightVolume = (int)(GEMaxAudioVolumeValue * volume);
  203. }
  204. /*!
  205. TODO: Document this method.
  206. Note: Does not do any bound checking, must be checked before called!
  207. */
  208. int AudioBufferPlayInstance::mixBlock(AUDIO_SAMPLE_TYPE *target,
  209. int samplesToMix)
  210. {
  211. SAMPLE_FUNCTION_TYPE sampleFunction = m_buffer->getSampleFunction();
  212. if (!sampleFunction) {
  213. // Unsupported sample type.
  214. return 0;
  215. }
  216. AUDIO_SAMPLE_TYPE *t_target = target + samplesToMix * 2;
  217. int sourcepos(0);
  218. if (m_buffer->getNofChannels() == 2) {
  219. // Stereo
  220. while (target != t_target) {
  221. sourcepos = m_fixedPos >> 12;
  222. target[0] = (((((sampleFunction)
  223. (m_buffer, sourcepos, 0) *
  224. (4096 - (m_fixedPos & 4095)) +
  225. (sampleFunction)(m_buffer, sourcepos + 1, 0) *
  226. (m_fixedPos & 4095)) >> 12) *
  227. m_fixedLeftVolume) >> 12);
  228. target[1] = (((((sampleFunction)
  229. (m_buffer, sourcepos, 1) *
  230. (4096 - (m_fixedPos & 4095)) +
  231. (sampleFunction)(m_buffer, sourcepos + 1, 1) *
  232. (m_fixedPos & 4095) ) >> 12) *
  233. m_fixedRightVolume) >> 12);
  234. m_fixedPos += m_fixedInc;
  235. target += 2;
  236. }
  237. }
  238. else {
  239. // Mono
  240. int temp(0);
  241. while (target != t_target) {
  242. sourcepos = m_fixedPos >> 12;
  243. temp = (((sampleFunction)(m_buffer, sourcepos, 0 ) *
  244. (4096 - (m_fixedPos & 4095)) +
  245. (sampleFunction)(m_buffer, sourcepos + 1, 0) *
  246. (m_fixedPos & 4095)) >> 12);
  247. target[0] = ((temp * m_fixedLeftVolume) >> 12);
  248. target[1] = ((temp * m_fixedRightVolume) >> 12);
  249. m_fixedPos += m_fixedInc;
  250. target += 2;
  251. }
  252. }
  253. return samplesToMix;
  254. }