javax.sound音频API全面解析:从基础使用到高级应用
本文全面介绍Java平台提供的javax.sound音频处理API,详细解析sampled和midi两个核心子包的功能与使用方法。通过四个完整的实战示例:WAV文件播放、实时音频生成、MIDI音乐播放与创作、音频录制功能,帮助开发者快速掌握Java音频编程技术。每个示例都包含详细的代码注释和异常处理,适合不同层次的Java开发者学习和参考。
javax.sound 包是 Java 平台提供的用于音频处理的 API,主要包含两个子包:
1、javax.sound.sampled - 处理采样音频(如 WAV、AIFF 等格式)
2、javax.sound.midi - 处理 MIDI 音乐数据
核心类概览
javax.sound.sampled 包
1、AudioSystem - 音频系统的入口点
2、AudioFormat - 描述音频数据格式
3、AudioInputStream - 音频数据输入流
4、Clip - 用于播放短音频片段
5、SourceDataLine - 用于实时音频播放
javax.sound.midi 包
1、Sequencer - MIDI 序列器
2、Synthesizer - MIDI 合成器
3、Sequence - MIDI 序列
4、MidiEvent - MIDI 事件
示例代码
1. 播放音频文件 (WAV)
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
public class AudioPlayer {
public static void playAudioFile(String filePath) {
try {
// 获取音频输入流
AudioInputStream audioStream = AudioSystem.getAudioInputStream(new File(filePath));
// 获取音频格式
AudioFormat format = audioStream.getFormat();
// 创建数据行信息
DataLine.Info info = new DataLine.Info(Clip.class, format);
// 检查系统是否支持该格式
if (!AudioSystem.isLineSupported(info)) {
System.out.println("不支持的音频格式");
return;
}
// 获取并打开音频剪辑
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
// 播放音频
audioClip.start();
// 等待播放完成
while (audioClip.isRunning()) {
Thread.sleep(100);
}
// 关闭资源
audioClip.close();
audioStream.close();
} catch (UnsupportedAudioFileException | IOException |
LineUnavailableException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
playAudioFile("example.wav");
}
}2. 实时音频播放
import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class ToneGenerator {
public static void generateTone(int frequency, int duration) {
try {
// 音频参数
float sampleRate = 44100;
int sampleSizeInBits = 16;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
// 创建音频格式
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
channels, signed, bigEndian);
// 创建数据行
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
// 生成正弦波数据
byte[] buffer = generateSineWave(frequency, duration, sampleRate);
// 播放音频
line.write(buffer, 0, buffer.length);
// 等待播放完成并清理
line.drain();
line.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
private static byte[] generateSineWave(int frequency, int duration, float sampleRate) {
int numSamples = (int) (duration * sampleRate / 1000);
byte[] output = new byte[numSamples * 2]; // 16-bit = 2 bytes per sample
for (int i = 0; i < numSamples; i++) {
double angle = 2.0 * Math.PI * i / (sampleRate / frequency);
short sample = (short) (Short.MAX_VALUE * Math.sin(angle));
// 将16位样本转换为字节
output[2 * i] = (byte) (sample & 0xFF);
output[2 * i + 1] = (byte) ((sample >> 8) & 0xFF);
}
return output;
}
public static void main(String[] args) {
// 播放 440Hz (A4) 音调,持续 2 秒
generateTone(440, 2000);
}
}3. MIDI 音乐播放
import javax.sound.midi.*;
import java.io.File;
import java.io.IOException;
public class MidiPlayer {
public static void playMidiFile(String filePath) {
try {
// 获取 MIDI 序列
Sequence sequence = MidiSystem.getSequence(new File(filePath));
// 获取序列器
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
sequencer.setSequence(sequence);
// 播放
sequencer.start();
// 等待播放完成
while (sequencer.isRunning()) {
Thread.sleep(100);
}
// 关闭序列器
sequencer.close();
} catch (InvalidMidiDataException | IOException |
MidiUnavailableException | InterruptedException e) {
e.printStackTrace();
}
}
public static void createAndPlayMidi() {
try {
// 创建新的序列
Sequence sequence = new Sequence(Sequence.PPQ, 24);
Track track = sequence.createTrack();
// 设置音色(程序改变事件)
ShortMessage programChange = new ShortMessage();
programChange.setMessage(ShortMessage.PROGRAM_CHANGE, 0, 0, 0); // 钢琴音色
track.add(new MidiEvent(programChange, 0));
// 添加音符事件(C大调音阶)
int[] notes = {60, 62, 64, 65, 67, 69, 71, 72}; // C4 到 C5
long tick = 0;
for (int note : notes) {
// 音符开始
ShortMessage noteOn = new ShortMessage();
noteOn.setMessage(ShortMessage.NOTE_ON, 0, note, 93);
track.add(new MidiEvent(noteOn, tick));
// 音符结束
ShortMessage noteOff = new ShortMessage();
noteOff.setMessage(ShortMessage.NOTE_OFF, 0, note, 0);
track.add(new MidiEvent(noteOff, tick + 48));
tick += 48;
}
// 播放序列
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
sequencer.setSequence(sequence);
sequencer.start();
// 等待播放完成
while (sequencer.isRunning()) {
Thread.sleep(100);
}
sequencer.close();
} catch (InvalidMidiDataException | MidiUnavailableException |
InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 播放 MIDI 文件
// playMidiFile("example.mid");
// 创建并播放简单的 MIDI 序列
createAndPlayMidi();
}
}4. 音频录制
import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class AudioRecorder {
private static final int RECORD_TIME = 5000; // 录制5秒
private AudioFormat format;
private TargetDataLine targetLine;
public AudioRecorder() {
// 设置音频格式
format = new AudioFormat(44100, 16, 1, true, false);
}
public void startRecording() {
try {
// 获取目标数据行
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open(format);
targetLine.start();
System.out.println("开始录制...");
// 创建线程进行录制
Thread recordingThread = new Thread(() -> {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < RECORD_TIME) {
int bytesRead = targetLine.read(buffer, 0, buffer.length);
if (bytesRead > 0) {
out.write(buffer, 0, bytesRead);
}
}
// 停止录制
targetLine.stop();
targetLine.close();
System.out.println("录制完成");
// 可以在这里保存或处理录制的音频数据
byte[] audioData = out.toByteArray();
System.out.println("录制数据大小: " + audioData.length + " 字节");
});
recordingThread.start();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
AudioRecorder recorder = new AudioRecorder();
recorder.startRecording();
}
}使用注意事项
1、异常处理:所有音频操作都需要处理可能的异常
2、资源管理:使用后务必关闭音频流和数据线
3、格式兼容性:检查系统是否支持特定的音频格式
4、性能考虑:实时音频处理需要注意缓冲区大小和延迟
最后更新于4月前
本文由人工编写,AI优化,转载请注明原文地址: Java音频处理完全指南:javax.sound使用详解与实战代码
推荐阅读
评论 (0)
发表评论
昵称:加载中...
暂无评论,快来发表第一条评论吧!