Java AudioSystem 和 TargetDataLine
我正在尝试从 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
来自 AudioSystem.write JavaDoc:
From AudioSystem.write JavaDoc:
由于 Wave 格式要求在文件开头写入长度,因此编写器正在查询
AudioInputStream
的getFrameLength
方法。 当返回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 yourAudioInputStream
. When this returnsNOT_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 theFile
version of the API.您应该查看 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.
您还可以尝试使用 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.