Trabalho com áudio gerado dinamicamente

Flash Player 10 e posterior, Adobe AIR 1.5 e posterior

Nota: A capacidade de gerar áudio dinamicamente está disponível a partir do Flash Player 10 e do Adobe AIR 1.5.

Em vez de carregar ou transmitir em fluxo um som existente, é possível gerar dados de áudio dinamicamente. Você pode gerar dados de áudio quando estiver atribuindo um ouvinte de eventos ao evento sampleData de um objeto Sound. (O evento sampleData é definido na classe SampleDataEvent do pacote flash.events.) Neste ambiente, o objeto Sound não carrega dados de som de um arquivo. Em vez disso, ele funciona como um soquete para dados de som que estão sendo transmitidos em fluxo através do uso da função que você atribui a esse evento.

Quando você adiciona um ouvinte de eventos sampleData a um objeto Sound, o objeto periodicamente solicita dados para adicioná-los ao buffer de som. Esse buffer contém dados para o objeto Sound reproduzir. Quando você chama o método play() do objeto Sound, ele despacha o evento sampleData ao solicitar novos dados de som. (Isto só se aplica quando o objeto Sound não carregou dados mp3 de um arquivo.)

O objeto SampleDataEvent inclui uma propriedade data . No ouvinte de eventos, você grava objetos ByteArray neste objeto data . As matrizes de bytes gravadas neste objeto somam-se aos dados de som em buffer reproduzidos pelo objeto Sound. A matriz de bytes no buffer é um fluxo de valores de ponto flutuante que variam de -1 a 1. Cada valor de ponto flutuante representa a amplitude de um canal (esquerdo ou direito) de uma amostra de som. A amostragem do som ocorre a 44.100 amostras por segundo. Cada amostra contém um canal esquerdo e direito, intercalados como dados de ponto flutuante na matriz de bytes.

Na função do manipulador, use o método ByteArray.writeFloat() para gravar na propriedade data do evento sampleData . Por exemplo, o seguinte código gera uma onda senoidal:

var mySound:Sound = new Sound(); 
mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWaveGenerator); 
mySound.play(); 
function sineWaveGenerator(event:SampleDataEvent):void 
{ 
    for (var i:int = 0; i < 8192; i++) 
    { 
        var n:Number = Math.sin((i + event.position) / Math.PI / 4); 
        event.data.writeFloat(n); 
        event.data.writeFloat(n); 
    } 
}

Quando você chama Sound.play() , o aplicativo começa a chamar seu manipulador de eventos, solicitando dados de amostra de som. O aplicativo continua enviando eventos à medida que o som é reproduzido, até você parar de fornecer dados ou chamar SoundChannel.stop() .

A latência do evento varia de uma plataforma para outra e pode mudar em versões futuras do Flash Player e do AIR. Não dependa de uma latência específica; em vez disso, você deve calculá-la. Para fazer esse cálculo, use a seguinte fórmula:

(SampleDataEvent.position / 44.1) - SoundChannelObject.position

Forneça de 2048 a 8192 amostras para a propriedade data do objeto SampleDataEvent (para cada chamada ao ouvinte de eventos). Para obter o melhor desempenho, forneça o máximo possível de amostras (até 8192). Quanto menos amostras forem fornecidas, maior será a probabilidade de ocorrerem cliques e estalos durante a reprodução. Esse comportamento pode diferir em várias plataformas e pode ocorrer em diversas situações; por exemplo, no redimensionamento do navegador. O código que funciona em uma plataforma quando você fornece apenas 2048 amostras pode não funcionar tão bem quando executado em outra plataforma. Se precisar da menor latência possível, pense na possibilidade de tornar o volume de dados selecionável pelo usuário.

Se você fornecer menos de 2048 amostras (por chamada ao ouvinte de eventos sampleData ), o aplicativo será interrompido depois de reproduzir as amostras restantes. Em seguida, o objeto SoundChannel despacha um evento SoundComplete.

Modificação do som de dados mp3

Use o método Sound.extract() para extrair dados de um objeto Sound. Você pode usar (e modificar) esses dados para gravá-los no fluxo dinâmico de outro objeto Sound para fins de reprodução. Por exemplo, o código a seguir usa os bytes de um arquivo MP3 carregado e os passa usando uma função de filtro, upOctave() :

var mySound:Sound = new Sound(); 
var sourceSnd:Sound = new Sound(); 
var urlReq:URLRequest = new URLRequest("test.mp3"); 
sourceSnd.load(urlReq); 
sourceSnd.addEventListener(Event.COMPLETE, loaded); 
function loaded(event:Event):void 
{ 
    mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); 
    mySound.play(); 
} 
function processSound(event:SampleDataEvent):void 
{ 
        var bytes:ByteArray = new ByteArray(); 
        sourceSnd.extract(bytes, 8192); 
        event.data.writeBytes(upOctave(bytes)); 
} 
function upOctave(bytes:ByteArray):ByteArray 
{ 
    var returnBytes:ByteArray = new ByteArray(); 
    bytes.position = 0; 
    while(bytes.bytesAvailable > 0) 
    { 
        returnBytes.writeFloat(bytes.readFloat()); 
        returnBytes.writeFloat(bytes.readFloat()); 
        if (bytes.bytesAvailable > 0) 
        { 
            bytes.position += 8; 
        } 
    } 
    return returnBytes; 
}

Limitações quanto aos sons gerados

Quando você usa um ouvinte de eventos sampleData com um objeto Sound, os outros únicos métodos Sound ativados são Sound.extract() e Sound.play() . Chamar qualquer outro método ou propriedade resultará em uma exceção. Todos os métodos e propriedades do objeto SoundChannel continuam ativados.