Archive DLL-free personalized HRTF binaural renderer
This commit is contained in:
@@ -26,10 +26,16 @@ from metadata import DirectPayloadIndex, PayloadIndex, write_summary
|
||||
import oamd_tracks
|
||||
from renderer import JocRenderer
|
||||
from native_renderer import NativeBackendUnavailable, NativeJocRenderer
|
||||
from binaural_renderer import (
|
||||
ROSSELLA_BLOCK_SAMPLES,
|
||||
ROSSELLA_LATENCY_SAMPLES,
|
||||
RosellaBinauralRenderer,
|
||||
resolve_personalized_headphone,
|
||||
)
|
||||
from speaker_backend import create_speaker_renderer
|
||||
from speaker_layouts import (SPEAKER_LAYOUT_CHOICES, get_speaker_layout,
|
||||
speaker_layout_display_name)
|
||||
from speaker_wav import SpeakerPcmSpool, write_speaker_wav
|
||||
from speaker_wav import BinauralPcmSpool, SpeakerPcmSpool, write_pcm_wav
|
||||
from variant_error import UnsupportedVariantError, write_variant_report
|
||||
|
||||
|
||||
@@ -38,13 +44,15 @@ FRAME_SAMPLES = 1536
|
||||
DEFAULT_OUTPUT_DIR = PROJECT_DIR / "output"
|
||||
|
||||
|
||||
def resolve_output(source, requested=None, speaker_layout=None):
|
||||
def resolve_output(source, requested=None, speaker_layout=None, *, binaural=False):
|
||||
"""解析成品路径;未指定时使用项目内的 ``output`` 目录。"""
|
||||
source = Path(source)
|
||||
if requested is not None:
|
||||
target = Path(requested)
|
||||
elif speaker_layout is not None:
|
||||
target = DEFAULT_OUTPUT_DIR / f"{source.stem}.{speaker_layout}.wav"
|
||||
elif binaural:
|
||||
target = DEFAULT_OUTPUT_DIR / f"{source.stem}.binaural.wav"
|
||||
else:
|
||||
target = DEFAULT_OUTPUT_DIR / (source.stem + ".adm.wav")
|
||||
return target.expanduser().resolve()
|
||||
@@ -105,8 +113,8 @@ def sha256(path):
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def choose_speaker_output_format(requested_format, clip_action, peak, clipped_values,
|
||||
*, input_func=input, interactive=None):
|
||||
def choose_pcm_output_format(requested_format, clip_action, peak, clipped_values,
|
||||
*, input_func=input, interactive=None):
|
||||
"""Resolve int24 clipping interactively or through an explicit policy."""
|
||||
if requested_format != "int24" or clipped_values == 0:
|
||||
return requested_format
|
||||
@@ -146,6 +154,10 @@ def choose_speaker_output_format(requested_format, clip_action, peak, clipped_va
|
||||
raise ValueError(f"未知 clip action: {action}")
|
||||
|
||||
|
||||
# Backward-compatible public name used by existing tests and callers.
|
||||
choose_speaker_output_format = choose_pcm_output_format
|
||||
|
||||
|
||||
def resolve_metadata(args, eac3, temp_dir):
|
||||
if args.metadata_dir:
|
||||
directory = Path(args.metadata_dir).resolve()
|
||||
@@ -198,7 +210,9 @@ def create_renderer(backend, gain, native_library=None, native_threads=None):
|
||||
|
||||
def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
backend="auto", native_library=None, native_threads=None, frame_sink=None,
|
||||
speaker_renderer=None, speaker_sink=None, speaker_metadata_offset=1473):
|
||||
speaker_renderer=None, speaker_sink=None, speaker_metadata_offset=1473,
|
||||
binaural_renderer=None, binaural_sink=None, binaural_metadata_offset=1473,
|
||||
raw_scale=1.0):
|
||||
values = np.memmap(bed_path, dtype=np.float32, mode="r")
|
||||
frame_width = FRAME_SAMPLES * 6
|
||||
if values.size % frame_width:
|
||||
@@ -216,6 +230,9 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
raw_write_seconds = 0.0
|
||||
speaker_render_seconds = 0.0
|
||||
speaker_write_seconds = 0.0
|
||||
binaural_render_seconds = 0.0
|
||||
binaural_write_seconds = 0.0
|
||||
elapsed = 0.0
|
||||
try:
|
||||
for frame_number, row in enumerate(index.rows[:frame_count]):
|
||||
bed6 = np.asarray(bed[frame_number], dtype=np.float32)
|
||||
@@ -226,7 +243,8 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
dsp_seconds += time.perf_counter() - stage
|
||||
if output is not None:
|
||||
stage = time.perf_counter()
|
||||
output[frame_number] = pcm16.T
|
||||
output[frame_number] = np.multiply(
|
||||
pcm16.T, np.float32(raw_scale), dtype=np.float32)
|
||||
raw_write_seconds += time.perf_counter() - stage
|
||||
if frame_sink is not None:
|
||||
stage = time.perf_counter()
|
||||
@@ -240,6 +258,22 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
stage = time.perf_counter()
|
||||
speaker_sink.write_frame(speaker_pcm)
|
||||
speaker_write_seconds += time.perf_counter() - stage
|
||||
if binaural_renderer is not None:
|
||||
payload = subs.get(11)
|
||||
outer_offset = (
|
||||
index.subpayload_sample_offset(row, 11)
|
||||
if payload is not None and hasattr(index, "subpayload_sample_offset")
|
||||
else 0
|
||||
)
|
||||
stage = time.perf_counter()
|
||||
binaural_pcm = binaural_renderer.render_frame(
|
||||
pcm16.T, payload, binaural_metadata_offset,
|
||||
outer_sample_offset=outer_offset)
|
||||
binaural_render_seconds += time.perf_counter() - stage
|
||||
if len(binaural_pcm):
|
||||
stage = time.perf_counter()
|
||||
binaural_sink.write_frame(binaural_pcm)
|
||||
binaural_write_seconds += time.perf_counter() - stage
|
||||
done = frame_number + 1
|
||||
if done % progress_every == 0 or done == frame_count:
|
||||
elapsed = time.perf_counter() - started
|
||||
@@ -247,6 +281,14 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
eta = (frame_count - done) / max(speed, 1e-9)
|
||||
print(f"[JOC:{backend_info['name']}] {done}/{frame_count} "
|
||||
f"{speed:.1f} frame/s ETA {eta:.1f}s", flush=True)
|
||||
if binaural_renderer is not None:
|
||||
stage = time.perf_counter()
|
||||
binaural_tail = binaural_renderer.finish()
|
||||
binaural_render_seconds += time.perf_counter() - stage
|
||||
if len(binaural_tail):
|
||||
stage = time.perf_counter()
|
||||
binaural_sink.write_frame(binaural_tail)
|
||||
binaural_write_seconds += time.perf_counter() - stage
|
||||
if output is not None:
|
||||
output.flush()
|
||||
elapsed = time.perf_counter() - started
|
||||
@@ -257,6 +299,9 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
close = getattr(speaker_renderer, "close", None)
|
||||
if close is not None:
|
||||
close()
|
||||
close = getattr(binaural_renderer, "close", None)
|
||||
if close is not None:
|
||||
close()
|
||||
breakdown = {
|
||||
"pipeline_wall_seconds": elapsed,
|
||||
"dsp_and_joc_parse_seconds": dsp_seconds,
|
||||
@@ -264,38 +309,57 @@ def render(index, bed_path, frame_count, raw_path, gain, progress_every,
|
||||
"raw_float_write_seconds": raw_write_seconds,
|
||||
"speaker_render_seconds": speaker_render_seconds,
|
||||
"speaker_spool_write_seconds": speaker_write_seconds,
|
||||
"binaural_render_seconds": binaural_render_seconds,
|
||||
"binaural_spool_write_seconds": binaural_write_seconds,
|
||||
}
|
||||
return dsp_seconds, backend_info, breakdown
|
||||
|
||||
|
||||
def build_parser():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="JustOneCacophony (JOC):E-AC-3 JOC → 25ch ADM BWF 或扬声器 WAV")
|
||||
description=("JustOneCacophony (JOC):E-AC-3 JOC → 25ch ADM BWF、"
|
||||
"扬声器 WAV 或 DLL-free Rosella 双耳 WAV"))
|
||||
parser.add_argument("input", type=Path, help="输入 .m4a/.eac3/.ec3")
|
||||
parser.add_argument("-o", "--output", type=Path, help="输出文件;默认按模式和布局命名")
|
||||
parser.add_argument("--speaker-output", type=Path,
|
||||
help="扬声器 WAV 路径;仅与 --speaker-layout 一起使用")
|
||||
parser.add_argument("--speaker-layout", choices=SPEAKER_LAYOUT_CHOICES,
|
||||
help="直接扬声器渲染布局,例如 2.0、5.1、7.1.2")
|
||||
parser.add_argument("--binaural-output", type=Path,
|
||||
help="双耳 WAV 路径;仅与 --binaural 一起使用")
|
||||
direct_mode = parser.add_mutually_exclusive_group()
|
||||
direct_mode.add_argument("--speaker-layout", choices=SPEAKER_LAYOUT_CHOICES,
|
||||
help="直接扬声器渲染布局,例如 2.0、5.1、7.1.2")
|
||||
direct_mode.add_argument("--binaural", action="store_true",
|
||||
help="直接 DLL-free Rosella 双耳渲染;不生成临时 ADM BWF")
|
||||
parser.add_argument("--speaker-format", choices=("float32", "int24"), default="float32",
|
||||
help="扬声器 WAV 格式,默认 float32")
|
||||
parser.add_argument("--binaural-format", choices=("float32", "int24"), default="float32",
|
||||
help="双耳 WAV 格式,默认 float32")
|
||||
parser.add_argument("--clip-action", choices=("ask", "continue", "float32", "abort"),
|
||||
default="ask",
|
||||
help="int24 削波处理:交互询问、继续截断、改 float32 或中止")
|
||||
parser.add_argument("--speaker-metadata-offset", type=int, default=1473,
|
||||
help="扬声器渲染 metadata 相对帧偏移,默认 1473 samples")
|
||||
parser.add_argument("--binaural-mode", choices=("near", "mid", "far"), default="mid",
|
||||
help="普通对象 Rosella 距离模式,默认 mid;LFE 始终走 special 低通")
|
||||
parser.add_argument("--personalized-headphone", "--binaural-hrtf", dest="personalized_headphone",
|
||||
type=Path, help="覆盖 HRTF/binaural.personalized_headphone")
|
||||
parser.add_argument("--binaural-tail-seconds", type=float, default=5.0,
|
||||
help="双耳 room/filterbank flush 上限,默认 5 秒")
|
||||
parser.add_argument("--binaural-tail-threshold", type=float, default=1.0e-8,
|
||||
help="双耳尾声裁切阈值,默认 1e-8;主体至少保留原时长")
|
||||
parser.add_argument("--binaural-chunk-frames", type=int, default=64,
|
||||
help="双耳内部批处理 E-AC-3 帧数,默认 64")
|
||||
parser.add_argument("--gain-db", type=float, default=0.0,
|
||||
help="成品增益 dB,默认 0(float32 系数 1.0)")
|
||||
help="成品增益 dB,默认 0;双耳路径以 float64 应用")
|
||||
parser.add_argument("--duration", type=float, help="只处理开头指定秒数")
|
||||
parser.add_argument("--object-delay-samples", type=int, default=1473,
|
||||
help="可选的对象 PCM/OAMD 时间补偿,默认 1473 samples")
|
||||
help="对象 PCM/OAMD 时间补偿;ADM 与双耳默认 1473 samples")
|
||||
parser.add_argument(
|
||||
"--joc-binaural-mode", choices=tuple(adm_atmos.JOC_BINAURAL_MODES),
|
||||
default=adm_atmos.JOC_BINAURAL_MODE_DEFAULT,
|
||||
help="实验性 ADM DBMD JOC 对象双耳模式:off=0、near=1、far=2、mid=3、"
|
||||
"unspecified=4(默认);不改变 PCM 或直接扬声器渲染")
|
||||
help="ADM DBMD JOC 模式:off/near/far/mid/unspecified;仅影响 ADM BWF")
|
||||
parser.add_argument("--trajectory-mode", choices=("compact", "dense64"), default="compact",
|
||||
help="对象轨迹表示;compact 用长线性插值压缩 AXML,dense64 保留逐 64-sample 块")
|
||||
help="ADM 对象轨迹表示;直接双耳路径不序列化 AXML")
|
||||
parser.add_argument("--ffmpeg", default=os.environ.get("FFMPEG", "ffmpeg"))
|
||||
parser.add_argument("--backend", choices=("auto", "native", "python"), default="auto",
|
||||
help="DSP 后端;auto 优先 C++,不可用时回退 Python")
|
||||
@@ -332,24 +396,45 @@ def main(argv=None):
|
||||
if not source.is_file():
|
||||
raise FileNotFoundError(source)
|
||||
speaker_mode = args.speaker_layout is not None
|
||||
binaural_mode = bool(args.binaural)
|
||||
if args.speaker_output is not None and not speaker_mode:
|
||||
raise ValueError("--speaker-output 必须与 --speaker-layout 一起使用")
|
||||
if args.output is not None and args.speaker_output is not None:
|
||||
raise ValueError("-o/--output 与 --speaker-output 不能同时使用")
|
||||
if args.binaural_output is not None and not binaural_mode:
|
||||
raise ValueError("--binaural-output 必须与 --binaural 一起使用")
|
||||
specific_outputs = [value for value in (args.speaker_output, args.binaural_output)
|
||||
if value is not None]
|
||||
if args.output is not None and specific_outputs:
|
||||
raise ValueError("-o/--output 与 --speaker-output/--binaural-output 不能同时使用")
|
||||
if len(specific_outputs) > 1:
|
||||
raise ValueError("--speaker-output 与 --binaural-output 不能同时使用")
|
||||
if args.speaker_metadata_offset < 0:
|
||||
raise ValueError("speaker-metadata-offset 不能为负数")
|
||||
if args.personalized_headphone is not None and not binaural_mode:
|
||||
raise ValueError("--personalized-headphone 仅与 --binaural 一起使用")
|
||||
if args.binaural_tail_seconds < 0:
|
||||
raise ValueError("binaural-tail-seconds 不能为负数")
|
||||
if args.binaural_tail_threshold < 0:
|
||||
raise ValueError("binaural-tail-threshold 不能为负数")
|
||||
if args.binaural_chunk_frames <= 0:
|
||||
raise ValueError("binaural-chunk-frames 必须大于 0")
|
||||
requested_output = (args.speaker_output if args.speaker_output is not None
|
||||
else args.binaural_output if args.binaural_output is not None
|
||||
else args.output)
|
||||
output = resolve_output(
|
||||
source, requested_output, args.speaker_layout if speaker_mode else None)
|
||||
source, requested_output, args.speaker_layout if speaker_mode else None,
|
||||
binaural=binaural_mode)
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
if args.duration is not None and args.duration <= 0:
|
||||
raise ValueError("duration 必须大于 0")
|
||||
if args.object_delay_samples < 0:
|
||||
raise ValueError("object-delay-samples 不能为负数")
|
||||
gain = np.float32(10.0 ** (args.gain_db / 20.0))
|
||||
if not np.isfinite(gain):
|
||||
raise ValueError("gain-db 超出 float32 范围")
|
||||
gain_float64 = 10.0 ** (args.gain_db / 20.0)
|
||||
gain = np.float32(gain_float64)
|
||||
if not math.isfinite(gain_float64) or not np.isfinite(gain):
|
||||
raise ValueError("gain-db 超出支持范围")
|
||||
binaural_model_path = (
|
||||
resolve_personalized_headphone(args.personalized_headphone)
|
||||
if binaural_mode and not args.metadata_only else None)
|
||||
ffmpeg = executable(args.ffmpeg, "FFmpeg")
|
||||
|
||||
total_started = time.perf_counter()
|
||||
@@ -394,7 +479,12 @@ def main(argv=None):
|
||||
speaker_wav_info = None
|
||||
speaker_clip_info = None
|
||||
speaker_actual_format = None
|
||||
binaural_backend_info = None
|
||||
binaural_wav_info = None
|
||||
binaural_clip_info = None
|
||||
binaural_actual_format = None
|
||||
if speaker_mode:
|
||||
timings["create_binaural_renderer"] = 0.0
|
||||
layout = get_speaker_layout(args.speaker_layout)
|
||||
speaker_name = speaker_layout_display_name(layout)
|
||||
speaker_decoder, speaker_backend_info = create_speaker_renderer(
|
||||
@@ -416,11 +506,11 @@ def main(argv=None):
|
||||
args.native_threads, None, speaker_decoder, spool,
|
||||
args.speaker_metadata_offset)
|
||||
spool.finalize()
|
||||
speaker_actual_format = choose_speaker_output_format(
|
||||
speaker_actual_format = choose_pcm_output_format(
|
||||
args.speaker_format, args.clip_action, spool.peak,
|
||||
spool.clipped_values)
|
||||
speaker_wav_info = timed_call(
|
||||
timings, "write_speaker_wav", write_speaker_wav,
|
||||
timings, "write_speaker_wav", write_pcm_wav,
|
||||
output, spool.values, speaker_actual_format, rate=RATE)
|
||||
speaker_clip_info = {
|
||||
"peak": spool.peak,
|
||||
@@ -436,7 +526,66 @@ def main(argv=None):
|
||||
timings["validate_adm"] = 0.0
|
||||
info = (f"speaker layout={speaker_name}, format={speaker_actual_format}, "
|
||||
f"peak={speaker_clip_info['peak']:.9g}")
|
||||
elif binaural_mode:
|
||||
model_path = binaural_model_path
|
||||
binaural_decoder = timed_call(
|
||||
timings, "create_binaural_renderer", RosellaBinauralRenderer,
|
||||
model_path, mode=args.binaural_mode,
|
||||
object_delay_samples=args.object_delay_samples,
|
||||
tail_seconds=args.binaural_tail_seconds,
|
||||
output_gain=gain_float64,
|
||||
chunk_frames=args.binaural_chunk_frames,
|
||||
backend=args.backend, native_library=args.native_library)
|
||||
print(
|
||||
f"[binaural] mode={args.binaural_mode} "
|
||||
f"backend={binaural_decoder.dsp_backend} "
|
||||
f"precision=float64/complex128 model={model_path}", flush=True)
|
||||
flush_samples = math.ceil(
|
||||
(args.binaural_tail_seconds * RATE
|
||||
+ ROSSELLA_LATENCY_SAMPLES + ROSSELLA_BLOCK_SAMPLES)
|
||||
/ ROSSELLA_BLOCK_SAMPLES) * ROSSELLA_BLOCK_SAMPLES
|
||||
spool = BinauralPcmSpool(
|
||||
temp_dir / "binaural_interleaved_f64.raw",
|
||||
frame_count * FRAME_SAMPLES + flush_samples,
|
||||
tail_threshold=args.binaural_tail_threshold)
|
||||
try:
|
||||
render_seconds, renderer_backend, render_breakdown = timed_call(
|
||||
timings, "render_and_stream", variant_call,
|
||||
output, source, render, index, bed_path, frame_count, raw_path,
|
||||
np.float32(1.0), max(1, args.progress_every),
|
||||
backend=args.backend, native_library=args.native_library,
|
||||
native_threads=args.native_threads,
|
||||
binaural_renderer=binaural_decoder, binaural_sink=spool,
|
||||
binaural_metadata_offset=args.object_delay_samples, raw_scale=gain)
|
||||
spool.finalize(minimum_samples=frame_count * FRAME_SAMPLES)
|
||||
binaural_actual_format = choose_pcm_output_format(
|
||||
args.binaural_format, args.clip_action, spool.peak,
|
||||
spool.clipped_values)
|
||||
binaural_wav_info = timed_call(
|
||||
timings, "write_binaural_wav", write_pcm_wav,
|
||||
output, spool.values, binaural_actual_format, rate=RATE)
|
||||
binaural_clip_info = {
|
||||
"peak": spool.peak,
|
||||
"over_unity_values": spool.clipped_values,
|
||||
"requested_format": args.binaural_format,
|
||||
"actual_format": binaural_actual_format,
|
||||
"clip_action": args.clip_action,
|
||||
"tail_threshold": args.binaural_tail_threshold,
|
||||
"source_samples": frame_count * FRAME_SAMPLES,
|
||||
"kept_samples": spool.sample_count,
|
||||
}
|
||||
binaural_backend_info = binaural_decoder.backend_info
|
||||
finally:
|
||||
spool.close()
|
||||
timings["build_adm_tracks"] = 0.0
|
||||
timings["finalize_adm"] = 0.0
|
||||
timings["validate_adm"] = 0.0
|
||||
info = (f"binaural mode={args.binaural_mode}, "
|
||||
f"format={binaural_actual_format}, "
|
||||
f"peak={binaural_clip_info['peak']:.9g}, "
|
||||
f"samples={binaural_clip_info['kept_samples']}")
|
||||
else:
|
||||
timings["create_binaural_renderer"] = 0.0
|
||||
master = adm_assemble.StreamingMaster(
|
||||
output, duration_sec, rate=RATE,
|
||||
joc_binaural_mode=adm_atmos.JOC_BINAURAL_MODES[args.joc_binaural_mode])
|
||||
@@ -469,10 +618,11 @@ def main(argv=None):
|
||||
else:
|
||||
output_sha = timed_call(timings, "sha256", sha256, output)
|
||||
total_seconds = time.perf_counter() - total_started
|
||||
mode_name = "speaker" if speaker_mode else "binaural" if binaural_mode else "adm"
|
||||
report = {
|
||||
"input": str(source),
|
||||
"output": str(output),
|
||||
"mode": "speaker" if speaker_mode else "adm",
|
||||
"mode": mode_name,
|
||||
"metadata": str(metadata_json) if metadata_json is not None else None,
|
||||
"metadata_backend": metadata_backend,
|
||||
"metadata_cache": str(metadata_cache_dir) if metadata_cache_dir is not None else None,
|
||||
@@ -480,11 +630,13 @@ def main(argv=None):
|
||||
"duration_sec": duration_sec,
|
||||
"gain_db": args.gain_db,
|
||||
"gain_float32": float(gain),
|
||||
"object_delay_samples": None if speaker_mode else args.object_delay_samples,
|
||||
"trajectory_mode": None if speaker_mode else args.trajectory_mode,
|
||||
"joc_binaural_mode": None if speaker_mode else args.joc_binaural_mode,
|
||||
"joc_binaural_mode_value": (None if speaker_mode else
|
||||
adm_atmos.JOC_BINAURAL_MODES[args.joc_binaural_mode]),
|
||||
"gain_float64": float(gain_float64),
|
||||
"object_delay_samples": (None if speaker_mode else args.object_delay_samples),
|
||||
"trajectory_mode": args.trajectory_mode if mode_name == "adm" else None,
|
||||
"joc_binaural_mode": args.joc_binaural_mode if mode_name == "adm" else None,
|
||||
"joc_binaural_mode_value": (
|
||||
adm_atmos.JOC_BINAURAL_MODES[args.joc_binaural_mode]
|
||||
if mode_name == "adm" else None),
|
||||
"render_seconds": render_seconds,
|
||||
"render_breakdown": render_breakdown,
|
||||
"renderer_backend": renderer_backend,
|
||||
@@ -493,11 +645,19 @@ def main(argv=None):
|
||||
"speaker_metadata_offset": args.speaker_metadata_offset if speaker_mode else None,
|
||||
"speaker_clip": speaker_clip_info,
|
||||
"speaker_wav": speaker_wav_info,
|
||||
"streaming_adm": not speaker_mode,
|
||||
"binaural_renderer_backend": binaural_backend_info,
|
||||
"binaural_mode": args.binaural_mode if binaural_mode else None,
|
||||
"personalized_headphone": (
|
||||
binaural_backend_info["model"] if binaural_backend_info else None),
|
||||
"binaural_clip": binaural_clip_info,
|
||||
"binaural_wav": binaural_wav_info,
|
||||
"output_clip": speaker_clip_info if speaker_mode else binaural_clip_info,
|
||||
"output_wav": speaker_wav_info if speaker_mode else binaural_wav_info,
|
||||
"streaming_adm": mode_name == "adm",
|
||||
"kept_raw": str(raw_path) if raw_path is not None else None,
|
||||
"timings": timings,
|
||||
"total_seconds": total_seconds,
|
||||
"adm_validation": None if speaker_mode else info,
|
||||
"adm_validation": info if mode_name == "adm" else None,
|
||||
"adm_metadata": getattr(master, "metadata_info", None) if master is not None else None,
|
||||
"sha256": output_sha,
|
||||
"python": platform.python_version(),
|
||||
@@ -515,6 +675,11 @@ def main(argv=None):
|
||||
f"speaker={render_breakdown['speaker_render_seconds']:.2f}s "
|
||||
f"pipeline={render_breakdown['pipeline_wall_seconds']:.2f}s "
|
||||
f"total={report['total_seconds']:.2f}s")
|
||||
elif binaural_mode:
|
||||
print(f"[time] JOC-DSP={render_seconds:.2f}s ({renderer_backend['name']}) "
|
||||
f"binaural={render_breakdown['binaural_render_seconds']:.2f}s "
|
||||
f"pipeline={render_breakdown['pipeline_wall_seconds']:.2f}s "
|
||||
f"total={report['total_seconds']:.2f}s")
|
||||
else:
|
||||
print(f"[time] DSP={render_seconds:.2f}s ({renderer_backend['name']}) "
|
||||
f"render+ADM-stream={render_breakdown['pipeline_wall_seconds']:.2f}s "
|
||||
|
||||
Reference in New Issue
Block a user