在 Java 應用程式中播放音效是常見需求。Java 標準庫 javax.sound.sampled 提供了底層音頻 API,無需第三方依賴即可播放 PCM 格式的音訊(如 WAV、AU、AIFF)。本文將透過一個完整的範例,詳細解析如何讀取音訊檔案、建立播放管線並輸出聲音。
播放音訊主要涉及以下關鍵類別:
package com.example.audio;
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class AudioPlayer {
// 指定要播放的音訊檔案路徑(專案根目錄下的重逢一笑.wav)
private static final String MUSIC_FILE = "重逢一笑.wav";
public static void main(String[] args) {
try {
// 1. 獲取音訊輸入流
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(MUSIC_FILE));
// 2. 獲取音訊格式
AudioFormat audioFormat = audioInputStream.getFormat();
// 3. 定義資料行資訊:指定 SourceDataLine、音訊格式、緩衝區大小
DataLine.Info dataLineInfo = new DataLine.Info(
SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED);
// 4. 從混音器獲取 SourceDataLine 實例
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
// 5. 開啟資料行(綁定音訊格式)
sourceDataLine.open(audioFormat);
// 6. 開始播放(預填緩衝區)
sourceDataLine.start();
// 7. 循環讀取音訊資料並寫入播放緩衝區
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = audioInputStream.read(buffer, 0, buffer.length)) != -1) {
if (bytesRead > 0) {
sourceDataLine.write(buffer, 0, bytesRead);
}
}
// 8. 等待內部緩衝區播放完畢,再關閉資源
sourceDataLine.drain();
sourceDataLine.close();
audioInputStream.close();
System.out.println("播放結束");
} catch (UnsupportedAudioFileException e) {
System.err.println("不支援的音訊格式:" + e.getMessage());
} catch (LineUnavailableException e) {
System.err.println("音訊裝置不可用:" + e.getMessage());
} catch (IOException e) {
System.err.println("檔案讀取錯誤:" + e.getMessage());
}
}
}
AudioSystem.getAudioInputStream(File) 會自動識別檔案格式並解析文件頭,返回包含格式資訊的 AudioInputStream。若格式不支援會拋出 UnsupportedAudioFileException。
透過 DataLine.Info 描述所需的資料行類型與格式,再由 AudioSystem.getLine() 從預設混音器獲取可用的 SourceDataLine。調用 open(format) 綁定格式,start() 啟動資料行準備接收資料。
以固定大小的位元組陣列(此處 1024 bytes)分塊讀取音訊資料,寫入 sourceDataLine.write()。該方法為阻塞式,直到資料被混音器消費或緩衝區有空間。循環結束後,drain() 確保剩餘資料播放完畢,避免聲音截斷。
FloatControl.Type.MASTER_GAIN 調整增益。Java Sound API 雖然底層,但掌握 AudioInputStream → SourceDataLine 的標準流程,即可實現零依賴的音訊播放功能。本範例代碼結構清晰,可直接整合至專案中作為音效播放模組。