Documente Academic
Documente Profesional
Documente Cultură
Lo primero que debes hacer para poder capturar audio en tu computadora es configurar
el audio digital para grabar. ¿Y como haces eso?
Coloca como referencia del proyecto la librería Microsoft Scripting Runtime y agrega el
componente Microsoft Common Dialog Control 6.0. La primera la necesitamos para
poder manejar los archivos del sistema y la segunda para que el usuario pueda guardar
el archivo Wav donde el desee.
Texto planoImprimir
1. Declare Function mciSendString _
2. Lib "winmm.dll" _
3. Alias "mciSendStringA" ( _
4. ByVal lpstrCommand As String, _
5. ByVal lpstrReturnString As String, _
6. ByVal uReturnLength As Long, _
7. ByVal hwndCallback As Long) As Long
8.
9. Declare Function mciGetErrorString _
10. Lib "winmm.dll" _
11. Alias "mciGetErrorStringA" ( _
12. ByVal dwError As Long, _
13. ByVal lpstrBuffer As String, _
14. ByVal uLength As Long) As Long
Texto planoImprimir
1. Dim s, m As String
2. Dim x, minutos As Integer
Estas variables están asociadas al control Timer y nos van a permitir mostrar al usuario
cuando se esta grabando o reproduciendo un archivo Wav.
Texto planoImprimir
1. Dim Result As Long
2. Dim errormsg As Integer
3. Dim cadena As String * 1024
4. Dim CadenaError As String * 1024
5. Dim mssg As String * 255
6. Dim i As Long
7. Dim BlockAlign As Integer
8. Dim sBytes As String
Estas son nuestras variables de trabajo, donde se almacenaran los valores devueltos por
las funciones API mciSendString y mciGetErrorString.
Texto planoImprimir
1. Dim lBytes As Long
Así que esta variable la utilizaremos para calcular el lugar exacto donde se produce el
error de almacenamiento del archivo wav.
Texto planoImprimir
1. Dim s, m As String
2. Dim x, minutos As Integer
Estas variables las utilizaremos con un control Timer para llevar el tiempo de grabación
y reproducción.
Como te habrás dado cuenta en la ilustración del formulario todos los botones están
desactivados menos el de grabar. Vamos a programar el evento clic de este botón:
Texto planoImprimir
1. Private Sub CmdRec_Click()
2.
3. ' cierro todos los dispositivos que pueden estar abiertos
4. mciSendString "close all", 0, 0, 0
5.
6. Result = mciSendString("open new Type waveaudio Alias sonido", cadena, Le
n(cadena), 0)
7.
8. ' Muestro un mensaje si se produce algun error
9. If Not Result = 0 Then
10. errormsg = mciGetErrorString(Result, CadenaError, 1024)
11. MsgBox CadenaError, 0, "Error"
12. End If
13.
14. ' Determinamos el formato de tiempo en millisegundos
15. Result = mciSendString("set sonido time format ms", cadena, 1024, 0)
16.
17. ' Determínanos el formato pcm del archivo wav (Microsoft standard)
18. Result = mciSendString("set sonido format tag pcm", cadena, 1024, 0)
19.
20. ' Determinamos las propiedades de grabación con calidad CD
21. Result = mciSendString("set sonido channels 2", cadena, 1024, 0) ' dos canales
de audio
22. Result = mciSendString("set sonido samplespersec 44100", cadena, 1024, 0) ' T
aza de muestreo
23. Result = mciSendString("set sonido bitspersample 16", cadena, 1024, 0) ' Bits
por muestra
24.
25. ' Determinamos el tipo de alineamientos de los byte del archivo
26. BlockAlign = CInt((CLng(16) / 8) * CLng(2))
27. Result = mciSendString("set sonido alignment " & Str$(BlockAlign), cadena, 1
024, 0)
28.
29. ' Calculamos donde se da el error interno dentro del archivo a grabar
30. lBytes = CLng(2) * ((CLng(2) * CLng(16)) / 8)
31. sBytes = Str$(lBytes)
32.
33. CmdStop.Enabled = True
34. CmdRec.Enabled = False
35.
36. ' Empezamos a grabar
37. Result = mciSendString("record sonido", cadena, Len(cadena), 0)
38.
39. End Sub
Recuerda que ambas funciones API siempre retornan un valor y La calidad de sonido
CD comprende 2 canales de audio, una frecuencia de muestreo de 44100 Hz y se
almacena a una tasa de 16 bits.
Texto planoImprimir
1. Private Sub CmdPlay_Click()
2.
3. CmdStop.Enabled = True
4. CmdNext.Enabled = True
5. cmdPrev.Enabled = True
6. CmdRec.Enabled = False
7. CmdGuardar.Enabled = False
8. CmdPlay.Enabled = False
9.
10. Result = mciSendString("play sonido from 0", cadena, Len(cadena), 0)
11.
12. End Sub
Texto planoImprimir
1. Result = mciSendString("play sonido from 0", cadena, Len(cadena), 0)
Ahora se quieres rebobinarlos para revisar tu sonido, puedes programar el botón Previo
Texto planoImprimir
1. Private Sub cmdPrev_Click()
2. If CmdPlay.Enabled = False Then
3. Timer1.Enabled = False
4. x=0
5. minutos = 0
6. Result = mciSendString("stop sonido", cadena, Len(cadena), 0)
7. Timer1.Enabled = True
8. Result = mciSendString("play sonido from 0", cadena, Len(cadena), 0)
9. Else
10. CmdGuardar.Enabled = True
11. CmdRec.Enabled = True
12. CmdStop.Enabled = False
13. CmdNext.Enabled = True
14. cmdPrev.Enabled = False
15. CmdPlay.Enabled = False
16. End If
17.
18. End Sub
Ahora hablemos del control Timer, este tiene un intervalo de 1000 el equivalente a un
segundo, cada segundo el control revisa que esta pasando con la aplicación basándose
en el comportamiento de los botones. Como se puede ver en el código siguiente:
Texto planoImprimir
1. Private Sub Timer1_Timer()
2. If CmdRec.Enabled = False And CmdStop.Enabled = True And CmdNext.En
abled = False Then
3. Label1.Caption = "Grabando....."
4. CalcularTiempo
5. Label2.Caption = m + ":" + s
6. End If
7.
8. If CmdRec.Enabled = False And CmdStop.Enabled = True And CmdNext.En
abled = True Then
9. Label1.Caption = "Reproduciendo....."
10. CalcularTiempo
11. Label2.Caption = m + ":" + s
12. End If
13.
14. If CmdStop.Enabled = False Then
15. Label1.Caption = "Detenido....."
16. Label2.Caption = "00:00"
17. x=0
18. minutos = 0
19. End If
20.
21. End Sub
Texto planoImprimir
1. Private Sub CalcularTiempo()
2. x = x + 1
3. If x = 60 Then
4. minutos = minutos + 1
5. x=0
6. End If
7. m = Trim(Str(minutos))
8. s = Trim(Str(x))
9.
10. If minutos < 10 Then m = "0" + m
11. If x < 10 Then s = "0" + s
12.
13. Label2.Caption = m + ":" + s
14.
15. End Sub
Ahora vamos a guardar en disco nuestro sonido, suena fácil pero vamos a tener que dar
unas vueltas primero.
Texto planoImprimir
1. Private Sub CmdGuardar_Click()
2. ' Grabar el archivo wav que esta en la memoria en una carpeta temporal
3. Result = mciSendString("save sonido C:\NewWav.wav", cadena, Len(cadena),
0)
4.
5. ' Aqui llamamos a un procedimiento para leer los valores del wav en memoria
6. GetRecStatus
7.
8. ' cierra el archivo en memoria
9. Result = mciSendString("close sonido", cadena, 1024, 0)
10. If Not Result = 0 Then
11. errormsg = mciGetErrorString(Result, CadenaError, 1024)
12. MsgBox CadenaError, 0, "Error (close)"
13. End If
14.
15. ' cierra todos los archivos en memoria
16. mciSendString "close all", 0, 0, 0
17.
18. ' Aqui accedemos al archivo temporal para modificarlo binariamente
19. FixWaveFile
20.
21. ' guardamos en disco
22. GrabarArchivo
23. End Sub
Creo que ya te conté que mciSendString no soporta path largos, así que vamos a guardar
nuestro sonido en un archivo temporal en el directorio raíz de C y llamamos al
procedimiento GetRecStatus que va a leer toda la información sobre el sonido grabado
que esta en memoria, esa información nos será útil ya que esa información no se grabo
en el archivo Wav.
Texto planoImprimir
1. Private Sub GetRecStatus()
2.
3. Dim i As Long
4. Dim MSchan As String
5. Dim MSbits As String
6. Dim MSsamples As String
7. Dim MSbytes As String
8. Dim lChan As Long
9. Dim lBits As Long
10. Dim lSamples As Long
11. Dim sChan As String
12. Dim mssg As String * 255
13.
14. ' Canales de audio
15. i = mciSendString("status sonido channels", mssg, 255, 0)
16. If Str(mssg) = "1" Then
17. MSchan = "mono"
18. sChan = "1"
19. Else
20. MSchan = "stereo"
21. sChan = "2"
22. End If
23.
24. ' bits por muestra
25. i = mciSendString("status sonido bitspersample", mssg, 255, 0)
26. MSbits = Str(mssg)
27.
28. 'muestra
29. i = mciSendString("status sonido samplespersec", mssg, 255, 0)
30. MSsamples = Str(mssg)
31.
32. ' Aqui se presenta unos de los errores la frecuencia que devuelve es 11025 Hz
33. ' cuando en realidad es 44100 Hz
34. i = mciSendString("status sonido bytespersec", mssg, 255, 0)
35. MSbytes = Str(mssg)
36.
37. ' Calculamos el valor real de los byte por segundos
38. lBytes = CLng(MSsamples) * ((CLng(sChan) * CLng(MSbits)) / 8)
39.
40. End Sub
Texto planoImprimir
1. Private Sub FixWaveFile()
2.
3. ' Este es el procedimiento para arreglar el error del archivo wav
4. Dim Indexnum As Integer
5. Dim x As Integer
6. Dim HexCode As String
7. Dim Hex1 As String
8. Dim Hex2 As String
9. Dim Hex3 As String
10. Dim lByteNum As Long ' numero del byte (29,30, & 31) en el archivo wave
11. Dim bByte As Byte ' byte hexadecimal a escribir
12.
13. ' obtiene el hexadecimal para la variable lByte
14. HexCode = Hex(lBytes) ' lBytes que calculamos en el procedimiento de graba
r
15. Do While Len(HexCode) < 6 ' Revisar si tiene los 6 caracteres necesarios
16. HexCode = "0" & HexCode ' Si no agregar ceros
17. Loop
18.
19. ' Nota: este valor debe ser escrito en el archivo al revés!
20. Hex1 = Right$(HexCode, 2) ' obtienes el ultimo byte hexadecimal
21. Hex2 = Mid$(HexCode, 3, 2) ' obtienes el byte de en medio
22. Hex3 = Left$(HexCode, 2) ' obtienes el primer byte
23.
24. 'Abres el archivo
25. Indexnum = FreeFile
26. Open "C:\NewWav.wav" For Binary Access Write As #Indexnum ' Abres com
o binario
27. lByteNum = 29 ' primer byte a escribir es el 29
28. bByte = CInt("&H" & Hex1)
29. Put #Indexnum, lByteNum, bByte 'escribe el valor bByte a la posición de lByt
eNum en el archivo
30. bByte = CInt("&H" & Hex2)
31. lByteNum = lByteNum + 1
32. Put #Indexnum, lByteNum, bByte
33. bByte = CInt("&H" & Hex3)
34. lByteNum = lByteNum + 1
35. Put #Indexnum, lByteNum, bByte
36. Close #1
37. End Sub
Estos dos procedimientos se los debo a S. Clark que se topo con el mismo problema que
yo y estoy realmente agradecida. Bueno, ahora que ya tenemos todo arreglado vamos
aguardar el sonido donde realmente queremos.
Texto planoImprimir
1. Public Sub GrabarArchivo()
2. Dim Nfile As String
3. Dim ruta As String
4. Dim osf As Object
5. Set osf = CreateObject("Scripting.FileSystemObject")
6. Dim origen As File
7. Set origen = osf.GetFile("C:\NewWav.wav")
8.
9. With MDialogo
10. .CancelError = False
11. .Filter = "WAV file (*.wav*)|*.wav"
12. .Flags = &H2 Or &H400
13. .InitDir = GetSetting(App.EXEName, App.EXEName, "Default Path")
14. .FileName = GetSetting(App.EXEName, App.EXEName, "Default Filename
")
15. .ShowSave
16.
17. ' obtenemos el nombre que el usuario le ha puesto
18. Nfile = .FileTitle
19.
20. ' obtenemos la ruta completa donde lo guardaremos
21. ruta = .FileName
22. wavruta = ruta
23. End With
24.
25. ' cambiamos el nombre del archivo
26. origen.Name = Nfile
27.
28. 'lo movemos a la ruta elegida por el usuario
29. origen.Move (ruta)
30. MsgBox "Archivo Salvado", vbInformation, "Salvar"
31.
32. End Sub
Primero creamos un objeto archivo de sistema para manejar nuestro archivo wav,
definimos una variable como tipo File y le asignamos el archivo en disco, abrimos un
cuadro de dialogo salvar para que el usuario coloque el nombre que le quiere poner al
archivo y en que carpeta lo quiere guardar. La variable Nfile almacena el nuevo nombre
del archivo y la variable ruta el path donde se guardara. Renombramos el archivo wav y
lo movemos a la ruta seleccionada.