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

            天行健 君子當(dāng)自強(qiáng)而不息

            創(chuàng)建游戲內(nèi)核(18)

             

            本篇是創(chuàng)建游戲內(nèi)核(17)的續(xù)篇,有關(guān)DirectAudio和DirectShow的基礎(chǔ)知識(shí)請(qǐng)參閱用DirectX Audio和DirectShow播放聲音和音樂(lè)

             

            使用SOUND控制DirectX Audio對(duì)象

            SOUND對(duì)象控制DirectSound和DirectMusic對(duì)象,控制回放聲音時(shí)的音量(全局音量控制),也觸發(fā)音頻流相關(guān)消息。

            來(lái)看看它的定義:

            #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();
            };
             


            接著是它的實(shí)現(xiàn):

            //------------------------------------------------------------------------------
            // 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類中,使用的函數(shù)主要有init,shutdown,set_volume。要使用init,必須給它傳遞一個(gè)父窗口的句柄,以及可選的混音器(mixer)設(shè)置(系統(tǒng)默認(rèn)為22050赫茲,單聲道,使用DSSCL_PRIORITY協(xié)作級(jí)別的16位采樣)。

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


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


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            欧美久久天天综合香蕉伊| 国产精品激情综合久久| 久久综合给合久久狠狠狠97色69| 久久国产免费直播| 国产成人久久激情91| 久久精品一区二区影院 | 久久精品中文字幕有码| 中文字幕无码久久久| 久久精品人人做人人妻人人玩| 99久久亚洲综合精品网站| 国产亚洲美女精品久久久2020| 久久99精品国产99久久6男男| 久久99九九国产免费看小说| 久久国产精品久久精品国产| 久久久WWW成人| 久久精品国产精品亚洲| 国产精品午夜久久| 久久人妻无码中文字幕| 久久国产成人精品麻豆| 亚洲欧美另类日本久久国产真实乱对白 | 久久久久久久久久久| 久久777国产线看观看精品| 精品人妻伦一二三区久久| 国产精品乱码久久久久久软件| 久久影院综合精品| 久久久久女教师免费一区| 日韩精品久久久肉伦网站| 久久久久这里只有精品| 久久久久久亚洲精品成人| 久久精品无码一区二区日韩AV | 久久亚洲欧美国产精品| 久久九九有精品国产23百花影院| 香蕉久久影院| 国产精品成人精品久久久| 久久精品一本到99热免费| 四虎亚洲国产成人久久精品| 国产精品久久久久aaaa| 久久强奷乱码老熟女网站| 亚洲国产精品久久久久婷婷软件 | 精品综合久久久久久888蜜芽| 深夜久久AAAAA级毛片免费看|