2010-05-29 5 views
1

Veuillez consulter la classe que j'ai créée au http://textsnip.com/see/WAVinAS3 pour analyser un fichier WAVE dans ActionScript 3.0.Comment lire un fichier WAV dans ActionScript?

Cette classe extrait correctement les informations de l'en-tête de fichier & blocs fmt, en isolant le bloc de données et en créant un nouveau ByteArray pour stocker le bloc de données. Il faut dans un fichier WAVE non compressé avec une étiquette de format 1. Le fichier WAVE est intégré dans mon SWF avec la balise embed Flex suivante:

[Embed(source="some_sound.wav", mimeType="application/octet-stream")] 
public var sound_class:Class; 
public var wave:WaveFile = new WaveFile(new sound_class()); 

Une fois le bloc de données est séparé, la classe tente de faire son objet qui peut diffuser les échantillons à partir du bloc de données. J'ai des problèmes avec le processus de streaming, probablement parce que je ne suis pas bon en maths et ne sais pas vraiment ce qui se passe avec les bits/octets, etc.

Voici les deux documents que j'utilise en tant que référence pour le format de fichier WAVE: http://www.lightlink.com/tjweber/StripWav/Canon.html https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

en ce moment, le fichier en cours de lecture de retour! En temps réel, même! Mais ... le son est vraiment déformé. Que se passe-t-il?

Répondre

1

Le problème est dans le gestionnaire onSampleData.

Dans votre fichier wav, les amplitudes sont stockées en tant que shorts signés, c'est-à-dire les bits 16 bits. Vous les lisez en 32 bits signés flotteurs. Les entiers et les flottants sont représentés différemment en binaire, ce qui ne fonctionnera jamais correctement.

Maintenant, le lecteur attend des flottants. Pourquoi ont-ils utilisé des flotteurs? Je ne sais pas avec certitude, mais une bonne raison est que cela permet au joueur d'accepter une valeur normalisée pour chaque échantillon. De cette façon, vous n'avez pas à vous préoccuper du bitdept utilisé par le joueur ou de savoir quel est le bitdept utilisé: la valeur max est 1, et la valeur min est -1, et c'est tout. Donc, votre problème est que vous devez convertir votre short signé en un float signé normalisé. Un court-circuit prend 16 bits, donc il peut stocker 2^16 (ou 65 536) valeurs différentes. Comme il est signé et que le signe prend un bit, la valeur maximale sera 2^15. Donc, vous savez que votre entrée est la plage -32 768 ... 32 767.

La valeur d'échantillon est normalisée et doit être comprise entre -1 et 1, d'autre part. Par conséquent, vous devez normaliser votre entrée. C'est assez facile. Il suffit de prendre la valeur lue et le diviser par la valeur maximale, et que vous avez votre amplitude d'entrée convertie à la plage -1 ... 1.

Quelque chose comme ceci:

private function onSampleData(evt:SampleDataEvent):void 
    { 
     var amplitude:int = 0; 
     var maxAmplitude:int = 1 << (bitsPerSample - 1); // or Math.pow(2, bitsPerSample - 1); 
     var sample:Number = 0; 
     var actualSamples:int = 8192; 
     var samplesPerChannel:int = actualSamples/channels; 

     for (var c:int = 0; c < samplesPerChannel ; c++) { 
      var i:int = 0; 
      while(i < channels && data.bytesAvailable >= 2) { 
       amplitude = data.readShort(); 
       sample = amplitude/maxAmplitude; 
       evt.data.writeFloat(sample); 
       i++; 
      } 
     } 
    } 

Un couple de choses à Note:

  1. maxAmplitude pourrait (et probablement devrait) être calculé lorsque vous lisez le bitdepth. Je le fais dans la méthode juste pour que vous puissiez le voir dans le code collé.

  2. Bien que maxAmplitude est calculé basé sur la lecture bitdepth et donc sera correct pour tout bitdepth, je lis un short dans la boucle, de sorte si votre fichier wav arrive à utiliser un différent bitdepth, ce La fonction ne fonctionnera pas correctement. Vous pouvez ajouter un commutateur et lire le nombre de données nécessaire (c'est-à-dire, readInt si bitdepth est 32). Cependant, 16 bits est une telle norme largement utilisée, que je doute que cela est pratiquement nécessaire. Cette fonction fonctionne pour stéréo wavs. Si vous voulez que cela fonctionne pour mono, réécrivez-le pour écrire deux fois le même échantillon . C'est-à-dire, pour chaque lecture, vous faites deux écritures (votre entrée est mono, mais le lecteur attend 2 échantillons ).

  3. J'ai enlevé la prise EOF, comme vous pouvez savoir si vous avez suffisamment de données pour lire de votre tampon de vérification bytesAvailable. Atteindre la fin de flux n'est pas exceptionnel de façon, OMI, donc je préfère contrôler ce cas sans un gestionnaire d'exception, mais c'est juste une préférence personnelle .

+0

PARFAIT! J'ai/savais/le problème était avec mon manque de compétences en mathématiques. J'ai plus ou moins branché ce droit dans ma classe et cela a fonctionné comme un charme. Réponse très bien écrite et complète. Je vous remercie! –

+0

Bien sûr. Content que cela ait aidé. –

Questions connexes