Java Utils - 实时PCM音频播放器(RealtimePcmPlayer)

功能概述

实时解码并播放 Base64 编码的 PCM 音频数据,支持多线程处理,确保音频播放流畅。


相关依赖

<dependency>
    <groupId>com.googlecode.soundlibs</groupId>
    <artifactId>mp3spi</artifactId>
    <version>1.9.5.4</version>
</dependency>

核心组件

1. 成员变量
  • sampleRate:音频采样率(如 24000 Hz)

  • line:音频输出线路(SourceDataLine

  • audioFormat:音频格式(采样率、位深、声道等)

  • decoderThread:解码线程(Base64 → 原始音频)

  • playerThread:播放线程(写入音频设备)

  • stopped:原子布尔值,控制线程退出

  • b64AudioBuffer:Base64 音频队列

  • RawAudioBuffer:原始音频队列


2. 构造函数
public RealtimePcmPlayer(int sampleRate) throws LineUnavailableException {
    this.sampleRate = sampleRate;
    this.audioFormat = new AudioFormat(this.sampleRate, 16, 1, true, false);
    // 打开音频线路
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
    line = (SourceDataLine) AudioSystem.getLine(info);
    line.open(audioFormat);
    line.start();
    // 启动解码和播放线程
    startThreads();
}

3. 解码线程
decoderThread = new Thread(() -> {
    while (!stopped.get()) {
        String b64Audio = b64AudioBuffer.poll();
        if (b64Audio != null) {
            byte[] rawAudio = Base64.getDecoder().decode(b64Audio);
            RawAudioBuffer.add(rawAudio);
        } else {
            Thread.sleep(100); // 队列为空时休眠
        }
    }
});

4. 播放线程
playerThread = new Thread(() -> {
    while (!stopped.get()) {
        byte[] rawAudio = RawAudioBuffer.poll();
        if (rawAudio != null) {
            playChunk(rawAudio);
        } else {
            Thread.sleep(100);
        }
    }
});

5. playChunk 方法
private void playChunk(byte[] chunk) throws IOException, InterruptedException {
    if (chunk == null || chunk.length == 0) return;

    int bytesWritten = 0;
    while (bytesWritten < chunk.length) {
        bytesWritten += line.write(chunk, bytesWritten, chunk.length - bytesWritten);
    }
    int audioLength = chunk.length / (this.sampleRate * 2 / 1000); // 计算音频时长(ms)
    Thread.sleep(audioLength - 10); // 等待播放完成
}
  • 将音频数据写入音频设备

  • 计算音频时长并休眠,确保播放完成

6. 其他方法
  • write(String b64Audio):写入 Base64 音频数据

  • cancel():清空音频队列(用于打断播放)

  • waitForComplete():等待所有音频播放完成

  • shutdown():停止线程并关闭音频设备

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值