Captura de entrada do som

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

A classe Microphone permite que o aplicativo se conecte a um microfone ou a outro dispositivo de entrada de som no sistema do usuário e transmita o áudio de entrada para os alto-falantes daquele sistema ou envie os dados de áudio a um servidor remoto, como o Flash Media Server. Você pode acessar os dados de áudio brutos a partir do microfone e gravá-los ou processá-los. Também pode enviar o áudio diretamente para os alto-falantes do sistema ou enviar dados de áudio compactados para um servidor remoto. É possível usar o codec Speex ou Nellymoser para os dados enviados a um servidor remoto. (O suporte para o codec Speex foi disponibilizado a partir do Flash Player 10 e do Adobe AIR 1.5.)

Acesso a um microfone

A classe Microphone não tem um método construtor. Em vez disso, você usa o método estático Microphone.getMicrophone() para obter uma nova ocorrência de Microphone, conforme mostrado a seguir:

var mic:Microphone = Microphone.getMicrophone();

A chamada do método Microphone.getMicrophone() sem um parâmetro retorna o primeiro dispositivo de entrada de som descoberto no sistema do usuário.

Um sistema pode ter mais de um dispositivo de entrada de som conectado a ele. O aplicativo pode usar a propriedade Microphone.names para obter uma matriz dos nomes de todos os dispositivos de entrada de som disponíveis. Em seguida, ele pode chamar o método Microphone.getMicrophone() com um parâmetro index que corresponde ao valor de índice de um nome de dispositivo na matriz.

Um sistema talvez não tenha um microfone ou outro dispositivo de entrada de som conectado a ele. É possível usar a propriedade Microphone.names ou o método Microphone.getMicrophone() para verificar se o usuário tem um dispositivo de entrada de som instalado. Se o usuário não tiver um dispositivo de entrada de som instalado, a matriz names terá um comprimento de zero e o método getMicrophone() retornará um valor null .

Quando o aplicativo chama o método Microphone.getMicrophone() , o Flash Player exibe a caixa de diálogo Configurações do Flash Player que solicita que o usuário permita ou negue acesso do Flash Player à câmara e ao microfone no sistema. Depois que o usuário clicar no botão Permitir ou Negar neste diálogo, um StatusEvent será despachado. A propriedade code dessa ocorrência de StatusEvent indica se o acesso ao microfone foi permitido ou negado, conforme mostrado neste exemplo:

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."); 
    } 
}

A propriedade StatusEvent.code conterá “Microphone.Unmuted”, se o acesso for permitido, ou “Microphone.Muted”, se o acesso for negado.

A propriedade Microphone.muted é definida como true ou false quando o usuário permite ou nega acesso ao microfone, respectivamente. No entanto, a propriedade muted não é definida na ocorrência de Microphone até que StatusEvent tenha sido despachado, de modo que seu aplicativo também deve esperar até o evento StatusEvent.STATUS ser despachado antes de verificar a propriedade Microphone.muted .

Para que o Flash Player exiba a caixa de diálogo de configurações, a janela de aplicativo precisa ser grande o suficiente para exibi-la (pelo menos 215 x 138 pixels). Caso contrário, o acesso é negado automaticamente.

O conteúdo em execução na caixa de proteção do aplicativo do AIR não precisa da permissão do usuário para acessar o microfone. Assim, eventos de status para ligar e desligar o som do microfone nunca são despachados. O conteúdo em execução no AIR fora da caixa de proteção do aplicativo requer a permissão do usuário, de modo que esses eventos de status podem ser despachados.

Roteamento de áudio do microfone para alto-falantes locais

A entrada de áudio de um microfone pode ser roteada para os alto-falantes do sistema local chamando o método Microphone.setLoopback() com um valor de parâmetro de true .

Quando o som de um microfone local é roteado para alto-falantes locais, há um risco de criar um loop de feedback de áudio, o que pode provocar sons estridentes e danificar o hardware de som. A chamada do método Microphone.setUseEchoSuppression() com um valor de parâmetro true reduz, mas não elimina completamente, o risco de ocorrência de feedback de áudio. A Adobe recomenda sempre chamar Microphone.setUseEchoSuppression(true) antes de chamar Microphone.setLoopback(true) , a menos que você tenha certeza de que o usuário esteja reproduzindo o som usando fones de ouvido ou outra coisa que não seja um alto-falante.

O código a seguir mostra como rotear o áudio de um microfone local para os alto-falantes do sistema local:

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

Alteração do áudio do microfone

O aplicativo pode alterar os dados de áudio de um microfone de duas maneiras. Primeiro, ele pode alterar o ganho do som de entrada, o que efetivamente multiplica os valores de entrada por um valor especificado para criar um som mais baixo ou mais silencioso. A propriedade Microphone.gain aceita valores numéricos entre 0 e 100 inclusive. Um valor de 50 funciona como um multiplicador de um e especifica o volume normal. Um valor de zero funciona como um multiplicador de zero e silencia efetivamente o áudio de entrada. Valores acima de 50 especificam um volume mais alto do que o normal.

O aplicativo também pode alterar a taxa de amostragem do áudio de entrada. Taxas de amostragem mais altas aumentam a qualidade do som, mas elas também criam fluxos de dados mais densos que usam mais recursos para transmissão e armazenamento. A propriedade Microphone.rate representa a taxa de amostragem de áudio medida em quilohertz (kHz). A taxa de amostragem padrão é de 8 kHz. É possível definir a propriedade Microphone.rate como um valor mais alto do que 8 kHz se o microfone oferecer suporte à taxa mais alta. Por exemplo, configurar a propriedade Microphone.rate com um valor de 11 define a taxa de amostragem como 11 kHz. Configurá-la como 22 define a taxa de amostragem como 22 kHz e assim por diante. As taxas de amostra disponíveis dependem do codec selecionado. Quando você usa o codec Nellymoser, pode especificar 5, 8, 11, 16, 22 e 44 kHz como taxa de amostra. Quando você usa o codec Speex (disponível a partir do Flash Player 10 e do Adobe AIR 1.5), só pode usar 16 kHz.

Detecção de atividade do microfone

Para conservar a largura de banda e os recursos de processamento, o Flash Player tenta detectar quando nenhum som está sendo transmitido por um microfone. Quando o nível de atividade do microfone permanece abaixo do limite do nível de silêncio por um certo período, o Flash Player para de transmitir a entrada de áudio e despacha um simples ActivityEvent. Se você usar o codec Speex (disponível no Flash Player 10 ou em versões posteriores e no Adobe AIR 1.5 ou em versões posteriores), defina o nível de silêncio como 0 para assegurar que o aplicativo transmitirá dados de áudio continuamente. A detecção da atividade de voz do Speex automaticamente reduz a largura de banda.

Nota: Um objeto Microphone despacha eventos Activity somente quando o aplicativo estiver monitorando o microfone. Assim, se você não chamar setLoopBack( true ) , adicione um ouvinte para eventos de amostra de dados, ou anexe o microfone a um objeto NetStream e, em seguida, nenhum evento activity será despachado.

Três propriedades da classe Microphone monitoram e controlam a detecção de atividade:

  • A propriedade somente leitura activityLevel indica a quantidade de som que o microfone está detectando em uma escala de 0 a 100.

  • A propriedade silenceLevel especifica a quantidade de som necessária para ativar o microfone e despachar um evento ActivityEvent.ACTIVITY . A propriedade silenceLevel também usa uma escala de 0 a 100, e o valor padrão é 10.

  • A propriedade silenceTimeout descreve o número de milissegundos que o nível de atividade deve permanecer abaixo do nível de silêncio, até que um evento ActivityEvent.ACTIVITY seja despachado para indicar que o microfone está silencioso. O valor padrão de silenceTimeout é 2000.

As propriedades Microphone.silenceLevel e Microphone.silenceTimeout são somente leitura, mas seus valores podem ser alterados usando o método Microphone.setSilenceLevel() .

Em alguns casos, o processo de ativação do microfone quando nova atividade é detectada pode provocar um pequeno atraso. Manter o microfone ativo durante todo o tempo pode remover esses atrasos na ativação. O aplicativo pode chamar o método Microphone.setSilenceLevel() com o parâmetro silenceLevel definido como zero para indicar ao Flash Player para manter o microfone ativo e continuar a coletar dados de áudio, mesmo quando nenhum som está sendo detectado. De modo oposto, a configuração do parâmetro silenceLevel como 100 impede que o microfone seja ativado de qualquer modo.

O exemplo a seguir exibe informações sobre o microfone e relata eventos de atividade e eventos de status despachados por um 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); 
}

Ao executar o exemplo acima, fale ou faça ruídos no microfone do sistema e observe as instruções de rastreamento resultantes serem exibidas em um console ou janela de depuração.

Envio e recebimento de áudio de um servidor de mídia

Recursos adicionais de áudio também estão disponíveis ao usar o ActionScript com um servidor de mídia de fluxo contínuo, como o Flash Media Server.

Em particular, seu aplicativo pode conectar um objeto Microphone a um objeto NetStream e transmitir dados diretamente do microfone do usuário para o servidor. Os dados de áudio também podem ser transmitidos do servidor para um aplicativo e reproduzidos como parte de um MovieClip ou usando um objeto Video.

O suporte para o codec Speex foi disponibilizado a partir do Flash Player 10 e do Adobe AIR 1.5. Para definir o codec usado para áudio compactado enviado ao servidor de mídia, defina a propriedade codec do objeto Microphone. Esta propriedade pode ter dois valores, que são enumerados na classe SoundCodec. Definir a propriedade do codec como SoundCodec.SPEEX seleciona o codec Speex para compactação de áudio. Definir a propriedade como SoundCodec.NELLYMOSER (o padrão) seleciona o codec Nellymoser para compactação de áudio.

Para obter mais informações, consulte a documentação on-line do Flash Media Server em www.adobe.com/go/learn_fms_docs_br .

Captura dos dados de som do microfone

No Flash Player 10.1 e no AIR 2 ou posteriores, você pode capturar os dados de um microfone, como uma matriz de bytes dos valores de ponto flutuantes. Cada valor representa uma amostragem dos dados de áudio monofônicos.

Para obter dados de microfone, defina um ouvinte de evento para o evento sampleData do objeto Microphone. O objeto Microphone despacha os eventos sampleData periodicamente à medida que o buffer do microfone é preenchido com amostragens de som. O objeto SampleDataEvent tem uma propriedade data que é uma matriz de bytes das amostragens de som. As amostras são representadas como valores de ponto flutuantes, cada uma representando uma amostragem de som monofônico.

O código a seguir captura os dados de som do microfone em um objeto ByteArray chamado 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); 
    } 
}

Você pode reutilizar os bytes de amostra como áudio de reprodução para um objeto Sound. Se fizer isso, defina a propriedade rate do objeto Microphone como 44, que é a taxa de amostragem usada pelos objetos Sound. (Você também pode converter as amostragens de microfone capturadas a uma taxa inferior a 44 kHz que é exigida pelo objeto Sound.) Além disso, tenha em mente que o objeto Microphone captura as as amostragens monofônicas, ao passo que o objeto Sound usa som estéreo. Por isso, escreva cada um dos bytes capturados pelo objeto Microphone no objeto Sound duas vezes. O exemplo a seguir captura quatro segundos de dados do microfone e o reproduz novamente usando um 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 obter mais informações sobre os sons de reprodução dos dados de amostragem do som, consulte Trabalho com áudio gerado dinamicamente .