Utilisation de données audio générées de façon dynamique

Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures

Remarque : Flash Player 10 et Adobe AIR 1.5 donnent désormais la possibilité de générer des données audio de façon dynamique.

Plutôt que de charger ou de diffuser en continu un son existant, vous pouvez générer des données audio de façon dynamique. Vous pouvez générer des données audio lorsque vous affectez un écouteur associé à l’événement sampleData d’un objet Sound (l’événement sampleData est défini dans la classe SampleDataEvent du package flash.events). Dans cet environnement, l’objet Sound ne charge pas de données audio à partir d’un fichier. Il agit en fait en tant que socket pour les données audio qui lui sont diffusées en continu par l’intermédiaire de la fonction que vous affectez à cet événement.

Lorsque vous ajoutez un écouteur d’événement sampleData à un objet Sound, celui-ci demande périodiquement des données à ajouter au tampon audio. Ce tampon contient des données destinées à être lues par l’objet. Une fois appelé, la méthode play() de l’objet Sound distribue l’événement sampleData lorsqu’il demande de nouvelles données audio. Ceci n’est vrai que si l’objet Sound n’a pas chargé de données mp3 à partir d’un fichier.

L’objet SampleDataEvent comprend une propriété data . Dans votre écouteur d’événement, vous écrivez des objets ByteArray dans cet objet data . Les tableaux d’octets que vous écrivez dans cet objet s’ajoutent aux données figurant dans le tampon que lit l’objet Sound. Le tableau d’octets que contient le tampon est un flux de valeurs en virgule flottante comprises en -1 et 1. Chaque valeur représente l’amplitude d’un canal unique (gauche ou droit) d’un échantillon audio. Le son est échantillonné à 44 100 échantillons par seconde. Chaque échantillon contient un canal gauche et un canal droit, entrelacés sous forme de données en virgule flottante dans le tableau d’octets.

Dans votre fonction gestionnaire, vous utilisez la méthode ByteArray.writeFloat() pour écrire dans la propriété data de l’événement sampleData . Par exemple, le code suivant génère une onde sinusoïdale :

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

Lorsque vous appelez Sound.play() , l’application commence à appeler votre gestionnaire d’événement pour demander des données audio d’échantillonnage. Elle continue à envoyer des événements pendant la lecture du son jusqu’à ce que vous cessiez de fournir des données ou que vous appeliez la méthode SoundChannel.stop() .

La période d’attente de l’événement varie selon les plates-formes et peut encore changer dans les futures versions de Flash Player et AIR. Plutôt que de vous appuyer sur une période d’attente spécifique, calculez-la. Pour calculer la période d’attente, utilisez la formule suivante :

(SampleDataEvent.position / 44.1) - SoundChannelObject.position

Fournissez entre 2 048 et 8 192 échantillons à la propriété data de l’objet SampleDataEvent (pour chaque appel du gestionnaire d’événement). Pour des performances optimales, fournissez autant d’échantillons que possible (8 192 au maximum). Moins vous fournissez d’échantillons, plus il est probable que des bruits parasites se feront entendre pendant la lecture. Ce comportement varie selon les plates-formes et peut se produire dans diverses situations, lors du redimensionnement du navigateur, par exemple. Un code qui fonctionne correctement sur une plate-forme lorsque vous fournissez uniquement 2 048 échantillons ne marchera pas aussi bien sur une autre plate-forme. S’il vous faut le plus court délai d’attente possible, envisagez de permettre à l’utilisateur de sélectionner la quantité de données.

Si vous fournissez moins de 2 048 échantillons (par appel de l’écouteur d’événement sampleData ), l’application s’arrête à l’issue de la lecture des échantillons restants. L’objet SoundChannel distribue alors un événement SoundComplete.

Modification du son issu de données MP3

La méthode SoundExtract vous permet d’extraire des données d’un objet Sound. Vous pouvez utiliser (et modifier) ces données pour accéder en écriture au flux continu dynamique d’un autre objet Sound à des fins de lecture. Ainsi, le code suivant utilise les octets d’un fichier MP3 chargé et les transmet par le biais d’une fonction de filtre, 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; 
}

Limitations relatives aux sons générés

Lorsque vous utilisez un écouteur d’événement sampleData avec un objet Sound, les seules autres méthodes Sound activées sont Sound.extract() et Sound.play() . L’appel d’autres méthodes ou propriétés donne lieu à une exception. Tous les méthodes et propriétés de l’objet SoundChannel sont toujours activées.