2009-02-28 27 views
4

J'essaie de capturer l'audio de l'entrée ligne de mon PC, pour ce faire, j'utilise la classe AudioSystem. Il existe deux choix possibles avec la méthode statique AudioSystem.write: Écrire dans un fichier ou Écrire dans un flux. Je peux l'obtenir pour écrire dans un fichier très bien, mais chaque fois que j'essaie d'écrire dans un flux, java.io.IOException est lancé (la longueur du flux n'est pas spécifiée). En ce qui concerne mon tampon, j'utilise un ByteArrayOutputStream. Y a-t-il un autre type de flux que je suis censé utiliser ou faire des erreurs ailleurs?Java AudioSystem et TargetDataLine

En outre dans un sujet connexe, on peut échantillonner la ligne audio (TargetDataLine) directement en appelant read. Est-ce la manière préférée de faire de la capture audio ou de l'utilisation de AudioSystem?

Mise à jour code source qui a été demandé:

final private TargetDataLine line; 
final private AudioFormat format; 
final private AudioFileFormat.Type fileType; 
final private AudioInputStream audioInputStream; 
final private ByteArrayOutputStream bos; 

// Constructor, etc. 

public void run() 
{ 
    System.out.println("AudioWorker Started"); 
    try 
    { 
     line.open(format); 
     line.start(); 

     // This commented part is regarding the second part 
     // of my question 
     // byte[] buff = new byte[512]; 
     // int bytes = line.read(buff, 0, buff.length); 

     AudioSystem.write(audioInputStream, fileType, bos); 

    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 

    System.out.println("AudioWorker Finished"); 
} 


// Stack trace in console 
AudioWorker Started 
java.io.IOException: stream length not specified 
    at com.sun.media.sound.WaveFileWriter.write(Unknown Source) 
    at javax.sound.sampled.AudioSystem.write(Unknown Source) 
    at AudioWorker.run(AudioWorker.java:41) 
AudioWorker Finished 
+0

pouvez-vous poster un peu de code? –

+0

Publiez la trace de la pile, au moins les premières images, jusqu'à votre application. – erickson

Répondre

2

De AudioSystem.write JavaDoc:

Ecrit un flux d'octets représentant un fichier audio du type de fichier spécifié à la sortie flux fourni. Certains types de fichiers requièrent que la longueur soit écrite dans l'en-tête du fichier; ces fichiers ne peuvent pas être écrits du début à la fin à moins que la longueur ne soit connue à l'avance. Une tentative d'écriture d'un fichier d'un tel type échouera avec une exception IOException si la longueur dans le type de fichier audio est AudioSystem.NOT_SPECIFIED.

+1

Cela ressemble à l'écriture de fichiers (bien que les fichiers sont aussi des flux ..)? Mais comment est-ce applicable à l'écriture sur un OutputStream? Cela signifie-t-il que ce n'est pas possible? – yxk

+0

@srand, je pense que cela a un sens, puisque vous n'êtes pas en streaming (ce qui nécessite un mécanisme différent), donc vous devez essentiellement spécifier la longueur avant d'écrire dans le flux de sortie. – Johnydep

1

Vous pouvez également essayer d'utiliser JMF qui est un peu poilu mais fonctionne un peu mieux que javax.sound.sampled choses. Il y a quelques tutoriels sur la page JMF qui décrivent comment enregistrer à partir de la ligne ou des canaux de micro.

2

Étant donné que le format Wave requiert que la longueur soit écrite au début du fichier, l'enregistreur interroge la méthode getFrameLength de votre AudioInputStream. Lorsque cela renvoie NOT_SPECIFIED — parce que votre enregistrement "en direct" des données de longueur encore indéterminée — l'écrivain lève l'exception.

Le File-orienté contourne cela en écrivant des données factices dans le champ de longueur, puis en rouvrant le fichier lorsque l'écriture est terminée et en écrasant cette zone du fichier.

Utilisez un format de sortie qui n'a pas besoin de la longueur à l'avance (au) ou utilisez un AudioInputStream qui renvoie une longueur de trame valide ou utilisez la version File de l'API.

+0

D'après ce que je comprends, AudioSystem.write écrit uniquement dans les fichiers? – yxk

+1

Quelle est l'utilité de la signature avec OutputStream alors? –

+0

@AlessandroDionisi Cela fonctionne pour certains formats, comme .au – erickson

2

Vous devriez consulter le tutoriel Richard Baldwin's sur le son Java. Il y a une liste complète des sources au bas de l'article où il utilise la lecture de TargetDataLine pour capturer l'audio.