Red de conocimiento informático - Material del sitio web - Cómo desarrollar aplicaciones de audio reales bajo la plataforma Linux

Cómo desarrollar aplicaciones de audio reales bajo la plataforma Linux

1. Audio digital La señal de audio es una señal analógica que cambia continuamente, pero las computadoras solo pueden procesar y grabar señales digitales binarias obtenidas de fuentes de sonido naturales. se recibe, se puede enviar a la computadora para su posterior procesamiento. Un sistema de audio digital reproduce el sonido original convirtiendo el patrón de onda de la onda sonora en una serie de datos binarios. El dispositivo que implementa este paso a menudo se denomina convertidor analógico a digital (A/D). El convertidor A/D muestrea ondas sonoras a una velocidad de decenas de miles de veces por segundo. Cada punto de muestreo registra el estado de la onda de sonido analógica original en un momento determinado, generalmente llamado muestra, y cada segundo el número de muestras tomadas. por el reloj se llama frecuencia de muestreo. Al conectar una serie de muestras consecutivas, se puede describir un sonido en la computadora. Para cada muestra en el proceso de muestreo, el sistema de audio digital asignará un determinado bit de almacenamiento para registrar la amplitud de la onda de sonido, lo que generalmente se denomina resolución de muestreo o precisión de muestreo. Cuanto mayor sea la precisión del muestreo, más delicado será el sonido. ser restaurado. El audio digital implica muchos conceptos. Para los programadores que programan audio en Linux, lo más importante es comprender los dos pasos clave de la digitalización del sonido: muestreo y cuantización. El muestreo consiste en leer la amplitud de la señal de sonido a intervalos regulares, mientras que la cuantificación consiste en convertir la amplitud de la señal de sonido muestreada en un valor digital. En esencia, el muestreo es la digitalización del tiempo, mientras que la cuantificación es la digitalización de la amplitud. A continuación se presentan varios indicadores técnicos que se utilizan a menudo en la programación de audio: 1. Frecuencia de muestreo La frecuencia de muestreo se refiere al número de muestras de amplitud de onda de sonido por segundo al digitalizar formas de onda de sonido analógicas. La selección de la frecuencia de muestreo debe seguir la teoría de muestreo de Nyquist (Harry Nyquist): si se muestrea una señal analógica, la frecuencia de señal más alta que se puede restaurar después del muestreo es solo la mitad de la frecuencia de muestreo, o siempre que la frecuencia de muestreo sea mayor. que la señal de entrada Al doble de la frecuencia más alta, la señal original se puede reconstruir a partir de la serie de señales muestreadas. El rango de frecuencia de la audición humana normal está aproximadamente entre 20 Hz y 20 kHz. Según la teoría de muestreo de Nyquist, para garantizar que el sonido no se distorsione, la frecuencia de muestreo debe rondar los 40 kHz. Las frecuencias de muestreo de audio más utilizadas incluyen 8 kHz, 11,025 kHz, 22,05 kHz, 16 kHz, 37,8 kHz, 44,1 kHz, 48 kHz, etc. Si se utiliza una frecuencia de muestreo más alta, también se puede lograr una calidad de sonido de DVD. 2. El número de bits de cuantificación sirve para digitalizar la amplitud de la señal de audio analógica. Determina el rango dinámico de la señal analógica después de la digitalización. Los más utilizados son 8 bits, 12 bits y 16 bits. Cuanto mayor sea el bit de cuantificación, mayor será el rango dinámico de la señal y más cerca estará la señal de audio digitalizada de la señal original, pero mayor será el espacio de almacenamiento requerido. 3. Número de canales El número de canales es otro factor importante que refleja la calidad de la digitalización del audio. Se divide en canales mono y duales. El doble canal también se llama estéreo. Hay dos líneas en el hardware. La calidad del sonido y el timbre son mejores que los del mono. Sin embargo, el espacio de almacenamiento ocupado después de la digitalización es el doble que el del mono. fuera de Por razones de seguridad, las aplicaciones en Linux no pueden operar directamente dispositivos de hardware como tarjetas de sonido, sino que deben usar los controladores proporcionados por el kernel. La esencia de la programación de audio en Linux es utilizar controladores para completar diversas operaciones en la tarjeta de sonido. El control del hardware implica la operación de bits individuales en el registro, que generalmente está directamente relacionado con el dispositivo y tiene requisitos de sincronización muy estrictos. Si estas tareas se dejan en manos del programador de aplicaciones, la programación de la tarjeta de sonido se volverá anormal. Compleja y difícil, la función del controlador es proteger estos detalles de bajo nivel del hardware, simplificando así la escritura de aplicaciones. Actualmente, existen dos tipos principales de controladores de tarjetas de sonido comúnmente utilizados en Linux: OSS y ALSA. La primera interfaz de programación de audio que apareció en Linux fue OSS (Open Sound System), que consta de un conjunto completo de módulos de controlador del kernel y puede proporcionar una interfaz de programación unificada para la mayoría de las tarjetas de sonido.

OSS tiene una historia relativamente larga. Algunos de estos módulos del kernel (OSS/Gratis) se publican de forma gratuita junto con el código fuente del kernel de Linux, mientras que otros son proporcionados por 4Front Technologies en formato binario. Debido al fuerte apoyo de las empresas comerciales, OSS se ha convertido en el estándar de facto para la programación de audio en Linux. Las aplicaciones que admiten OSS pueden funcionar bien en la mayoría de las tarjetas de sonido. Aunque OSS es muy maduro, después de todo es un producto comercial sin código fuente completamente abierto. ALSA (Arquitectura de sonido avanzada de Linux) simplemente llena este vacío. Es otra tarjeta de sonido para elegir al realizar programación de audio en Linux. Además de proporcionar un conjunto de módulos de controlador de kernel como OSS, ALSA también proporciona bibliotecas de funciones correspondientes específicamente para simplificar la escritura de aplicaciones. En comparación con la interfaz de programación original basada en ioctl proporcionada por OSS, la biblioteca de funciones de ALSA es más fácil de usar. conveniente. Las características principales de ALSA son: Soporte para múltiples dispositivos de tarjetas de sonido Controlador de kernel modular Soporte SMP y subprocesos múltiples Proporcionar una biblioteca de funciones de desarrollo de aplicaciones Compatible con aplicaciones OSS La mayor diferencia entre ALSA y OSS es que ALSA es un proyecto gratuito mantenido por voluntarios. es un producto comercial proporcionado por la empresa, por lo que su adaptabilidad al hardware es mejor que ALSA y puede admitir más tipos de tarjetas de sonido. Aunque ALSA no se usa tan ampliamente como OSS, tiene una interfaz de programación más amigable y es totalmente compatible con OSS. Sin duda, es una mejor opción para los programadores de aplicaciones. 3. Interfaz de programación Cómo operar varios dispositivos de audio es la clave para la programación de audio en Linux. A través de un conjunto de llamadas al sistema proporcionadas por el kernel, las aplicaciones pueden acceder a varias interfaces de dispositivos de audio proporcionadas por el controlador de la tarjeta de sonido. Programación en Linux. El método más simple y directo para la programación de audio se encuentra a continuación. 3.1 El acceso a dispositivos de audio, ya sea OSS o ALSA, se ejecuta en el espacio del kernel de Linux en forma de controladores del kernel. Si una aplicación desea acceder al dispositivo de hardware de la tarjeta de sonido, debe utilizar la llamada al sistema proporcionada por el kernel de Linux. . Desde el punto de vista de un programador, operar una tarjeta de sonido es en gran medida equivalente a operar un archivo de disco: primero use la llamada al sistema abierto para establecer una conexión con el hardware, y el descriptor de archivo devuelto en este momento se usará como base para posteriores operaciones de identificación; luego use la llamada del sistema de lectura para recibir datos del dispositivo, o use la llamada del sistema de escritura para escribir datos en el dispositivo, y todas las demás operaciones que no se ajusten al modo básico de lectura / escritura se pueden completar mediante la llamada al sistema ioctl, finalmente, use close. La llamada al sistema le dice al kernel de Linux que no se realizará ningún procesamiento adicional en el dispositivo. · llamada al sistema abierto La llamada al sistema abierto puede obtener acceso a la tarjeta de sonido y prepararse para llamadas posteriores al sistema. Su prototipo de función es el siguiente: int open(const char *pathname, int flags, int mode pathname es el nombre de); el archivo del dispositivo que se va a abrir, que suele ser /dev/dsp para una tarjeta de sonido. Los indicadores de parámetro se utilizan para indicar cómo se debe abrir el archivo del dispositivo. Puede ser O_RDONLY, O_WRONLY u O_RDWR, que indican respectivamente que el archivo del dispositivo se abre en modo de solo lectura, solo escritura o lectura-escritura. El parámetro suele ser opcional. Solo está disponible cuando se utilizará cuando el archivo del dispositivo especificado no exista, lo que indica qué permisos debe tener el archivo recién creado. Si la llamada al sistema abierto se completa con éxito, devolverá un número entero positivo como identificador del archivo, que se utilizará en llamadas al sistema posteriores. Si la llamada al sistema abierto falla, devolverá -1 y también configurará la variable global errno para indicar qué causó el error.

· llamada al sistema de lectura La llamada al sistema de lectura se utiliza para leer datos de la tarjeta de sonido. Su prototipo de función es el siguiente: int read(int fd, char *buf, size_t count); que se pasa antes Obtenido por la llamada al sistema abierto; el parámetro buf es un puntero de carácter al búfer, que se usa para guardar los datos obtenidos de la tarjeta de sonido; el recuento de parámetros se usa para limitar el número máximo de bytes obtenidos de la tarjeta de sonido. Si la llamada al sistema de lectura se completa con éxito, devolverá el número de bytes realmente leídos de la tarjeta de sonido, que generalmente es menor que el valor de recuento; si la llamada al sistema de lectura falla, devolverá -1 y establecerá la variable global errno; , para indicar qué causó el error. llamada al sistema de escritura La llamada al sistema de escritura se utiliza para escribir datos en la tarjeta de sonido. Su prototipo de función es el siguiente: size_t write(int fd, const char *buf, size_t count) la llamada al sistema write y la llamada al sistema read son similares. En gran medida, la única diferencia es que la escritura escribe datos en la tarjeta de sonido, mientras que la lectura lee datos de la tarjeta de sonido. El parámetro fd también es el identificador del archivo del dispositivo, que también se obtiene a través de la llamada al sistema abierta anterior; el parámetro buf es un puntero de caracteres al búfer, que almacena los datos que se escribirán en la tarjeta de sonido; se utiliza para limitar la cantidad de datos escritos en la tarjeta de sonido. Número máximo de bytes escritos. Si la llamada al sistema de escritura se completa con éxito, devolverá la cantidad de bytes realmente escritos en la tarjeta de sonido; si la llamada al sistema de lectura falla, devolverá -1 y también configurará la variable global errno para indicar qué causó el error. Ya sea de lectura o escritura, una vez llamado, el kernel de Linux bloqueará la aplicación actual hasta que los datos se lean o escriban correctamente desde la tarjeta de sonido. llamada al sistema ioctl La llamada al sistema ioctl puede controlar la tarjeta de sonido. Todas las operaciones en archivos del dispositivo que no se ajustan al modo básico de lectura/escritura se realizan a través de ioctl. Puede afectar el comportamiento del dispositivo o devolver el estado del dispositivo. Su función El prototipo es el siguiente: int ioctl(int fd, int request, ...); el parámetro fd es el identificador del archivo del dispositivo, que se obtiene cuando se abre el dispositivo, entonces si el dispositivo es más complejo; la solicitud de control correspondiente también tendrá muchos tipos. El propósito de la solicitud de parámetro es distinguir diferentes solicitudes de control. En términos generales, se necesitan otros parámetros al controlar el dispositivo, que se pueden determinar de acuerdo con diferentes solicitudes de control, y pueden ser diferentes. estar relacionados con el hardware directamente relacionado con el equipo. cerrar llamada al sistema: una vez que la aplicación ha terminado de usar la tarjeta de sonido, debe utilizar la llamada de cierre al sistema para cerrarla a fin de liberar los recursos de hardware ocupados a tiempo. El prototipo de función es el siguiente: int close(int fd); el parámetro fd es el identificador del archivo del dispositivo, que se obtiene cuando se enciende el dispositivo. Una vez que una aplicación realiza la llamada de cierre del sistema, el kernel de Linux liberará varios recursos relacionados con ella. Por lo tanto, se recomienda cerrar los dispositivos abiertos lo antes posible cuando no sean necesarios. 3.2 Archivos de dispositivos de audio Para los programadores de aplicaciones de Linux, la interfaz de programación de audio es en realidad un conjunto de archivos de dispositivos de audio a través de los cuales se pueden leer o escribir datos en la tarjeta de sonido, y se puede controlar la tarjeta de sonido y configurar la frecuencia de muestreo. Número de canales de armonía, etc. /dev/sndstat archivo de dispositivo /dev/sndstat es la interfaz más simple proporcionada por el controlador de la tarjeta de sonido. Generalmente es un archivo de solo lectura y su función se limita a informar el estado actual de la tarjeta de sonido. En términos generales, /dev/sndstat se proporciona a los usuarios finales para detectar tarjetas de sonido y no debe usarse en programas porque toda la información se puede obtener a través de llamadas al sistema ioctl.

El comando cat proporcionado por Linux puede obtener fácilmente el estado actual de la tarjeta de sonido desde /dev/sndstat: [xiaowp@linuxgam sound]$ cat /dev/sndstat /dev/dsp/dev/dsp proporcionado por el controlador de la tarjeta de sonido. para archivos de dispositivos de muestreo digital (muestreo) y grabación digital (grabación), que son muy importantes para la programación de audio en Linux: escribir datos en el dispositivo significa activar el convertidor D/A en la tarjeta de sonido para la reproducción y escribir datos en el dispositivo Leer datos significa activar el convertidor A/D en la tarjeta de sonido para grabar. Actualmente, muchas tarjetas de sonido proporcionan múltiples dispositivos de muestreo digital, a los que se puede acceder a través de archivos de dispositivo como /dev/dsp1 en Linux. DSP es la abreviatura de Procesador de señal digital. Es un chip especial que se utiliza para el procesamiento de señales digitales. La tarjeta de sonido lo utiliza para convertir señales analógicas y digitales. El dispositivo DSP en la tarjeta de sonido en realidad contiene dos componentes: cuando se abre en modo de solo lectura, el convertidor A/D se puede usar para la entrada de sonido y cuando se abre en modo de solo escritura, se puede usar el convertidor D/A; salida de sonido. Estrictamente hablando, las aplicaciones en Linux abren /dev/dsp en modo de solo lectura para ingresar sonido, o abren /dev/dsp en modo de solo escritura para generar sonido, pero de hecho, algunos controladores de tarjetas de sonido aún permiten leer y escribir. /dev/dsp para entrada y salida de sonido simultáneas, lo cual es muy crítico para ciertas aplicaciones (como teléfonos IP). Al leer datos del dispositivo DSP, la entrada de señal analógica de la tarjeta de sonido se convierte en una muestra digital (muestra) a través del convertidor A/D y se almacena en el búfer del núcleo del controlador de la tarjeta de sonido cuando la aplicación llama. sistema de lectura Al leer datos de la tarjeta de sonido, los resultados de las muestras digitales guardados en el búfer del núcleo se copian al búfer del usuario especificado por la aplicación. Cabe señalar que la frecuencia de muestreo de la tarjeta de sonido la determina el controlador en el kernel y no depende de la velocidad a la que la aplicación lee los datos de la tarjeta de sonido. Si la aplicación lee los datos demasiado lentamente, por lo que son inferiores a la frecuencia de muestreo de la tarjeta de sonido, los datos sobrantes se descartarán si los datos se leen demasiado rápido, por lo que son superiores a la frecuencia de muestreo de la tarjeta de sonido; , entonces el controlador de la tarjeta de sonido. Las aplicaciones que soliciten datos se bloquearán hasta que lleguen nuevos datos. Al escribir datos en el dispositivo DSP, la señal digital se convertirá en una señal analógica a través de un convertidor D/A y luego se producirá el sonido. La velocidad a la que la aplicación escribe datos también debe coincidir con la frecuencia de muestreo de la tarjeta de sonido. De lo contrario, si es demasiado lenta, el sonido se detendrá o se detendrá. Si es demasiado rápido, el controlador de la tarjeta de sonido lo bloqueará. el kernel hasta que el hardware sea capaz de procesar los nuevos datos. A diferencia de otros dispositivos, las tarjetas de sonido generalmente no admiten operaciones de E/S sin bloqueo. Ya sea leyendo datos de la tarjeta de sonido o escribiendo datos en la tarjeta de sonido, en realidad tiene un formato específico. El valor predeterminado es datos sin firmar de 8 bits, mono y frecuencia de muestreo de 8 KHz. se puede cambiar mediante llamadas al sistema ioctl. En términos generales, después de abrir el archivo del dispositivo /dev/dsp en la aplicación, debe configurar el formato apropiado antes de leer o escribir datos desde la tarjeta de sonido. /dev/audio/dev/audio es similar a /dev/dsp. Es compatible con dispositivos de audio en estaciones de trabajo Sun y utiliza codificación mu-law.

Si el controlador de la tarjeta de sonido admite /dev/audio, puede utilizar el comando cat en Linux para reproducir archivos de audio codificados con mu-law en una estación de trabajo Sun: [xiaowp@linuxgam sound]$ cat audio /dev. /audio Dado que el archivo de dispositivo /dev/audio se utiliza principalmente por razones de compatibilidad, es mejor no intentar usarlo en aplicaciones recientemente desarrolladas, sino que debe reemplazarse por /dev/dsp. Para aplicaciones, solo se puede usar uno de /dev/audio o /dev/dsp al mismo tiempo, porque son interfaces de software diferentes para el mismo hardware. /dev/mixer En el circuito de hardware de la tarjeta de sonido, el mezclador es un componente muy importante. Su función es combinar o superponer múltiples señales. Para diferentes tarjetas de sonido, el papel del mezclador puede variar. Los controladores de tarjetas de sonido que se ejecutan en el kernel de Linux generalmente proporcionan el archivo de dispositivo /dev/mixer, que es una interfaz de software para que las aplicaciones operen el mezclador. Los circuitos mezcladores suelen constar de dos partes: mezclador de entrada y mezclador de salida. El mezclador de entrada es responsable de recibir señales analógicas de varias fuentes diferentes, a veces denominadas canales de mezcla o dispositivos de mezcla. Después de que la señal analógica pasa a través del controlador de ganancia y el ajustador de volumen controlado por el software, se modula en nivel en diferentes canales de mezcla y luego se envía al mezclador de entrada para la síntesis del sonido. El interruptor electrónico del mezclador puede controlar qué canales tienen señales conectadas al mezclador. Algunas tarjetas de sonido solo permiten conectar un canal de mezcla como fuente de sonido para la grabación, mientras que algunas tarjetas de sonido permiten cualquier conexión al canal de mezcla. Las señales procesadas por el mezclador de entrada siguen siendo señales analógicas y se enviarán al convertidor A/D para su procesamiento digital. El principio de funcionamiento del mezclador de salida es similar al del mezclador de entrada. También hay múltiples fuentes de señal conectadas al mezclador y todas han sido ajustadas en ganancia de antemano. Después de que el mezclador de salida mezcla todas las señales analógicas, generalmente hay un ajustador de ganancia maestro para controlar el volumen del sonido de salida, y también hay algunos controladores de tono para ajustar el tono del sonido de salida. Las señales procesadas por el mezclador de salida también son señales analógicas y eventualmente se enviarán a parlantes u otros dispositivos de salida analógica. La programación del mezclador incluye cómo configurar el nivel del controlador de ganancia y cómo cambiar entre diferentes fuentes de sonido. Estas operaciones suelen ser discretas y no requieren muchos recursos de la computadora como grabación o reproducción. Dado que el funcionamiento del mezclador no se ajusta al modo de operación típico de lectura/escritura, excepto por las dos llamadas al sistema de apertura y cierre, la mayoría de las operaciones se completan mediante llamadas al sistema ioctl. A diferencia de /dev/dsp, /dev/mixer permite que múltiples aplicaciones accedan a él al mismo tiempo, y la configuración del mezclador se mantiene hasta que se cierra el archivo del dispositivo correspondiente. Para simplificar el diseño de aplicaciones, la mayoría de los controladores de tarjetas de sonido en Linux admiten la aplicación directa de las operaciones ioctl del mezclador al dispositivo de sonido. Es decir, si /dev/dsp ya está abierto, no es necesario abrir /. dev/mixer para operar el mezclador, puede usar directamente el identificador de archivo obtenido al abrir /dev/dsp para configurar el mezclador. /dev/sequencer Actualmente, la mayoría de los controladores de tarjetas de sonido también proporcionan el archivo de dispositivo /dev/sequencer, que se utiliza para operar el sintetizador de tabla de ondas incorporado en la tarjeta de sonido o para controlar instrumentos en el bus MIDI. Generalmente solo se usa en la computadora. software de música. 4. Marco de aplicación Al realizar programación de audio en Linux, la atención se centra en cómo operar correctamente los distintos archivos de dispositivo proporcionados por el controlador de la tarjeta de sonido. Dado que hay muchos conceptos y factores involucrados, seguir un marco común sin duda ayudará a simplificar el diseño de la aplicación.

4.1 Programación DSP Lo primero que se debe hacer al programar una tarjeta de sonido es abrir el dispositivo de hardware correspondiente. Esto se hace con la ayuda de la llamada al sistema open y generalmente se utiliza el archivo /dev/dsp. El modo de funcionamiento de la tarjeta de sonido también se debe especificar al abrir el dispositivo. Para las tarjetas de sonido que no admiten full duplex, deben abrirse en modo de solo lectura o de solo escritura. Solo se pueden abrir aquellas tarjetas de sonido que admitan full duplex. se abre en modo de solo lectura. Se abre en modo de escritura y depende de la implementación específica del controlador. Linux permite que las aplicaciones abran o cierren el archivo del dispositivo correspondiente a la tarjeta de sonido varias veces, lo que facilita el cambio entre el estado de reproducción y el estado de grabación. Se recomienda utilizar solo lectura o solo escritura siempre que sea posible al realizar la programación de audio. Abra el archivo del dispositivo de esta manera, porque esto no solo puede aprovechar al máximo los recursos de hardware de la tarjeta de sonido, sino que también facilita la optimización del controlador. El siguiente código demuestra cómo abrir la tarjeta de sonido en modo de sólo escritura para la operación de reproducción: int handle = open("/dev/dsp", O_WRONLY if (handle == -1) { perror("open /dev /); dsp"); return -1;} El controlador de la tarjeta de sonido que se ejecuta en el kernel de Linux mantiene especialmente un búfer. Su tamaño afectará el efecto de reproducción y grabación. Puede utilizar la llamada al sistema ioctl para ajustar su tamaño de forma adecuada. No es necesario ajustar el tamaño del búfer en el controlador. Si no hay requisitos especiales, el tamaño del búfer predeterminado generalmente es suficiente. Sin embargo, cabe señalar que el tamaño del búfer normalmente debe configurarse inmediatamente después de abrir el archivo del dispositivo, porque otras operaciones en la tarjeta de sonido pueden hacer que el controlador ya no pueda modificar el tamaño del búfer. El siguiente código demuestra cómo configurar el tamaño del búfer del kernel en el controlador de la tarjeta de sonido: int configuración = 0xnnnnssss; int resultado = ioctl(handle, SNDCTL_DSP_SETFRAGMENT, amp; configuración); size"); return -1;}// Verifique la exactitud del valor de configuración. Al configurar el tamaño del búfer, la configuración del parámetro en realidad consta de dos partes. Los 16 bits inferiores indican el tamaño del búfer. La fórmula de cálculo correspondiente es buffer_size = 2^ssss, es decir, si el valor de los 16 bits inferiores de la configuración del parámetro es 16, entonces el tamaño del búfer correspondiente se establecerá en 65536 bytes. Los 16 bits superiores de la configuración del parámetro se utilizan para indicar el número de secuencia máximo del fragmento. Su rango de valores es de 2 a 0x7FFF, donde 0x7FFF significa que no hay límite. Lo siguiente que debe hacer es configurar la cantidad de canales cuando la tarjeta de sonido está funcionando. Dependiendo de las condiciones específicas del dispositivo de hardware y del controlador, se puede configurar en 0 (mono) o 1 (estéreo). El siguiente código demuestra cómo configurar el número de canales: int canales = 0; // 0=mono 1=stereoint resultado = ioctl(handle, SNDCTL_DSP_STEREO, amp; canales); ioctl número de canal"); return -1;}if (canales! = 0) { // Solo admite estéreo} El formato de muestreo y la frecuencia de muestreo es otro tema que debe considerarse al realizar programación de audio. Todos los formatos de muestreo admitidos por el sonido card can Encontrado en el archivo de encabezado soundcard.h, el formato de muestreo utilizado actualmente se puede cambiar fácilmente mediante la llamada al sistema ioctl.

El siguiente código demuestra cómo configurar el formato de muestreo de la tarjeta de sonido: int format = AFMT_U8; int result = ioctl(handle, SNDCTL_DSP_SETFMT, amp; format); if (result == -1) { perror("ioctl sample format" ); return -1;} // Verifique la exactitud del valor de configuración. Configurar la frecuencia de muestreo de la tarjeta de sonido también es muy fácil. Simplemente establezca el valor del segundo parámetro en SNDCTL_DSP_SPEED al llamar a ioctl y especifique el valor de la frecuencia de muestreo. en el tercer parámetro. Eso es todo. Para la mayoría de las tarjetas de sonido, el rango de frecuencia de muestreo admitido es generalmente de 5 kHz a 44,1 kHz o 48 kHz, pero esto no significa que todas las frecuencias dentro de este rango serán compatibles con el hardware. Las frecuencias más utilizadas en la programación de audio en Linux son las tres de muestreo. Las frecuencias son 11025 Hz, 16000 Hz, 22050 Hz, 32000 Hz y 44100 Hz. El siguiente código demuestra cómo configurar la frecuencia de muestreo de la tarjeta de sonido: int rate = 22050; int result = ioctl(handle, SNDCTL_DSP_SPEED, amp; rate); if (result == -1) { perror("formato de muestra ioctl" ); return -1;} // Verifique la exactitud de los valores de configuración 4.2 Programación del mezclador El mezclador en la tarjeta de sonido consta de múltiples canales de mezcla, que se pueden programar a través del archivo del dispositivo /dev/mixer proporcionado por el controlador. Las operaciones en el mezclador se completan mediante llamadas al sistema ioctl y todos los comandos de control comienzan con SOUND_MIXER o MIXER. La Tabla 1 enumera varios comandos de control del mezclador comúnmente utilizados: Nombre Función SOUND_MIXER_VOLUME Ajuste del volumen maestro SOUND_MIXER_BASS Control de bajos SOUND_MIXER_TREBLE Control de agudos SOUND_MIXER_SYNTH Sintetizador FM SOUND_MIXER_PCM Convertidor D/A maestro SOUND_MIXER_SPEAKERPC. altavozSOUND_MIXER_LINE entrada de línea de audio Entrada de micrófono SOUND_MIXER_MIC Entrada SOUND_MIXER_CD CD Volumen de reproducción SOUND_MIXER_IMIX Convertidor D/A esclavo SOUND_MIXER_ALTPCM SOUND_MIXER_RECLEV Volumen de grabación Ganancia de entrada SOUND_MIXER_IGAIN Ganancia de salida SOUND_MIXER_OGAIN SOUND_MIXER_LINE1 Primera entrada de la tarjeta de sonido SOUND_MIXER_LINE2 Segunda entrada de la tarjeta de sonido LINE3 La tercera entrada de la tarjeta de sonido Tabla 1 El comando del mezclador ajusta el Ganancia de entrada y ganancia de salida de la tarjeta de sonido. Es una función principal del mezclador. Actualmente, la mayoría de las tarjetas de sonido usan un controlador de 8 o 16 bits, pero como programador, no necesita preocuparse por esto. , porque el controlador de la tarjeta de sonido será el encargado de convertirlos en forma porcentual, es decir, ya sea ganancia de entrada o ganancia de salida, su rango de valores es de 0 a 100.

Al programar el mezclador, puede usar la macro SOUND_MIXER_READ para leer la ganancia del canal de mezcla. Por ejemplo, al obtener la ganancia de entrada del micrófono, puede usar el siguiente código: int vol (fd, SOUND_MIXER_READ(SOUND_MIXER_MIC) , amp ; vol); printf ("La ganancia del micrófono está en d \n", vol); para dispositivos mono con un solo canal de mezcla, el tamaño de ganancia devuelto se almacena en el byte de orden inferior. Para un dispositivo de dos canales que admite múltiples canales de mezcla, la ganancia devuelta en realidad incluye dos partes, que representan los valores de los canales izquierdo y derecho respectivamente. El byte de orden bajo almacena el volumen del canal izquierdo. byte almacena el volumen del canal derecho.

El siguiente código puede extraer la ganancia de los canales izquierdo y derecho en secuencia del valor de retorno. 4.3 Marco de grabación y reproducción de audio El siguiente es un marco básico para la grabación y reproducción de sonido utilizando el dispositivo DSP en la tarjeta de sonido. Primero grabe unos segundos de datos de audio, guárdelos en el búfer de memoria y luego reprodúzcalos. Todas sus funciones se completan leyendo y escribiendo archivos del dispositivo /dev/dsp: /* * sound.c */#include #. include #include # include #include #include #include #define LENGTH 3 /* Segundos de almacenamiento*/#define RATE 8000 /* Frecuencia de muestreo*/#define TAMAÑO 8 /* Número de bits de cuantificación*/#define CHANNELS 1 /* Número de canales*/ /* Búfer de memoria utilizado para guardar datos de audio digital */unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8] int main(){ int fd; arg; /* Parámetros para llamadas ioctl*/ int status; /* Valor de retorno de la llamada al sistema*/ /* Abrir dispositivo de sonido*/ fd = open("/dev/dsp", O_RDWR); { perror("falló la apertura de /dev/dsp"); exit(1); ( estado == -1) perror("SOUND_PCM_WRITE_BITS ioctl falló"); if (arg != TAMAÑO) perror("no se puede establecer el tamaño de la muestra"); = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, amp; arg); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl falló"); if (arg != CHANNELS) perror("no se pudo establecer el número de canales"); Establezca la frecuencia de muestreo al muestrear */ arg = RATE status = ioctl(fd, SOUND_PCM_WRITE_RATE, amp; arg); if (status == -1) perror("SOUND_PCM_WRITE_WRITE ioctl falló"); */ while (1) { printf("Di algo:\n"); estado = read(fd, buf, sizeof(buf)); /* grabando*/ if (status != sizeof(buf)) perror( " leer número incorrecto de bytes"); printf("Dijiste:\n"); status = write(fd, buf, sizeof(buf)); /* reproducción*/ if (

status != sizeof(buf)) perror("escribió un número incorrecto de bytes"); /* Espere a que finalice la reproducción antes de continuar con la grabación*/ status == ioctl(fd, SOUND_PCM_SYNC, 0); perror ("SOUND_PCM_SYNC ioctl falló"); }} 4.4 Marco del mezclador A continuación se muestra un marco básico para programar el mezclador. Se puede utilizar para ajustar la ganancia de varios canales de mezcla. Esto se realiza leyendo y escribiendo /. archivo de dispositivo dev/mixer: /* * mezclador.c */#include #include #include #include #include #include /* Se utiliza para almacenar los nombres de todos los dispositivos de mezcla disponibles */const char * sound_device_names[] = SOUND_DEVICE_NAMES int; fd; /* Descriptor de archivo correspondiente al dispositivo de mezcla */int devmask, stereodevs /* Máscara de mapa de bits correspondiente a la información del mezclador */char *name /* Mostrar comando Uso y todos los dispositivos de mezcla disponibles */void use(); int i; fprintf(stderr, "uso: s \n" " s \n\n" "Dónde está uno de: \n", nombre, nombre para (i = 0; i lt; SOUND_MIXER_NRDEVICES; i) if); ((1