SDL游戏之路(二十二)--声音-Windows Store App
来源:互联网 发布:淘宝网外贸女装 编辑:程序博客网 时间:2024/05/18 03:08
声音
windows store app 程序真不好写,文件操作都是异步的,加上对语法和函数不熟,只能靠不断测试达到想要的效果。
1.声音文件是打包在安装包里的,部署的应用程序,先将打包在资源文件复制到应用程序可写目录。(不知道是否必须)
void SkGame::loadAllConfFroWP8(){#ifdef __WP8__create_task([this]() {#endif/** 预先加载配置文件到内存,这样可以避免windows store app 异步读取文件的麻烦 **/vector<string> vctStr;vctStr.push_back("conf/view/Dialog.BtCancle.conf.xml");vctStr.push_back("conf/view/Dialog.BtNo.conf.xml");vctStr.push_back("conf/view/Dialog.BtOk.conf.xml");vctStr.push_back("conf/view/Dialog.BtYes.conf.xml");vctStr.push_back("conf/view/SkViewInput.conf.xml");vctStr.push_back("conf/view/ViewFirst.BtGameBegin.conf.xml");vctStr.push_back("conf/view/ViewFirst.BtGameStart.conf.xml");vctStr.push_back("conf/view/ViewFirst.BtMusicPlay.conf.xml");vctStr.push_back("conf/view/ViewFirst.conf.xml");vctStr.push_back("conf/view/ViewFirst.DlGameInfo.conf.xml");vctStr.push_back("conf/view/ViewFirst.DlGameInfo2.conf.xml");vctStr.push_back("conf/view/ViewFirst.TfName.conf.xml");vctStr.push_back("conf/view/ViewFirst.TfPass.conf.xml");for(int i=0;i<(int)vctStr.size();i++){string sPath = vctStr.at(i);SkDoc m_doc;bool bRet = m_doc.init(sPath.c_str());if (bRet == true) {SkString sData = m_doc.m_data;g_SkComm.m_mapConf[sPath] = sData;}}g_SkComm.log("[%s][%d]map conf size=%d",__FILE__,__LINE__,g_SkComm.m_mapConf.size());/** 预先将资源文件copy到 应用程序的可写目录,这样可以使用系统提供的方式读写文件**/vctStr.clear();vctStr.push_back("mp3/bg.mp3");for(int i=0;i<(int)vctStr.size();i++){string sPath = vctStr.at(i);bool bExit = g_SkFile.wp8FileExist(sPath.c_str());if(!bExit){SkString testData;g_SkFile.readTxtFile(sPath.c_str(),testData);g_SkFile.saveBinFile(sPath.c_str(),testData);}}m_bInitOk = true;#ifdef __WP8__});#endif}
读写函数实现如下:
int SkFile::saveBinFile(const char * pPath, SkString & pData) {#ifdef __WP8__SkString stpath = pPath;stpath.replaceAll('/','-');Platform::String ^ str = ref new Platform::String(stows(stpath.c_str()).c_str());StorageFolder^ dir = ApplicationData::Current->LocalFolder;auto iFile = create_task(dir->CreateFileAsync(str, CreationCollisionOption::OpenIfExists)).then([this](StorageFile^ file){tmpfile = file;});iFile.wait();InMemoryRandomAccessStream^ memoryStream = ref new InMemoryRandomAccessStream(); DataWriter^ dataWriter = ref new DataWriter(memoryStream);Platform::Array<unsigned char>^ bytes = ref new Platform::Array<unsigned char>((unsigned char*)pData.c_str(),pData.length()); dataWriter->WriteBytes(bytes);IBuffer^ buffer = dataWriter->DetachBuffer();StorageFile^ file = this->tmpfile;auto iSave = create_task(FileIO::WriteBufferAsync(file , buffer)).then([this, file, buffer](task<void> task){task.get();});iSave.wait();return 0;#elsechar tmpFile[256];snprintf(tmpFile, sizeof(tmpFile), "%s/%s", getRootPath(), pPath);FILE *fp2 = fopen(tmpFile, "wb");if (fp2 == NULL) {return -2;}for(int i=0;i<pData.length();i+=1024){int ilen = 1024;if(i+ilen>pData.length()){ilen = pData.length()-i;}fwrite(pData.c_str()+i, ilen, 1, fp2);if(i+ilen>=pData.length()){break;}}fclose(fp2);#endifreturn 0;}int SkFile::readTxtFile(const char * pPath, SkString & sData) {#ifdef __WP8__//读取失败,再读取原始文件FILE *fp2 = NULL;fopen_s(&fp2,pPath, "rb");if (fp2 == NULL) {return -1;}sData.clear();char buf[1024];while (true) {int iLen = fread(buf, 1, sizeof(buf), fp2);if (iLen <= 0) {break;}sData.append(buf, iLen);}fclose(fp2);return 0;#elsechar tmpFile[256];snprintf(tmpFile, sizeof(tmpFile), "%s/%s", getRootPath(), pPath);FILE *fp2 = fopen(tmpFile, "rb");if (fp2 == NULL) {return -2;}sData.clear();char buf[1024];while (true) {int iLen = fread(buf, 1, sizeof(buf), fp2);if (iLen <= 0) {break;}sData.append(buf, iLen);}fclose(fp2);return 0;#endif}
2.编写一个声音管理类。(从官方下载的示例中可以找到,稍微做了一点修改。)
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A// PARTICULAR PURPOSE.//// Copyright (c) Microsoft Corporation. All rights reserved.//#pragma once#include <wrl.h>#include <mfmediaengine.h>#include <d3d11_1.h>//#include <d3d10.h>#include <ppltasks.h>#include <agile.h>#ifndef MEPLAYER_H#define MEPLAYER_H#define ME_CAN_SEEK 0x00000002namespace MEDIA{ inline void ThrowIfFailed(HRESULT hr) { if (FAILED(hr)) { // Set a breakpoint on this line to catch DirectX API errors throw Platform::Exception::CreateException(hr); } }}//-----------------------------------------------------------------------------// MediaEngineNotifyCallback//// Defines the callback method to process media engine events.//-----------------------------------------------------------------------------ref struct MediaEngineNotifyCallback abstract{internal: virtual void OnMediaEngineEvent(DWORD meEvent) = 0;};// MEPlayer: Manages the Media Engine.ref class MEPlayer: public MediaEngineNotifyCallback{ // DX11 related Microsoft::WRL::ComPtr<ID3D11Device> m_spDX11Device; Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_spDX11DeviceContext; Microsoft::WRL::ComPtr<IDXGIOutput> m_spDXGIOutput; Microsoft::WRL::ComPtr<IDXGISwapChain1> m_spDX11SwapChain; Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> m_spDXGIManager; // Media Engine related Microsoft::WRL::ComPtr<IMFMediaEngine> m_spMediaEngine; Microsoft::WRL::ComPtr<IMFMediaEngineEx> m_spEngineEx; BSTR m_bstrURL; BOOL m_fPlaying; BOOL m_fLoop; BOOL m_fEOS; BOOL m_fStopTimer; RECT m_rcTarget; DXGI_FORMAT m_d3dFormat; MFARGB m_bkgColor; HANDLE m_TimerThreadHandle; CRITICAL_SECTION m_critSec; concurrency::task<Windows::Storage::StorageFile^> m_pickFileTask; concurrency::cancellation_token_source m_tcs; BOOL m_fInitSuccess; BOOL m_fExitApp; BOOL m_fUseDX;internal: MEPlayer(); // DX11 related void CreateDX11Device(); void CreateBackBuffers(); // Initialize/Shutdown void Initialize(Windows::UI::Core::CoreWindow^ window); void Shutdown(); BOOL ExitApp(); // Media Engine related virtual void OnMediaEngineEvent(DWORD meEvent) override; // Media Engine related Options void AutoPlay(BOOL autoPlay) { if (m_spMediaEngine) { m_spMediaEngine->SetAutoPlay(autoPlay); } } void Loop() { if (m_spMediaEngine) { (m_fLoop) ? m_fLoop = FALSE : m_fLoop = TRUE; m_spMediaEngine->SetLoop(m_fLoop); } } BOOL IsPlaying() { return m_fPlaying; } void CloseFilePicker() { m_tcs.cancel(); } // Loading void OpenFile(); void SetURL(Platform::String^ szURL); void SetBytestream(Windows::Storage::Streams::IRandomAccessStream^ streamHandle); // Transport state void Play(); void Pause(); void FrameStep(); // Audio void SetVolume(float fVol); void SetBalance(float fBal); void Mute(BOOL mute); // Video void ResizeVideo(HWND hwnd); void EnableVideoEffect(BOOL enable); // Seeking and duration. void GetDuration(double *pDuration, BOOL *pbCanSeek); void SetPlaybackPosition(float pos); double GetPlaybackPosition(); BOOL IsSeeking(); // Window Event Handlers void UpdateForWindowSizeChange(); // Timer thread related void StartTimer(); void StopTimer(); void OnTimer(); DWORD RealVSyncTimer();private: ~MEPlayer(); Platform::Agile<Windows::UI::Core::CoreWindow> m_window;};#endif /* MEPLAYER_H */
3.在资源初始的时候,初始化音乐管理
g_myPlayer->Initialize(m_window.Get());
4.修改自定义的音乐管理类:
#ifndef SKMUSIC_H_#define SKMUSIC_H_#include "SkComm.h"namespace sk_park {/**1:效果音乐 2:背景音乐**/typedef enum _SkMusicType {SK_MUSIC_TYPE_CHUNK = 1, SK_MUSIC_TYPE_MUSIC = 2,} SkMusicType;class SkMusic {public:SkMusic();virtual ~SkMusic();/**加载音乐文件**/int load(SkMusicType mType, const char * pPath);void start();void stop();void pause();private:SkMusicType m_mType;#ifdef __WP8__bool m_loadOk;public:MEPlayer^ m_myPlayer;#elseMix_Music* m_pMusic;Mix_Chunk* m_pChunk;#endif};}extern sk_park::SkMusic g_SkMusic;#endif /* SKMUSIC_H_ */
实现如下:
#include "pch.h"#include "SkMusic.h"#include "SkFile.h"#include "SkString.h"using namespace sk_park;#ifdef __WP8__using namespace Windows::Storage;using namespace Concurrency;using namespace Platform;using namespace Windows::Foundation;using namespace Windows::Storage::Streams;using namespace Windows::Networking;using namespace Windows::Networking::Sockets;using namespace Windows::ApplicationModel::Core;extern MEPlayer^ g_myPlayer;SkMusic::SkMusic(){m_loadOk = false;}SkMusic::~SkMusic() {}int SkMusic::load(SkMusicType mType, const char * pPath){create_task([this,pPath]() {//m_myPlayer = ref new MEPlayer();m_myPlayer = g_myPlayer;StorageFile^ fileHandle = g_SkFile.getWp8File(pPath);m_myPlayer->SetURL(fileHandle->Path);auto oCreate = create_task(fileHandle->OpenAsync(Windows::Storage::FileAccessMode::Read)).then([this](IRandomAccessStream^ streamHandle){try {m_myPlayer->SetBytestream(streamHandle); // vidPlayer->SetBytestream(streamHandle); } catch(Platform::Exception^) { MEDIA::ThrowIfFailed(E_UNEXPECTED); }});oCreate.wait();m_loadOk = true;});return 0;}void SkMusic::start(){if(m_loadOk){m_myPlayer->Play();}}void SkMusic::stop(){if(m_loadOk){m_myPlayer->Pause();}}void SkMusic::pause(){if(m_loadOk){m_myPlayer->Pause();}}#elseSkMusic::SkMusic() {m_pMusic = NULL;m_pChunk = NULL;}SkMusic::~SkMusic() {if (m_pChunk != NULL) {Mix_FreeChunk(m_pChunk);m_pChunk = NULL;}if (m_pMusic != NULL) {Mix_FreeMusic(m_pMusic);m_pMusic = NULL;}}int SkMusic::load(SkMusicType mType, const char * pPath) {SkString sPath = pPath;#ifdef __ANDROID__sPath.replaceAll('/','-');#endifchar musicPath[256];snprintf(musicPath, sizeof(musicPath), "%s/%s", g_SkFile.getRootPath(),sPath.c_str());m_mType = mType;if (SK_MUSIC_TYPE_CHUNK == m_mType) {m_pChunk = Mix_LoadWAV(musicPath);#ifdef __ANDROID__if (m_pChunk == NULL) {SkString sData;int iRet = g_SkFile.readAndroidFile(pPath,sData);g_SkComm.log("[%s][%d]readAndroidFile=%d path=%s", __FILE__, __LINE__,iRet,pPath);if(iRet==0) {iRet = g_SkFile.saveBinFile(sPath.c_str(),sData);g_SkComm.log("[%s][%d]saveBinFile=%d path=%s", __FILE__, __LINE__,iRet,sPath.c_str());}m_pChunk = Mix_LoadWAV(musicPath);}#endifif (m_pChunk != NULL) {return 0;} else {return -1;}} else {m_pMusic = Mix_LoadMUS(musicPath);#ifdef __ANDROID__if (m_pMusic == NULL) {SkString sData;int iRet = g_SkFile.readAndroidFile(pPath,sData);g_SkComm.log("[%s][%d]readAndroidFile=%d path=%s", __FILE__, __LINE__,iRet,pPath);if(iRet==0) {iRet = g_SkFile.saveBinFile(sPath.c_str(),sData);g_SkComm.log("[%s][%d]saveBinFile=%d path=%s", __FILE__, __LINE__,iRet,sPath.c_str());}m_pMusic = Mix_LoadMUS(musicPath);}#endifif (m_pMusic != NULL) {return 0;} else {return -1;}}return -1;}void SkMusic::start() {if (SK_MUSIC_TYPE_CHUNK == m_mType) {if (m_pChunk != NULL) {Mix_PlayChannel(-1, m_pChunk, 0);}} else {if (Mix_PlayingMusic() == false) {if (m_pMusic != NULL) {Mix_PlayMusic(m_pMusic, -1);}} else {if (Mix_PausedMusic() == 1) {Mix_ResumeMusic();} else {//Mix_PauseMusic();}}}}void SkMusic::stop() {if (SK_MUSIC_TYPE_MUSIC == m_mType) {Mix_HaltMusic();}}void SkMusic::pause() {if (SK_MUSIC_TYPE_MUSIC == m_mType) {Mix_PauseMusic();}}#endifSkMusic g_SkMusic;
5.这样,点击播放按钮后,背景音乐出来了。
0 0
- SDL游戏之路(二十二)--声音-Windows Store App
- SDL游戏之路(二十一)--声音
- SDL游戏之路(十二)--游戏场景
- SDL游戏之路(一)--多平台支持--windows
- SDL游戏之路(二)--多平台支持--wp8
- SDL游戏之路(二十)--对话框-多行
- SDL游戏之路(八)--android+sdl+ndk+3d
- SDL游戏之路(九)--动画制作
- SDL游戏之路(十)--移动轨迹
- SDL游戏之路(十一)--按钮制作
- SDL游戏之路(十三)--中文显示
- SDL游戏之路(十四)--模拟键盘
- SDL游戏之路(十五)--英文输入法
- SDL游戏之路(十六)--中文输入法
- SDL游戏之路(十九)--对话框
- Windows Store app samples
- Windows store app CollectionViewSource
- Mac OS使用技巧之十二:解决APP Store更新、下载出错的问题
- 游戏特效-亮子
- 第八节:Struts2-标签库
- Python命名规则
- android自定义密码键盘
- LeetCode 题解(7):First Missing Positive
- SDL游戏之路(二十二)--声音-Windows Store App
- 图形化的机房综合资源管理系统的线路建立
- jquery中的call和apply方法
- Use unique_ptr to RAII your file objects
- android自定义密码键盘
- android视频播放(VideoView和MediaController)
- 在AD中开启高级功能查看用户属性
- HTTP for iOS在线播放
- .NET中验证域用户名以及密码的方式