Red de conocimiento informático - Problemas con los teléfonos móviles - ¿Cómo elegir una tarjeta de sonido o un micrófono en waveInOpen?

¿Cómo elegir una tarjeta de sonido o un micrófono en waveInOpen?

De hecho, la tarjeta de sonido es un dispositivo multimedia del PC, por lo que puedes utilizar el comando MCI (Media Control Interface) de Windows para controlar la tarjeta de sonido. MCI proporciona un conjunto de comandos de control independientes del dispositivo y es un método de alto nivel para acceder a dispositivos multimedia. Precisamente porque es un método de alto nivel, proporciona a los programadores una flexibilidad limitada. Cuando usan comandos MCI para controlar la grabación de la tarjeta de sonido, los programadores no pueden acceder a los datos de muestra en la memoria durante el proceso de grabación. La grabación se completa finalmente, los datos de muestreo se pueden obtener accediendo al archivo *.WAV. Aunque finalmente se obtienen los datos de muestreo, es problemático hacerlo. Más importante aún, puede llevar tiempo acceder al archivo. falla durante el proceso de muestreo. Detener y esperar operaciones de archivos, lo que resulta en un muestreo intermitente. En algunas situaciones donde los requisitos en tiempo real son relativamente altos (como análisis de forma de onda, control en tiempo real, etc.), el muestreo intermitente obviamente no es factible. La función de audio de forma de onda de bajo nivel de Windows proporciona el funcionamiento más flexible de la tarjeta de sonido. Permite el acceso aleatorio a cada dato muestreado en la memoria durante el proceso de muestreo, lo que puede superar por completo los problemas en tiempo real encontrados al usar comandos MCI. Windows proporciona funciones de audio de forma de onda de bajo nivel en forma de biblioteca de vínculos dinámicos Mmsystem.dll. Mmsystem.dll siempre incluye las siguientes funciones relacionadas con la entrada de forma de onda:

waveInAddBuffer: envía al búfer del dispositivo de entrada de sonido; waveInClose: cierra el dispositivo de entrada de sonido

waveInGetDevCaps: obtiene el rendimiento del dispositivo de entrada de sonido; waveInGetErrorText: obtiene el texto del mensaje de error de sonido

waveInGetID: obtiene el ID del dispositivo de entrada de sonido; el número de dispositivos de entrada de sonido

waveInGetPosition: obtiene la posición de entrada del dispositivo de sonido waveInMessage: envía información al dispositivo de entrada de sonido

waveInOpen: abre el dispositivo de entrada de sonido; Prepare el búfer de entrada de sonido

waveInReset: detenga el dispositivo de entrada de sonido. waveInStart: detenga el dispositivo de entrada de sonido

waveInStop: detenga la entrada de sonido waveInUnprepareHeader: borre el encabezado del archivo de sonido preparado

Necesita explicación Sí: diferentes herramientas de programación a menudo contendrán archivos de encabezado que describen estas funciones de audio de forma de onda de bajo nivel (por ejemplo, en Delphi4.0, el archivo que describe Mmsystem.dll es Mmsystem.pas), por lo que estos se llaman en diferentes herramientas de programación. Las funciones pueden usar nombres diferentes.

Al igual que con otros dispositivos, si desea utilizar la función de audio de forma de onda para controlar la tarjeta de sonido, debe seguir los siguientes pasos:

1. .

La función waveInOpen se usa para abrir un dispositivo de entrada de forma de onda, y su prototipo es el siguiente:

① WORD waveInOpen(lphWaveIn, wDeviceID, lpFormat, dwCallback, dwCallbackInstance, dwFlags) LPHWaveIn: lphWaveIn Esta variable se usa para recibe el identificador del dispositivo de entrada de forma de onda, este identificador debe guardarse, porque otras funciones de entrada de forma de onda también lo usarán.

②WORD wDeviceID Esta variable se usa para indicar el número de etiqueta del dispositivo de entrada de forma de onda. hay varias tarjetas de sonido en la PC (con precisión, cuando se dice que es un dispositivo de entrada de forma de onda), el sistema operativo asignará un número de etiqueta a cada tarjeta de sonido. Puede usar la función waveInGetNumDev para obtener el número N que puede ser. utilizado como dispositivo de entrada de forma de onda, entonces el rango de valores de wDeviceID es 0 ~ N-1. Si desea obtener el rendimiento de grabación correspondiente a cada número de etiqueta, puede usar la función waveInGetDevCaps si wDeviceID está configurado en W AVE_MAPPER (. es decir, -1), el sistema seleccionará automáticamente un dispositivo que cumpla con los requisitos (de acuerdo con los requisitos de lpFormat) ③lpFormat es un puntero El puntero a la estructura de datos PCMWAVEFORMAT debe indicar el modo de muestreo deseado en esta estructura de datos. esta estructura de datos es la siguiente:

Estructura Typedef pcmwaveformat_tag { WAVEFORMAT wf; //Información adicional sobre la configuración del formato PCM Una estructura de datos

WORD wBitsPerSample //Bits de cuantización

}PCMWAVEFORMAT;

Estructura Typedef waveformat_tag {

WORD wFormatTag; // Formato de datos de muestreo, actualmente solo se puede utilizar el formato PCM

WORD nChannels; //Número de canales (1 o 2)

DWORD nSamplesPerSec; //Velocidad de muestreo

DWORD nAvgBytesPerSec //Datos muestreados por segundo

WORD nBlockAlign; //La unidad para registrar la alineación de bloques. Este valor es nChannels*wBitsPerSample/8 }WAVEFORMAT;

④ DWORD dwCallback Defina la dirección de la función de devolución de llamada o el identificador de la ventana de devolución de llamada. La dirección de la función de devolución de llamada o ventana de devolución de llamada se utiliza para procesar mensajes generados por el dispositivo de entrada de forma de onda.

⑤DWORD dwCallbackInstance. Estos son datos definidos por el usuario, que se pasarán a la función de devolución de llamada (o ventana).

⑥DWORD dwFlags. Define la bandera que abre el dispositivo de entrada de forma de onda.

CALLBACK_WINDOW define dwCallback como el identificador de la ventana.

CALLBACK_FUNCTION define dwCallback como la dirección de la función.

También puede especificar aquí:

WAVE_FORMAT_QUERY solo consulta si el dispositivo de entrada de forma de onda admite el formato dado sin abrir realmente el dispositivo de entrada de forma de onda.

WAVE_ALLOWSYNC enciende el dispositivo de entrada de forma de onda en modo síncrono y el trabajo de grabación se realiza en segundo plano.

El siguiente programa Delphi ilustra el proceso de apertura de un dispositivo de entrada de forma de onda:

tipo

TRecorder = clase

privado

FWaveFmt: TWaveFormatEx; //En Delphi, WAVEFORMAT y PCMWAVEFORMAT se combinan en TwaveFor

matEx.

WaveHandle: HWaveIn;

WaveHdr1: PWAVEHDR; //Puntero a la estructura del encabezado del búfer de datos (ver más abajo)

WaveBuffer1: lpstr; Puntero de área (ver más abajo)

procedure CallBack(uMsg, dwInstance, dwParam1, dwParam2: stdcall

end;

Grabadora:=TRecorder.Create;

<…

Recorder.FWaveFmt.wFormatTag:=WAVE_FORMAT_PCM;

Grabadora .FWaveFmt.wBitsPerSample:=16;

Recorder.FWaveFmt.nSamplesPerSec:=11025;

Recorder.FWaveFmt.nAvgBytesPerSec:=22050;

Grabador. .nBlockAlign:=2;

WaveInOpen(@Recorder.WaveHandle, Wave_Mapper, mailto:@Recorder.FWaveFmt,

DWORD(@TRecorder.CallBack), DWORD(@Recorder), CALLBACK_FUNCTION WAVE_ALLOW

SYNC);

2. Asigne espacio en el búfer para los datos de muestreo

En el entorno Windows, puede utilizar GlobalAllocPtr. Sin embargo, para obtener una sección de espacio de memoria, debido a que el sistema operativo Windows adopta un mecanismo de administración de almacenamiento virtual, este espacio de memoria puede reemplazarse en el disco duro en cualquier momento. El tiempo dedicado a leer y escribir en el disco duro provocará una discontinuidad en el muestreo. Por lo tanto, antes de enviar el búfer al dispositivo de entrada de forma de onda, se debe llamar a la función WaveInPrepareHeader para garantizar que el búfer no será reemplazado en el disco duro. Por supuesto, antes de usar GlobalFreeP tr para liberar el búfer, primero debe usar la función WaveInUnprepareHeader para eliminar esta protección.

Las siguientes líneas de declaraciones Delphi ilustran el proceso de uso del búfer de grabación.

Recorder.WaveHdr1:=GlobalAllocPtr(GHND o GMEM_SHARE, Sizeof(WAVEHDR));

Recorder.WaveBuffer1:=GlobalAllocPtr(GHND o GMEM_SHARE, 1024);

Recorder.WaveHdr1.lpData:= Recorder.WaveBuffer1;

Recorder.WaveHdr1.dwBufferLength:=1024;

WaveInPrepareHeader(Recorder.WaveHandle, Recorder.WaveHdr1, tamaño de (WAVEHDR

));

WaveInAddBuffer(Recorder.WaveHandle, Recorder.WaveHdr1, tamaño de (WAVEHDR));

WaveInUnprepareHeader(Recorder.WaveHandle, Recorder.WaveHdr1, sizeof(TWAVE

HDR));

GlobalFreePtr(Recorder.WaveBuffer1);

Sin embargo, si solo abre un búfer para el dispositivo de entrada de forma de onda, cuando el búfer se llene con datos muestreados, el dispositivo de entrada de forma de onda no tendrá ningún búfer disponible y tendrá que detener el muestreo, lo que provocará Discontinuidad de muestreo. Por lo tanto, en aplicaciones prácticas, se deben preparar al menos dos buffers para el dispositivo de entrada de forma de onda y enviarlos al dispositivo de entrada de forma de onda al mismo tiempo utilizando el método anterior.

3. Inicie el dispositivo de entrada de forma de onda

Cuando todo lo anterior esté listo, use WaveInStart para iniciar el dispositivo de entrada de forma de onda y podrá iniciar la recopilación de datos durante el proceso de recopilación, una vez allí. es Cuando el búfer se llena con datos muestreados, el sistema vuelve a llamar a la función dwCallback especificada en WaveInOpen (o envía un mensaje a la ventana especificada). En Delphi4.0, el formato de la función de devolución de llamada es el siguiente: procedimiento CallBack(uMsg, dwInstance, dwParam1, dwParam2: DWORD donde uMsg es el número de etiqueta del mensaje de Windows, hay tres situaciones:

MM_WIM_OPEN indica que el dispositivo de entrada de forma de onda se abrió correctamente

MM_WIM_DATA indica que un búfer está lleno.

En este momento, dwParam1 lleva el puntero al encabezado del búfer de datos. Es a través de este puntero que se puede acceder aleatoriamente a cada dato muestreado en el búfer.

Como se muestra en el siguiente programa:

procedure TRecorder.CallBack(uMsg, dwInstance, dwParam1, dwParam2: DWORD

stdcall;

var i: Integer;

SPByte: ^Byte; //Se supone que se utiliza la cuantificación de 8 bits al abrir el dispositivo

SingleData: Integer;

BEGIN

caso uMsg de //uMsg es el número de marca de mensaje de Windows

MM_WIM_OPEN: //El mensaje enviado después de que el dispositivo de entrada de forma de onda se abre con éxito

MM_WIM_DATA: //Mensaje enviado cuando el buffer está lleno

begin

SPByte:= Pointer(dwParam1);

para i: =0 a Recorder.DataLength-1 do

begin

SingleData := SPByte^ //Accede a los datos en el búfer a través de SPByte

Inc(SPByte);

end;

end;

MM_WIM_CLOSE: //Mensaje enviado correctamente cuando el dispositivo de entrada de forma de onda está cerrado

end;

END

MM_WIM_CLOSE indica que el dispositivo de entrada de forma de onda se cierra correctamente. Cuando el dispositivo de entrada de forma de onda esté cerrado, no olvide usar Wave InPrepareHeader y GlobalFreePtr para liberar la memoria intermedia.

4. Apague el dispositivo de entrada de voz

waveInStop(hWaveIn) detiene la entrada de voz

waveInReset(hWaveIn) restablece el dispositivo de entrada de voz

waveInClose(hWaveIn) Cierra el dispositivo de entrada de voz. Donde hWaveIn es el identificador del dispositivo obtenido por WaveInOpen.

Antes de apagar el dispositivo de entrada de voz, debe restablecerlo; de lo contrario, el sistema mostrará este mensaje de error: "Los datos multimedia MMSYSTEM033 aún se están reproduciendo; reinicie el dispositivo o espere hasta que se descarguen los datos". jugó." Sin embargo, el dispositivo de entrada de voz solo se puede restablecer cuando el búfer está lleno de datos.

La función de entrada de forma de onda anterior devolverá 0 si la llamada se realiza correctamente; de ​​lo contrario, devolverá un valor distinto de 0; , puede usar la función waveInGetErrorText para obtener la información del error, esto se hace para facilitar la depuración.

3. Puntos a los que se debe prestar atención

Lo anterior describe la tecnología de programación de la tarjeta de sonido como una tarjeta A/D, pero también se debe prestar atención a los siguientes puntos

1. Las frecuencias de muestreo de las tarjetas de sonido no se limitan a 11025 Hz, 22050 Hz y 44100 Hz. Las frecuencias de muestreo de la mayoría de las tarjetas de sonido se pueden ajustar dentro de un rango determinado (por supuesto, habrá una cierta desviación). La frecuencia máxima de muestreo de algunas tarjetas de sonido puede alcanzar los 200 K Hz (puede variar según las diferentes marcas).

2. El búfer no se puede configurar demasiado pequeño, de lo contrario provocará un muestreo discontinuo. En la tarjeta de sonido del autor, si se usa 16 para la cuantificación, la frecuencia de muestreo es 22050 Hz y el búfer está configurado en 1 K bytes, en teoría se pueden obtener 22050 * 2 bytes de datos por segundo. De hecho, solo alrededor de 16000 * 2 bytes. de datos. Si el búfer se establece en 2 Kbytes, es coherente con el valor teórico.

3. El formato de datos después de la conversión A/D es el formato PCM, es decir: si se trata de una cuantificación de 8 bits, corresponde a datos sin signo de 8 bits, 0 corresponde al valor de amplitud total negativo, y 128 corresponde al nivel cero, 255 corresponde al valor de amplitud total positivo, si es una cuantificación de 16 bits, corresponde a datos con signo de 16 bits, -32768 corresponde al valor de amplitud total negativo, 0 corresponde al cero. nivel, y 32767 corresponde al valor positivo de amplitud total. Durante el proceso de programación, debe prestar atención a si el tipo de datos declarado es coherente con él. Por ejemplo, en Delphi4.0, los datos sin signo de 8 bits corresponden a datos de tipo Byte y los datos con signo de 16 bits corresponden a datos de tipo SmallInt. .

4. Dado que el extremo de entrada de la tarjeta de sonido suele tener un condensador de bloqueo de CC, la tarjeta de sonido no se puede utilizar para recoger directamente el flujo de CC. La solución es cortocircuitar el condensador de bloqueo de CC.

5. De manera similar, la tarjeta de sonido también puede generar una salida de señal de audio analógica utilizando la función API de Windows y la función D/A de la tarjeta de sonido.