Câu trả lời:
Tôi đã viết mã sau đây hoạt động tốt. Nhưng tôi nghĩ rằng nó chỉ hoạt động với .wav
định dạng.
public static synchronized void playSound(final String url) {
new Thread(new Runnable() {
// The wrapper thread is unnecessary, unless it blocks on the
// Clip finishing; see comments.
public void run() {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
Main.class.getResourceAsStream("/path/to/sounds/" + url));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}).start();
}
Thread
cần thiết. 2) Để biết ví dụ hay về việc sử dụng Clip
, hãy xem thông tin JavaSound. trang . 3) Nếu một phương thức yêu cầu URL
(hoặc File
) cung cấp cho nó một dang URL
(hoặc File
) thay vì chấp nhận một phương String
thức đại diện cho một phương thức. (Chỉ là một 'con ong trong nắp ca-pô của tôi'.) 4) e.printStackTrace();
cung cấp nhiều thông tin hơn với ít lần gõ hơn System.err.println(e.getMessage());
.
Một ví dụ tồi:
import sun.audio.*; //import the sun.audio package
import java.io.*;
//** add this into your application code as appropriate
// Open an input stream to the audio file.
InputStream in = new FileInputStream(Filename);
// Create an AudioStream object from the input stream.
AudioStream as = new AudioStream(in);
// Use the static class member "player" from class AudioPlayer to play
// clip.
AudioPlayer.player.start(as);
// Similarly, to stop the audio.
AudioPlayer.player.stop(as);
Tôi không muốn có quá nhiều dòng mã chỉ để phát ra một âm thanh chết tiệt đơn giản. Điều này có thể hoạt động nếu bạn có gói JavaFX (đã được bao gồm trong jdk 8 của tôi).
private static void playSound(String sound){
// cl is the ClassLoader for the current class, ie. CurrentClass.class.getClassLoader();
URL file = cl.getResource(sound);
final Media media = new Media(file.toString());
final MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.play();
}
Lưu ý: Bạn cần khởi tạo JavaFX . Một cách nhanh chóng để làm điều đó, là gọi hàm tạo của JFXPanel () một lần trong ứng dụng của bạn:
static{
JFXPanel fxPanel = new JFXPanel();
}
Để phát âm thanh trong java, bạn có thể tham khảo đoạn mã sau.
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
// To play sound using Clip, the process need to be alive.
// Hence, we use a Swing application.
public class SoundClipTest extends JFrame {
public SoundClipTest() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
this.setVisible(true);
try {
// Open an audio input stream.
URL url = this.getClass().getClassLoader().getResource("gameover.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
// Get a sound clip resource.
Clip clip = AudioSystem.getClip();
// Open audio clip and load samples from the audio input stream.
clip.open(audioIn);
clip.start();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SoundClipTest();
}
}
Vì bất kỳ lý do gì, câu trả lời hàng đầu của wchargein đã khiến tôi gặp lỗi con trỏ null khi tôi gọi this.getClass (). GetResourceAsStream ().
Những gì làm việc cho tôi là như sau:
void playSound(String soundFile) {
File f = new File("./" + soundFile);
AudioInputStream audioIn = AudioSystem.getAudioInputStream(f.toURI().toURL());
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}
Và tôi sẽ chơi âm thanh với:
playSound("sounds/effects/sheep1.wav");
âm thanh / hiệu ứng / lamb1.wav được đặt trong thư mục cơ sở của dự án của tôi trong Eclipse (vì vậy không nằm trong thư mục src).
getResourceAsStream()
sẽ trở lại null
nếu tài nguyên không được tìm thấy, hoặc ném ngoại lệ nếu name
là null
- không phải là một lỗi của câu trả lời đầu nếu con đường cho không có giá trị
Tôi đã tạo ra một khung trò chơi trước đây để hoạt động trên Android và Máy tính để bàn, phần máy tính để bàn xử lý âm thanh có thể được sử dụng làm nguồn cảm hứng cho những gì bạn cần.
Đây là mã để tham khảo.
package com.athanazio.jaga.desktop.sound;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sound {
AudioInputStream in;
AudioFormat decodedFormat;
AudioInputStream din;
AudioFormat baseFormat;
SourceDataLine line;
private boolean loop;
private BufferedInputStream stream;
// private ByteArrayInputStream stream;
/**
* recreate the stream
*
*/
public void reset() {
try {
stream.reset();
in = AudioSystem.getAudioInputStream(stream);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
line = getLine(decodedFormat);
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
line.close();
din.close();
in.close();
} catch (IOException e) {
}
}
Sound(String filename, boolean loop) {
this(filename);
this.loop = loop;
}
Sound(String filename) {
this.loop = false;
try {
InputStream raw = Object.class.getResourceAsStream(filename);
stream = new BufferedInputStream(raw);
// ByteArrayOutputStream out = new ByteArrayOutputStream();
// byte[] buffer = new byte[1024];
// int read = raw.read(buffer);
// while( read > 0 ) {
// out.write(buffer, 0, read);
// read = raw.read(buffer);
// }
// stream = new ByteArrayInputStream(out.toByteArray());
in = AudioSystem.getAudioInputStream(stream);
din = null;
if (in != null) {
baseFormat = in.getFormat();
decodedFormat = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, baseFormat
.getSampleRate(), 16, baseFormat.getChannels(),
baseFormat.getChannels() * 2, baseFormat
.getSampleRate(), false);
din = AudioSystem.getAudioInputStream(decodedFormat, in);
line = getLine(decodedFormat);
}
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
private SourceDataLine getLine(AudioFormat audioFormat)
throws LineUnavailableException {
SourceDataLine res = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class,
audioFormat);
res = (SourceDataLine) AudioSystem.getLine(info);
res.open(audioFormat);
return res;
}
public void play() {
try {
boolean firstTime = true;
while (firstTime || loop) {
firstTime = false;
byte[] data = new byte[4096];
if (line != null) {
line.start();
int nBytesRead = 0;
while (nBytesRead != -1) {
nBytesRead = din.read(data, 0, data.length);
if (nBytesRead != -1)
line.write(data, 0, nBytesRead);
}
line.drain();
line.stop();
line.close();
reset();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
stream.reset();
dẫn đến Resetting to invalid mark
. Bạn đề nghị làm gì để khắc phục điều này?
raw.mark(raw.available()+1)
sau khi khởi tạo raw
và sau đó trong vòng lặp while, và sau đó sử dụng raw.reset()
thay vì stream.reset()
. Vấn đề của tôi bây giờ là khi nó xuất hiện để thiết lập lại, có một khoảng cách giữa các lần phát. Tôi muốn đạt được một vòng lặp liên tục như bạn nhận được với Clip
. Tôi không sử dụng Clip
vì thao tác điều khiển như MASTER_GAIN có độ trễ đáng chú ý là ~ 500ms. Đây có lẽ nên là câu hỏi của riêng nó mà tôi sẽ đi xung quanh để hỏi sau.
do { ... } while
?
Có một cách khác để nhập tệp âm thanh hoạt động trong cả ứng dụng và ứng dụng: chuyển đổi tệp âm thanh thành tệp .java và chỉ cần sử dụng chúng trong mã của bạn.
Tôi đã phát triển một công cụ giúp cho quá trình này dễ dàng hơn nhiều. Nó đơn giản hóa API âm thanh Java một chút.
Tôi ngạc nhiên không ai đề nghị sử dụng Applet. Sử dụng Applet
. Bạn sẽ phải cung cấp tệp âm thanh tiếng bíp dưới dạng wav
tệp nhưng nó hoạt động. Tôi đã thử điều này trên Ubuntu:
package javaapplication2;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
public class JavaApplication2 {
public static void main(String[] args) throws MalformedURLException {
File file = new File("/path/to/your/sounds/beep3.wav");
URL url = null;
if (file.canRead()) {url = file.toURI().toURL();}
System.out.println(url);
AudioClip clip = Applet.newAudioClip(url);
clip.play();
System.out.println("should've played by now");
}
}
//beep3.wav was available from: http://www.pacdv.com/sounds/interface_sound_effects/beep-3.wav
Applet
không được dùng nữa kể từ Java 9.
Chủ đề này khá cũ nhưng tôi đã xác định một tùy chọn có thể chứng minh hữu ích.
Thay vì sử dụng AudioStream
thư viện Java, bạn có thể sử dụng một chương trình bên ngoài như Windows Media Player hoặc VLC và chạy nó bằng lệnh console thông qua Java.
String command = "\"C:/Program Files (x86)/Windows Media Player/wmplayer.exe\" \"C:/song.mp3\"";
try {
Process p = Runtime.getRuntime().exec(command);
catch (IOException e) {
e.printStackTrace();
}
Điều này cũng sẽ tạo ra một quy trình riêng biệt có thể được điều khiển chương trình.
p.destroy();
Tất nhiên điều này sẽ mất nhiều thời gian để thực thi hơn so với sử dụng thư viện nội bộ nhưng có thể có các chương trình có thể khởi động nhanh hơn và có thể không có GUI được cung cấp một số lệnh điều khiển nhất định.
Nếu thời gian không phải là điều cốt yếu thì điều này rất hữu ích.