音频管线(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),不影响功能,属有意为之。

相关条目