Dimanche 5 avril 2009 7 05 /04 /Avr /2009 15:29

Qu'il me soit permis de m'éloigner un peu de la finance et de présenter, dans un registre bien plus léger, un tutoriel sur l'utilisation des nouvelles fonctionnalités de la classe Sound sous le flash player 10.

Les développeurs AS3 que vous êtes auront bien-sûr constaté que la classe Sound diffuse, depuis la sortie de flash player 10, un nouvel événement: SampleData. Cet événement est distribué lorsque le lecteur demande de nouvelles données audio et permet de gérer le son généré dynamiquement ou lu. Dans cet environnement, l'objet Sound ne contient pas vraiment de données audio. Il agit en fait en tant que socket pour les données audio qui lui sont distribuées en continu par l'intermédiaire de la fonction écouteur. On va ainsi être en mesure de collecter, via des BytesArray, des échantillons du son généré ou lu. Le flash player 10 inclus parmi ses nouveautés une nouvelle fonctionnalité qui manquait cruellement aux anciennes versions: la méthode FileReference.save( data:*, defaultFileName:String = null). Les données collectées, qui en cet instant sont au format RAW (Real Audio Wrapper), vont alors pouvoir être encodées puis écrites en dur, via cette méthode, sur le disque. Pour plus de précision sur le format des données, on pourra se tourner vers les PCM (Modulation d'impulsion codée). Enfin présentons la méthode star de ce tutoriel: Sound.extract(target:ByteArray, length:Number, startPosition:Number = -1):Number. Cette méthode doit être employée lorsque l'on gére un son généré dynamiquement ou lu, à l'aide d'une fonction que l'on affecte à l'événement SampleData pour un autre objet Sound. En d'autres termes, on va utiliser cette méthode pour extraire les données audio d'un objet Sound. Le flash player autorise un fourchette pour le nombre d'échantillons à fournir: [2048, 8192]. La qualité sera bien-sûr maximal avec 8192.


Pour commencer, nous allons déclarer les objets dont nous avons besoins:


var sound:Sound = new Sound();
var dynamicSound:Sound = new Sound();
var soundChannel:SoundChannel = new SoundChannel();
var samples:ByteArray = new ByteArray();
var sndBytes:ByteArray = new ByteArray();
var myFileRefSave:FileReference = new FileReference();


Sur la scène nous disposons de 2 boutons, l'un de label "Record" et d'occurence "record" sert à lancer le son et collecter les échantillons et l'autre de label "Save" et d'occurence "save" sert à appeler la méthode save de FileReference.


record.addEventListener( MouseEvent.MOUSE_DOWN, startRecord );

function startRecord( pEvt:MouseEvent )
{
    sound = new Track();
   
    dynamicSound.addEventListener( SampleDataEvent.SAMPLE_DATA, sampleData );
    soundChannel = dynamicSound.play();
   
    save.addEventListener( MouseEvent.MOUSE_DOWN, stopRecord );
}

function sampleData( pEvt:SampleDataEvent ):void
{
    samples.position = 0;
   
    var len:Number = sound.extract( samples, 8192 );
   
    var left:Number;
    var right:Number;
   
    samples.position = 0;
   
    sndBytes.writeBytes( samples );
   
    for ( var c:int=0; c < len; c++ )
    {
        left = samples.readFloat();
        right = samples.readFloat();
       
        pEvt.data.writeFloat( left );
        pEvt.data.writeFloat( right );
    }
}

function stopRecord( pEvt:MouseEvent )
{
    myFileRefSave.save( FxWaveEncoder.encoder( sndBytes ), "snd.wav" );
}


Notons que Track est le nom de classe (ou liaison pour les anciens d'AS2) d'un son placé dans la librairie.
Avant d'être écrit on converti le son via la méthode static:
FxWaveEncoder.encoder( pSamples:ByteArray, channels:int = 2, bits:int = 16, rate:int = 44100 ):ByteArray

Voici la classe FxWaveEncoder qui permet d'encoder le format. Je remercie les membres de Médiabox qui m'ont aidé à calibrer cette classe:


package
{
    import flash.utils.Endian;
    import flash.utils.ByteArray;
   
    import flash.events.Event;

    public class FxWaveEncoder
    {
       
        // writeHeader ( 2, 16, 44100 )
        static public function encoder( pSamples:ByteArray, channels:int = 2, bits:int = 16, rate:int = 44100 ):ByteArray
        {
            var samples:ByteArray = new ByteArray();
           
            samples.writeBytes( FxWaveEncoder.convert( pSamples ) );
           
            var bytes: ByteArray = new ByteArray();
           
            bytes.endian = Endian.LITTLE_ENDIAN;
           
            bytes.writeUTFBytes( 'RIFF' );
           
            bytes.writeInt( samples.length - 8 );
           
            bytes.writeUTFBytes( 'WAVE' );
           
            bytes.writeUTFBytes( 'fmt ' );
           
            bytes.writeInt( int( 16 ) );
           
            bytes.writeShort( int( 1 ) );
           
            bytes.writeShort( channels );
           
            bytes.writeInt( rate );
           
            bytes.writeInt( int( rate * channels * ( bits / 8 ) ) );
           
            bytes.writeShort( int( channels * ( bits / 8 ) ) );
           
            bytes.writeShort( bits );
           
            bytes.writeUTFBytes( 'data' );
           
            bytes.writeInt( samples.length - 44 );
           
            bytes.writeBytes( samples );
           
            bytes.position = 0;
           
            return bytes;
        }
        static private function convert( pBytes:ByteArray ):ByteArray
        {
            var ba:ByteArray = new ByteArray ( ) ;
           
            ba.endian = Endian.LITTLE_ENDIAN;
           
            pBytes.position = 0;
           
            while( pBytes.position < pBytes.length ) ba.writeShort( pBytes.readFloat() * 32767 );
           
            return ba;
        }
    }
}


Pour les détails des chunks on pourra se référer aux liens de bas de page de cette article: WAVE
Ce n'est pas très sexy mais bien pratique.

Et voici le résultat:

Par Gilles De Truchis - Publié dans : Programmation AS3
Ecrire un commentaire - Voir les 0 commentaires
Retour à l'accueil

Un problème d'affichage...?

Certaines pages de ce site contiennent des animations Flash qui nécessitent la dernière version du flash player.

haut de page

Varennes EcoFin

Mon site internet migre vers une nouvelle adresse: Varennes EcoFin. Il s'agit d'un site en flash recentré sur mes travaux de recherches, ma thèse et des resources pour les étudiants (programmes, bases de données etc.). Pour accéder à la version sans flash (HTML5): Varennes EcoFin Sky.

Présentation

Recherche

Music Player

 
Créer un blog gratuit sur over-blog.com - Contact - C.G.U. - Signaler un abus - Articles les plus commentés