AudioSource.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "Base.h"
  2. #include "Node.h"
  3. #include "AudioBuffer.h"
  4. #include "AudioController.h"
  5. #include "AudioSource.h"
  6. #include "Game.h"
  7. #include "Node.h"
  8. namespace gameplay
  9. {
  10. AudioSource::AudioSource(AudioBuffer* buffer, ALuint source)
  11. : _alSource(source), _buffer(buffer), _looped(true), _gain(1.0f), _pitch(1.0f), _node(NULL)
  12. {
  13. alSourcei(_alSource, AL_BUFFER, buffer->_alBuffer);
  14. alSourcei(_alSource, AL_LOOPING, _looped);
  15. alSourcef(_alSource, AL_PITCH, _pitch);
  16. alSourcef(_alSource, AL_GAIN, _gain);
  17. alSourcefv(_alSource, AL_VELOCITY, (const ALfloat*)&_velocity);
  18. }
  19. AudioSource::~AudioSource()
  20. {
  21. if (_alSource)
  22. {
  23. alDeleteSources(1, &_alSource);
  24. _alSource = 0;
  25. }
  26. SAFE_RELEASE(_buffer);
  27. }
  28. AudioSource* AudioSource::create(const char* url)
  29. {
  30. GP_ASSERT(url);
  31. // Load from a .audio file.
  32. std::string pathStr = url;
  33. if (pathStr.find(".audio") != pathStr.npos)
  34. {
  35. Properties* properties = Properties::create(url);
  36. GP_ASSERT(properties);
  37. if (properties == NULL)
  38. {
  39. return NULL;
  40. }
  41. AudioSource* audioSource = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
  42. SAFE_DELETE(properties);
  43. return audioSource;
  44. }
  45. // Create an audio buffer from this URL.
  46. AudioBuffer* buffer = AudioBuffer::create(url);
  47. if (buffer == NULL)
  48. return NULL;
  49. // Load the audio source.
  50. ALuint alSource = 0;
  51. alGenSources(1, &alSource);
  52. if (alGetError() != AL_NO_ERROR)
  53. {
  54. SAFE_RELEASE(buffer);
  55. GP_ERROR("AudioSource::createAudioSource - Error generating audio source.");
  56. return NULL;
  57. }
  58. return new AudioSource(buffer, alSource);
  59. }
  60. AudioSource* AudioSource::create(Properties* properties)
  61. {
  62. // Check if the properties is valid and has a valid namespace.
  63. GP_ASSERT(properties);
  64. if (!properties || !(strcmp(properties->getNamespace(), "audio") == 0))
  65. {
  66. GP_WARN("Failed to load audio source from properties object: must be non-null object and have namespace equal to \'audio\'.");
  67. return NULL;
  68. }
  69. const char* path = properties->getString("path");
  70. if (path == NULL)
  71. {
  72. GP_WARN("Audio file failed to load; the file path was not specified.");
  73. return NULL;
  74. }
  75. // Create the audio source.
  76. AudioSource* audio = AudioSource::create(path);
  77. if (audio == NULL)
  78. {
  79. GP_WARN("Audio file '%s' failed to load properly.", path);
  80. return NULL;
  81. }
  82. // Set any properties that the user specified in the .audio file.
  83. if (properties->getString("looped") != NULL)
  84. {
  85. audio->setLooped(properties->getBool("looped"));
  86. }
  87. if (properties->getString("gain") != NULL)
  88. {
  89. audio->setGain(properties->getFloat("gain"));
  90. }
  91. if (properties->getString("pitch") != NULL)
  92. {
  93. audio->setPitch(properties->getFloat("pitch"));
  94. }
  95. Vector3 v;
  96. if (properties->getVector3("velocity", &v))
  97. {
  98. audio->setVelocity(v);
  99. }
  100. return audio;
  101. }
  102. AudioSource::State AudioSource::getState() const
  103. {
  104. ALint state;
  105. alGetSourcei(_alSource, AL_SOURCE_STATE, &state);
  106. switch (state)
  107. {
  108. case AL_PLAYING:
  109. return PLAYING;
  110. case AL_PAUSED:
  111. return PAUSED;
  112. case AL_STOPPED:
  113. return STOPPED;
  114. default:
  115. return INITIAL;
  116. }
  117. return INITIAL;
  118. }
  119. void AudioSource::play()
  120. {
  121. alSourcePlay(_alSource);
  122. // Add the source to the controller's list of currently playing sources.
  123. AudioController* audioController = Game::getInstance()->getAudioController();
  124. if (audioController->_playingSources.find(this) == audioController->_playingSources.end())
  125. audioController->_playingSources.insert(this);
  126. }
  127. void AudioSource::pause()
  128. {
  129. alSourcePause(_alSource);
  130. // Remove the source from the controller's set of currently playing sources
  131. // if the source is being paused by the user and not the controller itself.
  132. AudioController* audioController = Game::getInstance()->getAudioController();
  133. if (audioController->_pausingSource != this)
  134. {
  135. std::set<AudioSource*>::iterator iter = audioController->_playingSources.find(this);
  136. if (iter != audioController->_playingSources.end())
  137. {
  138. GP_WARN("\n\nRemoving an audio source from the list of playing sources...\n\n\n");
  139. audioController->_playingSources.erase(iter);
  140. }
  141. }
  142. }
  143. void AudioSource::resume()
  144. {
  145. if (getState() == PAUSED)
  146. {
  147. play();
  148. }
  149. }
  150. void AudioSource::stop()
  151. {
  152. alSourceStop(_alSource);
  153. // Remove the source from the controller's set of currently playing sources.
  154. AudioController* audioController = Game::getInstance()->getAudioController();
  155. std::set<AudioSource*>::iterator iter = audioController->_playingSources.find(this);
  156. if (iter != audioController->_playingSources.end())
  157. audioController->_playingSources.erase(iter);
  158. }
  159. void AudioSource::rewind()
  160. {
  161. alSourceRewind(_alSource);
  162. }
  163. bool AudioSource::isLooped() const
  164. {
  165. return _looped;
  166. }
  167. void AudioSource::setLooped(bool looped)
  168. {
  169. alGetError();
  170. alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE);
  171. ALCenum error = alGetError();
  172. if (error != AL_NO_ERROR)
  173. {
  174. GP_ERROR("AudioSource::setLooped Error: %d", error);
  175. }
  176. _looped = looped;
  177. }
  178. float AudioSource::getGain() const
  179. {
  180. return _gain;
  181. }
  182. void AudioSource::setGain(float gain)
  183. {
  184. alSourcef(_alSource, AL_GAIN, gain);
  185. _gain = gain;
  186. }
  187. float AudioSource::getPitch() const
  188. {
  189. return _pitch;
  190. }
  191. void AudioSource::setPitch(float pitch)
  192. {
  193. alSourcef(_alSource, AL_PITCH, pitch);
  194. _pitch = pitch;
  195. }
  196. const Vector3& AudioSource::getVelocity() const
  197. {
  198. return _velocity;
  199. }
  200. void AudioSource::setVelocity(const Vector3& velocity)
  201. {
  202. alSourcefv(_alSource, AL_VELOCITY, (ALfloat*)&velocity);
  203. _velocity = velocity;
  204. }
  205. Node* AudioSource::getNode() const
  206. {
  207. return _node;
  208. }
  209. void AudioSource::setNode(Node* node)
  210. {
  211. if (_node != node)
  212. {
  213. // Disconnect our current transform.
  214. if (_node)
  215. {
  216. _node->removeListener(this);
  217. }
  218. // Connect the new node.
  219. _node = node;
  220. if (_node)
  221. {
  222. _node->addListener(this);
  223. // Update the audio source position.
  224. transformChanged(_node, 0);
  225. }
  226. }
  227. }
  228. void AudioSource::transformChanged(Transform* transform, long cookie)
  229. {
  230. if (_node)
  231. {
  232. Vector3 translation = _node->getTranslationWorld();
  233. alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x);
  234. }
  235. }
  236. AudioSource* AudioSource::clone(NodeCloneContext &context) const
  237. {
  238. ALuint alSource = 0;
  239. alGenSources(1, &alSource);
  240. if (alGetError() != AL_NO_ERROR)
  241. {
  242. GP_ERROR("AudioSource::createAudioSource - Error generating audio source.");
  243. return NULL;
  244. }
  245. AudioSource* audioClone = new AudioSource(_buffer, alSource);
  246. _buffer->addRef();
  247. audioClone->setLooped(isLooped());
  248. audioClone->setGain(getGain());
  249. audioClone->setPitch(getPitch());
  250. audioClone->setVelocity(getVelocity());
  251. if (Node* node = getNode())
  252. {
  253. Node* clonedNode = context.findClonedNode(node);
  254. if (clonedNode)
  255. {
  256. audioClone->setNode(clonedNode);
  257. }
  258. }
  259. return audioClone;
  260. }
  261. }