1
0

AudioEngine-winrt.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * cocos2d-x http://www.cocos2d-x.org
  3. *
  4. * Copyright (c) 2010-2011 - cocos2d-x community
  5. *
  6. * Portions Copyright (c) Microsoft Open Technologies, Inc.
  7. * All Rights Reserved
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and limitations under the License.
  17. */
  18. #include "base/ccMacros.h"
  19. #include "platform/CCPlatformConfig.h"
  20. #if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
  21. #include "audio/winrt/AudioEngine-winrt.h"
  22. #include "platform/CCFileUtils.h"
  23. #include "base/CCDirector.h"
  24. #include "base/CCScheduler.h"
  25. using namespace cocos2d;
  26. using namespace cocos2d::experimental;
  27. AudioEngineImpl::AudioEngineImpl()
  28. : _lazyInitLoop(true)
  29. , _currentAudioID(0)
  30. {
  31. }
  32. AudioEngineImpl::~AudioEngineImpl()
  33. {
  34. auto scheduler = cocos2d::Director::getInstance()->getScheduler();
  35. scheduler->unschedule(schedule_selector(AudioEngineImpl::update), this);
  36. _audioCaches.clear();
  37. }
  38. bool AudioEngineImpl::init()
  39. {
  40. return true;
  41. }
  42. AudioCache* AudioEngineImpl::preload(const std::string& filePath, std::function<void(bool)> callback)
  43. {
  44. AudioCache* audioCache = nullptr;
  45. do
  46. {
  47. auto it = _audioCaches.find(filePath);
  48. if (it == _audioCaches.end()) {
  49. FileFormat fileFormat = FileFormat::UNKNOWN;
  50. std::string fileExtension = FileUtils::getInstance()->getFileExtension(filePath);
  51. if (fileExtension == ".wav")
  52. {
  53. fileFormat = FileFormat::WAV;
  54. }
  55. else if (fileExtension == ".ogg")
  56. {
  57. fileFormat = FileFormat::OGG;
  58. }
  59. else if (fileExtension == ".mp3")
  60. {
  61. fileFormat = FileFormat::MP3;
  62. }
  63. else
  64. {
  65. log("Unsupported media type file: %s\n", filePath.c_str());
  66. break;
  67. }
  68. audioCache = &_audioCaches[filePath];
  69. audioCache->_fileFormat = fileFormat;
  70. std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath);
  71. audioCache->_fileFullPath = fullPath;
  72. AudioEngine::addTask(std::bind(&AudioCache::readDataTask, audioCache));
  73. }
  74. else
  75. {
  76. audioCache = &it->second;
  77. }
  78. } while (false);
  79. if (callback)
  80. {
  81. if (audioCache)
  82. {
  83. audioCache->addLoadCallback(callback);
  84. }
  85. else
  86. {
  87. callback(false);
  88. }
  89. }
  90. return audioCache;
  91. }
  92. int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume)
  93. {
  94. auto audioCache = preload(filePath, nullptr);
  95. if (audioCache == nullptr)
  96. {
  97. return AudioEngine::INVALID_AUDIO_ID;
  98. }
  99. auto player = &_audioPlayers[_currentAudioID];
  100. player->_loop = loop;
  101. player->_volume = volume;
  102. audioCache->addPlayCallback(std::bind(&AudioEngineImpl::_play2d, this, audioCache, _currentAudioID));
  103. if (_lazyInitLoop) {
  104. _lazyInitLoop = false;
  105. auto scheduler = cocos2d::Director::getInstance()->getScheduler();
  106. scheduler->schedule(schedule_selector(AudioEngineImpl::update), this, 0.05f, false);
  107. }
  108. return _currentAudioID++;
  109. }
  110. void AudioEngineImpl::_play2d(AudioCache *cache, int audioID)
  111. {
  112. if (cache->_isReady){
  113. auto playerIt = _audioPlayers.find(audioID);
  114. if (playerIt != _audioPlayers.end()) {
  115. if (playerIt->second.play2d(cache)) {
  116. AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PLAYING;
  117. }
  118. else{
  119. _threadMutex.lock();
  120. _toRemoveAudioIDs.push_back(audioID);
  121. _threadMutex.unlock();
  122. }
  123. }
  124. }
  125. else {
  126. _threadMutex.lock();
  127. _toRemoveCaches.push_back(cache);
  128. _toRemoveAudioIDs.push_back(audioID);
  129. _threadMutex.unlock();
  130. }
  131. }
  132. void AudioEngineImpl::setVolume(int audioID, float volume)
  133. {
  134. auto& player = _audioPlayers[audioID];
  135. if (player._ready){
  136. player.setVolume(volume);
  137. }
  138. if (player.isInError()) {
  139. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  140. }
  141. }
  142. void AudioEngineImpl::setLoop(int audioID, bool loop)
  143. {
  144. auto& player = _audioPlayers[audioID];
  145. if (player._ready) {
  146. player._loop = loop;
  147. }
  148. if (player.isInError()) {
  149. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  150. }
  151. }
  152. bool AudioEngineImpl::pause(int audioID)
  153. {
  154. bool ret = false;
  155. auto& player = _audioPlayers[audioID];
  156. if (player._ready) {
  157. player.pause();
  158. AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PAUSED;
  159. }
  160. ret = !player.isInError();
  161. if (!ret) {
  162. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  163. }
  164. return ret;
  165. }
  166. bool AudioEngineImpl::resume(int audioID)
  167. {
  168. bool ret = false;
  169. auto& player = _audioPlayers[audioID];
  170. if (player._ready) {
  171. player.resume();
  172. AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PLAYING;
  173. }
  174. ret = !player.isInError();
  175. if (!ret) {
  176. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  177. }
  178. return ret;
  179. }
  180. bool AudioEngineImpl::stop(int audioID)
  181. {
  182. bool ret = false;
  183. auto& player = _audioPlayers[audioID];
  184. if (player._ready) {
  185. player.stop();
  186. ret = !player.isInError();
  187. }
  188. if (!ret) {
  189. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  190. }
  191. _audioPlayers.erase(audioID);
  192. return ret;
  193. }
  194. void AudioEngineImpl::stopAll()
  195. {
  196. for (auto &player : _audioPlayers) {
  197. player.second.stop();
  198. }
  199. _audioPlayers.clear();
  200. }
  201. float AudioEngineImpl::getDuration(int audioID)
  202. {
  203. auto& player = _audioPlayers[audioID];
  204. if (player._ready) {
  205. return player.getDuration();
  206. }
  207. else {
  208. return AudioEngine::TIME_UNKNOWN;
  209. }
  210. }
  211. float AudioEngineImpl::getCurrentTime(int audioID)
  212. {
  213. float ret = 0.0f;
  214. auto& player = _audioPlayers[audioID];
  215. if (player._ready) {
  216. ret = player.getCurrentTime();
  217. }
  218. return ret;
  219. }
  220. bool AudioEngineImpl::setCurrentTime(int audioID, float time)
  221. {
  222. bool ret = false;
  223. auto& player = _audioPlayers[audioID];
  224. if (player._ready) {
  225. ret = player.setTime(time);
  226. }
  227. if (!ret) {
  228. log("%s: audio id = %d, error.\n", __FUNCTION__, audioID);
  229. }
  230. return ret;
  231. }
  232. void AudioEngineImpl::setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback)
  233. {
  234. _audioPlayers[audioID]._finishCallback = callback;
  235. }
  236. void AudioEngineImpl::update(float dt)
  237. {
  238. int audioID;
  239. if (_threadMutex.try_lock()) {
  240. size_t removeAudioCount = _toRemoveAudioIDs.size();
  241. for (size_t index = 0; index < removeAudioCount; ++index) {
  242. audioID = _toRemoveAudioIDs[index];
  243. auto playerIt = _audioPlayers.find(audioID);
  244. if (playerIt != _audioPlayers.end()) {
  245. if (playerIt->second._finishCallback) {
  246. auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
  247. playerIt->second._finishCallback(audioID, *audioInfo.filePath);
  248. }
  249. _audioPlayers.erase(audioID);
  250. AudioEngine::remove(audioID);
  251. }
  252. }
  253. size_t removeCacheCount = _toRemoveCaches.size();
  254. for (size_t index = 0; index < removeCacheCount; ++index) {
  255. auto itEnd = _audioCaches.end();
  256. for (auto it = _audioCaches.begin(); it != itEnd; ++it) {
  257. if (&it->second == _toRemoveCaches[index]) {
  258. _audioCaches.erase(it);
  259. break;
  260. }
  261. }
  262. }
  263. _threadMutex.unlock();
  264. }
  265. for (auto it = _audioPlayers.begin(); it != _audioPlayers.end();) {
  266. audioID = it->first;
  267. auto& player = it->second;
  268. if (player._ready && player._state == AudioPlayerState::STOPPED) {
  269. if (player._finishCallback) {
  270. auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
  271. player._finishCallback(audioID, *audioInfo.filePath);
  272. }
  273. AudioEngine::remove(audioID);
  274. it = _audioPlayers.erase(it);
  275. }
  276. else{
  277. player.update();
  278. ++it;
  279. }
  280. }
  281. if (_audioPlayers.empty()){
  282. _lazyInitLoop = true;
  283. auto scheduler = cocos2d::Director::getInstance()->getScheduler();
  284. scheduler->unschedule(schedule_selector(AudioEngineImpl::update), this);
  285. }
  286. }
  287. void AudioEngineImpl::uncache(const std::string &filePath)
  288. {
  289. _audioCaches.erase(filePath);
  290. }
  291. void AudioEngineImpl::uncacheAll()
  292. {
  293. _audioCaches.clear();
  294. }
  295. #endif