• <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>

            天行健 君子當自強而不息

            創建游戲內核(20)

             

            本篇是創建游戲內核(19)的續篇,有關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的實現:

            //------------------------------------------------------------------------------
            // 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類同其他類的區別是: MUSIC_CHANNEL類只需要被初始化一次,初始化它使用的函數是MUSIC_CHANNEL::create。

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

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


            測試代碼:

            /*****************************************************************************
            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)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            亚洲一区精品伊人久久伊人| 国产精品九九久久免费视频 | 四虎影视久久久免费观看| 国产精品久久久久久久久久免费| 国产精品亚洲综合专区片高清久久久| 久久精品国产清自在天天线| 久久AV无码精品人妻糸列| 无码精品久久久天天影视| 久久久青草青青亚洲国产免观| 久久人人爽人人爽AV片| 久久精品国产免费观看| 久久中文字幕一区二区| 精品久久久久久无码不卡| 成人综合伊人五月婷久久| 久久夜色撩人精品国产| 久久夜色精品国产噜噜亚洲AV| 国产精品va久久久久久久| 狠狠色婷婷久久综合频道日韩| 久久综合九色综合久99| 国内精品久久久久久久久电影网| 久久精品中文字幕久久| 亚洲国产精品无码久久久不卡| 久久精品国产只有精品2020| 亚洲AV日韩精品久久久久久久| 久久se这里只有精品| 国内精品久久久久影院网站| 久久精品aⅴ无码中文字字幕不卡| 久久美女网站免费| 久久综合九色综合网站| 久久综合给合综合久久| 久久www免费人成看国产片 | 国产精品综合久久第一页| 99久久久国产精品免费无卡顿| 久久精品国产亚洲AV香蕉| 亚洲午夜福利精品久久| 久久国产精品无码网站| 久久精品视频网| 99久久精品国产毛片| 欧美久久精品一级c片片| 99久久无码一区人妻a黑| 韩国无遮挡三级久久|