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

            天行健 君子當自強而不息

            創建游戲內核(19)【OO改良版】

             

            本篇是創建游戲內核(18)【OO改良版】的續篇,關于該內核的細節說明請參閱創建游戲內核(19)


            接口:

            //======================================================================================
            // This class encapsulate sound buffer playing.
            //======================================================================================
            typedef class SOUND_CHANNEL
            {
                friend 
            class SOUND;

            public:
                SOUND_CHANNEL();
                ~SOUND_CHANNEL();

                IDirectSoundBuffer8*    get_ds_buffer();
                IDirectSoundNotify8*    get_ds_notify();

                BOOL create(SOUND_PTR sound, 
            long frequency, short channels, short bits_per_sample);
                
            void free();

                BOOL play(
            const SOUND_DATA_PTR sound_data, long volume_percent, long loop_times);
                
            void stop();

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

                signed 
            long get_pan();
                BOOL set_pan(signed 
            long level);

                
            long get_frequency();
                BOOL set_frequency(
            long frequency);

                BOOL is_playing();

            protected:
                BOOL _buffer_data();
                
            void _update();

            protected:
                SOUND_PTR               m_sound;         
            // pointer to parent sound object
                IDirectSoundBuffer8*    m_ds_buffer;     // pointer to DirectSound buffer object
                IDirectSoundNotify8*    m_ds_notify;     // pointer to DirectSound notify object

                
            short                   m_event_index;   

                
            long                    m_volume;        // sound buffer volume
                signed long             m_pan;           // sound buffer pan
                BOOL                    m_is_playing;    // sound buffer playing flag
                long                    m_loop_times;    // loop times

                
            long                    m_frequency;
                
            short                   m_bits_per_sample;
                
            short                   m_channels;

                SOUND_DATA              m_sound_data;

                
            short                   m_load_section;  // sound section will to be loaded
                short                   m_stop_section;  // sound section will to be stoped
                short                   m_next_notify;   // sound notification index will to be played
            } *SOUND_CHANNEL_PTR;

            實現:
            //------------------------------------------------------------------------------
            // Constructor, initialize member data.
            //------------------------------------------------------------------------------
            SOUND_CHANNEL::SOUND_CHANNEL()
            {
                m_sound     = NULL;
                m_ds_buffer = NULL;
                m_ds_notify = NULL;

                m_event_index = -1;

                m_volume     = 0;
                m_pan        = 0;
                m_frequency  = 0;
                m_is_playing = FALSE;
            }

            //------------------------------------------------------------------------------
            // Destructor, release sound buffer and sound notification, set the event state 
            // to nonsignaled.
            //------------------------------------------------------------------------------
            SOUND_CHANNEL::~SOUND_CHANNEL()
            {
                free();
            }

            //------------------------------------------------------------------------------
            // Release sound buffer and sound notification, set the event state to nonsignaled.
            //------------------------------------------------------------------------------
            void SOUND_CHANNEL::free()
            {
                
            // stop any playback
                stop();

                
            // release the sound notification and sound buffer
                release_com(m_ds_notify);    
                release_com(m_ds_buffer);

                
            // release event from parent SOUND class
                m_sound->release_event(this, &m_event_index);

                
            // set to no parent sound
                m_sound = NULL;
            }

            //------------------------------------------------------------------------------
            // Stop playing DirectSound buffer.
            //------------------------------------------------------------------------------
            void SOUND_CHANNEL::stop()
            {
                
            if(m_ds_buffer)
                    m_ds_buffer->Stop();

                m_is_playing = FALSE;
            }

            //------------------------------------------------------------------------------
            // Return pointer to DirectSound buffer.
            //------------------------------------------------------------------------------
            IDirectSoundBuffer8* SOUND_CHANNEL::get_ds_buffer()
            {
                
            return m_ds_buffer;
            }

            //------------------------------------------------------------------------------
            // Return pointer to DirectSound notify.
            //------------------------------------------------------------------------------
            IDirectSoundNotify8* SOUND_CHANNEL::get_ds_notify()
            {
                
            return m_ds_notify;
            }

            //------------------------------------------------------------------------------
            // Create sound buffer, set sound notification and event.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::create(SOUND_PTR sound, long frequency, short channels, short bits_per_sample)
            {
                
            // free a prior channel
                free();

                m_sound = sound;

                
            if(m_sound == NULL || m_sound->get_directsound() == NULL)
                    
            return FALSE;

                
            // save playback format
                m_frequency       = frequency;
                m_bits_per_sample = bits_per_sample;
                m_channels        = channels;

                WAVEFORMATEX _wave_format;

                
            // create a new sound buffer for this channel, using specified format.

                ZeroMemory(&_wave_format, 
            sizeof(WAVEFORMATEX));

                _wave_format.wFormatTag      = WAVE_FORMAT_PCM;
                _wave_format.nChannels       = (WORD) m_channels;
                _wave_format.nSamplesPerSec  = m_frequency;
                _wave_format.wBitsPerSample  = (WORD) m_bits_per_sample;
                _wave_format.nBlockAlign     = _wave_format.wBitsPerSample / 8 * _wave_format.nChannels;
                _wave_format.nAvgBytesPerSec = _wave_format.nSamplesPerSec * _wave_format.nBlockAlign;

                DSBUFFERDESC _buffer_desc;

                ZeroMemory(&_buffer_desc, 
            sizeof(DSBUFFERDESC));

                _buffer_desc.dwSize          = 
            sizeof(DSBUFFERDESC);
                _buffer_desc.dwFlags         = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | 
                                               DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE;
                _buffer_desc.dwBufferBytes   = g_sound_buffer_size;
                _buffer_desc.lpwfxFormat     = &_wave_format;

                IDirectSoundBuffer* _ds_buffer;

                
            if(FAILED(m_sound->get_directsound()->CreateSoundBuffer(&_buffer_desc, &_ds_buffer, NULL)))
                    
            return FALSE;

                
            // query for newer interface
                if(FAILED(_ds_buffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &m_ds_buffer)))
                {
                    _ds_buffer->Release();
                    
            return FALSE;
                }

                
            // release old object - we have the newer one now
                _ds_buffer->Release();

                
            // create the notification interface
                if(FAILED(m_ds_buffer->QueryInterface(IID_IDirectSoundNotify8, (void**) &m_ds_notify)))
                    
            return FALSE;

                HANDLE _event_handle;

                
            // get an event for this sound channel
                if(! m_sound->assign_event_for_sound_channel(this, &m_event_index, &_event_handle))
                    
            return FALSE;

                DSBPOSITIONNOTIFY _pos_notify[4];

                
            // setup the 4 notification positions
                _pos_notify[0].dwOffset     = g_sound_buffer_chunk - 1;
                _pos_notify[0].hEventNotify = _event_handle;
                _pos_notify[1].dwOffset     = g_sound_buffer_chunk * 2 - 1;
                _pos_notify[1].hEventNotify = _event_handle;
                _pos_notify[2].dwOffset     = g_sound_buffer_chunk * 3 - 1;
                _pos_notify[2].hEventNotify = _event_handle;
                _pos_notify[3].dwOffset     = g_sound_buffer_size - 1;
                _pos_notify[3].hEventNotify = _event_handle;

                
            if(FAILED(m_ds_notify->SetNotificationPositions(4, _pos_notify)))
                    
            return FALSE;

                
            // set pan and default volume
                set_volume(100);
                set_pan(0);

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Play sound buffer.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::play(const SOUND_DATA_PTR sound_data, long volume_percent, long loop_times)
            {
                
            if(sound_data == NULL || m_ds_buffer == NULL || m_ds_notify == NULL)
                    
            return FALSE;

                
            // stop any playback
                stop();

                
            // restore a lost buffer just in case
                m_ds_buffer->Restore();

                
            // setup playing information
                m_sound_data.copy_sound_data(sound_data);

                
            // set looping times
                m_loop_times = loop_times;

                
            // calculate stop section position
                if(m_loop_times == 0)
                    m_stop_section = -1;
                
            else
                    m_stop_section = (
            short
                        (((m_sound_data.m_buffer_size * m_loop_times) % g_sound_buffer_size) / g_sound_buffer_chunk) ;

                m_load_section = 0;

                
            // load sound data into sound buffer from sound file or sound data object
                _buffer_data();
                _buffer_data();
                _buffer_data();
                _buffer_data();

                
            // set the volume
                set_volume(volume_percent);

                
            // set position and begin play

                m_next_notify = 0;

                
            if(FAILED(m_ds_buffer->SetCurrentPosition(0)))
                    
            return FALSE;

                
            if(FAILED(m_ds_buffer->Play(0, 0, DSBPLAY_LOOPING)))
                    
            return FALSE;

                
            // flag as playing
                m_is_playing = TRUE;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Get sound buffer volume.
            //------------------------------------------------------------------------------
            long SOUND_CHANNEL::get_volume()
            {
                
            return m_volume;
            }

            //------------------------------------------------------------------------------
            // Set volume for sound buffer.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::set_volume(long percent)
            {
                
            if(! set_ds_buffer_volume(m_ds_buffer, percent))
                    
            return FALSE;

                m_volume = percent % 101;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Get sound buffer pan.
            //------------------------------------------------------------------------------
            signed long SOUND_CHANNEL::get_pan()
            {
                
            return m_pan;
            }

            //------------------------------------------------------------------------------
            // Set pan for sound buffer.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::set_pan(long level)
            {
                
            if(! set_ds_buffer_pan(m_ds_buffer, level))
                    
            return FALSE;    

                m_pan = level % 101;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Get sound buffer frequency.
            //------------------------------------------------------------------------------
            long SOUND_CHANNEL::get_frequency()
            {
                
            return m_frequency;
            }

            //------------------------------------------------------------------------------
            // Set frequency for sound buffer.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::set_frequency(long frequency)
            {
                
            if(m_ds_buffer == NULL)
                    
            return FALSE;

                
            if(FAILED(m_ds_buffer->SetFrequency(frequency)))
                    
            return FALSE;

                m_frequency = frequency;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Checks whether sound buffer is playing.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::is_playing()
            {
                
            if(m_sound == NULL || m_ds_buffer == NULL || m_ds_notify == NULL)
                    
            return FALSE;

                
            return m_is_playing;
            }

            //------------------------------------------------------------------------------
            // Load sound data into sound buffer from sound file or sound data object.
            //------------------------------------------------------------------------------
            BOOL SOUND_CHANNEL::_buffer_data()
            {
                
            if(m_ds_buffer == NULL)
                    
            return FALSE;

                
            // setup position to load in
                long _lock_pos = (m_load_section % 4) * g_sound_buffer_chunk;

                
            long  _size;
                
            char* _ptr;

                
            // lock sound buffer to get pointer to sound data
                if(FAILED(m_ds_buffer->Lock(_lock_pos, g_sound_buffer_chunk, (void**) &_ptr, (DWORD*) &_size, NULL, NULL, 0)))
                    
            return FALSE;

                
            // clear out buffer if nothing left to load
                if(m_sound_data.m_left_size == 0)
                    ZeroMemory(_ptr, _size);
                
            else
                {
                    
            // load in the data - take looping into account
                    long _load_size = _size;
                    
            long _load_pos  = 0;

                    
            // load sound data until specfied load _size is satisfied
                    for(;;)
                    {
                        
            if(m_sound_data.m_left_size > _load_size)
                        {
                            
            // load into sound data from buffer
                            memcpy(&_ptr[_load_pos], &m_sound_data.m_ptr[m_sound_data.m_file_curr_pos], _load_size);

                            
            // decrease _size of sound data needed to load, advance current sound buffer position.
                            m_sound_data.m_left_size     -= _load_size;
                            m_sound_data.m_file_curr_pos += _load_size;

                            
            break;
                        }
                        
            else        // m_sound_data._left_size <= _load_size
                        {
                            
            // load in sound data from buffer
                            memcpy(&_ptr[_load_pos], &m_sound_data.m_ptr[m_sound_data.m_file_curr_pos], m_sound_data.m_left_size);

                            
            // decrease _size of sound data needed to load, advance current sound buffer position.
                            _load_size -= m_sound_data.m_left_size;
                            _load_pos  += m_sound_data.m_left_size;

                            
            // check if we need to stop loop
                            if(m_loop_times >= 1)
                            {
                                m_loop_times--;

                                
            if(m_loop_times == 0)
                                {
                                    
            // clear out remaining buffer space
                                    if(_load_size)
                                        ZeroMemory(&_ptr[_load_pos], _load_size);

                                    m_sound_data.m_left_size = 0L;
                                    
            break;
                                }
                            }

                            
            // reset sound data current position and left _size
                            m_sound_data.m_file_curr_pos = m_sound_data.m_file_start_pos;
                            m_sound_data.m_left_size     = m_sound_data.m_buffer_size;

                            
            // set if we need to stop loading data
                            if(_load_size == 0)
                                
            break;
                        }
                    }
                }

                
            // unlock the buffer
                m_ds_buffer->Unlock(_ptr, _size, NULL, 0);

                
            // mark next section to load
                if(++m_load_section > 3)
                    m_load_section = 0;

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Update for sound buffer playing.
            //------------------------------------------------------------------------------
            void SOUND_CHANNEL::_update()
            {
                
            // check for end of sound
                if(m_next_notify == m_stop_section && m_sound_data.m_left_size == 0)
                    stop();
                
            else
                {
                    
            // buffer in more data
                    _buffer_data();

                    
            if(++m_next_notify > 3)
                        m_next_notify = 0;
                }
            }

            測試代碼:
            /*****************************************************************************
            PURPOSE:
                Test for class SOUND, SOUND_DATA, SOUND_CHANNEL.
            *****************************************************************************/


            #include "core_common.h"
            #include "core_framework.h"
            #include "core_sound.h"

            class APP : public FRAMEWORK
            {
            public:
                BOOL init()
                {
                    
            // Initialize DierctSound and DirectMusic.
                    m_sound.init(g_hwnd, 22050, 1, 16, DSSCL_NORMAL);

                    
            // load into sound data from wave file
                    m_sound_data[0].load_wav("test1.wav");
                    m_sound_data[1].load_wav("test2.wav");
                    
                    
            // create sound channel

                    m_sound_channel[0].create(&m_sound, 
                        m_sound_data[0].get_frequency(), m_sound_data[0].get_channels(), m_sound_data[0].get_bits_per_sample());

                    m_sound_channel[1].create(&m_sound, 
                        m_sound_data[1].get_frequency(), m_sound_data[1].get_channels(), m_sound_data[1].get_bits_per_sample());

                    
            // play sound
                    m_sound_channel[0].play(&m_sound_data[0], 100, 1);
                    m_sound_channel[1].play(&m_sound_data[1], 50, 0); 
            // lopping forever   
                    
                    
            return TRUE;
                }

                BOOL frame()
                {
                    
            return TRUE;
                }

                BOOL shutdown()
                {
                    
            return TRUE;
                }

            private:
                SOUND m_sound;
                SOUND_DATA m_sound_data[2];
                SOUND_CHANNEL m_sound_channel[2];

                FILE* _fp;
            };

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

                
            if(! build_window(inst, "MainClass", "MainWindow", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480))
                    
            return -1;
                
                app.run();

                
            return 0;
            }

            posted on 2007-10-10 20:28 lovedday 閱讀(226) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久久久久久97| 欧美午夜精品久久久久久浪潮| 久久久久久免费视频| 奇米影视7777久久精品| 国产精品久久波多野结衣| 色综合久久中文综合网| 久久影视综合亚洲| 久久免费的精品国产V∧| 国内精品久久久久久不卡影院| 一级女性全黄久久生活片免费| 99久久精品国产麻豆| 亚洲欧美另类日本久久国产真实乱对白| 东方aⅴ免费观看久久av| 久久艹国产| 久久精品aⅴ无码中文字字幕不卡| 久久艹国产| 久久91精品国产91久久小草 | 香蕉久久av一区二区三区| 99久久婷婷免费国产综合精品| 一本综合久久国产二区| 一本久久a久久精品综合夜夜| 久久亚洲精品成人AV| 精产国品久久一二三产区区别| 国产成人综合久久精品尤物| 久久精品国产亚洲AV麻豆网站| 久久精品国产男包| 久久久高清免费视频| 亚洲午夜福利精品久久| 久久久久久极精品久久久| 久久精品www| 欧美激情精品久久久久| 天天久久狠狠色综合| 精品一区二区久久| 久久免费视频观看| 99久久99久久| 岛国搬运www久久| 久久嫩草影院免费看夜色| 国产99久久久久久免费看 | 7777精品伊人久久久大香线蕉| 国产精品久久久天天影视香蕉 | 久久影院亚洲一区|