- 共享引擎(app/src/main):GestureEngine 6 手势识别、AudioEngine 三层音频 (ExoPlayer BGM 交叉淡入 / 对白 ducking / SoundPool 低延迟)、Game/GameEngine 状态机接口、MainActivity 全屏封面 + TalkBack - 《声命线》storyline:末世互动广播剧,3 幕 8 抉择点 4 结局 - 《声东击西》reflex:听声辨位反应,12 波战斗 + BGM 三档 BPM 变速 - 《暗室》escape:3x3 网格密室逃脱,钥匙→铁柜→保险丝→电箱→大门谜题链 - 文档:setup(从零搭建)/ architecture(架构)/ engine-api(引擎 API)/ asset-pipeline(资产流水线)/ games/*(三款游戏设计文档) - 资产管线:Qwen3-TTS 对白 + 程序合成音效/BGM + Mureka BGM 的 gen 脚本与台账, 全部 ogg 资产入库可复现 - env.d 环境脚本:android/tts 入库;sfx/mureka 含密钥不入库,仅提交 .example.sh 模板
44 lines
2.4 KiB
Python
44 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Add a dynamic silence-pad node to an encoder onnx so it accepts ANY audio length: pads the sample
|
|
axis up to the next multiple of 4096 with zeros (matches what eager does internally). argv: <in> <out>."""
|
|
import sys, os
|
|
import onnx
|
|
from onnx import helper, TensorProto
|
|
IN, OUT = sys.argv[1], sys.argv[2]
|
|
m = onnx.load(IN, load_external_data=True); g = m.graph
|
|
audio = g.input[0].name; adt = g.input[0].type.tensor_type.elem_type
|
|
opset = {o.domain: o.version for o in m.opset_import}.get("", 0)
|
|
print(f"input '{audio}' dtype={adt} opset={opset}", flush=True)
|
|
g.initializer.extend([
|
|
helper.make_tensor("_pc4096", TensorProto.INT64, [1], [4096]),
|
|
helper.make_tensor("_pzeros5", TensorProto.INT64, [5], [0, 0, 0, 0, 0]),
|
|
helper.make_tensor("_pidx2", TensorProto.INT64, [1], [2]),
|
|
helper.make_tensor("_pc0", adt, [], [0]),
|
|
])
|
|
for n in g.node: # rewire consumers to the padded tensor
|
|
for i, inp in enumerate(n.input):
|
|
if inp == audio: n.input[i] = "_audio_pad"
|
|
g.node.extend([ # pad = (4096 - N%4096) % 4096, pad end of axis 2
|
|
helper.make_node("Shape", [audio], ["_pshape"], name="_pad_shape"),
|
|
helper.make_node("Gather", ["_pshape", "_pidx2"], ["_pN"], name="_pad_gather", axis=0),
|
|
helper.make_node("Mod", ["_pN", "_pc4096"], ["_pr"], name="_pad_mod1"),
|
|
helper.make_node("Sub", ["_pc4096", "_pr"], ["_pt"], name="_pad_sub"),
|
|
helper.make_node("Mod", ["_pt", "_pc4096"], ["_ppad"], name="_pad_mod2"),
|
|
helper.make_node("Concat", ["_pzeros5", "_ppad"], ["_ppads"], name="_pad_concat", axis=0),
|
|
helper.make_node("Pad", [audio, "_ppads", "_pc0"], ["_audio_pad"], name="_pad_pad", mode="constant"),
|
|
])
|
|
avail = {i.name for i in g.initializer} | {i.name for i in g.input} | {""}
|
|
order, rem = [], list(g.node)
|
|
while rem:
|
|
nx, prog = [], False
|
|
for nd in rem:
|
|
if all(i in avail for i in nd.input): order.append(nd); [avail.add(o) for o in nd.output]; prog = True
|
|
else: nx.append(nd)
|
|
rem = nx
|
|
if not prog: raise RuntimeError("topo stuck")
|
|
del g.node[:]; g.node.extend(order)
|
|
for f in (OUT, OUT + ".data"):
|
|
if os.path.exists(f): os.remove(f)
|
|
onnx.save(m, OUT, save_as_external_data=True, all_tensors_to_one_file=True, location=os.path.basename(OUT) + ".data", size_threshold=1024)
|
|
print(f"padded encoder -> {OUT}", flush=True)
|