Sei sulla pagina 1di 15

Deteccion de Sonido Con Vb.

Net
abril 16, 2012 ingsistele Programacion en .Net

Un detector de sonido es una practica aplicacion que se puede


realizar implementando un microfono para determinar cualquier
tipo de ruido que se produzca y posteriormente realizar cualquier
actividad especifica al escuchar dicho sonido, existen dispositivos
electronicos especializados para realizar dicha labor, sin embargo,
en este tutorial se va a explicar una forma alternativa de llevarlo
acabo con nuestro computador.
para poder realizar esta aplicacion, vamos a hacer uso de la
transformada rapida de fourier y de varias clases que nos permiten
capturar la entrada de audio, generar la onda y determinar el
umbral de aproximacion de la onda a partir del cual se decidira si
existe sonido o no.
La aplicacion tendra la siguiente interfaz:
Bien amigos, para comenzar debo aclara que para la realizacion de
este software me he basado en varias aplicaciones que he
conseguido util, como son:
Grabador y activador de sonido con c# y Visualizador de sonido en
c# ambos alojados en la pagina web CodeProject.
Ahora elaboramos una presentacion como la siguiente en vb:
aqui, agregamos 1 picturebox, 2 botones, 1 TrackBar para graduar la
sensibilidad de la captura de audio, 1 groupbox, 2 textbox y varios
labels, se puede personalizar al gusto con otros picturebox tal y
como se ve en la anterior imagen.
Bien, acontinuacion es necesario crear las siguientes clases:
* WaveOut.vb para procesar y presentar la salida del audio
capturado.
* WaveNative.vb Para realizar operaciones en el core con la
tarjeta de audio.
* WaveIn.vb Encargada de procesar el audio que esta entrando
por el microfono.
* SignalGenerator.vb Para crear la onda y si se desea se puede
variar la forma de la onda por sinusoidal, triangular, cuadrada, etc.
* FourierTransform.vb que es la que recibe la onda auditiva y la
transforma en una descomposición en distintas frecuencias,
* FifoStream.vb Para procesar el flujo de entrada y salida,
* AudioFrame.vb para realizar gran parte de la deteccion del
audio y personalizar las graficas.
Sabiendo ya las clases que vamos a necesitar, podemos proceder a
codificar nuestro proyecto, en esta ocasion, solo voy escribir un
fragmento de la clase AudioFrame ya que es la que vamos a
utilizar en gran manera para interactuar con los elementos del
formulario y es la que se encarga de determinar si hay sonido o no.
En Dicho fragmento se estudiara solamente la subrutina proccess,
tal y como se ve a continuacion:
Clase AudioFrame.vb:
1 Imports System.Drawing
2
3 Imports System.Windows.Forms
4
5 Namespace detector_de_sonido
6
Class AudioFrame
7
8 Private _canvasTimeDomain As Bitmap
9
10 Private _canvasFrequencyDomain As Bitmap
11
12 Private _waveLeft As Double()
13
14 Private _waveRight As Double()
15
Private _fftLeft As Double()
16
17 Private _fftRight As Double()
18
19 Private _signalGenerator As SignalGenerator
20
21 Private _isTest As Boolean = False
22
23 Public IsEventActive As Boolean = False
24
25 Public IsDetectingEvents As Boolean = False
26
Public AmplitudeThreshold As Integer
27
28 'valor original de la amplitud=16384
29
30 Public Sub New(ByVal isTest As Boolean)
31
32 _isTest = isTest
33
34 End Sub
35
36 Public Sub Process(ByRef wave As Byte())
37
38 IsEventActive = False
39
_waveLeft = New Double(wave.Length \ 4 - 1) {}
40
41 _waveRight = New Double(wave.Length \ 4 - 1) {}
42
43 If _isTest = False Then
44
45 ' Split out channels from sample
46
47 Dim h As Integer = 0
48
For i As Integer = 0 To wave.Length - 1 Step 4
49
50 _waveLeft(h) = CDbl(BitConverter.ToInt16(wave, i))
51
52 _waveRight(h) = CDbl(BitConverter.ToInt16(wave, i + 2))
53
54 If IsDetectingEvents = True Then
55
56 If _waveLeft(h) > AmplitudeThreshold OrElse _waveLeft(h) < -AmplitudeThreshold Then
57
58 IsEventActive = True
59
End If
60
61 End If
62
63 _waveRight(h) = CDbl(BitConverter.ToInt16(wave, i + 2))
64
65 If IsDetectingEvents = True Then
66
67 If _waveRight(h) > AmplitudeThreshold OrElse _waveRight(h) < -AmplitudeThreshold The
68
IsEventActive = True
69
70 End If
71
72 End If
73
74 h += 1
75
76 Next
77
78 End If
79
End Sub
80 End Class
81
82 End Namespace
83
84
85
86
87
88
89
90

las variables IsEventActive, e IsDetectingEvents son las encargadas


de controlar las interrupciones que determinan si existe algun
sonido, ademas la variable AmplitudeThreshold indica el umbral o
nivel maximo de la amplitud de la onda para determinar que ha
ocurrido algun evento o ha entrado algun sonido.
Como la entrada de un microfono es una señal estero en la mayoria
de los casos se realiza una comparacion con la onda izquierda que
representa la señal con la variable que establece el umbral y se hace
la misma comparacion nuevamente pero con la onda de la entrada
derecha, si la señal de entrada supera al umbral establecido
automaticamente se coloca la variable IsEventActive en true o activa
tal y como se puede observar en el fragmento de codigo de arriba
dentro del ciclo for.
Bien para poder continuar es necesario descargar todas las clases
que conforman el proyecto, por ello les coloco el siguiente link para
que encuentren la informacion completa de las clases: Bajar Clases
del Proyecto.
a continuacion pasemos a programar dentro del formulario:
Inicialmente importemos las siguientes librerias,
1 Imports System.Collections.Generic
2
Imports System.ComponentModel
3
4 Imports System.Data
5
6 Imports System.Drawing
7
8 Imports System.Text
9
10Imports System.Windows.Forms
11
12Imports Deteccion_de_Sonido.detector_de_sonido 'lleva el nombre de acuerdo al espacio de
13Imports System.Threading
14
15'-----------
16
17Imports System.Diagnostics.Process
18
19Imports System.IO.Path
20
21

Luego declaremos las siguientes variables como globales:


1
2
Private _recorder As WaveInRecorder
3
4 Private _recorderBuffer As Byte()
5
6 Private _player As WaveOutPlayer
7
8 Private _playerBuffer As Byte()
9
10 Private _stream As FifoStream
11
Private _waveFormat As WaveFormat
12
13 Private _audioFrame As AudioFrame
14
15 Private _audioSamplesPerSecond As Integer = 44100
16
17 Private _audioFrameSize As Integer = 16384
18
19 Private _audioBitsPerSample As Byte = 16
20
21 Private _audioChannels As Byte = 2
22
Private _isPlayer As Boolean = False
23
24 Private _isTest As Boolean = False
25
26 Dim contador_eventos As Integer
27
28 Dim indicador, i, sensibilidad, cant_proces As Integer
29
30 ' Creamos una variable del tipo Thread
31
Private hebra As Thread
32
33 Dim pList1() As Process
34
35

Ahora vamos a crear la funcion Start que es la encargada de iniciar


la entrada de audio por el microfono, hay que recordar que aqui en
esta funcion vamos a activar o colocar en true la variable
IsDetectingEvents para que se comience a comparar la señal de
audio que entra con el umbral establecido para la amplitud.
la funcion o porcedimiento start se observa a continuacion:
1
2
Private Sub Start()
3
4 Stop_sonido()
5
6 Try
7
8 _waveFormat = New WaveFormat(_audioFrameSize, _audioBitsPerSample, _audioChannels)
9
10_recorder = New WaveInRecorder(0, _waveFormat, _audioFrameSize * 2, 3, New BufferDoneEven
11
12If _isPlayer = True Then
13
_player = New WaveOutPlayer(-1, _waveFormat, _audioFrameSize * 2, 3, New BufferFillEventH
14
15End If
16
17textBox1.AppendText(DateTime.Now.ToString() & " : Dispositivo de Audio Inicializado" & vb
18
19textBox1.AppendText(DateTime.Now.ToString() & " : Dispositivo de Audio en Escucha" & vbCr
20
21textBox1.AppendText(DateTime.Now & " : Muestras Por Segundo = " & _audioSamplesPerSecond.
22
23textBox1.AppendText(DateTime.Now & " : Tamaño de la Trama = " & _audioFrameSize.ToString(
24textBox1.AppendText(DateTime.Now & " : Bits por Muestra = " & _audioBitsPerSample.ToStrin
25
26textBox1.AppendText(DateTime.Now & " : Canales = " & _audioChannels.ToString() & vbCr & v
27
28_audioFrame.IsDetectingEvents = True
29
30Catch ex As Exception
31
32textBox1.AppendText(DateTime.Now & " : Ha Ocurrido una excepcion con el Audio" & vbCr & v
33
End Try
34
35End Sub
36
37

Luego pasamos a crear la funcion stop_sonido que detiene la


entrada de audio y libera de la memoria el player o el procesamiento
de la onda
Sub Stop_sonido()
1
2 If _recorder IsNot Nothing Then
3
4 Try
5
6 _recorder.Dispose()
7
8 Finally
9
_recorder = Nothing
10
11 End Try
12
13 End If
14
15 If _isPlayer = True Then
16
17 If _player IsNot Nothing Then
18
Try
19
20 _player.Dispose()
21
22 Finally
23
24 _player = Nothing
25
26 End Try
27
28 End If
29
' clear all pending data
30
31 _stream.Flush()
32
33 End If
34
35 End Sub
36
37
38
39

Ahora, en el evento load del formulario colocamos lo siguiente:


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Hand
1
2 sensibilidad = 16384
3
4 CheckForIllegalCrossThreadCalls = False 'Desactiva error por subproceso
5
6 contador_eventos = 0
7
8 Me.Text_num_eventos.Text = 0
9
indicador = 0
10
11 i = 0
12
13 If WaveNative.waveInGetNumDevs() = 0 Then
14
15 TextBox1.AppendText(DateTime.Now.ToString() & " : El Dispositivo de Audio no se Encu
16
Else
17
18 If _isPlayer = True Then
19
20 _stream = New FifoStream()
21
22 End If
23
24 _audioFrame = New AudioFrame(_isTest)
25
_audioFrame.AmplitudeThreshold = sensibilidad
26
27 Start()
28
29 End If
30
31 pList1 = Process.GetProcesses()
32
33 cant_proces = pList1.Count
34
35 End Sub
36
37
38
39

La funcion Filler es la encargada de manejar el flujo de datos


capturados por el microfono y pasarla al player o visualizadores de
onda:
1 Private Sub Filler(ByVal data As IntPtr, ByVal size As Integer)
2
3 If _isPlayer = True Then
4
5 If _playerBuffer Is Nothing OrElse _playerBuffer.Length < size Then
6
7 _playerBuffer = New Byte(size - 1) {}
8
End If
9
10 If _stream.Length >= size Then
11
12 _stream.Read(_playerBuffer, 0, size)
13
14 Else
15
16 For i As Integer = 0 To _playerBuffer.Length - 1
17
_playerBuffer(i) = 0
18
19
20 Next
21
22 End If
23
System.Runtime.InteropServices.Marshal.Copy(_playerBuffer, 0, data, size)
24
25 End If
26
27 End Sub
28
29

Posteriormente pasamos a elaborar el procedimiento DataArrived


que es el que se encarga de procesar los datos que van de llegando o
saliento despues de haber evaluado la señal de la onda:
1 Private Sub DataArrived(ByVal data As IntPtr, ByVal size As Integer)
2
3 indicador = 0
4
5 Me.Button_sdetec.Text = "Sonido No Detectado"
6
Me.Button_sdetec.ForeColor = Color.Black
7
8 Me.Button_sdetec.BackColor = Color.LightGray
9
10 If _recorderBuffer Is Nothing OrElse _recorderBuffer.Length < size Then
11
12 _recorderBuffer = New Byte(size - 1) {}
13
14 End If
15
If _recorderBuffer IsNot Nothing Then
16
17 System.Runtime.InteropServices.Marshal.Copy(data, _recorderBuffer, 0, size)
18
19 If _isPlayer = True Then
20
21 _stream.Write(_recorderBuffer, 0, _recorderBuffer.Length)
22
23 End If
24
25 _audioFrame.Process(_recorderBuffer)
26
_audioFrame.RenderTimeDomain(pictureBox1)
27
28 '-------------------------------------------
29 If (_audioFrame.IsEventActive = True) Then
30
31 contador_eventos += 1
32
33 Me.Text_num_eventos.Text = contador_eventos
34
35 indicador = 1
36
37 Me.Button_sdetec.Text = "Sonido Detectado"
38
Me.Button_sdetec.ForeColor = Color.White
39
40 Me.Button_sdetec.BackColor = Color.Red
41
42 End If
43
44 End If
45
46 End Sub
47
48
49
50

Esta funcion es muy importante ya que aqui se determina si hay


algun sonido o no, la comparacion que establece el if
_audioFrame.IsEventActive = True permite realizar las operaciones
a desencadenar si se detecto algun sonido, como se puede ver alli, se
incrementa la variable contador, la variable indicador se coloca en 1
y el texto y color del boton se cambian.
para ir variando la sensibilidad de nuestro detector de sonido solo
basta con cambiar el valor del umbral de la amplitud, dicho proceso
se lleva a cabo cuando variamos la barra de desplazamiento del
trackbar:
1 Private Sub TrackBar_sensibilidad_Scroll(ByVal sender As System.Object, ByVal e As System.E
2
3 If (Me.TrackBar_sensibilidad.Value = 0) Then
4
sensibilidad = 16384
5
6 _audioFrame.AmplitudeThreshold = sensibilidad
7
8 End If
9
10If (Me.TrackBar_sensibilidad.Value = 1) Then
11
12sensibilidad = 15500
13
14_audioFrame.AmplitudeThreshold = sensibilidad
15End If
16
17If (Me.TrackBar_sensibilidad.Value = 2) Then
18
19sensibilidad = 9900
20
21_audioFrame.AmplitudeThreshold = sensibilidad
22
23End If
End Sub
24
25
26

por ultimo elaboramos el procedimiento cerrar_ventana que


permitira cerrar el formulario de manera segura, ya que el
proceimiento stop_sonido solo detiene la captura de audio y sin
embargo existe una saturacion de flujo de datos ya que el microfono
permanecio todo el tiempo en escucha y eso genera cierto bloqueo al
programa, por tal motivo se crea una funcion aparte para cerrar la
ventana, tal y como se ve a continuacion:
Sub cerrar_ventana()
1
2 Dim j, posi, encontro As Integer
3
4 Dim nomp As String
5
6 Dim vect() As String
7
8 encontro = 0
9
For j = 0 To cant_proces - 1
10
11 Try
12
13 nomp = pList1(j).ProcessName.ToString
14
15 vect = Split(nomp, ".")
16
17 If (vect(0) = "Deteccion de Sonido") Then
18
19 posi = j
20
encontro = 1
21
22 End If
23
24 Catch ex As Exception
25
26 End Try
27
28 Next
29
hebra.Abort()
30
31 If (encontro = 1) Then
32
33 pList1(posi).Kill()
34
35 End If
36
End Sub
37
38
39
40
41

Luego, en el boton salir colocamos lo siguiente para el correcto


cierre de la aplicacion:
1
Private Sub Button_salir_Click(ByVal sender As System.Object, ByVal e As System.EventArg
2
3 'crear objeto y asignarlo al sub que queremos ejecutar
4
5 hebra = New Thread(AddressOf Stop_sonido)
6
7 'ponemos al hilo en marcha
8
9 hebra.Start()
10
cerrar_ventana()
11
12 End Sub
13

Asi como en el evento formclosing de la aplicacion:


1
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormC
2
3 'crear objeto y asignarlo al sub que queremos ejecutar
4
5 hebra = New Thread(AddressOf Stop_sonido)
6
7 'ponemos al hilo en marcha
8
9 hebra.Start()
10
cerrar_ventana()
11
12End Sub
13

Bien por ultimo solo resta hacerle una prueba a la aplicacion, se


ejecuta y empezamos a hacer ruidos, nos podemos dar cuenta como
se observa la señal que esta entrando por el microfono y si ocurre
algun evento, inmediantamente el contador comienza a avanzar y el
botn que indica el sonido se coloca de color rojo tal y como se ve en
la siguiente imagen:

Bueno eso es todo amigos, espero y este tutorial les resulte de


utilidad, si desean descargar la aplicacion pueden hacer click sobre
el siguiente link: Descargar Aplicacion

Potrebbero piacerti anche