OpenGL系统设计-融合DirectXAudio

<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} p.MsoBodyText, li.MsoBodyText, div.MsoBodyText {margin-top:0cm; margin-right:0cm; margin-bottom:6.0pt; margin-left:0cm; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} p.MsoBodyTextFirstIndent, li.MsoBodyTextFirstIndent, div.MsoBodyTextFirstIndent {mso-style-update:auto; mso-style-parent:正文文本; mso-style-link:" Char Char"; margin:0cm; margin-bottom:.0001pt; text-indent:19.85pt; mso-pagination:none; font-size:10.5pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-ansi-language:ZH-CN;} span.CharChar {mso-style-name:" Char Char"; mso-style-locked:yes; mso-style-link:正文首行缩进; mso-ansi-font-size:10.5pt; mso-bidi-font-size:10.5pt; font-family:宋体; mso-fareast-font-family:宋体; mso-ansi-language:ZH-CN; mso-fareast-language:ZH-CN; mso-bidi-language:AR-SA;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

DirectX的音频处理在 8.0以前的版本中被单独分为两个部分: DirectSound DirectMusic。在 DirectX 8中,它们被整合一体并称为 DirectX Audio。但是在实际处理中还必须针对 DirectSound DirectMusic分别操作。

DirectAudio中,最基本的也是必需的元素是音频片断,它通常是一段声音,来自于资源或者音频文件。

要使用 DirectAudio,我们首先来定义一个基本的声音的类 SOUND,它包括了一段表示声音数据的音频片断 dmSegment,用于保存声音以便进行播放控制的声音缓冲区 ds3DBuffer,以及一个表示是否 3D声音的标志。

 

// 包含单一声音信息的类

class SOUND

{

    public:

        IDirectMusicSegment8* dmSegment;        // 声音数据

        IDirectSound3DBuffer* ds3DBuffer;       //3D 声音缓冲区

        bool is3DSound;                         // 是否3D 声音

        void Set3DPos(float x, float y, float z){}  // 设置3D 声音的位置

        // 设置3D 声音的最大、最小距离

        void Set3DDistances(float minDistance, float maxDistance){}

        void Shutdown(void);                    // 关闭声音

        SOUND() : dmSegment(NULL),  ds3DBuffer(NULL), is3DSound(false)

        {   }

        ~SOUND() {  }

    };

 

SOUND 类中的 Set3DPos Set3DDistances 为空 表示在本例中我们的目的仅仅是使用 DirectSound 对于声音的各种特效暂时不考虑。如果需要,只需进行针对性扩充即可,当然,你需要对 DirectSound有所了解。

接下来我们来使用 DirectMusic处理 SOUND对象,这里也需要定义几个接口变量。 dmLoader是一个 IDirectMusicLoader8的接口指针,用于查找、列举、加载和缓存声音对象。声音对象可以是资源,也可以是文件。 dmPerformance是一个 IDirectMusicPerformance8的接口指针,用于综合管理音乐的回放。包括增加、删除端口,映射演奏通道( performance channels),播放声音片断,调度消息流程,管理事件通知等等。 dm3DAudioPath是一个 IDirectMusicAudioPath的接口指针,它用于实现声音数据流从数据源到主声音缓冲区的过程。 ds3DListener则是一个 IDirectSound3DListener接口指针,用于描述听者( listener)在 3D空间中的位置、方向及其他环境参数。 dsListenerParams是一个 DS3DLISTENER结构,用于描述 3D空间参数和听者的位置。

 

IDirectMusicLoader8* dmLoader;             

IDirectMusicPerformance8* dmPerformance;

IDirectMusicAudioPath* dm3DAudioPath;

IDirectSound3DListener* ds3DListener;

DS3DLISTENER dsListenerParams; 

 

DMInit 是我们定义的 DirectMusic 的初始化函数 DMInit 中首 先使用 COM 方法创建一个 IDirectMusicLoader8 对象和一个 IDirectMusicPerformance8 对象 这是使用 DirectMusic 中是必须的步骤。然后使用 InitAudio初始化音频,并创建标准的音频路径。最后设置听者的参数和声音目标文件的查找路径。

 

bool DMInit(void)

{

    HRESULT hr;

    WCHAR wcharStr[MAX_PATH];

    char pathStr[MAX_PATH];

   

   

    dm3DAudioPath=NULL;

    dmLoader=NULL;

    dmPerformance=NULL;

    ds3DListener=NULL;

 

    CoInitialize(NULL);

   

    // 创建IDirectMusicLoader8

    hr= CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,

        IID_IDirectMusicLoader8, (void**)&dmLoader);

    if(FAILED(hr))

    {

        return false;

    }

   

    // 创建IDirectMusicPerformance8

    hr= CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,

        IID_IDirectMusicPerformance8, (void**)&dmPerformance);

    if(FAILED(hr))

    {

        DMShutdown();

        return false;

    }

   

    // 初始化音频

    dmPerformance->InitAudio(NULL, NULL, g_hWnd, DMUS_APATH_SHARED_STEREOPLUSREVERB, 64,

                              DMUS_AUDIOF_ALL, NULL);

   

    // 创建音频路径

    hr= dmPerformance->CreateStandardAudioPath(DMUS_APATH_DYNAMIC_3D,

        64, TRUE, &dm3DAudioPath);

    if(FAILED(hr))

    {

        DMShutdown();

        return false;

    }

   

    // 获取听者信息

    hr= dm3DAudioPath->GetObjectInPath(0, DMUS_PATH_PRIMARY_BUFFER, 0,

GUID_NULL, 0,

IID_IDirectSound3DListener8,

(void**)&ds3DListener);

    if(FAILED(hr))

    {

        return false;

    }

   

   

    dsListenerParams.dwSize= sizeof(DS3DLISTENER);

    ds3DListener->GetAllParameters(&dsListenerParams);

   

    // 设置听者缺省位置

    dsListenerParams.vPosition.x= 0.0f;

    dsListenerParams.vPosition.y= 0.0f;

    dsListenerParams.vPosition.z= 0.0f;

    ds3DListener->SetAllParameters(&dsListenerParams, DS3D_IMMEDIATE);

   

    // 取得当前工作路径

    GetCurrentDirectory(MAX_PATH, pathStr);

   

    // 将文件名字符串转换成unicode 字符串,COM 需要,没办法

    MultiByteToWideChar(CP_ACP, 0, pathStr, -1, wcharStr, MAX_PATH);

   

    // 设置查找路径

    dmLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wcharStr, FALSE);

    return true;

}

 

DMShutdown负责关闭 DirectMusic,代码如下。

 

void DMShutdown(void)

{

    if(dmPerformance!=NULL)

    {

        dmPerformance->Stop(NULL, NULL, 0, 0);

        dmPerformance->CloseDown();

        dmPerformance->Release();

    }

 

    if(dm3DAudioPath!=NULL)

        dm3DAudioPath->Release();

   

    if(dmLoader!=NULL)

        dmLoader->Release();

   

    // COInitialize 对应

    CoUninitialize();

}

 

DirectMusic初始化后还需要和 DirectSound结合,即使用 DirectMusic来管理声音。 DMCreate就是用于创建一个来自于文件的声音。

 

bool DMCreate(SOUND* audio, char* filename, bool is3DSound)

{

    DS3DBUFFER dsBufferParams;

    HRESULT hr;

    WCHAR wcharStr[MAX_PATH];

   

    //DirectAudio 需要unicode 字符串

    MultiByteToWideChar(CP_ACP, 0, filename, -1, wcharStr, MAX_PATH);

   

    // 加载音频片断

    hr= dmLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,

                            IID_IDirectMusicSegment8,

                            wcharStr,

                            (void**)&audio->dmSegment);

    if(FAILED(hr))

    {

        return false;

    }

   

    // 如果是3D 声音

    if(is3DSound)

    {

        // 取得路径3D Buffer 和音频

        hr= dm3DAudioPath->GetObjectInPath(DMUS_PCHANNEL_ALL,

                            DMUS_PATH_BUFFER, 0,

                            GUID_NULL, 0, IID_IDirectSound3DBuffer,

                            (void**)&audio->ds3DBuffer);

        if(FAILED(hr))

        {

            return false;

        }

 

        // 取得3D 缓冲区参数

        dsBufferParams.dwSize= sizeof(DS3DBUFFER);

        audio->ds3DBuffer->GetAllParameters(&dsBufferParams);

       

        // 设置新的参数

        dsBufferParams.dwMode= DS3DMODE_HEADRELATIVE;

        audio->ds3DBuffer->SetAllParameters(&dsBufferParams, DS3D_IMMEDIATE);

       

// 重新设置3D 声音标志

        audio->is3DSound = true;

    }

 

    // 如果不是3D 声音

// 3D 声音通常作为背景音乐,本例使用的就是非3D 音乐

    else               

    {

        audio->ds3DBuffer= NULL;

        audio->is3DSound= false;

    }

    return true;

}

 

接下来就是最关键的声音回放了。声音的回放主要是两个过程,首先使用 IDirectMusicSegment8::Download下载音乐,然后使用 IDirectMusicPerformance8::PlaySegmentEx播放音乐片断。下面是负责音乐回放的 DMPlay函数。

 

 

// 播放声音,重复次数为numRepeats,DMUS_SEG_REPEAT_INFINITE 表示重复播放

// 直到显式的被停止为止; 0 表示只播放一次,不再重复。

void DMPlay(SOUND* audio, DWORD numRepeats)

{

    // 设置重复播放次数

    audio->dmSegment->SetRepeats(numRepeats);

   

    if(audio->is3DSound)

    {

        audio->dmSegment->Download(dm3DAudioPath);

        // 播放3D 音乐

        dmPerformance->PlaySegmentEx(audio->dmSegment, NULL, NULL,

                    DMUS_SEGF_SECONDARY, 0,

                    NULL, NULL, dm3DAudioPath);

    }

    else

    {

        audio->dmSegment->Download(dmPerformance);

        // 播放非3D 音乐

        dmPerformance->PlaySegmentEx(audio->dmSegment, NULL, NULL,

                    DMUS_SEGF_DEFAULT, 0,

                    NULL, NULL, NULL);

    }

}

 

如果播放音乐时的循环次数是无限,要让音乐停止的办法就是显式的调用 IDirectMusicPerformance8::StopEx函数。当然,应用程序中止时,音乐也会自动停止播放。 下面是停止音乐播放的函数DMStop。

 

// 停止播放某一声音

void DMStop(SOUND* audio)

{  

    dmPerformance->StopEx(audio->dmSegment, 0, 0); 

}

 

    接下来,将对DirectAudio 初始化和关闭的过程集成到DirectX 的初始化函数和关闭函数中。

 

SOUND       sound;

int DXInit()

{

……

    // 上面是DirectInput 的初始化,包括键盘和鼠标设备

 

    // 下面是DirectMusic 的初始化

    DMInit();

    // battle.mid 文件创建一个音频,非3D

    DMCreate(&sound, "battle.mid", FALSE);

    return  TRUE;

}

 

void DXShutdown()

{

……

    // 上面是DirectInput 的关闭部分,下面是增加的DirectAudio 的关闭部分

    sound.Shutdown();

    DMShutdown();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值