---- --------解决方案
public class SimpleWavPlayer {
public final static String encoded = "base64 encoded binary that
I previously parsed and outputted then copied here";
public static void main(String[] args)
throws IOException,
InterruptedException,
LineUnavailableException,
UnsupportedAudioFileException {
byte[] decoded = DatatypeConverter.parseBase64Binary(encoded);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(decoded));
Clip song = AudioSystem.getClip();
song.open(audioIn);
song.start();
// Wait for clip to finish.
final CountDownLatch latch = new CountDownLatch(1);
song.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
if (event.getType().equals(LineEvent.Type.STOP)) {
event.getLine().close();
latch.countDown();
}
}
});
latch.await();
}
}
----原始问题--------
我有一个包含base64编码的mp3文件的字符串。我想解码该文件然后播放它。
File file = new File("song.wav");
byte[] bytes = FileUtils.readFileToByteArray(file);
String encoded = Base64.encodeToString(bytes, 0);
byte[] decoded = Base64.decode(encoded, 0);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(/*what do i do here?*/);
Clip song = /*what do i do here?*/;
song.start;
我现在准备好了字节数组。如何使用此解码的字节数组使用clip或audioinputstr播放音乐
--------编辑1 ------------
我用两种不同的方式更新了代码。编译和运行,我可以查看编码的字符串,但没有声音。而不是使用FileUtils.readFileToByteArray();我将Path和Paths.get与File.readAllBytes()结合使用。我无法使FileUtils工作,因为它希望我使用apacha库,我不想使用第三方库。此外,我不知道这是否是重要信息,但我正在使用当前使用pulseaudio的archlinux安装。这是代码。感谢迄今为止的所有帮助。请原谅我的懒惰异常处理。
import java.io.OutputStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
//import java.io.*;
//import java.util.Base64.*;
import javax.xml.bind.DatatypeConverter;
import javax.sound.sampled.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import sun.audio.*;
import java.io.*;
public class wavestring {
public static void main(String[] args){
Path path = Paths.get("/home/me/Documents/audiototext/yo.wav");
byte[] bytes = null;
try{
bytes = Files.readAllBytes(path);
}catch(IOException e){
System.out.print("Idk man, something happened man");
}
String encoded = DatatypeConverter.printBase64Binary(bytes);
System.out.println(encoded);
byte[] decoded = DatatypeConverter.parseBase64Binary(encoded);
// Convert byte array to inputStream
InputStream is = new ByteArrayInputStream(decoded);
// // Get AudioInputStream from InputStream
AudioInputStream audioIn = null;
try{
audioIn = AudioSystem.getAudioInputStream(is);
}catch(UnsupportedAudioFileException u){
System.out.println("Well bruh...something happened");
}catch(IOException e){
System.out.println("brooooo");
}
// // Acquire audio format and create a DataLine.Infoobject:
AudioFormat format = audioIn.getFormat();
/*
//METHOD 3
AudioInputStream audioIn = null;
try{
audioIn = AudioSystem.getAudioInputStream(is);
}catch(UnsupportedAudioFileException u){
System.out.println("Well bruh...something happened");
}catch(IOException e){
System.out.println("brooooo");
}
// // Acquire audio format and create a DataLine.Infoobject:
AudioFormat format = audioIn.getFormat();
Clip song = null;
try{
song = AudioSystem.getClip();
song.open(audioIn);
}catch(LineUnavailableException l){
}catch(IOException e){
}
song.start();
*/
//METHOD 2
SourceDataLine source_line = null;
try{
source_line = (SourceDataLine) AudioSystem.getLine(new DataLine.Info(SourceDataLine.class, format));
source_line.open(format);
}catch(LineUnavailableException l){
System.out.println("yooooooo");
}
byte[] buffer = new byte[524288];
int bytes_read = 0;
while(true){
try{
bytes_read = audioIn.read(buffer);
}catch(IOException e){
System.out.println("idk man");
}
if(bytes_read < 0)
break;
source_line.write(buffer, 0, bytes_read);
}
try{
audioIn.close();
}catch(IOException e){
System.out.println("yooooooooooo man");
}
source_line.drain();
source_line.close();
//METHOD 1
/*DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip song = null;
try{
song = (Clip) AudioSystem.getLine(info);
}catch(LineUnavailableException l){
System.out.println("We were so close but something happened man");
}
song.start();*/
}
}
答案 0 :(得分:2)
所有问题的答案都在文档中。
首先,让我们看一下documentation for AudioSystem。有五种getAudioInputStream
方法。两个采用显式的AudioFormat参数,不适用于播放.wav文件。其余三种方法分别采用File,InputStream和URL。
由于您已经有一个字节数组,最好的选择是将字节包装在ByteArrayInputStream中。现在我们有一个可以传递给getAudioInputStream方法的InputStream。
如果您想知道如何获取Clip对象,那么文档又是您最好的朋友。如果您转到documentation for Clip,并查看页面顶部,您会看到一个包含多个链接的导航行,包括“USE”链接。按照该链接,您将获得list of all methods in the Java SE API which return a Clip or take a Clip as an argument.
恰好这是一个简短的列表:从Java 8开始,只有两种方法,都是静态的,可以返回一个Clip。一个采用零参数,而另一个采用显式的Mixer.Info。通常,您只想通过默认的混音器播放声音,因此只需使用零参数getClip()方法来获取新的剪辑。
所以现在你有一个Clip,但它还没有与你的AudioInputStream相关联。再次,文档来救我们。 documentation for AudioSystem.getClip()州:
必须使用
open(AudioFormat)
或open(AudioInputStream)
方法打开返回的剪辑。
因此,如果我们再次返回Clip documentation,我们会看到两个open
方法(从Java 8开始)。其中一个将AudioInputStream作为唯一参数。那就是你想要使用的那个。
最后,正如您似乎已经知道的那样,您必须通过调用其继承的start()方法来启动剪辑。
现在我们有足够的信息来编写代码:
AudioInputStream audioIn = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(decoded));
Clip song = AudioSystem.getClip();
song.open(audioIn);
song.start();
更新:以上应该可以为您播放声音。这是我编写的完整程序来测试它:
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.concurrent.CountDownLatch;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class SimpleWavPlayer {
public static void main(String[] args)
throws IOException,
InterruptedException,
LineUnavailableException,
UnsupportedAudioFileException {
for (String arg : args) {
Path file = Paths.get(arg);
byte[] decoded = Files.readAllBytes(file);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(decoded));
Clip song = AudioSystem.getClip();
song.open(audioIn);
song.start();
// Wait for clip to finish.
final CountDownLatch latch = new CountDownLatch(1);
song.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
if (event.getType().equals(LineEvent.Type.STOP)) {
event.getLine().close();
latch.countDown();
}
}
});
latch.await();
}
}
}
答案 1 :(得分:1)
未经测试,但您可以将其作为指南:
File file = new File("song.wav");
byte[] bytes = FileUtils.readFileToByteArray(file);
String encoded = Base64.encodeToString(bytes, 0);
byte[] decoded = Base64.decode(encoded, 0);
// Convert byte array to inputStream
InputStream is = new ByteArrayInputStream(decoded);
// Get AudioInputStream from InputStream
AudioInputStream audioIn = AudioSystem.getAudioInputStream(is);
// Acquire audio format and create a DataLine.Infoobject:
AudioFormat format = audioIn.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip song = (Clip) AudioSystem.getLine(info);
song.start();
部分基于此:link
答案 2 :(得分:1)
(代码主要来自this answer)
要在将文件读入内存后获取AudioInputStream
,您可以使用:
AudioInputStream audio_in = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
或者,您可以直接从文件中读取。如果文件很大,这会节省内存(通过不将所有内容一次存储在内存中)。 AudioSystem
有一个方便的方法:
AudioInputStream audio_in = AudioSystem.getAudioInputStream(file);
一旦你有一个AudioInputStream可以让你从文件中读取音频,你需要一个SourceDataLine
来让你通过扬声器播放音频。
AudioFormat audio_format = audio_in.getFormat();
SourceDataLine source_line = (SourceDataLine) AudioSystem.getLine(new DataLine.Info(SourceDataLine.class, audio_format));
source_line.open(audio_format);
然后你可以从文件中读取音频,并将其发送到扬声器,直到你到达文件的末尾:
byte[] buffer = new byte[65536]; // the exact size doesn't matter too much; I chose 64 KiB
while(true) {
int bytes_read = audio_in.read(buffer);
if(bytes_read < 0)
break; // end of file reached
source_line.write(buffer, 0, bytes_read);
}
请注意,SourceDataLine
只会缓冲一定数量的数据;一旦缓冲区已满,尝试写入更多数据将阻止(即使程序等待),直到已经写入数据为止。这意味着只有在播放了大部分文件后,上述循环才会完成。
一旦完成,剩下的就是清理:
audio_in.close();
source_line.drain();
source_line.close();
SourceDataLine.drain
等待线路缓冲完成播放的任何数据。如果你没有调用它,那么当你关闭SourceDataLine时文件将立即停止播放,这可能导致最后几秒被切断。