简体   繁体   English

Java AudioSystem和TargetDataLine

[英]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. 我正试图从我的电脑的线路输入音频,为此我正在使用AudioSystem类。 There is one of two choices with the static AudioSystem.write method: Write to a file Or Write to a stream. 静态AudioSystem.write方法有两种选择之一:写入文件或写入流。 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). 我可以让它写入文件就好了,但每当我尝试写入流时,我都会抛出java.io.IOException(未指定流长度)。 As for my buffer I am using a ByteArrayOutputStream. 至于我的缓冲区,我使用的是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 . 同样在相关主题中,可以通过调用read直接对( TargetDataLine )中的音频线进行采样。 Is this the preferred way doing audio capture or using AudioSystem? 这是进行音频捕获或使用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: 来自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. 如果音频文件类型的长度为AudioSystem.NOT_SPECIFIED,则尝试写入此类型的文件将失败并出现IOException。

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 . 由于Wave格式需要在文件开头写入长度,因此writer会查询AudioInputStreamgetFrameLength方法。 When this returns NOT_SPECIFIED —because your recording "live" data of as-yet-unspecified length— the writer throws the exception. 当这返回NOT_SPECIFIED您的录制“实时”数据尚未指定长度 - 作者抛出异常。

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. File -oriented通过将伪数据写入长度字段,然后在写入完成时重新打开文件并覆盖文件的该区域来解决此问题。

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. 使用不需要提前长度的输出格式(au),或使用返回有效帧长度的AudioInputStream ,或使用API​​的File版本。

You should check out Richard Baldwin's tutorial on Java sound. 你应该查看Richard Baldwin关于Java声音教程。 There's a complete source listing at the bottom of the article where he uses TargetDataLine's read to capture audio. 在文章的底部有一个完整的源列表,他使用TargetDataLine的读取来捕获音频。

You could also try looking into using JMF which is a bit hairy but works a bit better that javax.sound.sampled stuff. 您也可以尝试使用JMF,它有点毛茸茸但是比javax.sound.sampled更好一点。 There's quite a few tutorials on the JMF page which describe how to record from line in or mic channels. JMF页面上有很多教程描述了如何从线路输入或麦克风通道录制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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