Está en la página 1de 13

Recurso enviado por Angie Vargas para poder crear una grabadora wav en VB 6.

0 mediante la Api de windows


Link para descargar el cdigo fuente : Descargar

Descripcin del ejemplo


Durante un tiempo estuve utilizando la Grabadora de Windows para capturar audio de la tarjeta de sonido de mi computadora, pero realmente esa aplicacin no me satisfaca as que me embarque en el proyecto de construir mi propia grabadora. Pens que era fcil pero no lo era tanto como pens. Lo primero que debes hacer para poder capturar audio en tu computadora es configurar el audio digital para grabar. Y como haces eso?

1 - Revisa en tu barra de herramientas si tienes el icono de control de volumen, sino lo tienes ah puedes activarlo desde el panel de control Sonido y Multimedia. Si lo tienes ya dale doble clic. Te aparecer el control de volumen.

2 - Haz clic en el men Opciones, luego en Propiedades selecciona Grabacin.

3 - En la parte inferior de la pantalla selecciona Stereo Mix (como se ve en la figura) y ahora podrs grabar cualquier sonido que este reproduciendo tu PC. Si no lo haces solo escucharas esttica. Ahora desliza el control de volumen del Stereo Mix a la mitad, te preguntaras por que? Simple, porque si lo dejas a todo volumen la grabacin ser distorsionada.

Hasta aqu todo bien.

Abre tu Visual Basic 6.0, selecciona un Exe Estndar y agrgale un modulo. Coloca como referencia del proyecto la librera 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. En el modulo vamos a declarar 2 funciones del API de Windows: 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

La primera te permite tomar el control de cualquier dispositivo multimedia instalado en tu PC con simples instrucciones en ingles; la segunda te permite detector si a ocurrido un error con cualquiera de las instrucciones que has enviado. Ahora en el formulario vas a colocar 6 botones: CmdPrev, CmdNext, CmdPlay, CmdStop, CmdRec y CmdGuardar. Un control Timer, un control CommonDialog y dos etiquetas. Algo as:

Si quieres ponerle imgenes puede quedar as:

Coloca la propiedad Enable de los botones como falsa, menos la de CmdRec . Ya que tienes el formulario listo voy a contarte de 2 problemas que se me presentaron al realizar esta aplicacin. El primero fue que la funcin mciSendString tiene la limitante que no acepta path largos para salvar el archivo en memoria, as que si lo quieres guardar en mis documentos directamente no puedes; la solucin que encontr sin enrollarme mucho fue dar un rodeo y almacenar temporalmente el archivo en la unidad c y luego moverlo a donde yo quera. Resuelto ese problema me encontr con otro mas difcil y que me puso a pensar: el archivo guardado no se poda reproducir en ningn reproductor solo en la grabadora de Windows, su tamao era demasiado grande y si lo escuchabas era como una msica macabra sin relacin a lo que habas grabado. No te preocupes que eso tambin tiene solucin. Primero vamos a declarar unas variables: Texto planoImprimir 1. Dim s, m As String 2. Dim x, minutos As Integer

Estas variables estn asociadas al control Timer y nos van a permitir mostrar al usuario cuando se esta grabando o reproduciendo un archivo Wav. Texto planoImprimir 1. 2. 3. 4. 5. 6. 7. Dim Result As Long Dim errormsg As Integer Dim cadena As String * 1024 Dim CadenaError As String * 1024 Dim mssg As String * 255 Dim i As Long 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. Y tenemos esta variable muy importante: Texto planoImprimir 1. Dim lBytes As Long

Cuando se almacena un archivo wav con mciSendString, la funcin realmente no lo guarda con calidad CD esto es: 44100 Hz, l6 bits y 2 canales de audio sino que lo guarda a 11025, por esta razn no lo puedes escuchar en cualquier otro reproductor. La solucin a este problema se la debo al seor S. Clarke que se topo con el mismo problema que yo y publico sus descubrimientos en : www.rediware.com 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 grabacin y reproduccin. Como te habrs dado cuenta en la ilustracin del formulario todos los botones estn desactivados menos el de grabar. Vamos a programar el evento clic de este botn: 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. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.

If Not Result = 0 Then errormsg = mciGetErrorString(Result, CadenaError, 1024) MsgBox CadenaError, 0, "Error" End If ' Determinamos el formato de tiempo en millisegundos Result = mciSendString("set sonido time format ms", cadena, 1024, 0) ' Determnanos el formato pcm del archivo wav (Microsoft standard) Result = mciSendString("set sonido format tag pcm", cadena, 1024, 0)

' Determinamos las propiedades de grabacin con calidad CD 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. Ya tenemos nuestro sonido en memoria, entonces podemos reproducirlo. 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

Esta simple instruccin reproduce el archivo en memoria desde su primera posicin Texto planoImprimir 1. Result = mciSendString("play sonido from 0", cadena, Len(cadena), 0)

Ahora se quieres rebobinarlos para revisar tu sonido, puedes programar el botn 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

Fjate apagamos el Timer un momento, reinicializamos las variables de tiempo y detenemos el sonido que esta en memoria para poder otra vez encender el proceso de reproduccin. El botn Next lo que hace es detener la reproduccin.

Result = mciSendString("stop sonido", cadena, Len(cadena), 0) Esta sentencia detiene la reproduccin y la grabacin del sonido.

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 aplicacin basndose en el comportamiento de los botones. Como se puede ver en el cdigo 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

El procedimiento CalcularTiempo nos permite determinar el tiempo de reproduccin o grabacin como cualquier reproductor comercial 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 fcil 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 raz de C y llamamos al procedimiento GetRecStatus que va a leer toda la informacin sobre el sonido grabado que esta en memoria, esa informacin nos ser til ya que esa informacin 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

Cerramos el archivo en memoria para poder acceder a la copia en disco y llamamos al procedimiento FixWaveFile, que tendr acceso binario al archivo para corregir el error. 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 revs! 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 co mo 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 posicin 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. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.

Dim Nfile As String Dim ruta As String Dim osf As Object Set osf = CreateObject("Scripting.FileSystemObject") Dim origen As File Set origen = osf.GetFile("C:\NewWav.wav") With MDialogo .CancelError = False .Filter = "WAV file (*.wav*)|*.wav" .Flags = &H2 Or &H400 .InitDir = GetSetting(App.EXEName, App.EXEName, "Default Path") .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. Y aqu tienes un grabador de sonidos bsico, puedes probar el ejemplo, ampliarlo o utilizar el cdigo en tus propios programas, pero recuerda de donde lo sacaste y no quites merito a su autor. Espero haberte ayudado. Cualquier cosa puedes escribirme al correo acvg_correo@yahoo.com 2008 Angie Vargas - Caracas Venezuela

También podría gustarte