音频管线(Audio Pipeline)
基本信息
| 属性 |
值 |
| 源目录 |
src/main/java/com/mitchej123/hodgepodge/client/sound/(7 个类) |
| 安装入口 |
client/sound/SoundSetupHandler.java 的 SoundSetupHandler.register(),由 @SubscribeEvent onSoundSetup(SoundSetupEvent) 触发 |
| 安装时机 |
Minecraft 在 SoundManager 构造器里注册完原版库后下一行就抛出 SoundSetupEvent —— 这是 Forge 专门留的接缝,早于 SoundSystem 构造 |
| 底层库 |
Paulscode SoundSystem(LWJGL2 / LWJGL3 双后端) |
| 相关页 |
Sound 配置、音效增强菜单 |
功能
Hodgepodge 替换 Paulscode 的两个注册项 —— 一个 OpenAL 库、一个 OGG 解码器 —— 由此获得 5 项音频增强能力。这与本模组其余部分「只用 Mixin 打补丁」的做法不同:这里是替换实现,不改任何 Minecraft 类。
7 个类
| 类 |
角色 |
SoundSetupHandler |
安装钩子(唯一对外入口,17 行) |
LibraryHodgepodgeOpenAL |
替换 LibraryLWJGLOpenAL,提供解码内存释放、声道路由、混响挂载三个钩子 |
DownmixingOggCodec |
替换 CodecJOrbis,去二次方拷贝 + 立体声下混 |
SpatializeSupport |
立体声空间化(AL_SOFT_source_spatialize) |
ReverbSupport |
环境混响(ALC_EXT_EFX) |
SoundDeviceTweaks |
HRTF 与输出限制器(ALC_SOFT_HRTF / ALC_SOFT_output_limiter) |
OutputDeviceSupport |
输出设备枚举、切换与断连恢复(ALC_SOFT_reopen_device) |
五项增强
| 增强 |
配置开关 |
OpenAL 扩展 |
lwjgl3ify 必需 |
实现类 |
| 立体声下混 |
downmixStereoSounds(默认 true) |
无(纯 Java) |
否 |
DownmixingOggCodec |
| 立体声空间化 |
spatializeStereoSounds(默认 true) |
AL_SOFT_source_spatialize |
是 |
SpatializeSupport |
| 环境混响 |
environmentalReverb(默认 false) |
ALC_EXT_EFX |
否 |
ReverbSupport |
| 耳机 HRTF |
hrtf(默认 DEFAULT) |
ALC_SOFT_HRTF |
是 |
SoundDeviceTweaks |
| 输出限制器 |
outputLimiter(默认 DEFAULT) |
ALC_SOFT_output_limiter |
是 |
SoundDeviceTweaks |
| 输出设备管理 |
outputDeviceManagement.enabled(默认 true) |
ALC_SOFT_reopen_device |
是 |
OutputDeviceSupport |
两级后端的分水岭:LWJGL2(Java 8)打包的 OpenAL 早于上述 SOFT 扩展,只有 EFX 在两个层级都可用。源码注释(SoundDeviceTweaks.java:9-11、SpatializeSupport.java:9-11)明确:反射调用是刻意为之,因为 LWJGL2 与 LWJGL3 共用 org.lwjgl.openal 包名,同时上类路径会冲突。
数值
环境混响探测(ReverbSupport.java:37-48)
| 参数 |
值 |
说明 |
RAYS |
12 |
每次探测的射线数 |
RAY_LENGTH |
20 |
每条射线的最大长度(方块) |
| 单次探测最坏方块查询数 |
240 |
12 × 20 |
RAY_SPREAD |
1.2 |
射线扇在余弦空间的垂直张角,映射为约 +72°~−9° 的仰角 |
| 探测频率 |
每 5 客户端 tick 一次 = 4 Hz |
client/ClientTicker.java:25-32(ticks % 5 == 0) |
RAY_SPREAD = 1.2 的取值有源码论证(ReverbSupport.java:44-48):全球 2.0 不可用 —— 站在户外时每条向下的射线立刻命中地面,把分数拉低到「空地」与「大洞穴」无法区分;向上加权后两者才分得开。在平地、小屋、走廊、洞穴四种场景模拟中 1.2 给出的分数跨度最宽。
立体声下混(DownmixingOggCodec.java)
- 只改
readAll(),即非流式路径。音乐与黑胶唱片走流式,保持立体声自动生效。
planDownmix 计算下混增益以补偿立体声→单声道时的电平损失(:104-105);日志会打印 +%X.X dB 后缀。
- 排除列表
SoundConfig.downmixExclusions 默认 {"button", "click", "/gui", "menu", "typing", "page"},对 domain:path 做大小写不敏感匹配,使界面音效保持立体声。
- 下混是兜底,不是首选:
SpatializeSupport 在 OpenAL Soft 1.19+ 上能保留立体声宽度完成同样的定位,优先级更高。因此下混实际只在 Java 8 后端上起作用。
库替换的三处挂钩(LibraryHodgepodgeOpenAL.java:16-29)
| 挂钩 |
方法 |
内容 |
| 释放冗余解码数据 |
loadSound(FilenameURL) |
上传后调 buffer.trimData(0) 丢掉堆上的 byte[] 副本。Map 条目必须保留,因为 loadSound 用它的存在当「已解码」判据 |
| 声道路由 |
createChannel(int) |
建声道时按位置/非位置配置立体声与直连路径;池化声道复用时清掉混响状态 |
| 环境混响挂载 |
createChannel(int) |
位置音源路由到共享 effect slot |
交互
| 时机 |
行为 |
源位置 |
SoundSetupEvent |
LibraryHodgepodgeOpenAL.register() 先 removeLibrary(LibraryLWJGLOpenAL.class) 再 addLibrary(...);DownmixingOggCodec.register() 调 setCodec("ogg", ...)。成功各打一条 INFO |
SoundSetupHandler.java:21-24 |
| 安装失败 |
各 catch SoundSystemException,打 ERROR 后保持原状继续游戏 |
LibraryHodgepodgeOpenAL.java:57-59 |
| 声音库重建 |
构造器里 invalidate 四个 Support 类。注释指出:设备重建后旧 AL context 上的缓存全部失效,比较句柄不够(原生指针可能复用),「库被重建」才是可靠信号 |
LibraryHodgepodgeOpenAL.java:38-43 |
| 每 5 客户端 tick |
ClientTicker 依次调 OutputDeviceSupport.tick() / SoundDeviceTweaks.tick() / ReverbSupport.tick() |
ClientTicker.java:27-31 |
reverbStrength ≤ 0 |
静默一次既有效果(applyRoom(1f, RAY_LENGTH))后停止探测世界 |
ReverbSupport.java:90-93 |
| 玩家不在世界 |
直接返回 —— 源码注释:在世界里才保证 SoundSystem 已启动完,resolve() 才有活的 AL context |
ReverbSupport.java:86-89 |
已知边界
- 音频项改动大多需 Reload Sounds 或重启:
SoundConfig 多个 @Config.Comment 明确写了这一点(流式通道数、衰减模型、缓冲大小、解码上限等)。
- 混响需刷新:
hodgepodge.soundsmenu.enhancements.reload 提示「改完后刷新声音以应用到正在播放的音效」。
AL_SOFT_direct_channels / AL_SOFT_panning 属实验性路径,SpatializeSupport 注释标注为 experimental。
EnumValuesHook.java:52 的 catch (Throwable ignored) {} 吞掉的是调试 CSV 写入失败(printResults),不影响功能,属有意为之。
相关条目