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

            天行健 君子當自強而不息

            創建游戲內核(18)

             

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

             

            使用SOUND控制DirectX Audio對象

            SOUND對象控制DirectSound和DirectMusic對象,控制回放聲音時的音量(全局音量控制),也觸發音頻流相關消息。

            來看看它的定義:

            #define EVENT_NUM 32

            //======================================================================================
            // This class encapsulate for DirectPerformance and DirectLoader and sound play event handle.
            //======================================================================================
            class SOUND
            {
            protected:
                
            /////////////////////////////// Sound system related ///////////////////////////////

                HWND    _hwnd;      
            // pointer to parent window handle
                long    _volume;    // global sound buffer volume

                // Events for all sound channel, the last event takes charge to close all other events.
                HANDLE  _events[EVENT_NUM+1]; 

                
            // all sound channel pointers
                SOUND_CHANNEL*  _sound_channel[EVENT_NUM];

                HANDLE  _thread_handle;        
                DWORD   _thread_id;
                BOOL    _thread_active;

                
            static DWORD    handle_notifications(LPVOID data);

                
            /////////////////////////////// Sound related ///////////////////////////////

                IDirectSound8*          _ds;
                IDirectSoundBuffer*     _ds_buffer;

                
            long    _coop_level;
                
            long    _frequency;
                
            short   _channels;
                
            short   _bits_per_sample;

                
            /////////////////////////////// Music related - MIDI ///////////////////////////////

                IDirectMusicPerformance8*   _dm_perf;
                IDirectMusicLoader8*        _dm_loader;

            public:
                SOUND();
                ~SOUND();
                
                
            // assign and release events
                BOOL assign_event(SOUND_CHANNEL* sound_channel, short* event_index, HANDLE* event_handle);
                BOOL release_event(SOUND_CHANNEL* sound_channel, 
            short* event_index);

                
            // function to retrieve com interfaces
                IDirectSound8*              get_directsound_com();
                IDirectSoundBuffer*         get_primary_buffer_com();
                IDirectMusicPerformance8*   get_performance_com();
                IDirectMusicLoader8*        get_loader_com();

                
            // init and shutdown functions
                BOOL init(HWND hwnd, long frequency = 22050, short channels = 1, short bits_per_sample = 16,
                          
            long coop_level = DSSCL_PRIORITY);
                
            void shutdown();

                
            // volume get/get
                long get_volume();
                BOOL set_volume(
            long percent);

                
            // restore system to known state
                void restore();
            };
             


            接著是它的實現:

            //------------------------------------------------------------------------------
            // Constructor, initialize member data.
            //------------------------------------------------------------------------------
            SOUND::SOUND()
            {
                
            // initialize com
                CoInitialize(NULL);

                memset(
            this, 0, sizeof(*this));
            }

            //------------------------------------------------------------------------------
            // Destructor, release main sound buffer, close all event and thread.
            //------------------------------------------------------------------------------
            SOUND::~SOUND()
            {
                shutdown();

                
            // uninitialize com
                CoUninitialize();
            }

            //------------------------------------------------------------------------------
            // Initialize DierctSound and DirectMusic.
            //------------------------------------------------------------------------------
            BOOL SOUND::init(HWND hwnd, long frequency, short channels, short bits_per_sample, long coop_level)
            {
                
            // shutdown system in case of prior install
                shutdown();

                
            // save parent window handle
                if((_hwnd = hwnd) == NULL)
                    
            return FALSE;

                
            ///////////////////////////////////////////////////////////////////
                // Initialize DirectSound
                ///////////////////////////////////////////////////////////////////

                
            // save settings for sound setup
                if(coop_level == DSSCL_NORMAL)
                    coop_level = DSSCL_PRIORITY;

                _coop_level      = coop_level;
                _frequency       = frequency;
                _channels        = channels;
                _bits_per_sample = bits_per_sample;

                
            // create an IDirectSound8 object
                if(FAILED(DirectSoundCreate8(NULL, &_ds, NULL)))
                    
            return FALSE;

                
            // set cooperative mode
                if(FAILED(_ds->SetCooperativeLevel(_hwnd, _coop_level)))
                    
            return FALSE;

                
            // create sound buffer

                DSBUFFERDESC ds_buffer_desc;

                
            // get primary buffer control
                ZeroMemory(&ds_buffer_desc, sizeof(DSBUFFERDESC));

                ds_buffer_desc.dwSize        = 
            sizeof(DSBUFFERDESC);
                ds_buffer_desc.dwFlags       = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
                ds_buffer_desc.dwBufferBytes = 0;
                ds_buffer_desc.lpwfxFormat   = NULL;

                
            if(FAILED(_ds->CreateSoundBuffer(&ds_buffer_desc, &_ds_buffer, NULL)))
                    
            return FALSE;

                
            // set wave format for sound buffer

                WAVEFORMATEX wave_format;

                
            // set the primary buffer format

                ZeroMemory(&wave_format, 
            sizeof(WAVEFORMATEX));

                wave_format.wFormatTag      = WAVE_FORMAT_PCM;
                wave_format.nChannels       = (WORD) _channels;
                wave_format.nSamplesPerSec  = _frequency;
                wave_format.wBitsPerSample  = (WORD) _bits_per_sample;
                wave_format.nBlockAlign     = wave_format.wBitsPerSample / 8 * wave_format.nChannels;
                wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign;

                
            if(FAILED(_ds_buffer->SetFormat(&wave_format)))
                    
            return FALSE;

                
            // create the events, plus an extra one for thread termination.
                for(short i = 0; i < EVENT_NUM+1; i++)
                {
                    
            if((_events[i] = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
                        
            return FALSE;
                }

                
            // create a thread for handling notifications
                _thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) handle_notifications, this, 0, &_thread_id);

                
            if(_thread_handle == NULL)
                    
            return FALSE;

                
            ///////////////////////////////////////////////////////////////////
                // Initialize DirectMusic
                ///////////////////////////////////////////////////////////////////

                
            // create the DirectMusic loader object
                CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void**) &_dm_loader);

                
            // create the DirectMusic performance object
                CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8,
                                 (
            void**) &_dm_perf);

                
            // Initialize the performance with the standard audio path.
                // This initializes both DirectMusic and DirectSound and sets up the synthesizer. 
                _dm_perf->InitAudio(NULL, NULL, _hwnd, DMUS_APATH_SHARED_STEREOPLUSREVERB, 128, DMUS_AUDIOF_ALL, NULL);

                
            // set the performance global volume to +10 decibels
                long volume_level = 1000;

                
            if(FAILED(_dm_perf->SetGlobalParam(GUID_PerfMasterVolume, &volume_level, sizeof(long))))
                    
            return FALSE;

                CHAR    path[MAX_PATH];
                WCHAR   w_path[MAX_PATH];

                
            // tell DirectMusic where the default search path is

                GetCurrentDirectory(MAX_PATH, path);
                MultiByteToWideChar(CP_ACP, 0, path, -1, w_path, MAX_PATH);

                _dm_loader->SetSearchDirectory(GUID_DirectMusicAllTypes, w_path, FALSE);

                
            // set default volume to full
                set_volume(100);

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Release main sound buffer, close all events and threads.
            //------------------------------------------------------------------------------
            void SOUND::shutdown()
            {
                
            // stop the music, and close down.
                if(_dm_perf != NULL)
                {
                    _dm_perf->Stop(NULL, NULL, 0, 0);
                    _dm_perf->CloseDown();
                }

                
            // release the DirectMusic objects
                release_com(_dm_perf);
                release_com(_dm_loader);

                
            // go through all used sound channels and free them
                for(short i = 0; i < EVENT_NUM; i++)
                {
                    
            if(_sound_channel[i] != NULL)
                    {
                        _sound_channel[i]->free();
                        _sound_channel[i] = NULL;
                    }

                    
            // clear the event status
                    if(_events[i] != NULL)
                        ResetEvent(_events[i]);
                }

                
            // stop the primary channel from playing
                if(_ds_buffer != NULL)
                    _ds_buffer->Stop();

                
            // release the DirectSound objects
                release_com(_ds_buffer);
                release_com(_ds);

                
            // force a closure of the thread by triggering the last event and waiting for it to terminate
                if(_thread_handle != NULL)
                {
                    
            if(_events[EVENT_NUM] != NULL)
                    {
                        
            while(_thread_active)
                            
            // set the specified event object to the signaled state
                            SetEvent(_events[EVENT_NUM]);
                    }
                    
            else
                    {
                        
            // getting here means no event assigned
                        TerminateThread(_thread_handle, 0);
                    }
                }

                
            // close all event handles
                for(short i = 0; i < EVENT_NUM+1; i++)
                {
                    
            if(_events[i] != NULL)
                    {
                        CloseHandle(_events[i]);
                        _events[i] = NULL;
                    }
                }

                
            // free the thread handle
                if(_thread_handle != NULL)
                {
                    CloseHandle(_thread_handle);
                    _thread_handle = NULL;
                }

                _thread_id = 0;
            }

            //------------------------------------------------------------------------------
            // Return pointer to DirectSound.
            //------------------------------------------------------------------------------
            IDirectSound8* SOUND::get_directsound_com()
            {
                
            return _ds;
            }

            //------------------------------------------------------------------------------
            // Return pointer to primary DirectSound buffer.
            //------------------------------------------------------------------------------
            IDirectSoundBuffer* SOUND::get_primary_buffer_com()
            {
                
            return _ds_buffer;
            }

            //------------------------------------------------------------------------------
            // Return pointer to DirectMusic performance object.
            //------------------------------------------------------------------------------
            IDirectMusicPerformance8* SOUND::get_performance_com()
            {
                
            return _dm_perf;
            }

            //------------------------------------------------------------------------------
            // Return pointer to DirectMusic loader object.
            //------------------------------------------------------------------------------
            IDirectMusicLoader8* SOUND::get_loader_com()
            {
                
            return _dm_loader;
            }

            //------------------------------------------------------------------------------
            // Assign sound channel with specified event.
            //------------------------------------------------------------------------------
            BOOL SOUND::assign_event(SOUND_CHANNEL* sound_channel, short* event_index, HANDLE* event_handle)
            {
                
            for(short i = 0; i < EVENT_NUM; i++)
                {
                    
            if(_events[i] != NULL && _sound_channel[i] == NULL)
                    {
                        
            // set the specified event object to the nonsignaled state
                        ResetEvent(_events[i]);

                        _sound_channel[i] = sound_channel;
                        
                        *event_index  = i;
                        *event_handle = _events[i];

                        
            return TRUE;
                    }
                }

                
            return FALSE;
            }

            //------------------------------------------------------------------------------
            // Set the event state to nonsignaled.
            //------------------------------------------------------------------------------
            BOOL SOUND::release_event(SOUND_CHANNEL* sound_channel, short* event_index)
            {
                
            if((unsigned short)(*event_index) < EVENT_NUM && _sound_channel[*event_index] == sound_channel)
                {
                    ResetEvent(_events[*event_index]);

                    
            // set event channel pointer with NULL
                    _sound_channel[*event_index] = NULL;
                    *event_index = -1;

                    
            return TRUE;
                }

                
            return FALSE;
            }

            //------------------------------------------------------------------------------
            // Get global sound volume.
            //------------------------------------------------------------------------------
            long SOUND::get_volume()
            {
                
            return _volume;
            }

            //------------------------------------------------------------------------------
            // Set the global sound volume.
            //------------------------------------------------------------------------------
            BOOL SOUND::set_volume(long percent)
            {
                
            long volume;

                
            if(_ds_buffer == NULL)
                    
            return FALSE;

                
            // calculate a usable volume level
                if(percent == 0)
                    volume = DSBVOLUME_MIN;
                
            else
                    volume = -20 * (100 - (percent % 101));

                
            if(FAILED(_ds_buffer->SetVolume(volume)))
                    
            return FALSE;

                _volume = percent % 101;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Handle all sound events.
            //------------------------------------------------------------------------------
            DWORD SOUND::handle_notifications(LPVOID data)
            {
                MSG msg;

                SOUND* sound = (SOUND*) data;

                sound->_thread_active = TRUE;

                BOOL complete = FALSE;

                
            while(! complete)
                {
                    
            // wait for a message
                    DWORD result = MsgWaitForMultipleObjects(EVENT_NUM+1, sound->_events, FALSE, INFINITE, QS_ALLEVENTS);

                    
            // get channel index to update
                    DWORD channel_index = result - WAIT_OBJECT_0;

                    
            // check for channel update
                    if(channel_index >= 0 && channel_index < EVENT_NUM)
                    {
                        
            if(sound->_sound_channel[channel_index] != NULL)
                            sound->_sound_channel[channel_index]->_update();
                    }
                    
            else if(channel_index == EVENT_NUM) // check for thread closure
                        complete = TRUE;
                    
            else if(channel_index > EVENT_NUM)  // check for waiting messages
                    {
                        
            while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                        {
                            
            if(msg.message == WM_QUIT)
                            {
                                complete = TRUE;
                                
            break;
                            }
                        }
                    }
                }

                sound->_thread_active = FALSE;

                
            return 0L;
            }

            //------------------------------------------------------------------------------
            // Restore primary DirectSound buffer and DirectSound channel buffer.
            //------------------------------------------------------------------------------
            void SOUND::restore()
            {
                
            // handle primary
                if(_ds_buffer != NULL)
                    _ds_buffer->Restore();

                
            // handle all used sound channels
                for(short i = 0; i < EVENT_NUM; i++)
                {
                    
            if(_sound_channel[i] != NULL)
                        _sound_channel[i]->_ds_buffer->Restore();
                }
            }

            在SOUND類中,使用的函數主要有init,shutdown,set_volume。要使用init,必須給它傳遞一個父窗口的句柄,以及可選的混音器(mixer)設置(系統默認為22050赫茲,單聲道,使用DSSCL_PRIORITY協作級別的16位采樣)。

            SOUND::set_volume將percent參數設置為0(靜音)-- 100(最大音量)之間的值,就可以改變音量的設置。


            posted on 2007-09-29 21:27 lovedday 閱讀(381) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            国产成人精品久久一区二区三区av| 99久久国产综合精品成人影院| 久久亚洲美女精品国产精品| 久久精品国产亚洲Aⅴ香蕉| 91久久精品91久久性色| 无遮挡粉嫩小泬久久久久久久| 国产一区二区久久久| 久久天天躁狠狠躁夜夜2020| 国产精品成人久久久久三级午夜电影 | 欧美激情精品久久久久久久| 久久精品草草草| 久久―日本道色综合久久| 国产一区二区精品久久| 99999久久久久久亚洲| a高清免费毛片久久| 91精品国产91久久久久久| 色综合久久最新中文字幕| 大美女久久久久久j久久| 久久久久久A亚洲欧洲AV冫| 中文字幕久久精品| 亚洲午夜久久久久久久久电影网| 亚洲精品乱码久久久久久久久久久久| 亚洲中文字幕无码久久综合网| 日韩精品久久无码人妻中文字幕| 色诱久久久久综合网ywww| 日本免费久久久久久久网站| 久久97久久97精品免视看| 久久婷婷人人澡人人| 亚洲午夜久久久影院| 欧美一区二区精品久久| 久久人人爽人人爽人人片AV东京热| 久久久久亚洲AV片无码下载蜜桃| 久久久久久九九99精品| 久久精品国产一区二区三区不卡| 国产精品久久新婚兰兰| 久久精品毛片免费观看| 久久精品国产一区二区三区不卡| 久久永久免费人妻精品下载| 国产精品免费久久久久久久久| 精品多毛少妇人妻AV免费久久| 久久久久久a亚洲欧洲aⅴ|