Captura de entradas de sonido

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

La clase Microphone permite a la aplicación conectar un micrófono u otro dispositivo de entrada de sonido en el sistema del usuario, y difundir el audio de la entrada a los altavoces, o bien enviar los datos de audio a un servidor remoto, como Flash Media Server. Es posible acceder a los datos de audio sin procesar desde el micrófono y grabar o procesarlos; también se puede enviar el audio directamente a los altavoces del sistema o enviar datos de audio comprimidos a un servidor remoto. Se puede emplear el códec Speex o Nellymoser para los datos enviados a un servidor remoto. (El códec Speex se admite a partir de Flash Player 10 y Adobe AIR 1.5.)

Acceso a un micrófono

La clase Microphone no tiene un método constructor. En su lugar, se utiliza el método Microphone.getMicrophone() estático para obtener una nueva instancia de Microphone, tal como se muestra a continuación.

var mic:Microphone = Microphone.getMicrophone();

Si se llama al método Microphone.getMicrophone() sin un parámetro, se devuelve el primer dispositivo de entrada de sonido detectado en el sistema del usuario.

Un sistema puede tener más de un dispositivo de entrada de sonido conectado. La aplicación puede utilizar la propiedad Microphone.names para obtener un conjunto de los nombres de todos los dispositivos de entrada de sonido disponibles. A continuación, puede llamar al método Microphone.getMicrophone() con un parámetro index que coincide con el valor de índice del nombre de un dispositivo del conjunto.

Es posible que el sistema no tenga conectado un micrófono u otro dispositivo de entrada de sonido. Se puede utilizar la propiedad Microphone.names o el método Microphone.getMicrophone() para comprobar si el usuario tiene un dispositivo de entrada de sonido instalado. Si el usuario no tiene un dispositivo de entrada de sonido instalado, la longitud del conjunto names es cero y el método getMicrophone() devuelve un valor null .

Cuando la aplicación llama al método Microphone.getMicrophone() , Flash Player muestra el cuadro de diálogo Configuración de Flash Player, que pregunta al usuario si desea que Flash Player acceda a la cámara y al micrófono del sistema. Una vez que el usuario hace clic en el botón Allow (Permitir) o en el botón Deny (Denegar) de este cuadro de diálogo, se distribuye un objeto StatusEvent. La propiedad code de la instancia de StatusEvent indica si se ha permitido o denegado el acceso al micrófono, tal como se muestra en este ejemplo:

import flash.media.Microphone; 
 
var mic:Microphone = Microphone.getMicrophone(); 
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); 
 
function onMicStatus(event:StatusEvent):void 
{ 
    if (event.code == "Microphone.Unmuted") 
    { 
        trace("Microphone access was allowed."); 
    }  
    else if (event.code == "Microphone.Muted") 
    { 
         trace("Microphone access was denied."); 
    } 
}

La propiedad StatusEvent.code contiene "Microphone.Unmuted" si se ha permitido el acceso, o bien "Microphone.Muted" si se ha denegado.

la propiedad Microphone.muted se establece en true o false cuando el usuario permite o deniega el acceso al micrófono, respectivamente. Sin embargo, la propiedad muted no se establece en la instancia de Microphone hasta que se haya distribuido el objeto StatusEvent, de manera que la aplicación también debe esperar a que el evento StatusEvent.STATUS se distribuya antes de comprobar la propiedad Microphone.muted .

Para que Flash Player pueda mostrar el cuadro de diálogo de configuración, la aplicación se debe ser lo suficientemente amplia para mostrarlo (215 por 138 píxeles como mínimo). De lo contrario, el acceso se deniega automáticamente.

El contenido que se ejecuta en el entorno limitado de la aplicación de AIR no necesita el permiso de otro usuario para acceder al micrófono. De este modo, los eventos status para silenciar y quitar el silencio del micrófono nunca se distribuyen. El contenido que se ejecuta en AIR fuera del entorno limitado de la aplicación requiere permiso del usuario, por lo que estos eventos de estado se pueden distribuir.

Enrutamiento de audio de micrófono a altavoces locales

La entrada de audio de un micrófono puede enrutarse a los altavoces del sistema locales llamando al método Microphone.setLoopback() con un valor de parámetro true .

Cuando el sonido de un micrófono local se enruta a los altavoces locales, existe el riesgo de crear un bucle de acoplamiento de audio, que puede provocar sonidos estridentes e incluso dañar el hardware de sonido. Si se llama al método Microphone.setUseEchoSuppression() con un valor de parámetro true , se reduce (sin eliminarse por completo) el riesgo de que se produzca dicho acoplamiento de audio. Adobe recomienda llamar siempre a Microphone.setUseEchoSuppression(true) antes de llamar a Microphone.setLoopback(true) , a menos que se sepa con certeza que el usuario reproduce el sonido con auriculares u otro dispositivo distinto de los altavoces.

En el código siguiente se muestra cómo enrutar el audio de un micrófono local a los altavoces del sistema locales:

var mic:Microphone = Microphone.getMicrophone(); 
mic.setUseEchoSuppression(true); 
mic.setLoopBack(true);

Alteración del audio de micrófono

La aplicación puede alterar los datos de audio que proceden de un micrófono de dos maneras. Primero, puede cambiar la ganancia del sonido de la entrada, que multiplica de forma efectiva los valores de entrada por una cantidad especificada para crear un sonido más alto o más bajo. La propiedad Microphone.gain acepta valores numéricos entre 0 y 100 (ambos incluidos). Un valor de 50 funciona como un multiplicador de 1 y especifica un volumen normal. Un valor de 0 funciona como un multiplicador de 0 y silencia de forma efectiva el audio de la entrada. Los valores superiores a 50 especifican un volumen por encima del normal.

La aplicación también puede cambiar la frecuencia de muestreo del audio de la entrada. Las frecuencias de muestreo más altas aumentan la calidad del sonido, pero crean flujos de datos más densos que utilizan más recursos para la transmisión y el almacenamiento. La propiedad Microphone.rate representa la frecuencia de muestreo de audio calculada en kilohercios (kHz). La frecuencia de muestreo predeterminada es de 8 kHz. La propiedad Microphone.rate puede establecerse en un valor mayor que 8 kHz si el micrófono admite una frecuencia superior. Por ejemplo, si se establece la propiedad Microphone.rate en un valor de 11, se establece la velocidad de muestreo en 11 kHz; si se establece en 22, se establece la velocidad de muestreo en 22 kHz, y así sucesivamente. Las frecuencias de muestreo disponibles dependen del códec seleccionado. Cuando se usa el códec Nellymoser, puede especificar 5, 8, 11, 16, 22 y 44 kHz como frecuencia de muestreo. Si se utiliza el códec Speex (disponible a partir de Flash Player 10 y Adobe AIR 1.5), solo es posible utilizar frecuencias de 16 kHz.

Detección de actividad del micrófono

Para conservar los recursos de procesamiento y ancho de banda, Flash Player intenta detectar el momento en que el micrófono no transmite ningún sonido. Cuando el nivel de actividad del micrófono se mantiene por debajo del umbral de nivel de silencio durante un periodo de tiempo, Flash Player deja de transmitir la entrada de audio y distribuye un objeto ActivityEvent en su lugar. Si se utiliza el códec Speex (disponible en Flash Player 10 y en Adobe AIR 1.5 o versiones posteriores), se debe establecer el nivel de silencio en 0 para garantizar que la aplicación transmita datos de audio de forma continuada. La detección de actividad de voz de Speex reduce automáticamente el ancho de banda.

Nota: un objeto Microphone solo distribuye eventos Activity cuando la aplicación controla el micrófono. De este modo, si no se llama a setLoopBack( true ) , añada un detector de eventos de datos de muestra, o bien, añada el micrófono a un objeto NetStream y no se distribuirán eventos de actividad.

La clase Microphone tiene tres propiedades para supervisar y controlar la detección de actividad:

  • La propiedad de solo lectura activityLevel indica la cantidad de sonido que detecta el micrófono, en una escala de 0 a 100.

  • La propiedad silenceLevel especifica la cantidad de sonido necesaria para activar el micrófono y distribuir un evento ActivityEvent.ACTIVITY . La propiedad silenceLevel también utiliza una escala de 0 a 100, y el valor predeterminado es 10.

  • La propiedad silenceTimeout describe el número de milisegundos durante los cuales el nivel de actividad debe permanecer por debajo del nivel de silencio, hasta que se distribuye un evento ActivityEvent.ACTIVITY para indicar que el micrófono ya está en silencio. El valor predeterminado de silenceTimeout es 2000.

Las propiedades Microphone.silenceLevel y Microphone.silenceTimeout son de solo lectura, pero se puede utilizar el método Microphone.setSilenceLevel() para cambiar sus valores.

En algunos casos, el proceso de activación del micrófono cuando se detecta una nueva actividad puede provocar una breve demora. Esas demoras de activación pueden eliminarse manteniendo el micrófono activo todo el tiempo. La aplicación puede llamar al método Microphone.setSilenceLevel() con el parámetro silenceLevel establecido en cero para indicar a Flash Player que mantenga el micrófono activo y siga recopilando datos de audio, incluso cuando no se detecten sonidos. Y a la inversa, si se establece el parámetro silenceLevel en 100, se evita que el micrófono esté siempre activado.

El ejemplo siguiente muestra información sobre el micrófono e informa de los eventos de actividad y de estado que distribuye un objeto Microphone:

import flash.events.ActivityEvent; 
import flash.events.StatusEvent; 
import flash.media.Microphone; 
 
var deviceArray:Array = Microphone.names; 
trace("Available sound input devices:"); 
for (var i:int = 0; i < deviceArray.length; i++) 
{ 
    trace(" " + deviceArray[i]); 
} 
 
var mic:Microphone = Microphone.getMicrophone(); 
mic.gain = 60; 
mic.rate = 11; 
mic.setUseEchoSuppression(true); 
mic.setLoopBack(true); 
mic.setSilenceLevel(5, 1000); 
     
mic.addEventListener(ActivityEvent.ACTIVITY, this.onMicActivity); 
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); 
     
var micDetails:String = "Sound input device name: " + mic.name + '\n'; 
micDetails += "Gain: " + mic.gain + '\n'; 
micDetails += "Rate: " + mic.rate + " kHz" + '\n'; 
micDetails += "Muted: " + mic.muted + '\n'; 
micDetails += "Silence level: " + mic.silenceLevel + '\n'; 
micDetails += "Silence timeout: " + mic.silenceTimeout + '\n'; 
micDetails += "Echo suppression: " + mic.useEchoSuppression + '\n'; 
trace(micDetails); 
 
function onMicActivity(event:ActivityEvent):void 
{ 
    trace("activating=" + event.activating + ", activityLevel=" +  
        mic.activityLevel); 
} 
 
function onMicStatus(event:StatusEvent):void 
{ 
    trace("status: level=" + event.level + ", code=" + event.code); 
}

Cuando ejecute el ejemplo anterior, hable al micrófono del sistema o haga ruido, y verá que aparecen las sentencias trace resultantes en una consola o una ventana de depuración.

Intercambio de audio con un servidor multimedia

Al utilizar ActionScript con un servidor de flujo de medios como Flash Media Server estarán disponibles otras funciones de audio.

En concreto, la aplicación puede asociar un objeto Microphone a un objeto NetStream y transmitir datos directamente desde el micrófono del usuario al servidor. Los datos de audio también se pueden transmitir desde el servidor a una aplicación creada con Flash o Flex y reproducirse como parte de un objeto MovieClip, o bien mediante un objeto Video.

El códec Speex está disponible a partir de Flash Player 10 y Adobe AIR 1.5. Para definir el códec utilizado para audio comprimido enviado al servidor de medios, se debe establecer la propiedad codec del objeto Microphone. Esta propiedad puede tener dos valores, que se enumeran en la clase SoundCodec. Con la definición de la propiedad codec como SoundCodec.SPEEX , se selecciona el códec Speex para comprimir audio. Con el establecimiento de la propiedad en SoundCodec.NELLYMOSER (valor predeterminado), se selecciona el códec Nellymoser para comprimir audio.

Para obtener más información, consulte la documentación de Flash Media Server en línea en www.adobe.com/go/learn_fms_docs_es .

Captura de datos de sonido del micrófono

En Flash Player 10.1. y AIR 2, o posterior, es posible capturar datos a partir de los datos del micrófono como conjunto de bytes de valores de coma flotante. Cada valor representa un ejemplo de datos de audio monofónicos.

Para obtener los datos del micrófono, establezca un detector de eventos para el evento sampleData del objeto Microphone. El objeto Microphone distribuye eventos sampleData de forma periódica conforme el búfer del micrófono se llena con muestras de sonido. El objeto SampleDataEvent dispone de la propiedad data , que es un conjunto de bytes de muestras de sonido. Las muestras se representan como valores de coma flotante y cada una de ellas representa una muestra de sonido monofónico.

El siguiente código captura los datos de sonido del micrófono en un objeto ByteArray denominado soundBytes :

var mic:Microphone = Microphone.getMicrophone(); 
mic.setSilenceLevel(0, DELAY_LENGTH); 
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
function micSampleDataHandler(event:SampleDataEvent):void { 
    while(event.data.bytesAvailable)     { 
        var sample:Number = event.data.readFloat(); 
        soundBytes.writeFloat(sample); 
    } 
}

Es posible reutilizar los bytes de la muestra como audio de reproducción para un objeto Sound. Si es así, la propiedad rate del objeto Microphone se debe establecer en 44, que es la frecuencia de muestreo que utilizan los objetos Sound. (También se pueden convertir las muestras del micrófono capturadas con una frecuencia más baja a una frecuencia de 44 kHz necesaria para el objeto Sound.) Asimismo, se debe tener en cuenta que el objeto Microphone captura muestras monofónicas, mientras que el objeto Sound emplea sonido estéreo; por lo tanto, se debe escribir cada uno de los bytes capturados por el objeto Microphone en el objeto Sound dos veces. En el siguiente ejemplo se capturan 4 segundos de datos del micrófono y se reproducen utilizando un objeto Sound:

const DELAY_LENGTH:int = 4000; 
var mic:Microphone = Microphone.getMicrophone(); 
mic.setSilenceLevel(0, DELAY_LENGTH); 
mic.gain = 100; 
mic.rate = 44; 
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
 
var timer:Timer = new Timer(DELAY_LENGTH); 
timer.addEventListener(TimerEvent.TIMER, timerHandler); 
timer.start(); 
 
function micSampleDataHandler(event:SampleDataEvent):void 
{ 
    while(event.data.bytesAvailable) 
    { 
        var sample:Number = event.data.readFloat(); 
        soundBytes.writeFloat(sample); 
    } 
} 
var sound:Sound = new Sound(); 
var channel:SoundChannel; 
function timerHandler(event:TimerEvent):void 
{ 
    mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); 
    timer.stop(); 
    soundBytes.position = 0; 
    sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler); 
    channel.addEventListener( Event.SOUND_COMPLETE, playbackComplete ); 
    channel = sound.play(); 
} 
 
function playbackSampleHandler(event:SampleDataEvent):void 
{ 
    for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++) 
    { 
        trace(sample); 
        var sample:Number = soundBytes.readFloat(); 
        event.data.writeFloat(sample); 
        event.data.writeFloat(sample); 
    } 
} 
 
function playbackComplete( event:Event ):void 
{ 
    trace( "Playback finished."); 
}

Para obtener más información sobre la reproducción de sonidos a partir de los datos de muestra de sonido, consulte Trabajo con sonido generado dinámicamente .