• <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)自強而不息

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

             

            有關(guān)DirectAudio和DirectShow的基礎(chǔ)知識請參閱用DirectX Audio和DirectShow播放聲音和音樂。

             

            聲音內(nèi)核為快速和容易地將聲音和音樂加入到游戲中提供了一種解決方案,聲音內(nèi)核包含6個類組件,如下表所示:
             

            說明
            SOUND 包含DirectSound和DirectMusic對象,并控制音頻流(sound streaming)。
            SOUND_DATA 這個類包含了使用SOUND_CHANNEL播放的波形數(shù)據(jù)。
            SOUND_CHANNEL 這個類用于播放單個聲音,這種類一次最多可以同時使用32個(也就是說可以播放32個同步的聲音)。
            MUSIC_CHANNEL 可以使用這個類播放單個歌曲文件,無論此文件是MIDI文件還是DirectMusic本地歌曲,一次只能使用一個這樣的類。
            DLS 可下載聲音(downloadable sound)類對象,這個類允許用戶將不同的樂器加載到MUSIC_CHANNEL對象。
            MP3 一個.mp3音樂播放類對象,這個類允許用戶播放.mp3歌曲并檢測這些歌曲的當(dāng)前播放狀態(tài)。

             

            波形數(shù)據(jù)和SOUND_DATA

            SOUND_DATA類對象用于描述和包含單個的聲音(波形)。聲音頻率(sound frequency)、采樣精度(bits-per-sample)、音頻聲道數(shù)(number of channels)、文件大小以及聲源(source)都包含在SOUND_DATA類的聲明中,來看看它的定義:

            //======================================================================================
            // This class encapsulate how to load sound data.
            //======================================================================================
            class SOUND_DATA
            {
            private:
                friend class SOUND_CHANNEL; // let SOUND_CHANNEL can use this class's member data and function

            protected:
                long _frequency;
                short _channels;
                short _bits_per_sample;

                FILE*   _fp;                // pointer to sound file
                char*   _ptr;               // pointer to current sound buffer will to be played
                char*   _buf;               // buffer to store sound data

                long    _buffer_size;       // sound buffer size
                long    _left_size;         // left size of sound buffer which need to loaded

                long    _file_start_pos;    // start position of wave file will to be loaded
                long    _file_curr_pos;     // current position of wave file will to be loaded

            public:
                SOUND_DATA();
                ~SOUND_DATA();

                char* get_ptr();
                long  get_size();

                BOOL create();
                BOOL create(long size);
                void free();

                void set_format(long frequency, short channels, short bits_per_sample);
                void set_source(FILE* fp, long pos = -1, long size = -1);
                void set_source(void* ptr, long pos = -1, long size = -1);

                BOOL load_wav(char* filename, FILE* fp = NULL);
                BOOL load_wav_header(char* filename, FILE* fp = NULL);

                BOOL copy(SOUND_DATA* source);
            };
             

            #pragma pack(1)

            // .WAV file header
            struct WAVE_HEADER
            {
                
            char    riff_sig[4];            // 'RIFF'
                long    waveform_chunk_size;    // 8
                char    wave_sig[4];            // 'WAVE'
                char    format_sig[4];          // 'fmt ' (notice space after)
                long    format_chunk_size;      // 16;
                short   format_tag;             // WAVE_FORMAT_PCM
                short   channels;               // # of channels
                long    sample_rate;            // sampling rate
                long    bytes_per_sec;          // bytes per second
                short   block_align;            // sample block alignment
                short   bits_per_sample;        // bits per second
                char    data_sig[4];            // 'data'
                long    data_size;              // size of waveform data
            };

            #pragma pack()
             

            接著來看看SOUND_DATA的實現(xiàn):

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

                _frequency       = 22050;
                _channels        = 1;
                _bits_per_sample = 16;    
            }

            //------------------------------------------------------------------------------
            // Destructor, release sound data buffer.
            //------------------------------------------------------------------------------
            SOUND_DATA::~SOUND_DATA()
            {
                free();
            }

            //------------------------------------------------------------------------------
            // Create sound data buffer.
            //------------------------------------------------------------------------------
            BOOL SOUND_DATA::create()
            {
                
            return create(_buffer_size);
            }

            //------------------------------------------------------------------------------
            // Create sound data buffer with specified size.
            //------------------------------------------------------------------------------
            BOOL SOUND_DATA::create(long size)
            {
                
            // free prior allocated data
                free();

                
            // check for valid size
                if((_buffer_size = size) == 0)
                    
            return FALSE;

                
            // create a new buffer
                _buf = new char[_buffer_size];
                
            if(_buf == NULL)
                    
            return FALSE;

                
            // clear out new buffer
                ZeroMemory(_buf, _buffer_size);

                
            // point to new buffer
                _ptr = _buf;
                _fp  = NULL;    

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Release sound data buffer.
            //------------------------------------------------------------------------------
            void SOUND_DATA::free()
            {
                
            if(_buf != NULL)
                {
                    delete[] _buf;
                    _buf = NULL;
                }

                _ptr = NULL;
                _buffer_size = 0;
            }

            //------------------------------------------------------------------------------
            // Get pointer to sound data buffer.
            //------------------------------------------------------------------------------
            char* SOUND_DATA::get_ptr()
            {
                
            return _buf;
            }

            //------------------------------------------------------------------------------
            // Get size of sound data buffer.
            //------------------------------------------------------------------------------
            long SOUND_DATA::get_size()
            {
                
            return _buffer_size;
            }

            //------------------------------------------------------------------------------
            // Set play property for sound data buffer.
            //------------------------------------------------------------------------------
            void SOUND_DATA::set_format(long frequency, short channels, short bits_per_sample)
            {
                _frequency  = frequency;
                _channels   = channels;
                _bits_per_sample = bits_per_sample;
            }

            //------------------------------------------------------------------------------
            // Set position and size for sound data buffer.
            //------------------------------------------------------------------------------
            void SOUND_DATA::set_source(FILE* fp, long pos, long size)
            {
                _fp  = fp;
                _ptr = NULL;

                
            if(pos != -1)
                    _file_start_pos = _file_curr_pos = pos;

                
            if(size != -1)
                    _buffer_size = _left_size = size;
            }

            //------------------------------------------------------------------------------
            // Set position and size for sound buffer.
            //------------------------------------------------------------------------------
            void SOUND_DATA::set_source(void* ptr, long pos, long size)
            {
                _fp = NULL;
                _ptr = (
            char*) ptr;

                
            if(pos != -1)
                    _file_start_pos = _file_curr_pos = pos;

                
            if(size != -1)
                    _buffer_size = _left_size = size;
            }

            //------------------------------------------------------------------------------
            // Load in wave file. 
            //------------------------------------------------------------------------------
            BOOL SOUND_DATA::load_wav(char* filename, FILE* fp)
            {
                
            // load wave header information first
                if(! load_wav_header(filename, fp))
                    
            return FALSE;

                
            // create sound data buffer.
                if(! create())
                    
            return FALSE;

                
            // open file, seek to position and read in data.

                
            if(filename != NULL)
                {
                    
            if((fp = fopen(filename, "rb")) == NULL)
                        
            return FALSE;
                }

                fseek(fp, _file_start_pos, SEEK_SET);
                fread(_buf, 1, _buffer_size, fp);

                
            // reset start position and current position
                _file_start_pos = _file_curr_pos = 0;

                
            // close file
                if(filename != NULL)
                    fclose(fp);

                
            return TRUE;
            }

            //------------------------------------------------------------------------------
            // Load wave header from file.
            //------------------------------------------------------------------------------
            BOOL SOUND_DATA::load_wav_header(char* filename, FILE* fp)
            {
                
            if(filename == NULL && fp == NULL)
                    
            return FALSE;

                
            if(filename != NULL)
                {
                    
            if((fp = fopen(filename, "rb")) == NULL)
                        
            return FALSE;
                }

                
            // save position in file
                long org_file_pos = ftell(fp);

                BOOL rv = FALSE;

                
            // read in header and parse
                WAVE_HEADER wave_header;

                fread(&wave_header, 1, 
            sizeof(WAVE_HEADER), fp);

                
            // check signature
                if(!memcmp(wave_header.riff_sig, "RIFF", 4) && !memcmp(wave_header.wave_sig, "WAVE", 4) &&
                   !memcmp(wave_header.format_sig, "fmt ", 4) && !memcmp(wave_header.data_sig, "data", 4))
                {
                    
            // all signatures satisfied

                    _frequency = wave_header.sample_rate;
                    _channels  = wave_header.channels;
                    _bits_per_sample = wave_header.bits_per_sample;

                    _buffer_size = _left_size = wave_header.data_size;
                    _file_start_pos = _file_curr_pos = ftell(fp);

                    rv = TRUE;
                }

                
            // close if we opened file, otherwise return to original position.
                if(filename != NULL)
                    fclose(fp);
                
            else
                    fseek(fp, org_file_pos, SEEK_SET);

                
            return rv;
            }

            //------------------------------------------------------------------------------
            // Copy sound data from another sound data.
            //------------------------------------------------------------------------------
            BOOL SOUND_DATA::copy(SOUND_DATA* source)
            {
                
            if(source == NULL)
                    
            return FALSE;

                
            // note that _buf is not assigned!!

                _frequency       = source->_frequency;
                _channels        = source->_channels;
                _bits_per_sample = source->_bits_per_sample;

                _fp              = source->_fp;
                _ptr             = source->_ptr;
                _buffer_size     = source->_buffer_size;
                _left_size       = source->_left_size;
                _file_curr_pos   = source->_file_curr_pos;
                _file_start_pos  = source->_file_start_pos;

                
            return TRUE;
            }
             

            使用SOUND_DATA類對象存儲回放格式和聲音的數(shù)據(jù)源,聲音有兩個來源:一個文件或內(nèi)存緩沖區(qū)。另外,如果聲音太大而不能放進內(nèi)存中,可以設(shè)置成從音頻流讀取。

            加載單個.wav文件,最快的方法就是使用SOUND_DATA::load_wav函數(shù)。load_wav函數(shù)帶有兩個參數(shù):要加載的.wav文件的文件名以及源文件指針。對于這兩個參數(shù),只能用其中一個,同時將另外一個設(shè)置為NULL。源文件指針使程序員能夠?qū)⒍鄠€.wav文件打包進單個文件,并且仍然能夠單獨加載這些被打包的.wav文件。

            除了加載單個的.wav文件外,還可以采用設(shè)置聲音的數(shù)據(jù)源這種方式。當(dāng)聲音文件太大(超過64k)而無法存放到聲音緩沖區(qū)中的時候,這種方式就特別有用,方法就是將文件或內(nèi)存緩沖區(qū)中的聲音數(shù)據(jù)放到流中。SOUND_DATA::set_source函數(shù)正好用于解決這個問題,此函數(shù)有兩個版本可供使用:

            void set_source(FILE* fp, long pos = -1, long size = -1);
            void set_source(void* ptr, long pos = -1, long size = -1);

            可以選擇一個源文件指針或一個內(nèi)存指針,pos參數(shù)將聲音數(shù)據(jù)的起始位置(偏移量)傳送給SOUND_DATA類,size參數(shù)用于設(shè)置流的總字節(jié)數(shù)(聲音的大小)。

            注意pos和size的缺省值都是-1,就使得類能夠?qū)ξ募恢眠M行設(shè)置。為了達到設(shè)置聲音數(shù)據(jù)源的目的,首先必須使用set_format函數(shù)設(shè)置回放格式,然后必須使用load_wav_header函數(shù)解析波形文件頭,此函數(shù)所帶參數(shù)的含義同load_wav函數(shù)相同。

            另外,如果聲音被存儲到內(nèi)存中以及從內(nèi)存中流出,就必須使用SOUND_DATA::create函數(shù)創(chuàng)建此內(nèi)存緩沖區(qū)??梢宰约褐付ň彌_區(qū)的大小,也可以讓create函數(shù)使用通過load_wav_header函數(shù)解析出來的緩沖區(qū)大小。調(diào)用SOUND_DATA::get_ptr函數(shù)可以得到指向內(nèi)存緩沖區(qū)的指針,可以安全地使用此指針存儲聲音。


            posted on 2007-09-25 00:23 lovedday 閱讀(330) 評論(0)  編輯 收藏 引用

            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            久久精品人人做人人爽电影蜜月| 久久久久久综合一区中文字幕| 久久精品一区二区| 久久久久亚洲AV无码网站| 99久久精品国产一区二区| 午夜精品久久久久久影视riav| 亚洲国产视频久久| 精品久久久久成人码免费动漫| 日韩欧美亚洲综合久久影院Ds | 国产成人无码精品久久久久免费| 久久精品人人做人人妻人人玩| 久久婷婷成人综合色综合| 久久亚洲春色中文字幕久久久| 午夜久久久久久禁播电影| 人妻少妇久久中文字幕| 99久久久国产精品免费无卡顿| 国产精品久久网| 久久久久99精品成人片| 色妞色综合久久夜夜| 久久精品国产亚洲AV无码偷窥| 免费观看久久精彩视频| 亚洲国产一成久久精品国产成人综合| 久久强奷乱码老熟女网站| 久久久久久精品成人免费图片| 色综合久久无码中文字幕| 中文精品久久久久国产网址| 人妻丰满?V无码久久不卡| 亚洲va中文字幕无码久久不卡| 国产精品美女久久久m| 久久久久亚洲精品天堂久久久久久| 久久精品国产久精国产一老狼| 精品综合久久久久久97超人| 久久久久久久亚洲精品| 久久青青草原精品国产| 久久久久国产精品嫩草影院| 久久亚洲春色中文字幕久久久| 久久精品无码一区二区app| 精品久久8x国产免费观看| 亚洲国产成人精品无码久久久久久综合 | 久久精品国产亚洲AV大全| 久久强奷乱码老熟女网站|