AudioSource.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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(false), _gain(1.0f), _pitch(1.0f), _node(NULL)
  12. {
  13. GP_ASSERT(buffer);
  14. AL_CHECK( alSourcei(_alSource, AL_BUFFER, buffer->_alBuffer) );
  15. AL_CHECK( alSourcei(_alSource, AL_LOOPING, _looped) );
  16. AL_CHECK( alSourcef(_alSource, AL_PITCH, _pitch) );
  17. AL_CHECK( alSourcef(_alSource, AL_GAIN, _gain) );
  18. AL_CHECK( alSourcefv(_alSource, AL_VELOCITY, (const ALfloat*)&_velocity) );
  19. }
  20. AudioSource::~AudioSource()
  21. {
  22. if (_alSource)
  23. {
  24. AL_CHECK( alDeleteSources(1, &_alSource) );
  25. _alSource = 0;
  26. }
  27. SAFE_RELEASE(_buffer);
  28. }
  29. AudioSource* AudioSource::create(const char* url)
  30. {
  31. // Load from a .audio file.
  32. std::string pathStr = url;
  33. if (pathStr.find(".audio") != std::string::npos)
  34. {
  35. Properties* properties = Properties::create(url);
  36. if (properties == NULL)
  37. {
  38. GP_ERROR("Failed to create audio source from .audio file.");
  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. AL_CHECK( alGenSources(1, &alSource) );
  52. if (AL_LAST_ERROR())
  53. {
  54. SAFE_RELEASE(buffer);
  55. GP_ERROR("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_ERROR("Failed to load audio source from properties object: must be non-null object and have namespace equal to 'audio'.");
  67. return NULL;
  68. }
  69. std::string path;
  70. if (!properties->getPath("path", &path))
  71. {
  72. GP_ERROR("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.c_str());
  77. if (audio == NULL)
  78. {
  79. GP_ERROR("Audio file '%s' failed to load properly.", path.c_str());
  80. return NULL;
  81. }
  82. // Set any properties that the user specified in the .audio file.
  83. if (properties->exists("looped"))
  84. {
  85. audio->setLooped(properties->getBool("looped"));
  86. }
  87. if (properties->exists("gain"))
  88. {
  89. audio->setGain(properties->getFloat("gain"));
  90. }
  91. if (properties->exists("pitch"))
  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. AL_CHECK( 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. AL_CHECK( alSourcePlay(_alSource) );
  122. // Add the source to the controller's list of currently playing sources.
  123. AudioController* audioController = Game::getInstance()->getAudioController();
  124. GP_ASSERT(audioController);
  125. if (audioController->_playingSources.find(this) == audioController->_playingSources.end())
  126. audioController->_playingSources.insert(this);
  127. }
  128. void AudioSource::pause()
  129. {
  130. AL_CHECK( alSourcePause(_alSource) );
  131. // Remove the source from the controller's set of currently playing sources
  132. // if the source is being paused by the user and not the controller itself.
  133. AudioController* audioController = Game::getInstance()->getAudioController();
  134. GP_ASSERT(audioController);
  135. if (audioController->_pausingSource != this)
  136. {
  137. std::set<AudioSource*>::iterator iter = audioController->_playingSources.find(this);
  138. if (iter != audioController->_playingSources.end())
  139. audioController->_playingSources.erase(iter);
  140. }
  141. }
  142. void AudioSource::resume()
  143. {
  144. if (getState() == PAUSED)
  145. {
  146. play();
  147. }
  148. }
  149. void AudioSource::stop()
  150. {
  151. AL_CHECK( alSourceStop(_alSource) );
  152. // Remove the source from the controller's set of currently playing sources.
  153. AudioController* audioController = Game::getInstance()->getAudioController();
  154. GP_ASSERT(audioController);
  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. AL_CHECK( alSourceRewind(_alSource) );
  162. }
  163. bool AudioSource::isLooped() const
  164. {
  165. return _looped;
  166. }
  167. void AudioSource::setLooped(bool looped)
  168. {
  169. AL_CHECK( alSourcei(_alSource, AL_LOOPING, (looped) ? AL_TRUE : AL_FALSE) );
  170. if (AL_LAST_ERROR())
  171. {
  172. GP_ERROR("Failed to set audio source's looped attribute with error: %d", AL_LAST_ERROR());
  173. }
  174. _looped = looped;
  175. }
  176. float AudioSource::getGain() const
  177. {
  178. return _gain;
  179. }
  180. void AudioSource::setGain(float gain)
  181. {
  182. AL_CHECK( alSourcef(_alSource, AL_GAIN, gain) );
  183. _gain = gain;
  184. }
  185. float AudioSource::getPitch() const
  186. {
  187. return _pitch;
  188. }
  189. void AudioSource::setPitch(float pitch)
  190. {
  191. AL_CHECK( alSourcef(_alSource, AL_PITCH, pitch) );
  192. _pitch = pitch;
  193. }
  194. const Vector3& AudioSource::getVelocity() const
  195. {
  196. return _velocity;
  197. }
  198. void AudioSource::setVelocity(const Vector3& velocity)
  199. {
  200. AL_CHECK( alSourcefv(_alSource, AL_VELOCITY, (ALfloat*)&velocity) );
  201. _velocity = velocity;
  202. }
  203. void AudioSource::setVelocity(float x, float y, float z)
  204. {
  205. setVelocity(Vector3(x, y, z));
  206. }
  207. Node* AudioSource::getNode() const
  208. {
  209. return _node;
  210. }
  211. void AudioSource::setNode(Node* node)
  212. {
  213. if (_node != node)
  214. {
  215. // Disconnect our current transform.
  216. if (_node)
  217. {
  218. _node->removeListener(this);
  219. }
  220. // Connect the new node.
  221. _node = node;
  222. if (_node)
  223. {
  224. _node->addListener(this);
  225. // Update the audio source position.
  226. transformChanged(_node, 0);
  227. }
  228. }
  229. }
  230. void AudioSource::transformChanged(Transform* transform, long cookie)
  231. {
  232. if (_node)
  233. {
  234. Vector3 translation = _node->getTranslationWorld();
  235. AL_CHECK( alSourcefv(_alSource, AL_POSITION, (const ALfloat*)&translation.x) );
  236. }
  237. }
  238. AudioSource* AudioSource::clone(NodeCloneContext &context) const
  239. {
  240. GP_ASSERT(_buffer);
  241. ALuint alSource = 0;
  242. AL_CHECK( alGenSources(1, &alSource) );
  243. if (AL_LAST_ERROR())
  244. {
  245. GP_ERROR("Error generating audio source.");
  246. return NULL;
  247. }
  248. AudioSource* audioClone = new AudioSource(_buffer, alSource);
  249. _buffer->addRef();
  250. audioClone->setLooped(isLooped());
  251. audioClone->setGain(getGain());
  252. audioClone->setPitch(getPitch());
  253. audioClone->setVelocity(getVelocity());
  254. if (Node* node = getNode())
  255. {
  256. Node* clonedNode = context.findClonedNode(node);
  257. if (clonedNode)
  258. {
  259. audioClone->setNode(clonedNode);
  260. }
  261. }
  262. return audioClone;
  263. }
  264. }