gpt4 book ai didi

java - 如何在 Java 中播放 Opus 编码的音频?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:17:18 24 4
gpt4 key购买 nike

在播放解码后的音频时,我设法发出了从咯咯声到尖叫声再到恶魔吟唱的各种声音。其中最接近的听起来类似于快进播放,播放仅持续约 15 秒。我已经尝试使用解码和 AudioSystem API 方法的大量参数组合,但似乎没有任何效果。

那么,是什么导致了这种音频失真?

此文件的 Opusinfo 显示如下:

Processing file "test.opus"...

New logical stream (#1, serial: 00002c88): type opus
Encoded with libopus 1.1
User comments section follows...
ENCODER=opusenc from opus-tools 0.1.9
Opus stream 1:
Pre-skip: 356
Playback gain: 0 dB
Channels: 1
Original sample rate: 44100Hz
Packet duration: 20.0ms (max), 20.0ms (avg), 20.0ms (min)
Page duration: 1000.0ms (max), 996.8ms (avg), 200.0ms (min)
Total data length: 1930655 bytes (overhead: 1.04%)
Playback length: 4m:09.173s
Average bitrate: 61.99 kb/s, w/o overhead: 61.34 kb/s
Logical stream 1 ended

此文件可使用 VLC 正确播放。

要解码我尝试使用以下库的文件:

下SSCCE

package me.justinb.mediapad.audio;

import org.gagravarr.ogg.OggFile;
import org.gagravarr.ogg.OggPacket;
import org.jitsi.impl.neomedia.codec.audio.opus.Opus;
import javax.sound.sampled.*;
import java.io.*;
import java.nio.ByteBuffer;

public class OpusAudioPlayer {
private static int BUFFER_SIZE = 1024 * 1024;
private static int INPUT_BITRATE = 48000;
private static int OUTPUT_BITRATE = 44100;
private OggFile oggFile;
private long opusState;
private ByteBuffer decodeBuffer = ByteBuffer.allocate(BUFFER_SIZE);
private AudioFormat audioFormat = new AudioFormat(OUTPUT_BITRATE, 16, 1, true, false);

public static void main(String[] args) {
try {
OpusAudioPlayer opusAudioPlayer = new OpusAudioPlayer(new File("test.opus"));
opusAudioPlayer.play();
} catch (IOException e) {
e.printStackTrace();
}
}

public OpusAudioPlayer(File audioFile) throws IOException {
oggFile = new OggFile(new FileInputStream(audioFile));
opusState = Opus.decoder_create(INPUT_BITRATE, 1);
System.out.println("Audio format: " + audioFormat);
}

private byte[] decode(byte[] packetData) {
int frameSize = Opus.decoder_get_nb_samples(opusState, packetData, 0, packetData.length);
int decodedSamples = Opus.decode(opusState, packetData, 0, packetData.length, decodeBuffer.array(), 0, frameSize, 0);
if (decodedSamples < 0) {
System.out.println("Decode error: " + decodedSamples);
decodeBuffer.clear();
return null;
}
decodeBuffer.position(decodedSamples * 2); // 2 bytes per sample
decodeBuffer.flip();

byte[] decodedData = new byte[decodeBuffer.remaining()];
decodeBuffer.get(decodedData);
decodeBuffer.flip();
System.out.println(String.format("Encoded frame size: %d bytes", packetData.length));
System.out.println(String.format("Decoded frame size: %d bytes", decodedData.length));
System.out.println(String.format("Decoded %d samples", decodedSamples));
return decodedData;
}

public void play() {
int totalDecodedBytes = 0;
try {
SourceDataLine speaker = AudioSystem.getSourceDataLine(audioFormat);
OggPacket nextPacket = oggFile.getPacketReader().getNextPacket();
// Move to beginning of stream
while ( !nextPacket.isBeginningOfStream()) {
nextPacket = oggFile.getPacketReader().getNextPacket();
}
speaker.open();
speaker.start();
while(nextPacket != null) {
// Decode each packet
byte[] decodedData = decode(nextPacket.getData());
if(decodedData != null) {
// Write packet to SourceDataLine
speaker.write(decodedData, 0, decodedData.length);
totalDecodedBytes += decodedData.length;
}
nextPacket = oggFile.getPacketReader().getNextPacket();
}
speaker.drain();
speaker.close();
System.out.println(String.format("Decoded to %d bytes", totalDecodedBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
}

最佳答案

我的特殊问题似乎是由 VorbisJava 中的错误引起的。我现在正在使用 J-Ogg,它可以毫无问题地处理容器解析。我敢肯定有人会发现这很有用。

这是展示如何在 Java 中播放 Opus 编码音频的最终代码:

package me.justinb.mediapad.audio;

import de.jarnbjo.ogg.FileStream;
import de.jarnbjo.ogg.LogicalOggStream;
import org.jitsi.impl.neomedia.codec.audio.opus.Opus;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.Collection;

public class OpusAudioPlayer {
private static int BUFFER_SIZE = 1024 * 1024;
private static int INPUT_BITRATE = 48000;
private static int OUTPUT_BITRATE = 48000;

private FileStream oggFile;
private long opusState;

private ByteBuffer decodeBuffer = ByteBuffer.allocate(BUFFER_SIZE);

private AudioFormat audioFormat = new AudioFormat(OUTPUT_BITRATE, 16, 1, true, false);

public static void main(String[] args) {
try {
OpusAudioPlayer opusAudioPlayer = new OpusAudioPlayer(new File("test.opus"));
opusAudioPlayer.play();
} catch (IOException e) {
e.printStackTrace();
}
}

public OpusAudioPlayer(File audioFile) throws IOException {
oggFile = new FileStream(new RandomAccessFile(audioFile, "r"));
opusState = Opus.decoder_create(INPUT_BITRATE, 1);
}

private byte[] decode(byte[] packetData) {
int frameSize = Opus.decoder_get_nb_samples(opusState, packetData, 0, packetData.length);
int decodedSamples = Opus.decode(opusState, packetData, 0, packetData.length, decodeBuffer.array(), 0, frameSize, 0);
if (decodedSamples < 0) {
System.out.println("Decode error: " + decodedSamples);
decodeBuffer.clear();
return null;
}
decodeBuffer.position(decodedSamples * 2); // 2 bytes per sample
decodeBuffer.flip();

byte[] decodedData = new byte[decodeBuffer.remaining()];
decodeBuffer.get(decodedData);
decodeBuffer.flip();
return decodedData;
}

public void play() {
int totalDecodedBytes = 0;
try {
SourceDataLine speaker = AudioSystem.getSourceDataLine(audioFormat);
speaker.open();
speaker.start();
for (LogicalOggStream stream : (Collection<LogicalOggStream>) oggFile.getLogicalStreams()) {
byte[] nextPacket = stream.getNextOggPacket();
while (nextPacket != null) {
byte[] decodedData = decode(nextPacket);
if(decodedData != null) {
// Write packet to SourceDataLine
speaker.write(decodedData, 0, decodedData.length);
totalDecodedBytes += decodedData.length;
}
nextPacket = stream.getNextOggPacket();
}
}
speaker.drain();
speaker.close();
System.out.println(String.format("Decoded to %d bytes", totalDecodedBytes));
} catch (Exception e) {
e.printStackTrace();
}
}
}

关于java - 如何在 Java 中播放 Opus 编码的音频?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26251017/

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