Files
JustOneCacophony/README.md
T
TheM14 42d6da6302
ci / ubuntu-latest (push) Failing after 13s
ci / macos-latest (push) Has been cancelled
ci / windows-latest (push) Has been cancelled
Initial pure C++ implementation
2026-09-25 04:17:30 +08:00

7.0 KiB
Raw Blame History

JustOneCacophony — C++ Core

English · 数学说明 · 双耳渲染 · SIMD 派发

JustOneCacophony 的 C++ 实现:E-AC-3 JOC 码流解析、对象重建与渲染的执行内核。它从 E-AC-3 同步帧中提取 EMDF、ID14 JOC 参数与 ID11 OAMD 元数据,结合 FFmpeg 解码出的核心 5.1 PCM 重建 LFE 与 15 路对象 PCM,并输出 ADM BWF、指定扬声器布局的 WAV,或用编译好的 HRTF 方向场 直接输出双耳 WAV。

这是研究代码,不是完整、标准兼容或生产级的 JOC 解码器。它只覆盖已实现的码流形态,遇到未知 变体时明确报错,而不是假装一切都很和谐。

构建

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure

Windows(MSVC / VS 2022,静态 CRT)、Linux 与 macOS 由 .github/workflows/ci.yml 同时构建并跑 单元测试;本地只验证 MSVC。浮点行为是逐字节验收的一部分,因此不启用 fast-math:MSVC 用 /fp:precise,其他编译器用 -fno-fast-math。

Windows Release 默认带 /arch:AVX2(JOC_ENABLE_AVX2,默认 ON,见 CMakeLists.txt)。这个 开关是逐字节验收过的:所有渲染产物的 SHA-256 完全一致,换来 SOFA 双耳内核 12.4%、Rosella 1.8% 的提升。代价是运行要求——这样的 joc_core.dll 会执行 AVX2 指令,在 2013 年以前的 x86 上 直接非法指令退出。没有运行时派发,一个二进制只能二选一,所以:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DJOC_ENABLE_AVX2=OFF

得到基线 ISA(SSE2)、任何 x86-64 都能跑的产物。非 MSVC 构建永远不会带上这个开关。

路径与编码

库内部所有路径都是 UTF-8,只在系统边界转换(src/foundation/fs_utf8.*):Windows 上经 std::filesystem::path(内部 UTF-16)落到 _wfopen/CreateProcessW,其他平台直接是字节。 命令行参数在 Windows 上由 GetCommandLineW + CommandLineToArgvW 重新解析,控制台设为 UTF-8,因此日文/中文等非 ASCII 路径(含 ffmpeg 子进程与输出文件)都能正常工作;单元测试里有 一条非 ASCII 路径的回归用例守在 ctest 里。

产物

产物 说明
joc_core.dll 执行内核:码流解析、JOC/OAMD、DSP、扬声器与双耳渲染、ADM BWF/WAV 落盘、文件任务、流式接口
joc_cli.exe 文件任务命令行前端
include/joc_core.h 引擎、遥测与文件任务接口(纯 C)
include/joc_stream.h 面向嵌入者的流式 push/pull 接口(纯 C,仅包含它即可)

命令行

参数与上游 Python CLI 完全一致:输入是位置参数,默认输出 25 通道 ADM BWF,用 --speaker-layout 或 --binaural 切换到另外两种模式;未指定 -o 时产物落在 output/。

# 默认:ADM BWF(本身就是 24-bit,没有也不需要格式参数)
joc_cli "07. Gold Forever (2021 Master).m4a"
#   -> output/07. Gold Forever (2021 Master).adm.wav

joc_cli input.m4a -o out/adm.wav                 # 指定输出

# 扬声器布局
joc_cli input.m4a --speaker-layout 5.1           # -> output/<名称>.5.1.wav
joc_cli input.m4a --speaker-layout 7.1.4 --speaker-output out/714.wav --speaker-format int24

# 双耳(HRTF 默认取 <exe>/HRTF/binaural.sofa,其次 <exe>/HRTF/binaural.personalized_headphone)
joc_cli input.m4a --binaural
joc_cli input.m4a --binaural --sofa-hrtf HRTF/other.sofa   # 换一个 SOFA
joc_cli input.m4a --binaural --personalized-headphone      # Rosella 个性化模型
#   -> output/<名称>.binaural.wav

# 其它常用开关
joc_cli input.m4a --duration 30 --gain-db -3 --trajectory-mode dense64
joc_cli input.eac3 --metadata-only --print-metadata summary   # 只解析并打印元数据

--speaker-format / --binaural-format 默认 float32;int24 若会削波按 --clip-action 处理(默认 ask,非交互终端下需显式给出 continue/float32/abort)。--duration 以秒 为单位;--object-delay-samples、--speaker-metadata-offset、--binaural-tail-seconds、 --binaural-tail-threshold(默认 1e-8,双耳尾音裁切阈值)等默认值与上游一致。命令总是写出 <输出>.report.json(--report-json 可改路径)。

与上游参数的差异:--sofa-hrtf、--personalized-headphone、--backend python 以及 metadata sidecar(--metadata-dir/--metadata-cache/--metadata-backend sidecar)在本构建中 不可用,给出时立刻报错并说明原因,而不是静默忽略。本构建额外提供 --bed(已解码的 6 通道 float32 PCM,给出后不调用 ffmpeg 解码)、--kernels(滤波器组表路径)、--work-dir、 --report-json、--dry-run、--quiet。

库集成

引擎与文件任务使用 joc_core.h:joc_task_validate / joc_task_execute 跑一个文件任务并 通过回调返回状态事件,joc_task_result 给出帧数、峰值、字节数与 SHA-256。

播放器或解码组件使用 joc_stream.h:调用方按自己的节奏推入 E-AC-3 字节与对应的核心 PCM (或已重建的 objects16),再拉取渲染后的 PCM;分块粒度任意,输出与文件任务逐字节一致。

joc_stream_config config = {0};
config.struct_size = sizeof(config);
config.input = JOC_STREAM_IN_EAC3;      /* 或 JOC_STREAM_IN_PCM_OBJECTS16 */
config.output = JOC_STREAM_OUT_SPEAKER; /* 或 BINAURAL / PCM_OBJECTS16 */
config.speaker_layout_name = "5.1";
joc_stream* stream = NULL;
joc_stream_create(&config, &stream);
/* 循环:joc_stream_push(...) / joc_stream_pull(...) */
joc_stream_flush(stream);
joc_stream_destroy(stream);

契约:状态实例私有、可并存;同一实例的 push/pull 必须在同一线程;渲染是有状态的, 因此本版本不提供 seek——定位需要从流起点重新解码。扬声器/双耳通路的内核延迟为 961 样本,joc_stream_flush 负责排空双耳房间尾音。

目录

include/     公共 C ABI:joc_core.h(引擎/文件任务)、joc_stream.h(流式)、eac3joc_core.h(上游 ABI)
src/         实现:eac3_transport、emdf、joc_bitstream、joc_core、oamd、timeline、speaker、
             binaural、hrtf、adm、io、telemetry、task、stream、api、cli、simd
tests/       单元测试(CTest,自足,不需要外部素材)
docs/        数学说明、双耳渲染流程与 SIMD 派发

src/ 下 8 个文件是 JustOneCacophony 原生库的逐字节副本,永不修改(见 THIRD_PARTY_NOTICES.md)。

兼容性说明

object_delay_samples 默认 1473,与既有实现的行为保持一致;它是可配置字段,改动它会 改变 OAMD/ADM 时间对齐。上游调查认为该值应为 0,本项目为保持逐字节等价暂不改默认值。

许可

MIT,见 LICENSE;第三方来源与专利边界见 THIRD_PARTY_NOTICES.md。