Отлично с этим справляется следующий код:
- Код: Выделить всё
Imports System.Runtime.InteropServices
Public Class Form1
Private Const CALLBACK_FUNCTION = &H30000L
Private Const MM_WIM_DATA = &H3C0
Private Structure WAVEFORMATEX
Dim wFormatTag As Int16
Dim nChannels As Int16
Dim nSamplesPerSec As Int32
Dim nAvgBytesPerSec As Int32
Dim nBlockAlign As Int16
Dim wBitsPerSample As Int16
Dim cbSize As Int16
Sub New(ByVal sample As Int32)
cbSize = Marshal.SizeOf(Me)
wFormatTag = 1 : nChannels = 1 : nBlockAlign = 1
wBitsPerSample = 8 : nSamplesPerSec = sample : nAvgBytesPerSec = sample
End Sub
End Structure
Private Structure WAVEHDR
Dim lpData As IntPtr
Dim dwBufferLength As Int32
Dim dwBytesRecorded As Int32
Dim dwUser As IntPtr
Dim dwFlags As Int32
Dim dwLoops As Int32
Dim lpNext As IntPtr
Dim reserved As IntPtr
Sub New(ByVal sz As Int32)
lpData = Marshal.AllocHGlobal(sz)
dwBufferLength = sz
End Sub
Sub Free()
Marshal.FreeHGlobal(lpData)
End Sub
End Structure
Private Structure MyTag
Dim hwav As IntPtr
Dim hhdr As IntPtr
Dim szhdr As Integer
End Structure
Private MT As MyTag
Private Delegate Sub ProgrValDeleg(ByVal peakvol As Byte)
Private Delegate Sub PtrwaveInProc(ByVal phwi As IntPtr, ByVal uMsg As Int32, ByVal dwInstance As Int32, ByVal dwParam1 As Int32, ByVal dwParam2 As Int32)
Private Declare Function waveInOpen Lib "winmm" (ByRef phwi As IntPtr, ByVal uDeviceID As Int32, ByRef pwfx As WAVEFORMATEX, ByVal dwCallback As PtrwaveInProc, ByVal dwInstance As Int32, ByVal fdwOpen As Int32) As Int32
Private Declare Function waveInClose Lib "winmm" (ByVal phwi As IntPtr) As Int32
Private Declare Function waveInPrepareHeader Lib "winmm" (ByVal phwi As IntPtr, ByVal pwh As IntPtr, ByVal cbwh As Int32) As Int32
Private Declare Function waveInUnprepareHeader Lib "winmm" (ByVal phwi As IntPtr, ByVal pwh As IntPtr, ByVal cbwh As Int32) As Int32
Private Declare Function waveInAddBuffer Lib "winmm" (ByVal phwi As IntPtr, ByVal pwh As IntPtr, ByVal cbwh As Int32) As Int32
Private Declare Function waveInStart Lib "winmm" (ByVal phwi As IntPtr) As Int32
Private Declare Function waveInStop Lib "winmm" (ByVal phwi As IntPtr) As Int32
Private Sub Form1_HandleCreated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.HandleCreated
MicOpen()
End Sub
Private Sub Form1_HandleDestroyed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.HandleDestroyed
MicClose()
End Sub
Private Sub MicOpen()
MT.szhdr = Marshal.SizeOf(New WAVEHDR)
MT.hhdr = Marshal.AllocHGlobal(MT.szhdr)
Marshal.StructureToPtr(New WAVEHDR(512), MT.hhdr, False)
waveInOpen(MT.hwav, -1, New WAVEFORMATEX(4096), AddressOf waveInProc, 0, CALLBACK_FUNCTION)
waveInPrepareHeader(MT.hwav, MT.hhdr, MT.szhdr)
waveInAddBuffer(MT.hwav, MT.hhdr, MT.szhdr)
waveInStart(MT.hwav)
End Sub
Private Sub MicClose()
Dim whdr As WAVEHDR = Marshal.PtrToStructure(MT.hhdr, GetType(WAVEHDR))
waveInUnprepareHeader(MT.hwav, MT.hhdr, MT.szhdr)
waveInStop(MT.hwav)
waveInClose(MT.hwav)
whdr.Free()
Marshal.FreeHGlobal(MT.hhdr)
End Sub
Private Sub waveInProc(ByVal hwi As IntPtr, ByVal uMsg As Int32, ByVal dwInstance As Int32, ByVal dwParam1 As Int32, ByVal dwParam2 As Int32)
If MM_WIM_DATA <> uMsg Then Return
Dim whdr As WAVEHDR = Marshal.PtrToStructure(New IntPtr(dwParam1), GetType(WAVEHDR))
Dim currvol As Integer, mastervol As Byte
For i As Int32 = 0 To whdr.dwBytesRecorded - 1
currvol = Math.Abs(Marshal.ReadByte(whdr.lpData, i)) - 127
If (currvol > mastervol) Then mastervol = currvol
Next
On Error Resume Next
Invoke(New ProgrValDeleg(AddressOf PeakMeterProc), New Object() {mastervol})' тут возникает делема
waveInAddBuffer(hwi, New IntPtr(dwParam1), Marshal.SizeOf(whdr))
End Sub
Private Sub PeakMeterProc(ByVal peakvol As Byte)
Static prgrsbar As New ProgressBar
Controls.Add(prgrsbar)
prgrsbar.Minimum = 0
prgrsbar.Maximum = 16
If peakvol < 5 Then peakvol = 0
prgrsbar.Value = peakvol / 8
'TextBox1.Text = (peakvol / 8)
End Sub
End Class
в последнем Sub PeakMeterProc я решил вывести визуально, помимо прогрессбара, текстовое поле со значением уровня
всё просто здорово, но...
но при простое выдает ошибку:
Был произведен обратный вызов делегата типа "WindowsApplication1!WindowsApplication1.Form1+PtrwaveInProc::Invoke", полученного сборщиком мусора. Это может привести к сбоям приложения, а также к повреждению или утрате данных. При передаче делегатов в неуправляемый код управляемое приложение должно поддерживать их существование, пока не будет гарантировано, что они больше никогда не будут вызваны.
TextBox1.Text = (mastervol).tostring пытался разместить в Private Sub waveInProc результат нулевой, как организовать получение уровня сигнала в постоянном - бесконечном прослушивание входа, советовали nAudio библиотеку но не одного вменяемого примера не нашел, любой вариант подойдет