CAudioSource2_ptr ParaEngine::CAudioEngine2::Create(const char* sName, const char* sWavePath, bool bStream) { CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sName); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(!pWave) { pWave = new CAudioSource2(sName); iter->second = pWave; } if(pWave->m_pSource) { pWave->m_pSource->stop(); } } else { pWave = new CAudioSource2(sName); m_audio_file_map[sName] = pWave; } if(m_pAudioEngine == 0) return pWave; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; #ifdef PARAENGINE_MOBILE // streaming should be disabled since it is too slow on mobile disk. OUTPUT_LOG("streaming audio file %s is disabled since it is too slow on mobile disk\n", pEntry->GetLocalFileName().c_str()); bStream = false; #endif if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); // OUTPUT_LOG("info:streaming audio file from %s\n", filename.c_str()); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), true)) { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } else { OUTPUT_LOG("warning: failed to copy audio file from %s to %s\n", pEntry->GetLocalFileName().c_str(), filename.c_str()); } } else { pSource = m_pAudioEngine->create(sName, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); // OUTPUT_LOG("info:playing in memory audio file from %s\n", pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sName, file.getBuffer(), file.getSize(), file_extension.c_str()); } else { OUTPUT_LOG("warning: failed to open audio file %s\n", pEntry->GetLocalFileName().c_str()); } } if(pSource) { pWave->SetSource(pSource); // if there is pending looped sound, we will play it. For non-looping sound that has just finished downloading, we will ignore it. if(pWave->m_bIsAsyncLoadingWhileLoopPlaying) { pWave->play2d(true); } } } else { CWaveFileDownloadCallBackData2 callBack(sName, sWavePath, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sName, sWavePath, bStream); if(pSource) { pWave->SetSource(pSource); } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { #ifdef PARAENGINE_MOBILE OUTPUT_LOG("audio file opened: %s \n", sWavePath); #endif std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave->SetSource(pSource); } } } } return pWave; }
HRESULT ParaEngine::CAudioEngine2::PlayWaveFile( const char* sWavePath, bool bLoop, bool bStream/*=false*/, int dwPlayOffset/*=0*/ ) { if(!IsValidAndEnabled() || GetGlobalVolume()<=0.f) return E_FAIL; // check if the wave file is already prepared before CAudioSource2_ptr pWave; AudioFileMap_type::iterator iter = m_audio_file_map.find(sWavePath); if (iter!=m_audio_file_map.end()) { pWave = iter->second; if(pWave && pWave->m_pSource) { if(pWave->m_pSource->isPlaying()) { // already playing, so return. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s already playing. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); #endif return S_OK; } } else { // it usually means that the music is pending for downloading. #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: %s pending for download\n", sWavePath); #endif return S_OK; } } else { // prepare the wave file. bool bSucceed = false; AssetFileEntry* pEntry = CAssetManifest::GetSingleton().GetFile(sWavePath); if(pEntry) { if(pEntry->DoesFileExist()) { // we already downloaded the file, so load it. IParaAudioSource* pSource = NULL; if(bStream) { // Since local cache filename does not have file extension, however audio engine needs to have an extension in order to load from file. // so we will create a file with the proper extension in the same directory. std::string filename = pEntry->GetFullFilePath() + "." + CParaFile::GetFileExtension(sWavePath); if(!CParaFile::DoesFileExist(filename.c_str(), false)) { if(CParaFile::CopyFile(pEntry->GetLocalFileName().c_str(), filename.c_str(), false)) { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { pSource = m_pAudioEngine->create(sWavePath, filename.c_str(), bStream); } } else { // always load from memory if no streaming is specified. ParaEngine::CParaFile file(pEntry->GetLocalFileName().c_str()); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); } } if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } else { // push to the queue. m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); CWaveFilePlayCallBackData2 callBack(sWavePath, bLoop, bStream); // we shall wait for asset completion. pEntry->SyncFile_Async(callBack); } } else { #if !(defined(STATIC_PLUGIN_CAUDIOENGINE)) && !(defined(PARAENGINE_MOBILE) && defined(WIN32)) if(ParaEngine::CParaFile::DoesFileExist(sWavePath, false)) { IParaAudioSource* pSource = m_pAudioEngine->create(sWavePath, sWavePath, bStream); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; #ifdef DEBUG_AUDIO OUTPUT_LOG("PlayWaveFile: new audio %s prepared \n", sWavePath); #endif } } else #endif { // currently it will unzip file each time a zipped music is played. We may first check a fixed temp location and play it from there before extracting to it. ParaEngine::CParaFile file(sWavePath); if(!file.isEof()) { std::string file_extension = CParaFile::GetFileExtension(sWavePath); IParaAudioSource* pSource = m_pAudioEngine->createFromMemory(sWavePath, file.getBuffer(), file.getSize(), file_extension.c_str()); if(pSource) { pWave = new CAudioSource2(sWavePath, pSource); m_audio_file_map[sWavePath] = pWave; bSucceed = true; } } } } if(!bSucceed) { m_audio_file_map[sWavePath] = CAudioSource2_ptr(new CAudioSource2(sWavePath)); OUTPUT_LOG("unable to prepare wave file %s\r\n", sWavePath); return E_FAIL; } } // play the sound if(pWave) { if( ! (pWave->play2d(bLoop, false)) ) { return E_FAIL; } #ifdef DEBUG_AUDIO if(pWave->m_pSource) { OUTPUT_LOG("PlayWaveFile: play2d is called for %s. audio pos: %d, audio time:%f, total size %d, volume %f\n", sWavePath, pWave->m_pSource->getCurrentAudioPosition(), pWave->m_pSource->getCurrentAudioTime(), pWave->m_pSource->getTotalAudioSize(), pWave->m_pSource->getVolume()); } #endif } return S_OK; }