Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Enregistrer le son du Microphone

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Stefbuet, le 12 mars 2011

Dans cet article je vais traiter de la capture du son depuis un microphone avec la nouvelle API de création dynamique de sons de Flash1), puis j’expliquerais comment convertir ces données au format WAV et comment les envoyer sur un serveur ou les enregistrer sur le poste du client. La compression MP3 et OGG sera abordée en fin d’article.

Voici un exemple d'application, qui nécessite le Flash Player 10.2 au minimum

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Récupérer les données du microphone

Tout d’abord, il faut récupérer l’instance unique Microphone qui est un singleton. Pour cela on utilise la fonction statique Microphone.getMicrophone. Attention cette méthode demandera à l’utilisateur avec un petit panneau s’il accepte de vous donner accès aux données de son micro, dans le cas contraire vous ne pourrez pas manipuler ces données.

Une fois le microphone récupéré, nous pouvons le configurer. Pour une bonne qualité d’enregistrement mettre le flux à 44100Hz (propriété rate à 44). Le volume de réception du micro est traduit par la propriété gain qui par default est de 50 mais peut monter jusqu’a 100. Ensuite une fonction intéressante permettant d’éviter l’écho dans le micro qui survient par exemple quand le micro est trop près des haut-parleurs peut être activée (recommandé) avec la fonction setUseEchoSuppression. Vous pouvez choisir de laisser Flash activer ou pas le flux de données en fonction du volume sonore avec la propriété enableVAD ce qui peut être pratique pour une application type VoIP mais pour de l’enregistrement pur nous la désactiverons. Pour finir vous pouvez choisir d’entendre ce que le microphone capte dans les hauts parleurs en utilisant la méthode setLoopBack. Ce qui nous donne au final pour initialiser notre microphone avant de commencer l’enregistrement:

 
var micro:Microphone = Microphone.getMicrophone();
micro.enableVAD=false;
micro.rate=44;
micro.setUseEchoSuppression(true);
micro.setLoopBack(true);

Nous allons créer un ByteArray afin de contenir les valeurs d’amplitude de l’onde mécanique du son enregistré par le microphone. Ces données sont renvoyées périodiquement par le microphone avec un événement SAMPLE_DATA que nous allons écouter. Une fois ces données enregistrées, il est possible d’effectuer de multiples traitements dessus, par exemple rendre le son plus grave pour une voix à la Dark Vador, ou rajouter de l’echo, etc…

 
var recordingData:ByteArray=new ByteArray();
micro.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicrophoneData);
function onMicrophoneData(e:SampleDataEvent):void {
	while(e.data.bytesAvailable)
		recordingData.writeFloat(e.data.readFloat());
}

Gestion des données

Mais comment utiliser les données enregistrées ? Nous pouvons jouer ce son ultérieurement à l’enregistrement grâce à l’API de génération dynamique de son de Flash. Pour cela nous créons un son écoutons l’événement SAMPLE_DATA qui sera appelé a chaque fois que le son nécessité des données, c’est à ce moment qui nous lui fournirons les données enregistrées par le micro :

 
var recordedSound:Sound=new Sound();
recordingData.position=0;
recordedSound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSoundSample);
 
recordedSound.play();
 
function onSoundSample(e:SampleDataEvent):void {
 
	for(var i:Number=0; (i<4096)&&(recordingData.bytesAvailable>0); i++) {
		var data:Number=recordingData.readFloat();
		e.data.writeFloat(data);
		e.data.writeFloat(data);
	}
}

Mais comment enregistrer ce son? Sous cette forme brute les données ne sont pas exploitable ou presque par les logiciels de lecture audio. Le format audio le plus simple est surement le format WAV qui consiste à rajouter un ‘header’ avant toutes les données brutes. La conversion du BytesArray de données brute en BytesArray de données WAV peut être effectué à l’aide de différentes classes assez nombreuses sur le net, dont une sur MediaBox mais ici nous utiliserons celle distribué officiellement par Adobe, disponible ici.

L’utilisation est très simple. On définit le nombre de canal du son, dans notre cas 1 à moins que vous ayez un microphone stéréo :-P. Il faut aussi définir le flux audio c'est-à-dire 44110Hz et le nombre de bit utilisés pour le flux, 16bit pour nous.

 
var writer:WAVWriter=new WAVWriter();
var wavData:ByteArray=new ByteArray();
writer.numOfChannels = 1;
writer.sampleBitRate = 16; 
writer.samplingRate = 44100;

Et on lance la conversion qui s’effectue très rapidement contrairement à un traitement de type encodage MP3, Ogg qui nécessite l’utilisation d’événements pour suivre le traitement. Nous obtenons alors un ByteArray qu’il suffit d’enregistrer au format *.wav pour l’utiliser ultérieurement.

 
recordingData.position=0;
var waveData:ByteArray=new ByteArray() ;
writer.processSamples(wavData, recordingData, 44100, 1);

Enregistrement des données

Il ne reste plus qu’a sauvegarder le fichier WAV. Pour cela deux possibilitées, soit l’enregistrer sur le poste du client en passant par l’API FileReference :

var fileRef:FileReference = new FileReference ();
fileRef.save(wavData, "monSon.wav" );

Ou alors enregistrer le son sur un serveur distant avec un petit script PHP qu'on appel à partir de Flash:

 
var req:URLRequest=new URLRequest("http://mywebsite.com/uploadSound.php);
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
req.requestHeaders.push(header);
req.method = URLRequestMethod.POST;
req.data = wavData;
 
var l:Loader=new URLLoader();
l.load(req);

Pour faire propre n’oubliez pas d’écouter les événements COMPLETE et IO_ERROR. La page Php est très basique, elle se contente de sauvegarder les données reçues dans un fichier avec une extension Wav sur le serveur :

 
<?php
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
	$imageBytes = $GLOBALS["HTTP_RAW_POST_DATA"];
	$file = fopen(“testFichier.wav”, "w");
 
	if(!fwrite($file, $imageBytes)){
		echo "ERROR";
	}
	else {
		echo "OK";
	}
 
	fclose($file);
}
?>

Conclusion

Maintenant vous vous apercevrez que le format WAV est très lourd car il ne possède aucune compression. Cependant il existe plusieurs portages de bibliothèques d’encodage audio vers Flash avec l’API Alchemy, ce qui permet d’aller relativement vite. Mais la vitesse reste relativement lente en fonction de type de compression nécessaire.

Vous pouvez utiliser assez simplement pour réaliser de la compression Mp3 le portage de la bibliothèque LAME disponible ici : https://github.com/kikko/Shine-MP3-Encoder-on-AS3-Alchemy Note : Avant d'encoder votre ByteArray avec cette lib mettez la position de ce ByteArray à 0, sinon vous aurez une erreur (format non reconnus) car cette lib part du principe que votre ByteArray est tout prés à être utilisé (donc avec une position à 0).

J’ai aussi eu l’occasion d’utiliser l’encodage OGG, mais celui-ci est plus lent et à le désavantage de ne pas pouvoir être chargé en streaming nativement par Flash. Cependant on peut décoder l’OGG et le lire sous Flash après chargement complet du son, pratique pour les petits sons. Un encodeur Ogg est disponible ici : http://labs.byhook.com/2011/02/15/ogg-vorbis-encoder-for-flash-alchemy-series-part-1/

Sources de l'exemple

Par lilive, le 20/03/2011

J'ai ajouté à cet intéressant tutoriel la petite application qui est en haut de page. J'ai utilisé les méthode de Stéphane, et cherché comment faire des effets simples (les modes Dark Vador et Toon). Pour compiler j'ai utilisé le Flex SDK 4.5.
1) Vous devez donc publier votre application pour le Flah Player 10.2 minimum