简体   繁体   中英

Java AudioSystem and TargetDataLine

I am trying to capture audio from the line-in from my PC, to do this I am using AudioSystem class. There is one of two choices with the static AudioSystem.write method: Write to a file Or Write to a stream. I can get it to write to a file just fine, but whenever I try to write to a stream I get thrown java.io.IOException (stream length not specified). As for my buffer I am using a ByteArrayOutputStream. Is there another kind of stream I am supposed to be using or messing up somewhere else?

Also in a related subject, one can sample the audio line in ( TargetDataLine ) directly by calling read . Is this the preferred way doing audio capture or using AudioSystem?

Update Source code that was requested:

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

From AudioSystem.write JavaDoc:

Writes a stream of bytes representing an audio file of the specified file type to the output stream provided. Some file types require that the length be written into the file header; such files cannot be written from start to finish unless the length is known in advance. An attempt to write a file of such a type will fail with an IOException if the length in the audio file type is AudioSystem.NOT_SPECIFIED.

Since the Wave format requires the length to be written at the beginning of the file, the writer is querying the getFrameLength method of your AudioInputStream . When this returns NOT_SPECIFIED —because your recording "live" data of as-yet-unspecified length— the writer throws the exception.

The File -oriented works around this by writing dummy data to the length field, then re-opening the file when the write is complete and overwriting that area of the file.

Use an output format that doesn't need the length in advance (au), or use an AudioInputStream that returns a valid frame length, or use the File version of the API.

You should check out Richard Baldwin's tutorial on Java sound. There's a complete source listing at the bottom of the article where he uses TargetDataLine's read to capture audio.

You could also try looking into using JMF which is a bit hairy but works a bit better that javax.sound.sampled stuff. There's quite a few tutorials on the JMF page which describe how to record from line in or mic channels.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM