Esta página está en construcción: perdonen los errores, repeticiones y temas inacabados.

This page is being developed: I am sorry for errors, duplications  and unfinished subjects.

 

Entrada de sonido en Visual Basic (incluido en conversaciones con Enrique Tomás)

En Visual Basic se definen variables de todo tipo, números, letreros, arrays o vectores, estructuras que incluyen uno o varios de los tipos anteriores, etc. Pero estos son como nombres privados de Basic que no tienen existencia en un mundo más amplio, como el de Windows, de manera que resulta difícil pero indispensable conectar ambos mundos, cuando alguien quiera ampliar las propiedades de VBasíc con las llamadas de Windows, como las API (Application Programming Interface).

Estas API son extraordinariamente sensitivas a la menor incorrección o descortesía y se cierran como la mimosa o el puercoespín. Las funciones y subrrutinas (las funciones devuelven un valor al ejecutarse, las subrrutinas no, sólo hacen algo) a llamar en este orden para grabar señal de sonido en memoria y recuperarla son:

waveInGetNumDevs Lib "winmm.dll" () As Long

waveInGetDevCaps Lib "winmm.dll" Alias "waveInGetDevCapsA" (ByVal uDeviceID As Long, lpCaps As WAVEINCAPS, ByVal uSize As Long) As Long

waveInOpen Lib "winmm.dll" (lphWaveIn As Long, ByVal uDeviceID As Long, lpFormat As WAVEFORMAT, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long

waveInPrepareHeader Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long

waveInAddBuffer Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long

waveInStart Lib "winmm.dll" (ByVal hWaveIn As Long) As Long

waveInReset Lib "winmm.dll" (ByVal hWaveIn As Long) As Long

waveInStop Lib "winmm.dll" (ByVal hWaveIn As Long) As Long

waveInUnprepareHeader Lib "winmm.dll" (ByVal hWaveIn As Long, lpWaveInHdr As WAVEHDR, ByVal uSize As Long) As Long

waveInClose Lib "winmm.dll" (ByVal hWaveIn As Long) As Long

Y asimismo son necesarias  algunas funciones para usar la memoria donde se guarda la señal muestreada.

GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long

GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long

GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long

Y sobre todo, estas perlas que permiten conectar los dos mundos de los que hablábamos

CopyStructFromPtr Lib "kernel32" Alias "RtlMoveMemory" (struct As Any, ByVal ptr As Long, ByVal cb As Long)

CopyPtrFromStruct Lib "kernel32" Alias "RtlMoveMemory" (ByVal ptr As Long, struct As Any, ByVal cb  As Long)

Describámoslas en cristiano:

WaveInGetNumDevs. Es la función que accede a la información que tiene el sistema operativo ( o sea,  Windows en nuestro caso) acerca de los dispositivos periféricos de audio operativos, y nos devuelve el número de ellos que son capaces de soportar entrada de audio.

waveInGetDevCaps. Es una función que accede a la información que el driver (o sea,    ) de la tarjeta de sonido nos presta, y nos devuelve una estructura (variable mixta que incluye otras, sus campos, en su interior, digamos) de datos llamada WAVEINCAPS, en la que podemos encontrar información sobre el nombre, versión, capacidades, etcétera, accediendo a sus campos.

waveInOpen. Una vez que tenemos información sobre la tarjeta de sonido, hemos de tratarla al más estilo UNIX, es decir, vamos a identificarla a partir de ahora con un manejador. ¿Qué es un manejador? En realidad, no es más que un número con el que el sistema va a identificar a partir de ahora un descriptor de fichero abierto, es decir, un número que identifica plenamente al dispositivo.

Por ejemplo, esta rutina

        CopyStructFromPtr senales(indi).senal(0), inHdr(indi).lpData, longitud_muestreo_bytes

copia longitud_muestreo_bytes los bytes ocupados por el muestreo, en una estructura de señales, es decir, varias señales unidas e indexadas. La rutina pasa la posición de la señal muestreada en el principio de una de las señales indexadas. El índice permite disponer de dos buffer que se alternan, de modo que mientras el conversor muestrea, el programa  puede procesar la señal muestreada anteriormente.

Atención: como los conversores suelen codificar la señal en valores enteros positivos, puede ser necesario llevar esos valores a enteros con signo, es decir, restar a cada muestra la mitad del ámbito. Para un byte, 8 bits, restar 128. Para 2, 16 bits, 32000 y pico.

Veamos una implementación de estas rutinas con una interesantísima cualidad: funciona.

'TIPO DE SENAL

'1. reservo memoria para muestrear

 hMem = GlobalAlloc(&H42, longitud_muestreo_bytes) 'moveable
inHdr.lpData = GlobalLock(hMem)
inHdr.dwBufferLength = longitud_muestreo_bytes 'BUFFER_SIZE
'2. muestreo
rc = waveInOpen(hWaveIn, DEVICEID, formato_senal, 0, 0, 0)
rc = waveInPrepareHeader(hWaveIn, inHdr, Len(inHdr)
rc = waveInAddBuffer(hWaveIn, inHdr, Len(inHdr))
rc = waveInStart(hWaveIn)
'=====================================================================
'3. llevo a array para procesa

'BUFFER de BYTES de 0 a 255, cero en 128
CopyStructFromPtr senal(0), inHdr.lpData, longitud_muestreo_bytes
' la señal en un buffer para su procesado.

'
Pasos de muestreo de señal audio para su procesado posterior  

 


Vuelta al Principio     Última actualización:  martes, 09 de julio de 2013      Visitantes: contador de visitas