青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

創建游戲內核(19)

 

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

 

使用SOUND_CHANNEL播放聲音

前面介紹了如何初始化聲音系統以及如何加載聲音數據,很自然地,接下來就要講述如何播放聲音了,這也正是SOUND_CHANNEL類的用途所在。

首先定義兩個全局變量來保存音頻緩沖的大小和每個音頻數據塊的大小。

// these are the fixed sizes for sound channel buffers
const long g_sound_buffer_size = 65536;
const long g_sound_buffer_chunk = g_sound_buffer_size / 4;

第一個變量g_sound_buffer_size表示分配給用于播放聲音的每個DirectSound緩沖區的字節數,這里使用65536字節,因為此大小的緩沖區足夠保存相當于數秒高品質的聲音數據。第二個g_sound_buffer_chunk是單個聲音數據塊的大小,使用4個數據塊,每個數據塊存儲了流式聲音的一個小的采樣。每播放完一個數據塊,緊接著就 開始播放下一個數據塊,同時使用新的聲音數據加載前一個數據塊。

一般不必改變這兩個變量的值,除非想要節約內存。如果想節約內存,只需將g_sound_buffer_size變量的值改變成較小的數字即可。g_sound_buffer_size變量使用不同的大小,各有其優勢,比如g_sound_buffer_size變量的值越大,聲音內核將新數據放到流中的頻率就越小,當然這也意味著要占用更多的內存。

來看看SOUND_CHANNEL的定義:

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

protected:
    SOUND*                  _sound;         
// pointer to parent sound object
    IDirectSoundBuffer8*    _ds_buffer;     // pointer to DirectSound buffer object
    IDirectSoundNotify8*    _ds_notify;     // pointer to DirectSound notify object
    short                   _event_index;   

    
long                    _volume;        // sound buffer volume
    signed long             _pan;           // sound buffer pan
    BOOL                    _is_playing;    // sound buffer playing flag
    long                    _loop_times;    // loop times

    
long                    _frequency;
    
short                   _bits_per_sample;
    
short                   _channels;

    SOUND_DATA              _sound_data;

    
short                   _load_section;  // sound section will to be loaded
    short                   _stop_section;  // sound section will to be stoped
    short                   _next_notify;   // sound notification index will to be played

    BOOL _buffer_data();
    
void _update();

public:
    SOUND_CHANNEL();
    ~SOUND_CHANNEL();

    IDirectSoundBuffer8*    get_sound_buffer_com();
    IDirectSoundNotify8*    get_notify_com();

    BOOL create(SOUND* sound, 
long frequency = 22050, short channels = 1, short bits_per_sample = 16);
    BOOL create(SOUND* sound, SOUND_DATA* sound_data);
    
void free();

    BOOL play(SOUND_DATA* sound_data, 
long volume_percent = 100, long loop = 1);
    
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();
};
 

接著來看看它的實現:

//------------------------------------------------------------------------------
// Constructor, initialize member data.
//------------------------------------------------------------------------------
SOUND_CHANNEL::SOUND_CHANNEL()
{
    _sound     = NULL;
    _ds_buffer = NULL;
    _ds_notify = NULL;

    _event_index = -1;

    _volume     = 0;
    _pan        = 0;
    _frequency  = 0;
    _is_playing = FALSE;
}

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

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

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

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

    
if((_sound = sound) == NULL)
        
return FALSE;

    
if(_sound->get_directsound_com() == NULL)
        
return FALSE;

    
// save playback format
    _frequency       = frequency;
    _bits_per_sample = bits_per_sample;
    _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) _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;

    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(_sound->get_directsound_com()->CreateSoundBuffer(&buffer_desc, &ds_buffer, NULL)))
        
return FALSE;

    
// query for newer interface
    if(FAILED(ds_buffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &_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(_ds_buffer->QueryInterface(IID_IDirectSoundNotify8, (void**) &_ds_notify)))
        
return FALSE;

    HANDLE event_handle;

    
// get an event for this
    if(! _sound->assign_event(this, &_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(_ds_notify->SetNotificationPositions(4, pos_notify)))
        
return FALSE;

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

    
return TRUE;
}

//------------------------------------------------------------------------------
// Create sound buffer.
//------------------------------------------------------------------------------
BOOL SOUND_CHANNEL::create(SOUND* sound, SOUND_DATA* sound_data)
{
    
return create(sound, sound_data->_frequency, sound_data->_channels, sound_data->_bits_per_sample);
}

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

    
// release the notification
    release_com(_ds_notify);

    
// release the sound buffer
    release_com(_ds_buffer);

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

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

//------------------------------------------------------------------------------
// Play sound buffer.
//------------------------------------------------------------------------------
BOOL SOUND_CHANNEL::play(SOUND_DATA* sound_data, long volume_percent, long loop_times)
{
    
if(sound_data == NULL || _ds_buffer == NULL || _ds_notify == NULL)
        
return FALSE;

    
// stop any playback
    stop();

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

    
// setup playing information
    _sound_data.copy(sound_data);

    
// set looping times
    _loop_times = loop_times;

    
// calculate stop section position
    if(_loop_times == 0)
        _stop_section = -1;
    
else
        _stop_section = (
short
            (((_sound_data._buffer_size * _loop_times) % g_sound_buffer_size) / g_sound_buffer_chunk) ;

    _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

    _next_notify = 0;

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

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

    
// flag as playing
    _is_playing = TRUE;

    
return TRUE;
}

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

    _is_playing = FALSE;
}

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

//------------------------------------------------------------------------------
// Set volume for sound buffer.
//------------------------------------------------------------------------------
BOOL SOUND_CHANNEL::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;
}

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

//------------------------------------------------------------------------------
// Set pan for sound buffer.
//------------------------------------------------------------------------------
BOOL SOUND_CHANNEL::set_pan(long level)
{
    signed 
long pan;
    
    
if(_ds_buffer == NULL)
        
return FALSE;

    
// calculate a suable setting
    if(level < 0)
        pan = DSBPAN_LEFT / 100 * (-level % 101);
    
else
        pan = DSBPAN_LEFT / 100 * (level % 101);

    
if(FAILED(_ds_buffer->SetPan(pan)))
        
return FALSE;

    _pan = level % 101;

    
return TRUE;
}

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

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

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

    _frequency = frequency;

    
return TRUE;
}

//------------------------------------------------------------------------------
// Checks whether sound buffer is playing.
//------------------------------------------------------------------------------
BOOL SOUND_CHANNEL::is_playing()
{
    
if(_sound == NULL || _ds_buffer == NULL || _ds_notify == NULL)
        
return FALSE;

    
return _is_playing;
}

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

    
// setup position to load in
    long lock_pos = (_load_section % 4) * g_sound_buffer_chunk;

    
long size;
    
char* ptr;

    
// lock sound buffer to get pointer to sound data
    if(FAILED(_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(_sound_data._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(_sound_data._left_size > load_size)
            {
                
// load in sound data
                if(_sound_data._fp != NULL)
                {
                    
// load in sound data from file
                    fseek(_sound_data._fp, _sound_data._file_curr_pos, SEEK_SET);
                    fread(&ptr[load_pos], 1, load_size, _sound_data._fp);
                }
                
else
                    
// load into sound data from buffer
                    memcpy(&ptr[load_pos], &_sound_data._ptr[_sound_data._file_curr_pos], load_size);

                
// decrease sound data, advance current sound buffer position.
                _sound_data._left_size     -= load_size;
                _sound_data._file_curr_pos += load_size;
                
break;
            }
            
else        // _sound_data._left_size <= load_size
            {
                
// load in sound data
                if(_sound_data._fp != NULL)
                {
                    
// load in sound data from file
                    fseek(_sound_data._fp, _sound_data._file_curr_pos, SEEK_SET);
                    fread(&ptr[load_pos], 1, _sound_data._left_size, _sound_data._fp);
                }
                
else
                    
// load in sound data from buffer
                    memcpy(&ptr[load_pos], &_sound_data._ptr[_sound_data._file_curr_pos], _sound_data._left_size);

                
// decrease sound data, advance current sound buffer position.
                load_size -= _sound_data._left_size;
                load_pos  += _sound_data._left_size;

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

                    
if(_loop_times == 0)
                    {
                        
// clear out remaining buffer space
                        if(load_size)
                            ZeroMemory(&ptr[load_pos], load_size);

                        _sound_data._left_size = 0L;
                        
break;
                    }
                }

                
// reset sound data current position and left size
                _sound_data._file_curr_pos = _sound_data._file_start_pos;
                _sound_data._left_size     = _sound_data._buffer_size;

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

    
// unlock the buffer
    _ds_buffer->Unlock(ptr, size, NULL, 0);

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

    
return TRUE;
}

//------------------------------------------------------------------------------
// Update for sound buffer palying.
//------------------------------------------------------------------------------
void SOUND_CHANNEL::_update()
{
    
// check for end of sound
    if(_next_notify == _stop_section && _sound_data._left_size == 0)
        stop();
    
else
    {
        
// buffer in more data
        _buffer_data();

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

最多可以將SOUND_CHANNEL類實例化32次,也就是說同時可以用多達32個聲道進行播放(聲音內核不允許同時32個以上的實例,任何超過32的值,都無法被成功初始化)。調用SOUND_CHANNEL::create函數可以初始化各個聲道,需要提供一個預初始化的SOUND類以及回放格式。為方便起見,甚至可以使用存儲在SOUND_DATA類中的回放格式創建聲道。

使用SOUND_CHANNEL類進行的操作中,最頻繁的就是播放聲音、停止播放聲音以及改變聲音的音量。要播放聲音,需要給SOUND_CHANNEL::play函數傳遞三個參數:保存在SOUND_DATA類中要播放的聲音數據、音量的大小以及連續播放聲音的次數。

接著我們編寫測試代碼:

點擊下載源碼和工程

/*****************************************************************************
PURPOSE:
    Test for class SOUND, SOUND_DATA, SOUND_CHANNEL.
*****************************************************************************/


#include "Core_Global.h"

class APP : public APPLICATION
{
private:
    SOUND _sound;
    SOUND_DATA _sound_data[2];
    SOUND_CHANNEL _sound_channel[2];

    FILE* _fp;

public:
    APP()
    {
        _fp = NULL;
    }

    BOOL init();
    BOOL frame();
    BOOL shutdown();
};

BOOL APP::init()
{
    
// Initialize DierctSound and DirectMusic.
    _sound.init(get_hwnd());

    
// load into sound data from wave file
    _sound_data[0].load_wav("test1.wav", NULL);
    _sound_data[1].load_wav("test2.wav", NULL);
    
    
// create sound channel
    _sound_channel[0].create(&_sound, &_sound_data[0]);
    _sound_channel[1].create(&_sound, &_sound_data[1]);

    
// play sound
    _sound_channel[0].play(&_sound_data[0]);
    _sound_channel[1].play(&_sound_data[1], 100, 0); 
// lopping forever   
    
    
return TRUE;
}

BOOL APP::frame()
{    
    
return TRUE;
}

BOOL APP::shutdown()
{
    
if(_fp) 
        fclose(_fp);

    
return TRUE;
}

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

    
return app.run();
}

posted on 2007-09-29 22:03 lovedday 閱讀(377) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美午夜剧场| 亚洲欧美日韩爽爽影院| 免费成人黄色av| 嫩草国产精品入口| 亚洲伦理自拍| 欧美日韩国产精品自在自线| 亚洲无吗在线| 欧美 日韩 国产 一区| 玖玖在线精品| 亚洲在线网站| 好吊一区二区三区| 欧美女人交a| 久久精品卡一| 亚洲免费成人av| 久久久欧美一区二区| 日韩亚洲在线观看| 亚洲第一区在线| 国产精品家教| 欧美国产精品久久| 久久超碰97人人做人人爱| 一本大道久久a久久精二百| 免费在线成人av| 久久精品成人一区二区三区| 亚洲精品在线一区二区| 亚洲小视频在线观看| 亚洲精品国产精品国自产观看浪潮 | 亚洲国产一区二区在线| 欧美精品久久久久久久免费观看 | 99精品欧美一区| 久久国产免费看| 国产精品乱码一区二三区小蝌蚪| 欧美日韩伊人| 欧美日本网站| 国产一区二区精品久久99| 国产嫩草影院久久久久 | 日韩写真视频在线观看| 久久久999国产| 国产精品久久精品日日| 亚洲精品一区二区三| 久久免费国产精品| 亚洲一区二三| 日韩午夜三级在线| 麻豆乱码国产一区二区三区| 国产午夜精品视频免费不卡69堂| 国产日韩久久| 亚洲永久免费| 亚洲精品网址在线观看| 亚洲色图在线视频| 亚洲一卡二卡三卡四卡五卡| 欧美激情1区2区| 亚洲啪啪91| 亚洲一区精品电影| 亚洲精品日韩一| 欧美精品在线免费播放| 亚洲精品美女久久7777777| 欧美国产日韩xxxxx| 亚洲欧洲在线一区| 亚洲看片网站| 欧美日韩综合在线| 国产一区二区欧美日韩| 久久国产精品久久久久久久久久| 亚洲在线中文字幕| 久久躁狠狠躁夜夜爽| 欧美国产亚洲精品久久久8v| 亚洲全部视频| 亚洲经典自拍| 欧美日韩亚洲一区二区三区| 亚洲美女色禁图| 亚洲狼人精品一区二区三区| 国产精品二区在线观看| 欧美在线亚洲综合一区| 亚洲日本乱码在线观看| 亚洲一级一区| 国产夜色精品一区二区av| 久久久久久91香蕉国产| 亚洲欧洲精品一区二区| 欧美啪啪一区| 西瓜成人精品人成网站| 欧美成人黑人xx视频免费观看| 久久久久久亚洲精品中文字幕 | 久久本道综合色狠狠五月| 久久久www免费人成黑人精品| 亚洲欧洲免费视频| 一区二区三区四区五区精品视频 | 欧美日韩成人综合天天影院| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 日韩天堂在线观看| 亚洲天堂成人在线视频| 国内精品久久久久久| 亚洲一区二区三区免费观看| 亚洲欧美激情一区二区| 在线免费高清一区二区三区| 亚洲毛片一区| 伊人久久婷婷| 久久野战av| 欧美在线亚洲综合一区| 欧美视频国产精品| 久久精品道一区二区三区| 欧美sm视频| 亚洲欧洲一区二区三区| 一区二区欧美视频| 国产精品视频一区二区高潮| 亚洲日本中文字幕| 亚洲黄色影片| 欧美日韩免费在线| 欧美在线免费观看亚洲| 久久久国产视频91| 99re8这里有精品热视频免费| 亚洲精品一区二区三区福利| 国产精品区一区二区三区| 久久久久一区| 欧美乱妇高清无乱码| 欧美一区二视频| 一区二区三区成人精品| 国产精品视频精品| 欧美国产高清| 久久久噜噜噜久久中文字免| 亚洲乱码久久| 欧美在线视频不卡| 亚洲乱码视频| 久久国产欧美日韩精品| 9i看片成人免费高清| 亚洲二区免费| 久久国产精品久久久久久久久久| 中文高清一区| 亚洲制服少妇| 亚洲一区在线直播| 欧美日韩视频在线观看一区二区三区 | 欧美高清在线一区| 老司机午夜免费精品视频| 国产日韩一区二区三区在线播放| 亚洲人成网站在线播| 久久国产精品久久久| 久久国产日韩| 国产视频一区在线| 午夜精品理论片| 欧美专区亚洲专区| 国产欧美丝祙| 久久精品二区三区| 老牛国产精品一区的观看方式| 国产亚洲欧美中文| 欧美一区亚洲| 久久中文精品| 亚洲经典自拍| 在线中文字幕不卡| 亚洲在线一区二区| 国产精品综合久久久| 欧美专区日韩视频| 免费视频久久| 亚洲精品欧美一区二区三区| 欧美日本一区| 亚洲综合不卡| 免费视频一区二区三区在线观看| 在线精品视频免费观看| 免费成人美女女| 亚洲精品免费一二三区| 亚洲专区国产精品| 国产午夜精品理论片a级探花| 欧美在线视频播放| 欧美高清视频免费观看| 一本色道久久综合亚洲精品按摩| 国产精品久在线观看| 欧美在线999| 亚洲国产精品尤物yw在线观看| 亚洲美女黄网| 国产一区二区三区在线观看网站| 久久人人爽人人爽爽久久| 篠田优中文在线播放第一区| 国产人久久人人人人爽| 久久久精品免费视频| 亚洲精品一区二区三区婷婷月 | 亚洲麻豆国产自偷在线| 欧美在线免费| 亚洲乱码国产乱码精品精天堂 | 亚洲午夜视频在线观看| 久久久水蜜桃av免费网站| 夜夜狂射影院欧美极品| 国产女人精品视频| 欧美国产高潮xxxx1819| 亚洲欧美成人一区二区在线电影| 免费久久99精品国产| 午夜欧美精品久久久久久久| 欧美日韩123| 亚洲欧美一区二区三区在线 | 亚洲精品影院| 久久免费视频一区| 亚洲一区二区在线免费观看视频| 伊人成人在线| 国产欧美va欧美不卡在线| 欧美日韩在线不卡| 老色鬼久久亚洲一区二区 | 欧美先锋影音| 亚洲国产成人在线视频| 久久久久久伊人| 亚洲女ⅴideoshd黑人| 欧美日韩在线高清| 美国三级日本三级久久99| 欧美一区二区三区免费在线看| 欧美在线999| 在线视频日韩精品|