gpt4 book ai didi

java - SourceDataLine 跳过指定数量的字节(JavaSound)

转载 作者:行者123 更新时间:2023-12-02 11:24:00 27 4
gpt4 key购买 nike

由于某些原因,我需要使用 SourceDataLine 而不是 Clip 在程序中播放音频。将framePosition(我想跳过)分配给Clip很容易,但是SourceDataLine没有这个方便的API。

我想使用AudioInputStream.skip(n),其中n是请求的要跳过的字节数。但如果我想跳过 1.25 秒,我不知道如何正确设置 n 。我怎样才能做到这一点?

我的代码来自这个site(MP3 player sample) .
请检查函数stream

中的 in.skip()
public class AudioFilePlayer {

public static void main(String[] args) {
final AudioFilePlayer player = new AudioFilePlayer ();
player.play("something.mp3");
}

public void play(String filePath) {
final File file = new File(filePath);

try (final AudioInputStream in = getAudioInputStream(file)) {

final AudioFormat outFormat = getOutFormat(in.getFormat());
final Info info = new Info(SourceDataLine.class, outFormat);

try (final SourceDataLine line =
(SourceDataLine) AudioSystem.getLine(info)) {

if (line != null) {
line.open(outFormat);
line.start();
stream(getAudioInputStream(outFormat, in), line);
line.drain();
line.stop();
}
}

} catch (UnsupportedAudioFileException
| LineUnavailableException
| IOException e) {
throw new IllegalStateException(e);
}
}

private AudioFormat getOutFormat(AudioFormat inFormat) {
final int ch = inFormat.getChannels();
final float rate = inFormat.getSampleRate();
return new AudioFormat(PCM_SIGNED, rate, 16, ch, ch * 2, rate, false);
}

private void stream(AudioInputStream in, SourceDataLine line)
throws IOException {
in.skip(proper number); //There is my question
final byte[] buffer = new byte[65536];
for (int n = 0; n != -1; n = in.read(buffer, 0, buffer.length)) {
line.write(buffer, 0, n);
}
}}

最佳答案

每个 AudioInputStream 都有一个 AudioFormat 对象,您可以通过 format() 获取该对象。方法。要了解 1.25 秒有多少字节,您需要计算 1.25 秒有多少帧以及帧有多大:

AudioFormat format = audioInputStream.format();
float b = format.getFrameSize() * format.getFrameRate() * 1.25f;
// round to nearest full frame
long n = (b/format.getFrameSize())*format.getFrameSize();
long skipped = audioInputStream.skip(b);
// you might want to check skipped to see whether the
// requested number of bytes was indeed skipped.

解释一下:

  • 是所有 channel 的一个完整样本。因此,如果您有立体声信号,则一帧就是两个样本,即左侧和右侧。
  • FrameSize 是帧使用的字节数。对于 CD 质量,这将是每 channel 2 字节,即每帧 4 字节(在立体声情况下)。
  • FrameRate是每秒的帧数。
  • 由于您不应该分割帧,因此必须舍入为整个帧。

请注意,上面的代码假设您有 PCM 编码的音频。如果您有其他内容,请首先使用 pcmStream = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, audioInputStream) 转码为 PCM。

关于java - SourceDataLine 跳过指定数量的字节(JavaSound),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49725091/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com