分享
 
 
 

VB.NET实现DirectSound9 (7) 录音

王朝c#·作者佚名  2006-12-17
窄屏简体版  字體: |||超大  

关键字: VB.NET DirectX 9 DirectSound 录音 riff文件格式 作者:董含君

下午看了微软提供的例子,居然把录音定位成Beginner级别

晕哦,虽说我认为这个例子是微软提供的最”直接”的例子,但是步骤超多.而且还牵扯到多线程开辟缓冲区回调riff文件格式 IO 输出等等.由于录音的复杂性,以及微软这个例子的直接性,坚持原创的我最终还是复制了大量的代码.(希望不要骂我....)

OK,先来说录音的步骤,里面牵扯到riff或者使用技巧的地方,有注释.我仅仅说步骤.附带截图一张

首先需要说明与往常不同的概念

1 声卡(或者windows)把音频设备分成2个部分,一个是录音设备(Capture),另一个是回放设备(PlayBack)

2 前面我们用的是Device创建回放设备,这次需要使用Capture创建录音设备,录音设备不像回放,设备的能力往往很关键(回放虽说也很关键,但是设备能力基本上差别不大),所以不能单单使用一个默认就行,需要用户指定,甚至用枚举的办法逐个测试性能(看看是否支持这种格式)

3 利用 Dim CapList As New CaptureDevicesCollection

得到list之后

Dim info As DeviceInformation

'''先得到可以使用的信息

''' 设备信息由这个集合提供

For Each info In CapList

ListBox1.Items.Add(info.Description)

Next

枚举出所有设备

4 创建Capture的时候,需要指定使用那个设备了,(回放的时候也可以指定,但是我们用的是默认的)

'利用选择的设备

Cap = New Capture(CapList(ListBox1.SelectedIndex).DriverGuid)

5 尝试所有支持的类型

就是一个for 循环里面嵌套下面的try语句

try

Cap=new capture(....)

catch

'''''失败的时候继续尝试下一个

end try

6 完成设备的准备工作之后,DirectSound初始化完成

7 录音,

第一步创建riff(理解成riff即可)

第二步创建录音用的缓冲区(包括文件缓冲区以及CaptureBuffer)

第三步创建新的线程用于捕获数据

8 停止

停止capture

讲缓冲区内容写入磁盘

修改riff的文件信息

释放资源

9 播放,利用最简单的办法播放文件

大体步骤就这些,录音的时候函数之间的关系比较复杂.但是没有更简单的办法.

注释比较详细,关于riff的文件操作方法内部也有注释.或者直接复制到你的程序直接用也行.

以下是源代码

Imports Microsoft.DirectX.DirectSound

Imports System.IO

Imports System.Threading

Public Class Form1

Inherits System.Windows.Forms.Form

Private Structure FormatInfo

Public format As WaveFormat

Public Overrides Function ToString() As String

Return ConvertWaveFormatToString(format)

End Function 'ToString

End Structure 'FormatInfo

Dim DevPlay As New Device

Dim BufPlay As SecondaryBuffer

Dim Formats As New ArrayList

Dim Cap As Capture

Dim CapList As New CaptureDevicesCollection

Private InputFormatSupported(19) As Boolean

Public InputFormat As WaveFormat

Private WaveFile As FileStream = Nothing

Private Writer As BinaryWriter = Nothing

Public applicationNotify As Notify = Nothing

Public applicationBuffer As CaptureBuffer = Nothing

Public NotifySize As Integer = 0

Private NotifyThread As Thread = Nothing

Public NotificationEvent As AutoResetEvent = Nothing

Public PositionNotify(NumberRecordNotifications) As BufferPositionNotify

Public Const NumberRecordNotifications As Integer = 16

Public CaptureBufferSize As Integer = 0

Public NextCaptureOffset As Integer = 0

Private SampleCount As Integer = 0

#Region " Windows 窗体设计器生成的代码 "

Public Sub New()

MyBase.New()

'该调用是 Windows 窗体设计器所必需的。

InitializeComponent()

'在 InitializeComponent() 调用之后添加任何初始化

End Sub

'窗体重写 dispose 以清理组件列表。

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'Windows 窗体设计器所必需的

Private components As System.ComponentModel.IContainer

'注意: 以下过程是 Windows 窗体设计器所必需的

'可以使用 Windows 窗体设计器修改此过程。

'不要使用代码编辑器修改它。

Friend WithEvents ListBox1 As System.Windows.Forms.ListBox

Friend WithEvents ListBox2 As System.Windows.Forms.ListBox

Friend WithEvents TextBox1 As System.Windows.Forms.TextBox

Friend WithEvents Button1 As System.Windows.Forms.Button

Friend WithEvents Button2 As System.Windows.Forms.Button

Friend WithEvents Button3 As System.Windows.Forms.Button

Friend WithEvents Button4 As System.Windows.Forms.Button

Friend WithEvents Label1 As System.Windows.Forms.Label

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

Me.ListBox1 = New System.Windows.Forms.ListBox

Me.ListBox2 = New System.Windows.Forms.ListBox

Me.TextBox1 = New System.Windows.Forms.TextBox

Me.Button1 = New System.Windows.Forms.Button

Me.Button2 = New System.Windows.Forms.Button

Me.Button3 = New System.Windows.Forms.Button

Me.Button4 = New System.Windows.Forms.Button

Me.Label1 = New System.Windows.Forms.Label

Me.SuspendLayout()

'

'ListBox1

'

Me.ListBox1.ItemHeight = 12

Me.ListBox1.Location = New System.Drawing.Point(16, 16)

Me.ListBox1.Name = "ListBox1"

Me.ListBox1.Size = New System.Drawing.Size(216, 64)

Me.ListBox1.TabIndex = 1

'

'ListBox2

'

Me.ListBox2.ItemHeight = 12

Me.ListBox2.Location = New System.Drawing.Point(16, 88)

Me.ListBox2.Name = "ListBox2"

Me.ListBox2.Size = New System.Drawing.Size(216, 100)

Me.ListBox2.TabIndex = 2

'

'TextBox1

'

Me.TextBox1.Location = New System.Drawing.Point(24, 208)

Me.TextBox1.Name = "TextBox1"

Me.TextBox1.Size = New System.Drawing.Size(208, 21)

Me.TextBox1.TabIndex = 3

Me.TextBox1.Text = "c:\0001.wav"

'

'Button1

'

Me.Button1.Location = New System.Drawing.Point(24, 240)

Me.Button1.Name = "Button1"

Me.Button1.Size = New System.Drawing.Size(64, 24)

Me.Button1.TabIndex = 4

Me.Button1.Text = "recode"

'

'Button2

'

Me.Button2.Location = New System.Drawing.Point(96, 240)

Me.Button2.Name = "Button2"

Me.Button2.Size = New System.Drawing.Size(72, 24)

Me.Button2.TabIndex = 5

Me.Button2.Text = "stop"

'

'Button3

'

Me.Button3.Location = New System.Drawing.Point(176, 240)

Me.Button3.Name = "Button3"

Me.Button3.Size = New System.Drawing.Size(80, 24)

Me.Button3.TabIndex = 6

Me.Button3.Text = "play"

'

'Button4

'

Me.Button4.Location = New System.Drawing.Point(272, 240)

Me.Button4.Name = "Button4"

Me.Button4.Size = New System.Drawing.Size(96, 24)

Me.Button4.TabIndex = 7

Me.Button4.Text = "disposebuff"

'

'Label1

'

Me.Label1.Location = New System.Drawing.Point(248, 16)

Me.Label1.Name = "Label1"

Me.Label1.Size = New System.Drawing.Size(264, 160)

Me.Label1.TabIndex = 8

Me.Label1.Text = "声音格式"

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)

Me.ClientSize = New System.Drawing.Size(536, 277)

Me.Controls.Add(Me.Label1)

Me.Controls.Add(Me.Button4)

Me.Controls.Add(Me.Button3)

Me.Controls.Add(Me.Button2)

Me.Controls.Add(Me.Button1)

Me.Controls.Add(Me.TextBox1)

Me.Controls.Add(Me.ListBox2)

Me.Controls.Add(Me.ListBox1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim info As DeviceInformation

'''先得到可以使用的信息

''' 设备信息由这个集合提供

For Each info In CapList

ListBox1.Items.Add(info.Description)

Next

End Sub

Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged

'利用选择的设备

Cap = New Capture(CapList(ListBox1.SelectedIndex).DriverGuid)

'''枚举支持的格式

'''尝试各种格式,只能用try catch 了

Dim fmt As WaveFormat

Dim TestCapture As CaptureBuffer

Dim CaptureDesc As New CaptureBufferDescription

'ListBox2.Items.Clear()

ScanAvailableInputFormats(Cap)

FillFormatListBox()

End Sub

Sub ScanAvailableInputFormats(ByVal cap As Capture)

'-----------------------------------------------------------------------------

' Name: ScanAvailableInputFormats()

' Desc: Tests to see if 20 different standard wave formats are supported by

' the capture device

'-----------------------------------------------------------------------------

Dim format As New WaveFormat

Dim dscheckboxd As New CaptureBufferDescription

Dim pDSCaptureBuffer As CaptureBuffer = Nothing

' This might take a second or two, so throw up the hourglass

Cursor = Cursors.WaitCursor

format.FormatTag = WaveFormatTag.Pcm

' Try 20 different standard formats to see if they are supported

Dim iIndex As Integer

For iIndex = 0 To 19

GetWaveFormatFromIndex(iIndex, format)

' To test if a capture format is supported, try to create a

' new capture buffer using a specific format. If it works

' then the format is supported, otherwise not.

dscheckboxd.BufferBytes = format.AverageBytesPerSecond

dscheckboxd.Format = format

Try

pDSCaptureBuffer = New CaptureBuffer(dscheckboxd, cap)

InputFormatSupported(iIndex) = True

Catch

InputFormatSupported(iIndex) = False

End Try

pDSCaptureBuffer.Dispose()

Next iIndex

Cursor = Cursors.Default

End Sub 'ScanAvailableInputFormats

Private Sub GetWaveFormatFromIndex(ByVal Index As Integer, ByRef format As WaveFormat)

'-----------------------------------------------------------------------------

' Name: GetWaveFormatFromIndex()

' Desc: Returns 20 different wave formats based on Index

'-----------------------------------------------------------------------------

Dim SampleRate As Integer = Index / 4

Dim iType As Integer = Index Mod 4

Select Case SampleRate

Case 0

format.SamplesPerSecond = 48000

Case 1

format.SamplesPerSecond = 44100

Case 2

format.SamplesPerSecond = 22050

Case 3

format.SamplesPerSecond = 11025

Case 4

format.SamplesPerSecond = 8000

End Select

Select Case iType

Case 0

format.BitsPerSample = 8

format.Channels = 1

Case 1

format.BitsPerSample = 16

format.Channels = 1

Case 2

format.BitsPerSample = 8

format.Channels = 2

Case 3

format.BitsPerSample = 16

format.Channels = 2

End Select

format.BlockAlign = CShort(format.Channels * (format.BitsPerSample / 8))

format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond

End Sub 'GetWaveFormatFromIndex

Private Shared Function ConvertWaveFormatToString(ByVal format As WaveFormat) As String

'-----------------------------------------------------------------------------

' Name: ConvertWaveFormatToString()

' Desc: Converts a wave format to a text string

'-----------------------------------------------------------------------------

Return format.SamplesPerSecond.ToString() + " Hz, " + format.BitsPerSample.ToString() + "-bit " + IIf(format.Channels = 1, "Mono", "Stereo")

End Function 'ConvertWaveFormatToString

Sub FillFormatListBox()

'-----------------------------------------------------------------------------

' Name: FillFormatListBox()

' Desc: Fills the format list box based on the availible formats

'-----------------------------------------------------------------------------

Dim info As New FormatInfo

Dim strFormatName As String = String.Empty

Dim format As New WaveFormat

Dim iIndex As Integer

For iIndex = 0 To InputFormatSupported.Length - 1

If True = InputFormatSupported(iIndex) Then

' Turn the index into a WaveFormat then turn that into a

' string and put the string in the listbox

GetWaveFormatFromIndex(iIndex, format)

info.format = format

Formats.Add(info)

End If

Next iIndex

ListBox2.DataSource = Formats

End Sub 'FillFormatListBox

Sub CreateRIFF()

'*************************************************************************

'

'

' Here is where the file will be created. A

'

' wave file is a RIFF file, which has chunks

'

' of data that describe what the file contains.

'

' A wave RIFF file is put together like this:

'

'

'

' The 12 byte RIFF chunk is constructed like this:

'

' Bytes(0 - 3) 'R' 'I' 'F' 'F'

'

' Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description.

'

' (4 bytes for "WAVE" + 24 bytes for format chunk length +

'

' 8 bytes for data chunk description + actual sample data size.)

'

' Bytes(8 - 11) 'W' 'A' 'V' 'E'

'

'

'

' The 24 byte FORMAT chunk is constructed like this:

'

' Bytes(0 - 3) 'f' 'm' 't' ' '

'

' Bytes 4 - 7 : The format chunk length. This is always 16.

'

' Bytes 8 - 9 : File padding. Always 1.

'

' Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo.

'

' Bytes 12- 15: Sample rate.

'

' Bytes 16- 19: Number of bytes per second.

'

' Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or

'

' 16 bit mono, 4 for 16 bit stereo.

'

' Bytes 22- 23: Number of bits per sample.

'

'

'

' The DATA chunk is constructed like this:

'

' Bytes(0 - 3) 'd' 'a' 't' 'a'

'

' Bytes 4 - 7 : Length of data, in bytes.

'

' Bytes 8 -...: Actual sample data.

'

'

'

'**************************************************************************

' Open up the wave file for writing.

WaveFile = New FileStream(TextBox1.Text, FileMode.Create)

Writer = New BinaryWriter(WaveFile)

' Set up file with RIFF chunk info.

Dim ChunkRiff As Char() = {"R", "I", "F", "F"}

Dim ChunkType As Char() = {"W", "A", "V", "E"}

Dim ChunkFmt As Char() = {"f", "m", "t", " "}

Dim ChunkData As Char() = {"d", "a", "t", "a"}

Dim shPad As Short = 1 ' File padding

Dim nFormatChunkLength As Integer = &H10 ' Format chunk length.

Dim nLength As Integer = 0 ' File length, minus first 8 bytes of RIFF description. This will be filled in later.

Dim shBytesPerSample As Short = 0 ' Bytes per sample.

' Figure out how many bytes there will be per sample.

If 8 = InputFormat.BitsPerSample And 1 = InputFormat.Channels Then

shBytesPerSample = 1

ElseIf 8 = InputFormat.BitsPerSample And 2 = InputFormat.Channels Or (16 = InputFormat.BitsPerSample And 1 = InputFormat.Channels) Then

shBytesPerSample = 2

ElseIf 16 = InputFormat.BitsPerSample And 2 = InputFormat.Channels Then

shBytesPerSample = 4

End If

' Fill in the riff info for the wave file.

Writer.Write(ChunkRiff)

Writer.Write(nLength)

Writer.Write(ChunkType)

' Fill in the format info for the wave file.

Writer.Write(ChunkFmt)

Writer.Write(nFormatChunkLength)

Writer.Write(shPad)

Writer.Write(InputFormat.Channels)

Writer.Write(InputFormat.SamplesPerSecond)

Writer.Write(InputFormat.AverageBytesPerSecond)

Writer.Write(shBytesPerSample)

Writer.Write(InputFormat.BitsPerSample)

' Now fill in the data chunk.

Writer.Write(ChunkData)

Writer.Write(CInt(0)) ' The sample length will be written in later.

End Sub 'CreateRIFF

Sub CreateCaptureBuffer()

'-----------------------------------------------------------------------------

' Name: CreateCaptureBuffer()

' Desc: Creates a capture buffer and sets the format

'-----------------------------------------------------------------------------

Dim dscheckboxd As New CaptureBufferDescription

If Not Nothing Is applicationNotify Then

applicationNotify.Dispose()

applicationNotify = Nothing

End If

If Not Nothing Is applicationBuffer Then

applicationBuffer.Dispose()

applicationBuffer = Nothing

End If

If 0 = InputFormat.Channels Then

Return

End If

' Set the notification size

NotifySize = IIf(1024 > InputFormat.AverageBytesPerSecond / 8, 1024, InputFormat.AverageBytesPerSecond / 8)

NotifySize -= NotifySize Mod InputFormat.BlockAlign

' Set the buffer sizes

CaptureBufferSize = NotifySize * NumberRecordNotifications

' Create the capture buffer

dscheckboxd.BufferBytes = CaptureBufferSize

InputFormat.FormatTag = WaveFormatTag.Pcm

dscheckboxd.Format = InputFormat ' Set the format during creatation

applicationBuffer = New CaptureBuffer(dscheckboxd, Cap)

NextCaptureOffset = 0

InitNotifications()

End Sub 'CreateCaptureBuffer

Sub InitNotifications()

'-----------------------------------------------------------------------------

' Name: InitNotifications()

' Desc: Inits the notifications on the capture buffer which are handled

' in the notify thread.

'-----------------------------------------------------------------------------

If Nothing Is applicationBuffer Then

Throw New ArgumentNullException

End If

' Create a thread to monitor the notify events

If Nothing Is NotifyThread Then

NotifyThread = New Thread(New ThreadStart(AddressOf WaitThread))

NotifyThread.Start()

' Create a notification event, for when the sound stops playing

NotificationEvent = New AutoResetEvent(False)

End If

' Setup the notification positions

Dim i As Integer

For i = 0 To NumberRecordNotifications - 1

PositionNotify(i).Offset = NotifySize * i + NotifySize - 1

PositionNotify(i).EventNotifyHandle = NotificationEvent.Handle

Next i

applicationNotify = New Notify(applicationBuffer)

' Tell DirectSound when to notify the app. The notification will come in the from

' of signaled events that are handled in the notify thread.

applicationNotify.SetNotificationPositions(PositionNotify, NumberRecordNotifications)

End Sub 'InitNotifications

Private Sub WaitThread()

While Created

'Sit here and wait for a message to arrive

NotificationEvent.WaitOne(Timeout.Infinite, True)

RecordCapturedData()

End While

End Sub 'WaitThread

Sub RecordCapturedData()

'-----------------------------------------------------------------------------

' Name: RecordCapturedData()

' Desc: Copies data from the capture buffer to the output buffer

'-----------------------------------------------------------------------------

Dim CaptureData As Byte() = Nothing

Dim ReadPos As Integer

Dim CapturePos As Integer

Dim LockSize As Integer

If Nothing Is applicationBuffer Or Nothing Is WaveFile Then

Return

End If

applicationBuffer.GetCurrentPosition(CapturePos, ReadPos)

LockSize = ReadPos - NextCaptureOffset

If LockSize < 0 Then

LockSize += CaptureBufferSize

End If

' Block align lock size so that we are always write on a boundary

LockSize -= LockSize Mod NotifySize

If 0 = LockSize Then

Return

End If

' Read the capture buffer.

CaptureData = CType(applicationBuffer.Read(NextCaptureOffset, GetType(Byte), LockFlag.None, LockSize), Byte())

' Write the data into the wav file

Writer.Write(CaptureData, 0, CaptureData.Length)

' Update the number of samples, in bytes, of the file so far.

SampleCount += CaptureData.Length

' Move the capture offset along

NextCaptureOffset += CaptureData.Length

NextCaptureOffset = NextCaptureOffset Mod CaptureBufferSize ' Circular buffer

End Sub 'RecordCapturedData

Private Sub ListBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox2.SelectedIndexChanged

InputFormat = CType(Formats(ListBox2.SelectedIndex), FormatInfo).format

Label1.Text = CType(ListBox2.SelectedItem, FormatInfo).format.ToString

End Sub

Sub StartOrStopRecord(ByVal StartRecording As Boolean)

'-----------------------------------------------------------------------------

' Name: StartOrStopRecord()

' Desc: Starts or stops the capture buffer from recording

'-----------------------------------------------------------------------------

If StartRecording Then

' Create a capture buffer, and tell the capture

' buffer to start recording

CreateCaptureBuffer()

applicationBuffer.Start(True)

Else

' Stop the capture and read any data that

' was not caught by a notification

If Nothing Is applicationBuffer Then

Return

End If

' Stop the buffer, and read any data that was not

' caught by a notification

applicationBuffer.Stop()

RecordCapturedData()

Writer.Seek(4, SeekOrigin.Begin) ' Seek to the length descriptor of the RIFF file.

Writer.Write(CInt(SampleCount + 36)) ' Write the file length, minus first 8 bytes of RIFF description.

Writer.Seek(40, SeekOrigin.Begin) ' Seek to the data length descriptor of the RIFF file.

Writer.Write(SampleCount) ' Write the length of the sample data in bytes.

Writer.Close() ' Close the file now.

Writer = Nothing ' Set the writer to null.

WaveFile = Nothing ' Set the FileStream to null.

End If

End Sub 'StartOrStopRecord

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

CreateRIFF()

StartOrStopRecord(True)

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

StartOrStopRecord(False)

End Sub

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

DevPlay.SetCooperativeLevel(Me, CooperativeLevel.Priority)

BufPlay = New SecondaryBuffer(TextBox1.Text, DevPlay)

BufPlay.Play(0, BufferPlayFlags.Default)

End Sub

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

BufPlay.Stop()

BufPlay.Dispose()

End Sub

Private Sub MainForm_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

If Not Nothing Is NotificationEvent Then

NotificationEvent.Set()

End If

If Not Nothing Is applicationBuffer Then

If applicationBuffer.Capturing Then

StartOrStopRecord(False)

End If

End If

End

End Sub 'MainForm_Closing

End Class

=======================================

OK DirectSound最后的部分写完了.总体感觉微软的封装还是有道理的

既要体现出易用性,而且还要充分发挥硬件的能力.如果你觉得某些特性用不到(很多其实都用不到)

你可以自己在DirectSound的基础上制作自己的声效引擎方便自己使用.

现在也存在不少优秀的声效引擎(在模拟器里面经常见到),至于是否自己开发,就要看你的兴趣了

如果您对DirectSound感兴趣,可以来我的Blog或者留言版发表看法.

http://Blog.csdn.net/a11s

下一个目标,托管的DirectPlay

(可能跟DSound中间插入DDraw一样,DPlay的时候顺便搞定DInput)

==========End DirectSound 9==================

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有