• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            創(chuàng)建游戲內核(20)

             

            本篇是創(chuàng)建游戲內核(19)的續(xù)篇,有關DirectAudio和DirectShow的基礎知識請參閱用DirectX Audio和DirectShow播放聲音和音樂。

             

            沒有了音樂,游戲將變得毫無樂趣,可以通過使用類MUSIC_CHANNEL來播放.MID和DirectMusic本地歌曲(.SGT)。


            下載源碼和工程

             

            來看看類MUSIC_CHANNEL的定義:

            //======================================================================================
            // This class encapsulate midi file playing.
            //======================================================================================
            typedef class MUSIC_CHANNEL
            {
                friend 
            class SOUND;

            public:
                MUSIC_CHANNEL();
                ~MUSIC_CHANNEL();

                IDirectMusicSegment8* get_dm_segment();

                BOOL create(SOUND_PTR sound);
                BOOL load(
            const char* filename);
                BOOL free();

                BOOL set_dls(DLS* dls);

                BOOL play(
            long volume_percent = 100, long loop_time = 1);
                BOOL stop();

                
            long get_volume();
                BOOL set_volume(
            long percent = 100);

                BOOL set_tempo(
            long percent);
                BOOL is_playing();

            protected:
                SOUND_PTR               _sound;
                IDirectMusicSegment8*   _dm_segment;
                
            long                    _volume;
            } *MUSIC_CHANNEL_PTR;

             

            以及類MUSIC_CHANNEL的實現(xiàn):

            //------------------------------------------------------------------------------
            // Set volume for the default audio path of DirectMusic perforfamce.
            //------------------------------------------------------------------------------
            BOOL set_audio_path_volume(IDirectMusicPerformance8* dm_perf, long percent)
            {
                IDirectMusicAudioPath8* audio_path;
                
            long volume;

                
            if(dm_perf == NULL)
                    
            return FALSE;

                
            // retrieves the default audiopath
                if(FAILED(dm_perf->GetDefaultAudioPath(&audio_path)))
                    
            return FALSE;

                
            // calculate a usable volume level
                if(percent == 0)
                    volume = -9600;
                
            else
                    volume = (
            long) (-32.0 * (100.0 - (float)(percent % 101)));

                
            // set the audio volume on the audiopath, the volume can be faded in or out.
                if(FAILED(audio_path->SetVolume(volume, 0)))
                {
                    audio_path->Release();
                    
            return FALSE;
                }

                audio_path->Release();    

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Set tempo for DirectMusic performance.
            //------------------------------------------------------------------------------
            BOOL set_performance_tempo(IDirectMusicPerformance8* dm_perf, long percent)
            {
                
            if(dm_perf == NULL)
                    
            return FALSE;

                
            // calculate tempo setting based on percentage
                float tempo = (float) percent / 100.0f;

                
            // set master performance tempo
                if(FAILED(dm_perf->SetGlobalParam(GUID_PerfMasterTempo, (void*) &tempo, sizeof(float))))
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Constructor, initialize member data.
            //------------------------------------------------------------------------------
            MUSIC_CHANNEL::MUSIC_CHANNEL()
            {
                memset(
            this, 0, sizeof(*this));
            }

            //------------------------------------------------------------------------------
            // Destructor, release resource.
            //------------------------------------------------------------------------------
            MUSIC_CHANNEL::~MUSIC_CHANNEL()
            {
                free();
            }

            //------------------------------------------------------------------------------
            // Release DirectMusic segment and loader resource.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::free()
            {
                stop();

                
            // unload instrument data
                if(_sound && _dm_segment)
                {
                    
            // unloads instrument data from a performance
                    if(_sound->get_dm_performance())
                    {
                        
            if(FAILED(_dm_segment->Unload(_sound->get_dm_performance())))
                            
            return FALSE;
                    }

                    
            // releases the loader's reference to an object
                    if(_sound->get_dm_loader())
                    {
                        
            if(FAILED(_sound->get_dm_loader()->ReleaseObjectByUnknown(_dm_segment)))
                            
            return FALSE;
                    }
                }
                
                release_com(_dm_segment);
                
                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Stop playing music segment.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::stop()
            {
                
            // return if not setup correctly
                if(_sound == NULL || _sound->get_dm_performance() == NULL || _dm_segment == NULL)
                    
            return FALSE;

                
            // stop palyback
                if(FAILED(_sound->get_dm_performance()->Stop(_dm_segment, NULL, 0, 0)))
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Return direct music segment.
            //------------------------------------------------------------------------------
            IDirectMusicSegment8* MUSIC_CHANNEL::get_dm_segment()
            {
                
            return _dm_segment;
            }

            //------------------------------------------------------------------------------
            // Attach SOUND object to music channel.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::create(SOUND_PTR sound)
            {
                free();

                
            // make sure all objects there
                if((_sound = sound) == NULL)
                    
            return FALSE;

                
            if(_sound->get_dm_performance() == NULL || _sound->get_dm_loader() == NULL)
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Retrieve DirestMusic segment from DirectMusic loader and download band data to 
            // performance.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::load(const char* filename)
            {
                free();

                
            if(_sound == NULL)
                    
            return FALSE;

                
            if(_sound->get_dm_performance() == NULL || _sound->get_dm_loader() == NULL)
                    
            return FALSE;

                
            // setup DMUS_OBJECTDESC structure which used to describe a loadable object

                DMUS_OBJECTDESC obj_desc;

                ZeroMemory(&obj_desc, 
            sizeof(DMUS_OBJECTDESC));

                obj_desc.dwSize      = 
            sizeof(DMUS_OBJECTDESC);
                obj_desc.guidClass   = CLSID_DirectMusicSegment;
                obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;

                mbstowcs(obj_desc.wszFileName, filename, MAX_PATH);

                
            // retrieves an objet from a file or resource and returns the specified interface
                if(FAILED(_sound->get_dm_loader()->GetObject(&obj_desc, IID_IDirectMusicSegment8, (LPVOID*) &_dm_segment)))
                    
            return FALSE;

                
            // setup MIDI playing
                if(strstr(filename, ".mid"))
                {
                    
            if(FAILED(_dm_segment->SetParam(GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, NULL)))
                        
            return FALSE;
                }

                
            // download band data to a performance
                if(FAILED(_dm_segment->Download(_sound->get_dm_performance())))
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Download band data from DLS.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::set_dls(DLS* dls)
            {
                
            if(dls == NULL || dls->get_dm_colletion() == NULL)
                    
            return FALSE;

                
            if(_sound == NULL || _sound->get_dm_performance() == NULL)
                    
            return FALSE;

                
            if(_dm_segment == NULL)
                    
            return FALSE;

                
            // sets data on a track inside this segment
                if(FAILED(_dm_segment->SetParam(GUID_ConnectToDLSCollection, 0xFFFFFFFF, 0, 0, (void*) dls->get_dm_colletion())))
                    
            return FALSE;

                
            // unload and then re-download new instruments
                
                // unloads instrument data from a performance
                if(FAILED(_dm_segment->Unload(_sound->get_dm_performance())))
                    
            return FALSE;

                
            // downloads band data to a performance
                if(FAILED(_dm_segment->Download(_sound->get_dm_performance())))
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Play music segment.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::play(long volume_percent, long loop_time)
            {
                stop();

                
            // return if no setup coorectly
                if(_sound == NULL || _sound->get_dm_performance() == NULL || _dm_segment == NULL)
                    
            return FALSE;

                
            // set the number of loops
                if(loop_time == 0)
                    _dm_segment->SetRepeats(DMUS_SEG_REPEAT_INFINITE);
                
            else
                    _dm_segment->SetRepeats(loop_time - 1);

                
            // set the playback volume
                set_volume(volume_percent);

                
            // play on default audio path
                if(FAILED(_sound->get_dm_performance()->PlaySegmentEx(_dm_segment, NULL, NULL, 0, 0, NULL, NULL, NULL)))
                    
            return FALSE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Get volume of music channel.
            //------------------------------------------------------------------------------
            long MUSIC_CHANNEL::get_volume()
            {
                
            return _volume;
            }

            //------------------------------------------------------------------------------
            // Set volume for music chanel.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::set_volume(long percent)
            {
                
            if(_sound == NULL)
                    
            return FALSE;

                
            if(! set_audio_path_volume(_sound->get_dm_performance(), percent))
                    
            return FALSE;

                _volume = percent % 101;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Set tempo for DirectMusic performance.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::set_tempo(long percent)
            {
                
            if(_sound == NULL)
                    
            return FALSE;

                
            return set_performance_tempo(_sound->get_dm_performance(), percent);
            }

            //------------------------------------------------------------------------------
            // Ascertains whether segment is playing.
            //------------------------------------------------------------------------------
            BOOL MUSIC_CHANNEL::is_playing()
            {
                
            // return if not setup correctly
                if(_sound == NULL || _sound->get_dm_performance() == NULL || _dm_segment == NULL)
                    
            return FALSE;

                
            // ascertains whether a specified segment or segment state is currently being heard from the speakers
                if(_sound->get_dm_performance()->IsPlaying(_dm_segment, NULL) == S_OK)
                    
            return TRUE;

                
            return FALSE;
            }

            MUSIC_CHANNEL類同其他類的區(qū)別是: MUSIC_CHANNEL類只需要被初始化一次,初始化它使用的函數(shù)是MUSIC_CHANNEL::create。

            MUSIC_CHANNEL::free函數(shù)將歌曲從內存中釋放掉,以便給要加載的其他歌曲留出空間。加載歌曲時,要給MUSIC_CHANNEL::load函數(shù)提供一個音樂文件名,而且音樂還必須是.MID或DirectMusic本地歌曲(*.SGT)文件。Midi文件必須以.MID結尾,否則MUSIC_CHANNEL函數(shù)就不會采用適當?shù)幕胤鸥袷脚渲肈irectMusic。

            一旦加載了歌曲,就可以使用MUSIC_CHANNEL::play函數(shù)播放。


            測試代碼:

            /*****************************************************************************
            PURPOSE:
                Test for class MUSIC_CHANNEL.
            *****************************************************************************/


            #include "Core_Global.h"

            class APP : public APPLICATION
            {
            public:
                BOOL init()
                {
                    
            // Initialize DierctSound and DirectMusic.
                    _sound.init(get_hwnd());

                    
            // create music channel
                    _music_channel.create(&_sound);

                    
            // Retrieve DirestMusic segment from DirectMusic loader and download band data to performance.
                    if(! _music_channel.load("song.mid"))
                        
            return FALSE;

                    _music_channel.set_tempo(200);

                    _music_channel.play(100, 0);
                    
                    
            return TRUE;
                }

                BOOL frame()
                {
                    
            return TRUE;
                }

                BOOL shutdown()
                {
                    
            return TRUE;
                }

            private:
                SOUND _sound;
                MUSIC_CHANNEL _music_channel;

            };

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
            {
                APP app;

                
            return app.run();
            }

            posted on 2007-10-09 16:44 lovedday 閱讀(379) 評論(0)  編輯 收藏 引用

            公告

            導航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            囯产极品美女高潮无套久久久| 一本久久久久久久| 丁香色欲久久久久久综合网| 色综合久久中文字幕无码| 99国产欧美久久久精品蜜芽 | 久久久久久午夜精品| 国产香蕉久久精品综合网| 久久99国内精品自在现线| 国产精品免费久久久久电影网| 亚洲va久久久久| 久久国产乱子精品免费女| 国产成人综合久久精品红| 久久777国产线看观看精品| 久久亚洲AV成人无码软件| 日本久久久久久中文字幕| 少妇精品久久久一区二区三区| 国产精品免费久久久久影院 | 成人午夜精品无码区久久| 久久久久久国产精品无码下载 | 99精品久久精品| 久久SE精品一区二区| 久久夜色撩人精品国产| 色综合久久最新中文字幕| 亚洲精品tv久久久久久久久| 亚洲精品NV久久久久久久久久| 久久91精品国产91久久户| 久久久久国产精品嫩草影院| 久久精品视频91| 久久无码精品一区二区三区| 精品一区二区久久久久久久网站| 久久久久人妻一区精品色| 久久婷婷五月综合色奶水99啪| 亚洲国产精品综合久久一线| 国内精品久久久久久不卡影院| 久久狠狠色狠狠色综合| 久久青草国产手机看片福利盒子| 丁香五月网久久综合| 亚洲国产精品久久久久婷婷老年| 国产精品99久久99久久久| 99久久中文字幕| 91久久精品视频|