Java AudioSystem 和 TargetDataLine

发布于 2024-07-14 20:59:06 字数 1749 浏览 9 评论 0原文

我正在尝试从 PC 的线路输入捕获音频,为此我使用 AudioSystem 类。 静态 AudioSystem.write 方法有两种选择之一:写入文件或写入流。 我可以让它很好地写入文件,但是每当我尝试写入流时,我都会抛出 java.io.IOException (未指定流长度)。 至于我的缓冲区,我使用的是 ByteArrayOutputStream。 我是否应该使用另一种流或在其他地方弄乱?

此外在相关主题中,可以对 (TargetDataLine) 直接调用 阅读。 这是进行音频捕获或使用 AudioSystem 的首选方式吗?

更新 请求的源代码:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不即不离 2024-07-21 20:59:06

来自 AudioSystem.write JavaDoc:

将表示指定文件类型的音频文件的字节流写入提供的输出流。 某些文件类型要求将长度写入文件头; 除非事先知道长度,否则无法从头到尾写入此类文件。 如果音频文件类型中的长度为 AudioSystem.NOT_SPECIFIED,则尝试写入此类类型的文件将失败并抛出 IOException。

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.

夜司空 2024-07-21 20:59:06

由于 Wave 格式要求在文件开头写入长度,因此编写器正在查询 AudioInputStreamgetFrameLength 方法。 当返回 NOT_SPECIFIED 时(因为您记录的“实时”数据的长度尚未指定),写入器会抛出异常。

面向文件的方法通过将虚拟数据写入长度字段来解决此问题,然后在写入完成后重新打开文件并覆盖文件的该区域。

使用不需要提前长度 (au) 的输出格式,或使用返回有效帧长度的 AudioInputStream,或使用 API 的 File 版本。

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.

无妨# 2024-07-21 20:59:06

您应该查看 Richard Baldwin 的 教程爪哇的声音。 文章底部有完整的源列表,其中他使用 TargetDataLine 的读取来捕获音频。

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.

感情洁癖 2024-07-21 20:59:06

您还可以尝试使用 JMF,虽然有点麻烦,但比 javax.sound.sampled 的东西效果更好一些。 JMF 页面上有很多教程描述如何从线路输入或麦克风通道进行录音。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文