主要是想请兄弟把此程序的基本原理讲一下(特别是缓存那块 我不明白)由于篇幅问题 窗体声明部分代码我省掉了 回调函数和指针名称等请引用代码源名称 越详细越好 还有接下来想做数据传输 实现语音通讯 请各位高手给点建议 谢谢大家!
源代码如下:
Option ExplicitPublic Const BUF_SIZE = 327680
Public Const SAMPLES = 22050&
Public Const BITS = 16
Public Const CHANNEL = 1Public Const WIM_OPEN = &H1
Public Const WIM_CLOSE = &H2
Public Const WIM_DATA = &H3
Public Const WOM_OPEN = &H4
Public Const WOM_CLOSE = &H5
Public Const WOM_DONE = &H6
Private hWaveIn As Long
Private hWaveOut As Long
Private inHdr As WAVEHDRw
Private outHdr As WAVEHDR
Private WavInFmt As WAVEFORMAT
Private WavOutFmt As WAVEFORMAT
Private hMemIn As Long
Private hMemOut As Long
Private prevWndProc As Long
Private DesthWnd As LongPublic Sub RegisterWinProc(ByVal hWnd As Long)
prevWndProc = GetWindowLong(hWnd, GWL_WNDPROC) '取得一个指定窗口的窗口地址 并赋值给prevWndProc
SetWindowLong hWnd, GWL_WNDPROC, AddressOf WndProc
DesthWnd = hWndEnd SubPublic Sub UnRegisterWinProc(ByVal hWnd As Long)
SetWindowLong hWnd, GWL_WNDPROC, prevWndProcEnd SubFunction WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'If (Msg = WM_USER) Then
' Select Case wParam
' Case WIM_OPEN
' MsgBox "WaveInOpen ok."
' Case WIM_CLOSE
' MsgBox "WaveInClose ok."
' Case WIM_DATA
' MsgBox "Buffer full."
' Case WOM_OPEN
' MsgBox "WaveOutOpen ok."
' Case WOM_CLOSE
' MsgBox "WaveOutClose ok."
' Case WOM_DONE
' MsgBox "Data sent."
' End Select
'End IfSelect Case Msg
Case MM_WIM_DATA
MsgBox "Buffer full."
outHdr.lpData = inHdr.lpData
Case MM_WIM_OPEN
' MsgBox "WaveInOpen ok."
Case MM_WIM_CLOSE
' MsgBox "WaveInClose ok."
Case MM_WOM_DONE
MsgBox "Playback finished."
Case MM_WOM_OPEN
' MsgBox "WaveOutOpen ok."
Case MM_WOM_CLOSE
' MsgBox "WaveOutClose ok."
End SelectWndProc = CallWindowProc(prevWndProc, hWnd, Msg, wParam, lParam)
End FunctionPublic Function MywaveInProc(ByVal hwi As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long) As Long
Select Case (uMsg)
Case MM_WIM_DATA
' PostMessage DesthWnd, WM_USER, WIM_DATA, 0
Case MM_WIM_OPEN
' PostMessage DesthWnd, WM_USER, WIM_OPEN, 0
Case MM_WIM_CLOSE
' PostMessage DesthWnd, WM_USER, WIM_CLOSE, 0
End SelectEnd FunctionPublic Function MywaveOutProc(ByVal hwo As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long) As Long
Select Case (uMsg)
Case MM_WOM_DONE
' PostMessage DesthWnd, WM_USER, WOM_DONE, 0
Case MM_WOM_OPEN
' PostMessage DesthWnd, WM_USER, WOM_OPEN, 0
Case MM_WOM_CLOSE
' PostMessage DesthWnd, WM_USER, WOM_CLOSE, 0
End SelectEnd FunctionPublic Sub WaveInInit(ByVal nCh As Integer, ByVal Sample As Long, ByVal nBits As Integer)
Dim ret As Long
Dim Msg As String * 200
WavInFmt.wFormatTag = WAVE_FORMAT_PCM
WavInFmt.nChannels = nCh
WavInFmt.nSamplesPerSec = Sample
WavInFmt.nBlockAlign = nBits * nCh / 8
WavInFmt.wBitsPerSample = nBits
WavInFmt.cbSize = 0
WavInFmt.nAvgBytesPerSec = nBits * Sample * nCh / 8
ret = waveInOpen(hWaveIn, WAVE_MAPPER, WavInFmt, DesthWnd, 0, CALLBACK_WINDOW) 'AddressOf MywaveInProc, 0, CALLBACK_FUNCTION)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInOpen:" & Msg
Exit Sub
End If
hMemIn = GlobalAlloc(GMEM_MOVEABLE + GMEM_SHARE + GMEM_ZEROINIT, BUF_SIZE)
inHdr.lpData = GlobalLock(hMemIn)
inHdr.dwBufferLength = BUF_SIZE
inHdr.dwFlags = 0
inHdr.dwLoops = 0
inHdr.dwUser = 0
ret = waveInPrepareHeader(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInPrepareHeader" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveInRecord()
Dim ret As Long
Dim Msg As String * 200
ret = waveInAddBuffer(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInAddBuffer" & Msg
Exit Sub
End If
ret = WaveInStart(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInAddBuffer" & Msg
Exit Sub
End IfEnd Sub
Public Sub WaveInDeinit()
Dim ret As Long
Dim Msg As String * 200
ret = waveInStop(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInStop" & Msg
Exit Sub
End If
ret = waveInReset(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInReset" & Msg
Exit Sub
End If
ret = waveInUnprepareHeader(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInUnprepareHeader" & Msg
Exit Sub
End If
GlobalUnlock hMemIn
GlobalFree hMemIn
ret = waveInClose(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInClose" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveOutInit(ByVal nCh As Integer, ByVal Sample As Long, ByVal nBits As Integer)
Dim ret As Long
Dim Msg As String * 200
WavOutFmt.wFormatTag = WAVE_FORMAT_PCM
WavOutFmt.nChannels = nCh
WavOutFmt.nSamplesPerSec = Sample
WavOutFmt.nBlockAlign = nBits * nCh / 8
WavOutFmt.wBitsPerSample = nBits
WavOutFmt.cbSize = 0
WavOutFmt.nAvgBytesPerSec = nBits * Sample * nCh / 8
ret = waveOutOpen(hWaveOut, WAVE_MAPPER, WavOutFmt, DesthWnd, 0, CALLBACK_WINDOW) ' AddressOf MywaveOutProc, 0, CALLBACK_FUNCTION)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutOpen:" & Msg
Exit Sub
End If
hMemOut = GlobalAlloc(GMEM_MOVEABLE + GMEM_SHARE + GMEM_ZEROINIT, BUF_SIZE)
outHdr.lpData = GlobalLock(hMemOut)
outHdr.dwBufferLength = BUF_SIZE
outHdr.dwFlags = 0
outHdr.dwLoops = 0
outHdr.dwUser = 0
ret = waveOutPrepareHeader(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutPrepareHeader" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveOutPlayback()
Dim ret As Long
Dim Msg As String * 200ret = waveOutWrite(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutWrite" & Msg
Exit Sub
End IfEnd Sub
Public Sub WaveOutDeinit()
Dim ret As Long
Dim Msg As String * 200
ret = waveOutReset(hWaveOut)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutReset" & Msg
Exit Sub
End If
ret = waveOutUnprepareHeader(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutUnprepareHeader" & Msg
Exit Sub
End If
GlobalUnlock hMemOut
GlobalFree hMemOut
ret = waveOutClose(hWaveOut)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutClose" & Msg
Exit Sub
End IfEnd Sub
源代码如下:
Option ExplicitPublic Const BUF_SIZE = 327680
Public Const SAMPLES = 22050&
Public Const BITS = 16
Public Const CHANNEL = 1Public Const WIM_OPEN = &H1
Public Const WIM_CLOSE = &H2
Public Const WIM_DATA = &H3
Public Const WOM_OPEN = &H4
Public Const WOM_CLOSE = &H5
Public Const WOM_DONE = &H6
Private hWaveIn As Long
Private hWaveOut As Long
Private inHdr As WAVEHDRw
Private outHdr As WAVEHDR
Private WavInFmt As WAVEFORMAT
Private WavOutFmt As WAVEFORMAT
Private hMemIn As Long
Private hMemOut As Long
Private prevWndProc As Long
Private DesthWnd As LongPublic Sub RegisterWinProc(ByVal hWnd As Long)
prevWndProc = GetWindowLong(hWnd, GWL_WNDPROC) '取得一个指定窗口的窗口地址 并赋值给prevWndProc
SetWindowLong hWnd, GWL_WNDPROC, AddressOf WndProc
DesthWnd = hWndEnd SubPublic Sub UnRegisterWinProc(ByVal hWnd As Long)
SetWindowLong hWnd, GWL_WNDPROC, prevWndProcEnd SubFunction WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'If (Msg = WM_USER) Then
' Select Case wParam
' Case WIM_OPEN
' MsgBox "WaveInOpen ok."
' Case WIM_CLOSE
' MsgBox "WaveInClose ok."
' Case WIM_DATA
' MsgBox "Buffer full."
' Case WOM_OPEN
' MsgBox "WaveOutOpen ok."
' Case WOM_CLOSE
' MsgBox "WaveOutClose ok."
' Case WOM_DONE
' MsgBox "Data sent."
' End Select
'End IfSelect Case Msg
Case MM_WIM_DATA
MsgBox "Buffer full."
outHdr.lpData = inHdr.lpData
Case MM_WIM_OPEN
' MsgBox "WaveInOpen ok."
Case MM_WIM_CLOSE
' MsgBox "WaveInClose ok."
Case MM_WOM_DONE
MsgBox "Playback finished."
Case MM_WOM_OPEN
' MsgBox "WaveOutOpen ok."
Case MM_WOM_CLOSE
' MsgBox "WaveOutClose ok."
End SelectWndProc = CallWindowProc(prevWndProc, hWnd, Msg, wParam, lParam)
End FunctionPublic Function MywaveInProc(ByVal hwi As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long) As Long
Select Case (uMsg)
Case MM_WIM_DATA
' PostMessage DesthWnd, WM_USER, WIM_DATA, 0
Case MM_WIM_OPEN
' PostMessage DesthWnd, WM_USER, WIM_OPEN, 0
Case MM_WIM_CLOSE
' PostMessage DesthWnd, WM_USER, WIM_CLOSE, 0
End SelectEnd FunctionPublic Function MywaveOutProc(ByVal hwo As Long, ByVal uMsg As Long, ByVal dwInstance As Long, ByRef hdr As WAVEHDR, ByVal dwParam2 As Long) As Long
Select Case (uMsg)
Case MM_WOM_DONE
' PostMessage DesthWnd, WM_USER, WOM_DONE, 0
Case MM_WOM_OPEN
' PostMessage DesthWnd, WM_USER, WOM_OPEN, 0
Case MM_WOM_CLOSE
' PostMessage DesthWnd, WM_USER, WOM_CLOSE, 0
End SelectEnd FunctionPublic Sub WaveInInit(ByVal nCh As Integer, ByVal Sample As Long, ByVal nBits As Integer)
Dim ret As Long
Dim Msg As String * 200
WavInFmt.wFormatTag = WAVE_FORMAT_PCM
WavInFmt.nChannels = nCh
WavInFmt.nSamplesPerSec = Sample
WavInFmt.nBlockAlign = nBits * nCh / 8
WavInFmt.wBitsPerSample = nBits
WavInFmt.cbSize = 0
WavInFmt.nAvgBytesPerSec = nBits * Sample * nCh / 8
ret = waveInOpen(hWaveIn, WAVE_MAPPER, WavInFmt, DesthWnd, 0, CALLBACK_WINDOW) 'AddressOf MywaveInProc, 0, CALLBACK_FUNCTION)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInOpen:" & Msg
Exit Sub
End If
hMemIn = GlobalAlloc(GMEM_MOVEABLE + GMEM_SHARE + GMEM_ZEROINIT, BUF_SIZE)
inHdr.lpData = GlobalLock(hMemIn)
inHdr.dwBufferLength = BUF_SIZE
inHdr.dwFlags = 0
inHdr.dwLoops = 0
inHdr.dwUser = 0
ret = waveInPrepareHeader(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInPrepareHeader" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveInRecord()
Dim ret As Long
Dim Msg As String * 200
ret = waveInAddBuffer(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInAddBuffer" & Msg
Exit Sub
End If
ret = WaveInStart(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInAddBuffer" & Msg
Exit Sub
End IfEnd Sub
Public Sub WaveInDeinit()
Dim ret As Long
Dim Msg As String * 200
ret = waveInStop(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInStop" & Msg
Exit Sub
End If
ret = waveInReset(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInReset" & Msg
Exit Sub
End If
ret = waveInUnprepareHeader(hWaveIn, inHdr, Len(inHdr))
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInUnprepareHeader" & Msg
Exit Sub
End If
GlobalUnlock hMemIn
GlobalFree hMemIn
ret = waveInClose(hWaveIn)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInClose" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveOutInit(ByVal nCh As Integer, ByVal Sample As Long, ByVal nBits As Integer)
Dim ret As Long
Dim Msg As String * 200
WavOutFmt.wFormatTag = WAVE_FORMAT_PCM
WavOutFmt.nChannels = nCh
WavOutFmt.nSamplesPerSec = Sample
WavOutFmt.nBlockAlign = nBits * nCh / 8
WavOutFmt.wBitsPerSample = nBits
WavOutFmt.cbSize = 0
WavOutFmt.nAvgBytesPerSec = nBits * Sample * nCh / 8
ret = waveOutOpen(hWaveOut, WAVE_MAPPER, WavOutFmt, DesthWnd, 0, CALLBACK_WINDOW) ' AddressOf MywaveOutProc, 0, CALLBACK_FUNCTION)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutOpen:" & Msg
Exit Sub
End If
hMemOut = GlobalAlloc(GMEM_MOVEABLE + GMEM_SHARE + GMEM_ZEROINIT, BUF_SIZE)
outHdr.lpData = GlobalLock(hMemOut)
outHdr.dwBufferLength = BUF_SIZE
outHdr.dwFlags = 0
outHdr.dwLoops = 0
outHdr.dwUser = 0
ret = waveOutPrepareHeader(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutPrepareHeader" & Msg
Exit Sub
End IfEnd SubPublic Sub WaveOutPlayback()
Dim ret As Long
Dim Msg As String * 200ret = waveOutWrite(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutWrite" & Msg
Exit Sub
End IfEnd Sub
Public Sub WaveOutDeinit()
Dim ret As Long
Dim Msg As String * 200
ret = waveOutReset(hWaveOut)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutReset" & Msg
Exit Sub
End If
ret = waveOutUnprepareHeader(hWaveOut, outHdr, Len(outHdr))
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutUnprepareHeader" & Msg
Exit Sub
End If
GlobalUnlock hMemOut
GlobalFree hMemOut
ret = waveOutClose(hWaveOut)
If ret <> 0 Then
waveOutGetErrorText ret, Msg, Len(Msg)
MsgBox "waveOutClose" & Msg
Exit Sub
End IfEnd Sub
Public hWaveIn As Long
Public WavInFmt As WAVEFORMAT'录音缓冲
Public Const WaveInMaxQueen = 8
Public hMemInBuffer(BUF_SIZE, WaveInMaxQueen - 1) As Byte
Public inHdrArray(WaveInMaxQueen - 1) As WAVEHDR
Public currWavInHdr As Integer, lastWavInHdr As Integer, nextWavInHdr As IntegerPublic Recording As Boolean
Public Function WndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case Msg
Case MM_WIM_DATA
waveInUnprepareHeader hWaveIn, inHdrArray(currWavInHdr), Len(inHdrArray(0))
CopyMemory WavRecordData(0), hMemInBuffer(0, currWavInHdr), BUF_SIZE + 1
'可以先定义一个WavRecordData(), 这样拷贝过去的就是录音获取到的数据
nextWavInHdr = (currWavInHdr - 1 + WaveInMaxQueen) Mod WaveInMaxQueen
currWavInHdr = (currWavInHdr + 1) Mod WaveInMaxQueen
'注:这里的计算方式我大致觉得就是队列,但这是网上别人的计算放大,就沿用了
If Recording Then
inHdrArray(nextWavInHdr).dwFlags = 0
inHdrArray(nextWavInHdr).dwLoops = 0
waveInPrepareHeader hWaveIn, inHdrArray(nextWavInHdr), Len(inHdrArray(0))
waveInAddBuffer hWaveIn, inHdrArray(nextWavInHdr), Len(inHdrArray(0))
End If
。Public Sub WaveInInit(ByVal nCh As Integer, ByVal Sample As Long, ByVal nBits As Integer)
Dim ret As Long
Dim Msg As String * 200
Dim wIndex As Integer
WavInFmt.wFormatTag = WAVE_FORMAT_PCM
WavInFmt.nChannels = nCh
WavInFmt.nSamplesPerSec = Sample
WavInFmt.nBlockAlign = nBits * nCh / 8
WavInFmt.wBitsPerSample = nBits
WavInFmt.cbSize = 0
WavInFmt.nAvgBytesPerSec = nBits * Sample * nCh / 8
ret = waveInOpen(hWaveIn, WAVE_MAPPER, WavInFmt, DesthWnd, 0, CALLBACK_WINDOW)
If ret <> 0 Then
waveInGetErrorText ret, Msg, Len(Msg)
MsgBox "waveInOpen:" & Msg
Exit Sub
End If'初始化多缓冲区
For wIndex = 0 To WaveInMaxQueen - 1
inHdrArray(wIndex).dwFlags = 0
inHdrArray(wIndex).dwLoops = 0
inHdrArray(wIndex).dwBytesRecorded = 0
inHdrArray(wIndex).dwUser = 0
inHdrArray(wIndex).dwBufferLength = BUF_SIZE + 1
inHdrArray(wIndex).lpData = VarPtr(hMemInBuffer(0, wIndex))
Next wIndex
For wIndex = 0 To WaveInMaxQueen - 2
waveInPrepareHeader hWaveIn, inHdrArray(wIndex), Len(inHdrArray(0))
waveInAddBuffer hWaveIn, inHdrArray(wIndex), Len(inHdrArray(0))
Next wIndex
currWavInHdr = 0
nextWavInHdr = 0End Sub
**********************************************************
实时录音并显示波形、频谱 本文讲述如何实时录音,以及将录音波形频谱实时显示的方法。Windows提供了一个多媒体控制接口(MCI),用它可以录音,很方便。但是这种方法不能实时给出录音的原始数据,因此要显示波形和频谱都是不可能实现的。要达到实时的效果,就要使用Windows提供的另一套函数,即低级音频函数。其中和录音有关的是以waveIn开头的一组函数。 低级音频函数的使用比较繁琐,大致要有以下几个步骤。 用waveInOpen打开设备,并设置回调。因为要保证实时性,所以不能用查询的方式,而必须设置回调。
为设备分配足够的内存做缓冲区,动态分配或静态数组都可以。为了保证实时性,程序用了双缓冲技术,在处理一个缓冲区数据的同时另一个缓冲区用于录音。为了便于说明写成Buffer1、Buffer2。
将Buffer1关联到设备上去,waveInPrepareBuffer、waveInAddBuffer。
开始录音,waveInStart
当驱动程序填满这个缓冲区(Buffer1)时就会产生回调(消息为WIM_DATA),这时立刻将Buffer2关联到设备上继续录音,然后处理Buffer1,当驱动程序填满Buffer2时又会产生回调,这是再将Buffer1关联到设备上,而去处理Buffer2,如此反复就使得录音能够实时的进行下去。
停止录音,waveInStop
关闭设备,waveInClose
上面就是实时录音的一个基本流程,产生回调时,其lParam就是一个指向WAVEHDR结构的指针,通过这个指针就可以得到原始数据(注意了:我这个程序只是单声道8位的PCM格式,因此正好一个字节就是一个采样点的值,对于其他格式的我就不知道了)。有了原始数据就可以很容易的画出波形了,而频谱也就是多一次FFT变换而已,没什么太难的。 这里是我用LCC写的例子,非常简单,而且相信大家都可以很容易的移植到BCB上来。另外,我偷了一下懒,FFT用了我以前封装到DLL中的函数(现在已经忘了怎么写了^_^),可以在此下载 (不要觉得奇怪,就是这个时钟,将其中的DEMO.DLL拿来用就是了)。当然你也可以自己写一个FFT放到程序里去。-*-*-PATCH-*-*-2002-06-11 上次那个程序还不好,原因是双缓冲还不能满足实时的要求,因此这次用了8缓冲循环技术。新的程序也是用LCC写的。
开始时依次将0-6号缓冲区关联到设备上,而7号缓冲区不关联,然后开始录音,这是驱动程序开始向0号缓冲区输出数据,当0号缓冲区数据满时产生回调,这时驱动程序会自动向1号缓冲区输出数据,但这时应将7号缓冲区关联到设备上去,然后处理0号缓冲区的数据。然后当1号缓冲区数据满时又会产生回调,这时驱动程序会自动向2号缓冲区输出数据,而将0号缓冲区关联到设备上去。这样如此反复,始终保持1个缓冲区用于驱动输出数据,1个缓冲区用于处理数据,6个缓冲区处于等待状态。
而如果只有两个缓冲区,就只能一个用于驱动输出,一个用于处理数据。这样在产生回调的时候就会出现没有处于等待状态的缓冲区的情况,这样驱动程序就不能自动向缓冲区输出数据。而要等waveInPrepareBuffer、waveInAddBuffer调用之后,这样就会出现一个小小的间隙,而导致录音不连续。-*-*-PATCH-*-*-2002-06-11 只是我的个人观点,有什么不对的地方,还望指教。-*-*-PATCH-*-*-2003-04-07 程序中有一个错误,在WIM_DATA的处理过程里。 case WIM_DATA:
waveInUnprepareHeader(hwi,pwhi,sizeof(WAVEHDR));//释放错误。
nextWavHdr=(currWavHdr-1+MAX_INQUEU)%MAX_INQUEU;
currWavHdr=(currWavHdr+1)%MAX_INQUEU;
if(b_playing)
{
pwhi=&whis[nextWavHdr];
pwhi->dwFlags=0;
pwhi->dwLoops=0;
waveInPrepareHeader(hwi,pwhi,sizeof(WAVEHDR));
waveInAddBuffer(hwi,pwhi,sizeof(WAVEHDR));
}当0号缓冲区数据满时,应该释放0号句柄。这第一次是对的,但是第二次当1号缓冲满的时候,程序却释放了7号句柄。这里是错的,解决方法就是计算正确的句柄号。或者,
waveInUnprepareHeader(hwi,LPWAVEHDR(lParam),sizeof(WAVEHDR)); 这样就可以了,感谢flinming发现这个问题。 另外,《网络语音传输》中的程序也有这个问题,请大家自己改吧。-*-*-PATCH-*-*-2003-04-07
我是五一前盯上这个技术,本来只是想做一个语音的音量电平指示,就像很多录音软件那样,后来发现并不是很好做,搜索引擎都馊翻了,资料少得可怜,大多说用peakmeter,说微软有例子,事实上找不到,而且peakmeter根本不行,发了封mail给waveCN的作者(著名国产录音软件),很快得到回复说是边录边分析其中的数据,这里很感谢waveCN。后来慢慢找到一些关于WaveIn API的资料,google里发现一些论坛形式的帖子,原来就是CSDN的社区,再一搜,得到一些很好的经验,特别是512字节的缓冲,上边说收的时候缓冲两个数据就能放了。但是我觉得我如果要作网络传输,压缩和考虑网络带宽是一个重要的问题。据说ITU的G792压缩很好,但是原码是c,不精通的,没办法。。