GEAudioMixer.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /**
  2. * Copyright (c) 2011 Nokia Corporation.
  3. *
  4. * Part of the Qt GameEnabler.
  5. */
  6. #include "GEAudioMixer.h"
  7. #include <memory.h>
  8. #include "trace.h" // For debug macros
  9. #include <QDebug>
  10. using namespace GE;
  11. /*!
  12. \class AudioMixer
  13. \brief An AudioSource capable of combining all of its child sources into
  14. a single audio stream.
  15. */
  16. /*!
  17. Constructor.
  18. */
  19. AudioMixer::AudioMixer(QObject *parent)
  20. : AudioSource(parent),
  21. m_mixingBuffer(0),
  22. m_mixingBufferLength(0),
  23. m_fixedGeneralVolume((int)GEMaxAudioVolumeValue)
  24. {
  25. }
  26. /*!
  27. Destructor.
  28. */
  29. AudioMixer::~AudioMixer()
  30. {
  31. destroyList();
  32. if (m_mixingBuffer) {
  33. delete [] m_mixingBuffer;
  34. m_mixingBuffer = 0;
  35. }
  36. }
  37. /*!
  38. Returns the absolute volume.
  39. */
  40. float AudioMixer::absoluteVolume() const
  41. {
  42. return (float)m_fixedGeneralVolume / 4096.0f;
  43. }
  44. /*!
  45. Returns the general volume.
  46. */
  47. float AudioMixer::generalVolume()
  48. {
  49. return (float)m_fixedGeneralVolume *
  50. (float)audioSourceCount() / GEMaxAudioVolumeValue;
  51. }
  52. /*!
  53. Adds \a source to the list of audio sources. Returns true if the given audio
  54. source was added into the list, false otherwise.
  55. */
  56. bool AudioMixer::addAudioSource(AudioSource *source)
  57. {
  58. DEBUG_POINT;
  59. if (!source) {
  60. // Invalid argument!
  61. DEBUG_INFO("The given source is NULL!");
  62. return false;
  63. }
  64. QMutexLocker locker(&m_mutex);
  65. Q_UNUSED(locker); // To prevent warnings.
  66. m_sourceList.push_back(source);
  67. return true;
  68. }
  69. /*!
  70. Removes \a source from the list of audio sources. Returns true if
  71. found and removed, false otherwise.
  72. Note: The removed item is not deleted!
  73. */
  74. bool AudioMixer::removeAudioSource(AudioSource *source)
  75. {
  76. QMutexLocker locker(&m_mutex);
  77. Q_UNUSED(locker); // To prevent warnings
  78. return m_sourceList.removeOne(source);
  79. }
  80. /*!
  81. Destroys all the sources in the list.
  82. */
  83. void AudioMixer::destroyList()
  84. {
  85. DEBUG_POINT;
  86. QMutexLocker locker(&m_mutex);
  87. Q_UNUSED(locker); // To prevent warnings
  88. QList<AudioSource*>::iterator iter;
  89. for (iter = m_sourceList.begin(); iter != m_sourceList.end(); iter++) {
  90. delete *iter;
  91. }
  92. m_sourceList.clear();
  93. }
  94. /*!
  95. Returns the audio source list count.
  96. */
  97. int AudioMixer::audioSourceCount()
  98. {
  99. QMutexLocker locker(&m_mutex);
  100. Q_UNUSED(locker); // To prevent warnings
  101. DEBUG_INFO("Will return" << m_sourceList.count());
  102. return m_sourceList.count();
  103. }
  104. /*!
  105. From AudioSource.
  106. Mix the requested amount of samples from all mixer's audiosources
  107. into a single buffer.
  108. */
  109. int AudioMixer::pullAudio(AUDIO_SAMPLE_TYPE *target, int bufferLength)
  110. {
  111. QMutexLocker locker(&m_mutex);
  112. Q_UNUSED(locker); // To prevent warnings
  113. if (m_sourceList.isEmpty()) {
  114. DEBUG_INFO("No items in the source list!");
  115. return 0;
  116. }
  117. if (m_mixingBufferLength < bufferLength) {
  118. if (m_mixingBuffer)
  119. delete [] m_mixingBuffer;
  120. m_mixingBufferLength = bufferLength;
  121. m_mixingBuffer = new AUDIO_SAMPLE_TYPE[m_mixingBufferLength];
  122. }
  123. memset(target, 0, sizeof(AUDIO_SAMPLE_TYPE) *bufferLength);
  124. AUDIO_SAMPLE_TYPE *t;
  125. AUDIO_SAMPLE_TYPE *t_target;
  126. AUDIO_SAMPLE_TYPE *s;
  127. QList<AudioSource*>::iterator iter(m_sourceList.begin());
  128. while (iter != m_sourceList.end()) {
  129. if (!(*iter)) {
  130. // NULL pointer!
  131. DEBUG_INFO("Warning: stumbled on a null pointer!");
  132. continue;
  133. }
  134. // Process the list item.
  135. int mixed = (*iter)->pullAudio(m_mixingBuffer, bufferLength);
  136. if (mixed > 0) {
  137. // Mix to main.
  138. t = target;
  139. t_target = t + mixed;
  140. s = m_mixingBuffer;
  141. while (t != t_target) {
  142. *t += (((*s) * m_fixedGeneralVolume) >> 12);
  143. t++;
  144. s++;
  145. }
  146. }
  147. if ((*iter)->canBeDestroyed()) {
  148. // Auto-destroy the current audio source.
  149. //
  150. // Note: The auto-destroy feature is undergoing testing and may
  151. // cause unpredictable crashes with some use cases!
  152. delete *iter;
  153. iter = m_sourceList.erase(iter);
  154. }
  155. else {
  156. iter++;
  157. }
  158. }
  159. //DEBUG_INFO("Done, will return buffer length: " << bufferLength);
  160. return bufferLength;
  161. }
  162. /*!
  163. Sets \a volume as the absolute volume.
  164. */
  165. void AudioMixer::setAbsoluteVolume(float volume)
  166. {
  167. m_fixedGeneralVolume = GEMaxAudioVolumeValue * volume;
  168. emit absoluteVolumeChanged(m_fixedGeneralVolume);
  169. }
  170. /*!
  171. Sets \a volume as the general volume, relative to the channel count
  172. (audio source count).
  173. */
  174. void AudioMixer::setGeneralVolume(float volume)
  175. {
  176. const int sourceCount(audioSourceCount());
  177. // Safety checks for possible division by zero error.
  178. if (volume == 0) {
  179. m_fixedGeneralVolume = 0.0f;
  180. }
  181. else if (sourceCount) {
  182. m_fixedGeneralVolume =
  183. (GEMaxAudioVolumeValue / (float)audioSourceCount() * volume);
  184. }
  185. qDebug() << "Volume : " << m_fixedGeneralVolume;
  186. emit generalVolumeChanged(m_fixedGeneralVolume);
  187. }