2016-02-20 3 views
0

Je lisais cet article: http://www.java-tips.org/java-se-tips-100019/120-javax-sound/917-capturing-audio-with-java-sound-api.html Je ne veux pas écrire tout le code de l'article avant ...Java Comprendre ByteArrayOutputStream et ByteArrayInputStream

Je dois clarifier ma compréhension et j'ai besoin d'explications sur les utilisations de ByteArrayInputStream et ByteArrayOutputStream ...

Basé sur le code complet:

Dans le captureAudio() méthode se concentrant sur la boucle tandis que

while (running) { 
    int count = line.read(buffer, 0, buffer.length); 
    if (count > 0) { 
     out.write(buffer, 0, count); 
    } 
} 
out.close(); 

Par définition (vérifier la ligne 64 et 65):

final TargetDataLine line = (TargetDataLine) 
    AudioSystem.getLine(info); 

sur la ligne 79: la ligne est le microphone et audio // Lit les données du tampon d'entrée de la ligne de données. En d'autres termes, les octets reçus du microphone sont localisés ou stockés dans les octets buffer.

Sur la ligne 81:

 out.write(buffer, 0, count); 

out est un objet ByteArrayOutputStream ..

La classe ByteArrayOutputStream de l'API Java IO vous permet de des données de capture écrites dans un flux dans un tableau . Vous écrivez vos données à le ByteArrayOutputStream et lorsque vous avez terminé, vous appelez la méthode ByteArrayOutputStream toByteArray() pour obtenir toutes les données écrites dans un tableau d'octets. Le tampon se développe automatiquement au fur et à mesure que les données y sont écrites.

Dans mes mots: ByteArrayOutputStream croîtra en prenant les octets de mémoire tampon définis en quantité count

De l'autre côté:

Dans la méthode playAudio().

Je peux voir que la première ligne (ligne 101 du code complet) tous les octets sont prises !!!

byte audio[] = out.toByteArray(); 

https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html#toByteArray()

crée un tableau d'octets nouvellement allouée. Sa taille est la taille actuelle de ce flux de sortie et le contenu valide de la mémoire tampon ont été copiés en .

Maintenant, dans les lignes (102 et 103)

InputStream input = 
    new ByteArrayInputStream(audio); 

Sur les lignes (105 jusqu'à 107), les octets sont transmis throught:

final AudioInputStream ais = 
    new AudioInputStream(input, format, 
    audio.length/format.getFrameSize()); 

mise au point dans la boucle de temps et près de lignes

int count; 
while ((count = ais.read(
    buffer, 0, buffer.length)) != -1) { 
    if (count > 0) { 
     line.write(buffer, 0, count); 
    } 
    } 
line.drain(); 
line.close(); 

Les octets proviennent de ais

Et la ligne (lignes 110 et 111) représente les haut-parleurs

final SourceDataLine line = (SourceDataLine) 
    AudioSystem.getLine(info); 

La Question 1 est:

out, de méthode captureAudio, prendra octets à l'infini, mais comment input, à partir de playAudio méthode, prend exactement les octets requis pour les sonner de manière cohérente?

Rappelez-vous: out.toByteArray(); prendre tous les octets, mais les haut-parleurs pas à plusieurs reprises les mêmes octets ...

Le Question 2 est:

Puis-je gérer cette situation de lecture microphone (TargetDataLine) et écrire à haut-parleur (SourceDataLine) sans utiliser ces deux objets (ByteArrayOutputStream et ByteArrayInputStream) comme article connexe?

Comme code suivant:

while (running) { 
    int count = microphone.read(buffer, 0, buffer.length); 
    if (count > 0) { 
     speaker.write(buffer, 0, count); 
    } 
} 
speaker.drain(); 
speaker.close(); 

Le Question 3 est:

Comment puis-je mettre en œuvre un répéteur (son de capture du microphone et jouer sur les haut-parleurs, infiniment, 1 ou 2 heures)?

Remarque: Sans vous soucier des problèmes de stockage octets en mémoire (sans stocker dans le fichier) sans délais de lecture.

+1

d'abord nous avons besoin de vous comprendre! - ce n'est pas compréhensible - peut-être vous mieux de l'afficher en espagnol ou dans une autre langue – gpasch

+0

@ gpasch, quel texte n'est pas clair selon vous? –

Répondre

0

Je ne suis pas familier avec l'API Sound. Mais, il n'y a pas de raison particulière pour que votre dernier extrait de code ne fonctionne pas en supposant que l'entrée peut être lue sans fin, alors que la sortie peut être alimentée sans fin. Le seul problème est de savoir si une fin ou l'autre "stalles" (ici mon manque de connaissance de l'API Sound vient jouer).

Si le côté de sortie se bloque pour une raison quelconque, alors le côté d'entrée peut potentiellement déborder de la mémoire tampon interne, perdant ainsi des informations. Si l'entrée est bloquée, ce n'est pas vraiment un problème. Je ne sais pas si c'est un problème réel avec l'API Sound. En revanche, si deux threads se produisaient (ou utilisaient une E/S Async), l'un gérant l'entrée et l'autre gérant la sortie, le côté entrée donnerait à votre programme la possibilité de mettre en cache les données entrantes en utilisant votre sémantique plutôt que les API. sémantique, tandis que le canal de sortie est bloqué.Les problèmes avec les ByteArrayStreams sont simplement des mécanismes à remplir et tout tableau d'octets en expansion, sans le gérer vous-même, et, de même, ajouter une sémantique de flux à un tableau d'octets sous-jacent (qui possède toutes sortes de capacités utiles).

+0

Thaks Je pense que ByteArrayOutputStream et ByteArrayInputStream vont croître, mais les deux doivent être en train de rétrécir (d'un côté, il y aura des octets, mais de l'autre côté, ils seront supprimés). Comme bytearrayoutputstream va décrémenter sa taille (ou sera à nouveau vide) ?, car chaque 'out.write (buffer, 0, count);' est appelé, bytearoutoutputs sera croissant, et How does pass (les derniers octets exacts lus) à ByteArrayInputStream? ou Comment 'ByteArrayInputStream (audio);' lire exactement les derniers octets non lus? 'out.toByteArray()' voici tous les octets (même les premiers octets pour les derniers octets) –