@adatechnology/game-audio 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1071) hide show
  1. package/README.md +31 -6
  2. package/assets/sfx/CREDITOS.md +2 -2
  3. package/assets/sfx/ambiente/ambience_city_day_01.ogg +0 -0
  4. package/assets/sfx/ambiente/ambience_city_day_02.ogg +0 -0
  5. package/assets/sfx/ambiente/ambience_construction_01.ogg +0 -0
  6. package/assets/sfx/ambiente/ambience_night_01.ogg +0 -0
  7. package/assets/sfx/ambiente/ambience_room_tone_01.ogg +0 -0
  8. package/assets/sfx/ambiente/ambience_room_tone_02.ogg +0 -0
  9. package/assets/sfx/ambiente/ambience_rural_day_01.ogg +0 -0
  10. package/assets/sfx/ambiente/ambience_rural_day_02.ogg +0 -0
  11. package/assets/sfx/ambiente/rain_loop_01.ogg +0 -0
  12. package/assets/sfx/ambiente/water_river_loop_01.ogg +0 -0
  13. package/assets/sfx/ambiente/water_river_loop_02.ogg +0 -0
  14. package/assets/sfx/ambiente/water_river_loop_03.ogg +0 -0
  15. package/assets/sfx/ambiente/water_splash_01.ogg +0 -0
  16. package/assets/sfx/ambiente/water_splash_02.ogg +0 -0
  17. package/assets/sfx/ambiente/water_splash_03.ogg +0 -0
  18. package/assets/sfx/ambiente/water_splash_04.ogg +0 -0
  19. package/assets/sfx/ambiente/water_splash_05.ogg +0 -0
  20. package/assets/sfx/ambiente/water_splash_06.ogg +0 -0
  21. package/assets/sfx/ambiente/water_splash_07.ogg +0 -0
  22. package/assets/sfx/ambiente/water_splash_08.ogg +0 -0
  23. package/assets/sfx/ambiente/water_splash_09.ogg +0 -0
  24. package/assets/sfx/ambiente/water_splash_10.ogg +0 -0
  25. package/assets/sfx/ambiente/water_splash_11.ogg +0 -0
  26. package/assets/sfx/ambiente/water_splash_12.ogg +0 -0
  27. package/assets/sfx/ambiente/water_splash_13.ogg +0 -0
  28. package/assets/sfx/ambiente/water_splash_14.ogg +0 -0
  29. package/assets/sfx/ambiente/water_splash_15.ogg +0 -0
  30. package/assets/sfx/armas/bolt_lift_medium_01.ogg +0 -0
  31. package/assets/sfx/armas/bolt_lift_medium_02.ogg +0 -0
  32. package/assets/sfx/armas/bolt_lift_medium_03.ogg +0 -0
  33. package/assets/sfx/armas/bolt_lift_medium_04.ogg +0 -0
  34. package/assets/sfx/armas/bolt_lift_medium_05.ogg +0 -0
  35. package/assets/sfx/armas/bolt_lock_medium_01.ogg +0 -0
  36. package/assets/sfx/armas/bolt_lock_medium_02.ogg +0 -0
  37. package/assets/sfx/armas/bolt_lock_medium_03.ogg +0 -0
  38. package/assets/sfx/armas/bolt_lock_medium_04.ogg +0 -0
  39. package/assets/sfx/armas/bolt_lock_medium_05.ogg +0 -0
  40. package/assets/sfx/armas/bolt_pull_heavy_01.ogg +0 -0
  41. package/assets/sfx/armas/bolt_pull_medium_01.ogg +0 -0
  42. package/assets/sfx/armas/bolt_pull_medium_02.ogg +0 -0
  43. package/assets/sfx/armas/bolt_pull_medium_03.ogg +0 -0
  44. package/assets/sfx/armas/bolt_pull_medium_04.ogg +0 -0
  45. package/assets/sfx/armas/bolt_pull_medium_05.ogg +0 -0
  46. package/assets/sfx/armas/bolt_pull_medium_06.ogg +0 -0
  47. package/assets/sfx/armas/bolt_push_heavy_01.ogg +0 -0
  48. package/assets/sfx/armas/bolt_push_medium_01.ogg +0 -0
  49. package/assets/sfx/armas/bolt_push_medium_02.ogg +0 -0
  50. package/assets/sfx/armas/bolt_push_medium_03.ogg +0 -0
  51. package/assets/sfx/armas/bolt_push_medium_04.ogg +0 -0
  52. package/assets/sfx/armas/bolt_push_medium_05.ogg +0 -0
  53. package/assets/sfx/armas/bolt_push_medium_06.ogg +0 -0
  54. package/assets/sfx/armas/casing_drop_concreto_01.ogg +0 -0
  55. package/assets/sfx/armas/casing_drop_concreto_02.ogg +0 -0
  56. package/assets/sfx/armas/casing_drop_concreto_03.ogg +0 -0
  57. package/assets/sfx/armas/casing_drop_metal_01.ogg +0 -0
  58. package/assets/sfx/armas/casing_drop_metal_02.ogg +0 -0
  59. package/assets/sfx/armas/casing_drop_metal_03.ogg +0 -0
  60. package/assets/sfx/armas/casing_drop_terra_01.ogg +0 -0
  61. package/assets/sfx/armas/casing_drop_terra_02.ogg +0 -0
  62. package/assets/sfx/armas/casing_drop_terra_03.ogg +0 -0
  63. package/assets/sfx/armas/charging_handle_pull_light_01.ogg +0 -0
  64. package/assets/sfx/armas/charging_handle_pull_light_02.ogg +0 -0
  65. package/assets/sfx/armas/charging_handle_pull_light_03.ogg +0 -0
  66. package/assets/sfx/armas/charging_handle_pull_light_04.ogg +0 -0
  67. package/assets/sfx/armas/charging_handle_pull_medium_01.ogg +0 -0
  68. package/assets/sfx/armas/charging_handle_pull_medium_02.ogg +0 -0
  69. package/assets/sfx/armas/charging_handle_pull_medium_03.ogg +0 -0
  70. package/assets/sfx/armas/charging_handle_pull_medium_04.ogg +0 -0
  71. package/assets/sfx/armas/charging_handle_pull_medium_05.ogg +0 -0
  72. package/assets/sfx/armas/charging_handle_release_medium_01.ogg +0 -0
  73. package/assets/sfx/armas/charging_handle_release_medium_02.ogg +0 -0
  74. package/assets/sfx/armas/charging_handle_release_medium_03.ogg +0 -0
  75. package/assets/sfx/armas/charging_handle_release_medium_04.ogg +0 -0
  76. package/assets/sfx/armas/charging_handle_release_medium_05.ogg +0 -0
  77. package/assets/sfx/armas/cylinder_close_light_01.ogg +0 -0
  78. package/assets/sfx/armas/cylinder_close_light_02.ogg +0 -0
  79. package/assets/sfx/armas/cylinder_close_light_03.ogg +0 -0
  80. package/assets/sfx/armas/cylinder_close_light_04.ogg +0 -0
  81. package/assets/sfx/armas/cylinder_close_light_05.ogg +0 -0
  82. package/assets/sfx/armas/cylinder_eject_light_01.ogg +0 -0
  83. package/assets/sfx/armas/cylinder_eject_light_02.ogg +0 -0
  84. package/assets/sfx/armas/cylinder_eject_light_03.ogg +0 -0
  85. package/assets/sfx/armas/cylinder_open_light_01.ogg +0 -0
  86. package/assets/sfx/armas/cylinder_open_light_02.ogg +0 -0
  87. package/assets/sfx/armas/cylinder_open_light_03.ogg +0 -0
  88. package/assets/sfx/armas/cylinder_open_light_04.ogg +0 -0
  89. package/assets/sfx/armas/cylinder_open_light_05.ogg +0 -0
  90. package/assets/sfx/armas/lever_close_medium_01.ogg +0 -0
  91. package/assets/sfx/armas/lever_close_medium_02.ogg +0 -0
  92. package/assets/sfx/armas/lever_open_medium_01.ogg +0 -0
  93. package/assets/sfx/armas/lever_open_medium_02.ogg +0 -0
  94. package/assets/sfx/armas/mag_out_heavy_01.ogg +0 -0
  95. package/assets/sfx/armas/mag_out_heavy_02.ogg +0 -0
  96. package/assets/sfx/armas/mag_out_light_01.ogg +0 -0
  97. package/assets/sfx/armas/mag_out_light_02.ogg +0 -0
  98. package/assets/sfx/armas/mag_out_light_03.ogg +0 -0
  99. package/assets/sfx/armas/mag_out_light_04.ogg +0 -0
  100. package/assets/sfx/armas/mag_out_medium_01.ogg +0 -0
  101. package/assets/sfx/armas/mag_out_medium_02.ogg +0 -0
  102. package/assets/sfx/armas/mag_out_medium_03.ogg +0 -0
  103. package/assets/sfx/armas/mag_seat_heavy_01.ogg +0 -0
  104. package/assets/sfx/armas/mag_seat_heavy_02.ogg +0 -0
  105. package/assets/sfx/armas/mag_seat_light_01.ogg +0 -0
  106. package/assets/sfx/armas/mag_seat_light_02.ogg +0 -0
  107. package/assets/sfx/armas/mag_seat_light_03.ogg +0 -0
  108. package/assets/sfx/armas/mag_seat_light_04.ogg +0 -0
  109. package/assets/sfx/armas/mag_seat_light_05.ogg +0 -0
  110. package/assets/sfx/armas/mag_seat_light_06.ogg +0 -0
  111. package/assets/sfx/armas/mag_seat_medium_01.ogg +0 -0
  112. package/assets/sfx/armas/mag_seat_medium_02.ogg +0 -0
  113. package/assets/sfx/armas/mag_seat_medium_03.ogg +0 -0
  114. package/assets/sfx/armas/pistol_22lr_close_01.ogg +0 -0
  115. package/assets/sfx/armas/pistol_22lr_close_02.ogg +0 -0
  116. package/assets/sfx/armas/pistol_22lr_far_01.ogg +0 -0
  117. package/assets/sfx/armas/pistol_22lr_far_02.ogg +0 -0
  118. package/assets/sfx/armas/pistol_22lr_far_03.ogg +0 -0
  119. package/assets/sfx/armas/pistol_22lr_far_04.ogg +0 -0
  120. package/assets/sfx/armas/pistol_45_close_01.ogg +0 -0
  121. package/assets/sfx/armas/pistol_45_close_02.ogg +0 -0
  122. package/assets/sfx/armas/pistol_45_close_03.ogg +0 -0
  123. package/assets/sfx/armas/pistol_45_close_04.ogg +0 -0
  124. package/assets/sfx/armas/pistol_45_close_05.ogg +0 -0
  125. package/assets/sfx/armas/pistol_45_far_01.ogg +0 -0
  126. package/assets/sfx/armas/pistol_45_far_02.ogg +0 -0
  127. package/assets/sfx/armas/pistol_45_far_03.ogg +0 -0
  128. package/assets/sfx/armas/pistol_45_far_04.ogg +0 -0
  129. package/assets/sfx/armas/pistol_9mm_close_01.ogg +0 -0
  130. package/assets/sfx/armas/pistol_9mm_close_02.ogg +0 -0
  131. package/assets/sfx/armas/pistol_9mm_close_03.ogg +0 -0
  132. package/assets/sfx/armas/pistol_9mm_close_04.ogg +0 -0
  133. package/assets/sfx/armas/pistol_9mm_close_05.ogg +0 -0
  134. package/assets/sfx/armas/pistol_9mm_close_06.ogg +0 -0
  135. package/assets/sfx/armas/pistol_9mm_far_01.ogg +0 -0
  136. package/assets/sfx/armas/pistol_9mm_far_02.ogg +0 -0
  137. package/assets/sfx/armas/pistol_9mm_far_03.ogg +0 -0
  138. package/assets/sfx/armas/pistol_9mm_far_04.ogg +0 -0
  139. package/assets/sfx/armas/pump_back_heavy_01.ogg +0 -0
  140. package/assets/sfx/armas/pump_back_heavy_02.ogg +0 -0
  141. package/assets/sfx/armas/pump_back_heavy_03.ogg +0 -0
  142. package/assets/sfx/armas/pump_back_heavy_04.ogg +0 -0
  143. package/assets/sfx/armas/pump_back_heavy_05.ogg +0 -0
  144. package/assets/sfx/armas/pump_forward_heavy_01.ogg +0 -0
  145. package/assets/sfx/armas/pump_forward_heavy_02.ogg +0 -0
  146. package/assets/sfx/armas/pump_forward_heavy_03.ogg +0 -0
  147. package/assets/sfx/armas/revolver_38_357_close_01.ogg +0 -0
  148. package/assets/sfx/armas/revolver_38_357_close_02.ogg +0 -0
  149. package/assets/sfx/armas/revolver_38_357_close_03.ogg +0 -0
  150. package/assets/sfx/armas/revolver_38_357_close_04.ogg +0 -0
  151. package/assets/sfx/armas/revolver_38_357_far_01.ogg +0 -0
  152. package/assets/sfx/armas/revolver_38_357_far_02.ogg +0 -0
  153. package/assets/sfx/armas/revolver_38_357_far_03.ogg +0 -0
  154. package/assets/sfx/armas/revolver_38_357_far_04.ogg +0 -0
  155. package/assets/sfx/armas/rifle_308_3006_close_01.ogg +0 -0
  156. package/assets/sfx/armas/rifle_308_3006_close_02.ogg +0 -0
  157. package/assets/sfx/armas/rifle_308_3006_close_03.ogg +0 -0
  158. package/assets/sfx/armas/rifle_308_3006_close_04.ogg +0 -0
  159. package/assets/sfx/armas/rifle_308_3006_close_05.ogg +0 -0
  160. package/assets/sfx/armas/rifle_308_3006_close_06.ogg +0 -0
  161. package/assets/sfx/armas/rifle_308_3006_far_01.ogg +0 -0
  162. package/assets/sfx/armas/rifle_308_3006_far_02.ogg +0 -0
  163. package/assets/sfx/armas/rifle_308_3006_far_03.ogg +0 -0
  164. package/assets/sfx/armas/rifle_308_3006_far_04.ogg +0 -0
  165. package/assets/sfx/armas/rifle_308_3006_far_05.ogg +0 -0
  166. package/assets/sfx/armas/rifle_308_3006_far_06.ogg +0 -0
  167. package/assets/sfx/armas/rifle_5_56_close_01.ogg +0 -0
  168. package/assets/sfx/armas/rifle_5_56_close_02.ogg +0 -0
  169. package/assets/sfx/armas/rifle_5_56_close_03.ogg +0 -0
  170. package/assets/sfx/armas/rifle_5_56_close_04.ogg +0 -0
  171. package/assets/sfx/armas/rifle_5_56_close_05.ogg +0 -0
  172. package/assets/sfx/armas/rifle_5_56_far_01.ogg +0 -0
  173. package/assets/sfx/armas/rifle_5_56_far_02.ogg +0 -0
  174. package/assets/sfx/armas/rifle_5_56_far_03.ogg +0 -0
  175. package/assets/sfx/armas/rifle_5_56_far_04.ogg +0 -0
  176. package/assets/sfx/armas/rifle_7_62x39_close_01.ogg +0 -0
  177. package/assets/sfx/armas/rifle_7_62x39_close_02.ogg +0 -0
  178. package/assets/sfx/armas/rifle_7_62x39_close_03.ogg +0 -0
  179. package/assets/sfx/armas/rifle_7_62x39_close_04.ogg +0 -0
  180. package/assets/sfx/armas/rifle_7_62x39_close_05.ogg +0 -0
  181. package/assets/sfx/armas/rifle_7_62x39_close_06.ogg +0 -0
  182. package/assets/sfx/armas/rifle_7_62x39_close_07.ogg +0 -0
  183. package/assets/sfx/armas/rifle_7_62x39_close_08.ogg +0 -0
  184. package/assets/sfx/armas/rifle_7_62x39_close_09.ogg +0 -0
  185. package/assets/sfx/armas/rifle_7_62x39_close_10.ogg +0 -0
  186. package/assets/sfx/armas/rifle_7_62x39_close_11.ogg +0 -0
  187. package/assets/sfx/armas/rifle_7_62x39_close_12.ogg +0 -0
  188. package/assets/sfx/armas/rifle_7_62x39_far_01.ogg +0 -0
  189. package/assets/sfx/armas/rifle_7_62x39_far_02.ogg +0 -0
  190. package/assets/sfx/armas/rifle_7_62x39_far_03.ogg +0 -0
  191. package/assets/sfx/armas/shell_insert_heavy_01.ogg +0 -0
  192. package/assets/sfx/armas/shell_insert_heavy_02.ogg +0 -0
  193. package/assets/sfx/armas/shell_insert_heavy_03.ogg +0 -0
  194. package/assets/sfx/armas/shell_insert_heavy_04.ogg +0 -0
  195. package/assets/sfx/armas/shell_insert_heavy_05.ogg +0 -0
  196. package/assets/sfx/armas/shell_insert_heavy_06.ogg +0 -0
  197. package/assets/sfx/armas/shell_insert_heavy_07.ogg +0 -0
  198. package/assets/sfx/armas/shell_insert_heavy_08.ogg +0 -0
  199. package/assets/sfx/armas/shell_insert_heavy_09.ogg +0 -0
  200. package/assets/sfx/armas/shotgun_12_close_01.ogg +0 -0
  201. package/assets/sfx/armas/shotgun_12_close_02.ogg +0 -0
  202. package/assets/sfx/armas/shotgun_12_close_03.ogg +0 -0
  203. package/assets/sfx/armas/shotgun_12_close_04.ogg +0 -0
  204. package/assets/sfx/armas/shotgun_12_close_05.ogg +0 -0
  205. package/assets/sfx/armas/shotgun_12_close_06.ogg +0 -0
  206. package/assets/sfx/armas/shotgun_12_far_01.ogg +0 -0
  207. package/assets/sfx/armas/shotgun_12_far_02.ogg +0 -0
  208. package/assets/sfx/armas/shotgun_12_far_03.ogg +0 -0
  209. package/assets/sfx/armas/shotgun_12_far_04.ogg +0 -0
  210. package/assets/sfx/armas/shotgun_12_far_05.ogg +0 -0
  211. package/assets/sfx/armas/shotgun_12_far_06.ogg +0 -0
  212. package/assets/sfx/armas/slide_release_light_01.ogg +0 -0
  213. package/assets/sfx/armas/slide_release_light_02.ogg +0 -0
  214. package/assets/sfx/armas/slide_release_light_03.ogg +0 -0
  215. package/assets/sfx/armas/slide_release_light_04.ogg +0 -0
  216. package/assets/sfx/armas/slide_release_light_05.ogg +0 -0
  217. package/assets/sfx/armas/slide_release_light_06.ogg +0 -0
  218. package/assets/sfx/armas/slide_release_medium_01.ogg +0 -0
  219. package/assets/sfx/armas/slide_release_medium_02.ogg +0 -0
  220. package/assets/sfx/armas/slide_release_medium_03.ogg +0 -0
  221. package/assets/sfx/armas/slide_release_medium_04.ogg +0 -0
  222. package/assets/sfx/armas/sniper_338_300wm_close_01.ogg +0 -0
  223. package/assets/sfx/armas/sniper_338_300wm_close_02.ogg +0 -0
  224. package/assets/sfx/armas/sniper_338_300wm_close_03.ogg +0 -0
  225. package/assets/sfx/armas/sniper_338_300wm_close_04.ogg +0 -0
  226. package/assets/sfx/armas/sniper_338_300wm_close_05.ogg +0 -0
  227. package/assets/sfx/armas/sniper_338_300wm_close_06.ogg +0 -0
  228. package/assets/sfx/armas/sniper_338_300wm_close_07.ogg +0 -0
  229. package/assets/sfx/armas/sniper_338_300wm_far_01.ogg +0 -0
  230. package/assets/sfx/armas/sniper_338_300wm_far_02.ogg +0 -0
  231. package/assets/sfx/armas/sniper_338_300wm_far_03.ogg +0 -0
  232. package/assets/sfx/armas/sniper_338_300wm_far_04.ogg +0 -0
  233. package/assets/sfx/armas/sniper_338_300wm_far_05.ogg +0 -0
  234. package/assets/sfx/armas/sniper_338_300wm_far_06.ogg +0 -0
  235. package/assets/sfx/armas/speedloader_light_01.ogg +0 -0
  236. package/assets/sfx/armas/speedloader_light_02.ogg +0 -0
  237. package/assets/sfx/armas/speedloader_light_03.ogg +0 -0
  238. package/assets/sfx/armas/speedloader_light_04.ogg +0 -0
  239. package/assets/sfx/armas/speedloader_light_05.ogg +0 -0
  240. package/assets/sfx/armas/speedloader_light_06.ogg +0 -0
  241. package/assets/sfx/armas/speedloader_light_07.ogg +0 -0
  242. package/assets/sfx/armas/speedloader_light_08.ogg +0 -0
  243. package/assets/sfx/armas/suppressed_pistol_close_01.ogg +0 -0
  244. package/assets/sfx/armas/suppressed_pistol_close_02.ogg +0 -0
  245. package/assets/sfx/armas/suppressed_pistol_close_03.ogg +0 -0
  246. package/assets/sfx/armas/suppressed_pistol_close_04.ogg +0 -0
  247. package/assets/sfx/armas/suppressed_pistol_close_05.ogg +0 -0
  248. package/assets/sfx/armas/suppressed_pistol_far_01.ogg +0 -0
  249. package/assets/sfx/armas/suppressed_pistol_far_02.ogg +0 -0
  250. package/assets/sfx/armas/suppressed_pistol_far_03.ogg +0 -0
  251. package/assets/sfx/armas/suppressed_pistol_far_04.ogg +0 -0
  252. package/assets/sfx/armas/suppressed_pistol_far_05.ogg +0 -0
  253. package/assets/sfx/armas/suppressed_rifle_close_01.ogg +0 -0
  254. package/assets/sfx/armas/suppressed_rifle_close_02.ogg +0 -0
  255. package/assets/sfx/armas/suppressed_rifle_close_03.ogg +0 -0
  256. package/assets/sfx/armas/suppressed_rifle_close_04.ogg +0 -0
  257. package/assets/sfx/armas/suppressed_rifle_far_01.ogg +0 -0
  258. package/assets/sfx/armas/suppressed_rifle_far_02.ogg +0 -0
  259. package/assets/sfx/armas/suppressed_rifle_far_03.ogg +0 -0
  260. package/assets/sfx/armas/suppressed_rifle_far_04.ogg +0 -0
  261. package/assets/sfx/explosoes-fogo/debris_rain_mixed_01.ogg +0 -0
  262. package/assets/sfx/explosoes-fogo/debris_rain_mixed_02.ogg +0 -0
  263. package/assets/sfx/explosoes-fogo/debris_rain_mixed_03.ogg +0 -0
  264. package/assets/sfx/explosoes-fogo/debris_rain_mixed_04.ogg +0 -0
  265. package/assets/sfx/explosoes-fogo/debris_rain_mixed_05.ogg +0 -0
  266. package/assets/sfx/explosoes-fogo/debris_rain_mixed_06.ogg +0 -0
  267. package/assets/sfx/explosoes-fogo/debris_rain_mixed_07.ogg +0 -0
  268. package/assets/sfx/explosoes-fogo/debris_rain_stone_01.ogg +0 -0
  269. package/assets/sfx/explosoes-fogo/debris_rain_stone_02.ogg +0 -0
  270. package/assets/sfx/explosoes-fogo/debris_rain_stone_03.ogg +0 -0
  271. package/assets/sfx/explosoes-fogo/debris_rain_stone_04.ogg +0 -0
  272. package/assets/sfx/explosoes-fogo/debris_rain_stone_05.ogg +0 -0
  273. package/assets/sfx/explosoes-fogo/debris_rain_stone_06.ogg +0 -0
  274. package/assets/sfx/explosoes-fogo/debris_rain_stone_07.ogg +0 -0
  275. package/assets/sfx/explosoes-fogo/debris_rain_stone_08.ogg +0 -0
  276. package/assets/sfx/explosoes-fogo/debris_rain_stone_09.ogg +0 -0
  277. package/assets/sfx/explosoes-fogo/explosion_big_01.ogg +0 -0
  278. package/assets/sfx/explosoes-fogo/explosion_big_02.ogg +0 -0
  279. package/assets/sfx/explosoes-fogo/explosion_big_03.ogg +0 -0
  280. package/assets/sfx/explosoes-fogo/explosion_big_04.ogg +0 -0
  281. package/assets/sfx/explosoes-fogo/explosion_big_05.ogg +0 -0
  282. package/assets/sfx/explosoes-fogo/explosion_car_01.ogg +0 -0
  283. package/assets/sfx/explosoes-fogo/explosion_car_02.ogg +0 -0
  284. package/assets/sfx/explosoes-fogo/explosion_car_03.ogg +0 -0
  285. package/assets/sfx/explosoes-fogo/explosion_car_04.ogg +0 -0
  286. package/assets/sfx/explosoes-fogo/explosion_far_close_01.ogg +0 -0
  287. package/assets/sfx/explosoes-fogo/explosion_far_close_02.ogg +0 -0
  288. package/assets/sfx/explosoes-fogo/explosion_far_close_03.ogg +0 -0
  289. package/assets/sfx/explosoes-fogo/explosion_far_close_04.ogg +0 -0
  290. package/assets/sfx/explosoes-fogo/explosion_flashbang_01.ogg +0 -0
  291. package/assets/sfx/explosoes-fogo/explosion_flashbang_02.ogg +0 -0
  292. package/assets/sfx/explosoes-fogo/explosion_grenade_01.ogg +0 -0
  293. package/assets/sfx/explosoes-fogo/explosion_grenade_02.ogg +0 -0
  294. package/assets/sfx/explosoes-fogo/explosion_grenade_03.ogg +0 -0
  295. package/assets/sfx/explosoes-fogo/explosion_grenade_04.ogg +0 -0
  296. package/assets/sfx/explosoes-fogo/explosion_grenade_05.ogg +0 -0
  297. package/assets/sfx/explosoes-fogo/explosion_grenade_06.ogg +0 -0
  298. package/assets/sfx/explosoes-fogo/explosion_small_bang_01.ogg +0 -0
  299. package/assets/sfx/explosoes-fogo/explosion_small_bang_02.ogg +0 -0
  300. package/assets/sfx/explosoes-fogo/explosion_small_bang_03.ogg +0 -0
  301. package/assets/sfx/explosoes-fogo/explosion_small_bang_04.ogg +0 -0
  302. package/assets/sfx/explosoes-fogo/explosion_small_bang_05.ogg +0 -0
  303. package/assets/sfx/explosoes-fogo/explosion_small_bang_06.ogg +0 -0
  304. package/assets/sfx/explosoes-fogo/explosion_small_bang_07.ogg +0 -0
  305. package/assets/sfx/explosoes-fogo/explosion_small_bang_08.ogg +0 -0
  306. package/assets/sfx/explosoes-fogo/explosion_small_bang_09.ogg +0 -0
  307. package/assets/sfx/explosoes-fogo/explosion_small_bang_10.ogg +0 -0
  308. package/assets/sfx/explosoes-fogo/fire_crackle_01.ogg +0 -0
  309. package/assets/sfx/explosoes-fogo/fire_crackle_02.ogg +0 -0
  310. package/assets/sfx/explosoes-fogo/fire_crackle_03.ogg +0 -0
  311. package/assets/sfx/explosoes-fogo/fire_crackle_05.ogg +0 -0
  312. package/assets/sfx/explosoes-fogo/fire_crackle_07.ogg +0 -0
  313. package/assets/sfx/explosoes-fogo/fire_extinguish_01.ogg +0 -0
  314. package/assets/sfx/explosoes-fogo/fire_extinguish_02.ogg +0 -0
  315. package/assets/sfx/explosoes-fogo/fire_ignite_01.ogg +0 -0
  316. package/assets/sfx/explosoes-fogo/fire_ignite_02.ogg +0 -0
  317. package/assets/sfx/explosoes-fogo/fire_ignite_03.ogg +0 -0
  318. package/assets/sfx/explosoes-fogo/fire_ignite_04.ogg +0 -0
  319. package/assets/sfx/explosoes-fogo/fire_loop_01.ogg +0 -0
  320. package/assets/sfx/explosoes-fogo/fire_loop_03.ogg +0 -0
  321. package/assets/sfx/explosoes-fogo/fire_loop_04.ogg +0 -0
  322. package/assets/sfx/explosoes-fogo/fire_loop_gas_01.ogg +0 -0
  323. package/assets/sfx/explosoes-fogo/fire_loop_gas_02.ogg +0 -0
  324. package/assets/sfx/explosoes-fogo/fire_loop_gas_03.ogg +0 -0
  325. package/assets/sfx/explosoes-fogo/fire_loop_gas_04.ogg +0 -0
  326. package/assets/sfx/explosoes-fogo/fire_loop_liquid_01.ogg +0 -0
  327. package/assets/sfx/explosoes-fogo/fire_loop_liquid_02.ogg +0 -0
  328. package/assets/sfx/explosoes-fogo/fire_loop_liquid_03.ogg +0 -0
  329. package/assets/sfx/explosoes-fogo/fire_loop_plastic_01.ogg +0 -0
  330. package/assets/sfx/explosoes-fogo/fire_loop_plastic_02.ogg +0 -0
  331. package/assets/sfx/explosoes-fogo/fire_loop_plastic_03.ogg +0 -0
  332. package/assets/sfx/explosoes-fogo/fire_loop_plastic_04.ogg +0 -0
  333. package/assets/sfx/explosoes-fogo/fire_loop_small_01.ogg +0 -0
  334. package/assets/sfx/explosoes-fogo/fire_pop_01.ogg +0 -0
  335. package/assets/sfx/explosoes-fogo/fire_pop_02.ogg +0 -0
  336. package/assets/sfx/explosoes-fogo/fire_pop_03.ogg +0 -0
  337. package/assets/sfx/explosoes-fogo/flamethrower_loop_01.ogg +0 -0
  338. package/assets/sfx/explosoes-fogo/gas_leak_01.ogg +0 -0
  339. package/assets/sfx/explosoes-fogo/molotov_break_ignite_01.ogg +0 -0
  340. package/assets/sfx/explosoes-fogo/molotov_break_ignite_02.ogg +0 -0
  341. package/assets/sfx/impactos/ceramic_hit_close_01.ogg +0 -0
  342. package/assets/sfx/impactos/concrete_block_drag_close_01.ogg +0 -0
  343. package/assets/sfx/impactos/concrete_block_drag_close_02.ogg +0 -0
  344. package/assets/sfx/impactos/concrete_block_drag_close_03.ogg +0 -0
  345. package/assets/sfx/impactos/concrete_block_drag_close_04.ogg +0 -0
  346. package/assets/sfx/impactos/concrete_block_drag_close_05.ogg +0 -0
  347. package/assets/sfx/impactos/concrete_block_drag_close_06.ogg +0 -0
  348. package/assets/sfx/impactos/concrete_block_drag_close_07.ogg +0 -0
  349. package/assets/sfx/impactos/crack_close_01.ogg +0 -0
  350. package/assets/sfx/impactos/crack_close_02.ogg +0 -0
  351. package/assets/sfx/impactos/crack_close_03.ogg +0 -0
  352. package/assets/sfx/impactos/crack_close_04.ogg +0 -0
  353. package/assets/sfx/impactos/crack_close_05.ogg +0 -0
  354. package/assets/sfx/impactos/crack_close_06.ogg +0 -0
  355. package/assets/sfx/impactos/crack_close_07.ogg +0 -0
  356. package/assets/sfx/impactos/crack_close_08.ogg +0 -0
  357. package/assets/sfx/impactos/crack_close_09.ogg +0 -0
  358. package/assets/sfx/impactos/crack_close_10.ogg +0 -0
  359. package/assets/sfx/impactos/crumble_close_01.ogg +0 -0
  360. package/assets/sfx/impactos/crumble_close_02.ogg +0 -0
  361. package/assets/sfx/impactos/crumble_close_03.ogg +0 -0
  362. package/assets/sfx/impactos/crumble_close_04.ogg +0 -0
  363. package/assets/sfx/impactos/crumble_close_05.ogg +0 -0
  364. package/assets/sfx/impactos/flesh_fruit_splat_close_01.ogg +0 -0
  365. package/assets/sfx/impactos/flesh_fruit_splat_close_02.ogg +0 -0
  366. package/assets/sfx/impactos/flesh_fruit_splat_close_03.ogg +0 -0
  367. package/assets/sfx/impactos/furniture_push_wood_close_01.ogg +0 -0
  368. package/assets/sfx/impactos/glass_blunt_heavy_close_01.ogg +0 -0
  369. package/assets/sfx/impactos/glass_blunt_heavy_close_02.ogg +0 -0
  370. package/assets/sfx/impactos/glass_blunt_heavy_close_03.ogg +0 -0
  371. package/assets/sfx/impactos/glass_blunt_heavy_close_04.ogg +0 -0
  372. package/assets/sfx/impactos/glass_blunt_heavy_close_05.ogg +0 -0
  373. package/assets/sfx/impactos/glass_blunt_light_close_01.ogg +0 -0
  374. package/assets/sfx/impactos/glass_blunt_light_close_02.ogg +0 -0
  375. package/assets/sfx/impactos/glass_blunt_light_close_03.ogg +0 -0
  376. package/assets/sfx/impactos/glass_blunt_light_close_04.ogg +0 -0
  377. package/assets/sfx/impactos/glass_blunt_light_close_05.ogg +0 -0
  378. package/assets/sfx/impactos/glass_blunt_medium_close_01.ogg +0 -0
  379. package/assets/sfx/impactos/glass_blunt_medium_close_02.ogg +0 -0
  380. package/assets/sfx/impactos/glass_blunt_medium_close_03.ogg +0 -0
  381. package/assets/sfx/impactos/glass_blunt_medium_close_04.ogg +0 -0
  382. package/assets/sfx/impactos/glass_blunt_medium_close_05.ogg +0 -0
  383. package/assets/sfx/impactos/glass_bottle_break_close_01.ogg +0 -0
  384. package/assets/sfx/impactos/glass_debris_fall_close_01.ogg +0 -0
  385. package/assets/sfx/impactos/glass_debris_fall_close_02.ogg +0 -0
  386. package/assets/sfx/impactos/glass_debris_fall_close_03.ogg +0 -0
  387. package/assets/sfx/impactos/glass_debris_fall_close_04.ogg +0 -0
  388. package/assets/sfx/impactos/glass_shatter_close_01.ogg +0 -0
  389. package/assets/sfx/impactos/glass_shatter_close_02.ogg +0 -0
  390. package/assets/sfx/impactos/glass_shatter_close_03.ogg +0 -0
  391. package/assets/sfx/impactos/glass_shatter_close_04.ogg +0 -0
  392. package/assets/sfx/impactos/glass_shatter_close_05.ogg +0 -0
  393. package/assets/sfx/impactos/glass_shatter_close_06.ogg +0 -0
  394. package/assets/sfx/impactos/glass_shatter_close_07.ogg +0 -0
  395. package/assets/sfx/impactos/glass_shatter_close_08.ogg +0 -0
  396. package/assets/sfx/impactos/glass_shatter_close_09.ogg +0 -0
  397. package/assets/sfx/impactos/gravel_hit_close_21.ogg +0 -0
  398. package/assets/sfx/impactos/gravel_hit_close_22.ogg +0 -0
  399. package/assets/sfx/impactos/gravel_hit_close_23.ogg +0 -0
  400. package/assets/sfx/impactos/gravel_hit_close_24.ogg +0 -0
  401. package/assets/sfx/impactos/gravel_hit_close_25.ogg +0 -0
  402. package/assets/sfx/impactos/gravel_hit_close_26.ogg +0 -0
  403. package/assets/sfx/impactos/gravel_hit_close_27.ogg +0 -0
  404. package/assets/sfx/impactos/gravel_hit_close_28.ogg +0 -0
  405. package/assets/sfx/impactos/gravel_hit_close_29.ogg +0 -0
  406. package/assets/sfx/impactos/impact_generic_light_close_01.ogg +0 -0
  407. package/assets/sfx/impactos/impact_generic_light_close_02.ogg +0 -0
  408. package/assets/sfx/impactos/impact_generic_light_close_03.ogg +0 -0
  409. package/assets/sfx/impactos/impact_generic_light_close_04.ogg +0 -0
  410. package/assets/sfx/impactos/impact_generic_light_close_05.ogg +0 -0
  411. package/assets/sfx/impactos/masonry_blunt_close_01.ogg +0 -0
  412. package/assets/sfx/impactos/masonry_blunt_close_02.ogg +0 -0
  413. package/assets/sfx/impactos/masonry_blunt_close_03.ogg +0 -0
  414. package/assets/sfx/impactos/masonry_blunt_close_04.ogg +0 -0
  415. package/assets/sfx/impactos/masonry_blunt_close_05.ogg +0 -0
  416. package/assets/sfx/impactos/masonry_blunt_close_06.ogg +0 -0
  417. package/assets/sfx/impactos/masonry_blunt_close_07.ogg +0 -0
  418. package/assets/sfx/impactos/masonry_bullet_close_01.ogg +0 -0
  419. package/assets/sfx/impactos/masonry_bullet_close_02.ogg +0 -0
  420. package/assets/sfx/impactos/masonry_bullet_close_03.ogg +0 -0
  421. package/assets/sfx/impactos/masonry_bullet_close_04.ogg +0 -0
  422. package/assets/sfx/impactos/masonry_bullet_close_05.ogg +0 -0
  423. package/assets/sfx/impactos/masonry_bullet_close_21.ogg +0 -0
  424. package/assets/sfx/impactos/masonry_bullet_close_22.ogg +0 -0
  425. package/assets/sfx/impactos/masonry_bullet_close_23.ogg +0 -0
  426. package/assets/sfx/impactos/masonry_bullet_close_24.ogg +0 -0
  427. package/assets/sfx/impactos/masonry_bullet_close_25.ogg +0 -0
  428. package/assets/sfx/impactos/masonry_bullet_close_26.ogg +0 -0
  429. package/assets/sfx/impactos/masonry_bullet_close_27.ogg +0 -0
  430. package/assets/sfx/impactos/masonry_bullet_close_28.ogg +0 -0
  431. package/assets/sfx/impactos/metal_blunt_close_01.ogg +0 -0
  432. package/assets/sfx/impactos/metal_blunt_close_02.ogg +0 -0
  433. package/assets/sfx/impactos/metal_blunt_close_03.ogg +0 -0
  434. package/assets/sfx/impactos/metal_blunt_close_04.ogg +0 -0
  435. package/assets/sfx/impactos/metal_blunt_close_05.ogg +0 -0
  436. package/assets/sfx/impactos/metal_blunt_heavy_close_01.ogg +0 -0
  437. package/assets/sfx/impactos/metal_blunt_heavy_close_02.ogg +0 -0
  438. package/assets/sfx/impactos/metal_blunt_heavy_close_03.ogg +0 -0
  439. package/assets/sfx/impactos/metal_blunt_heavy_close_04.ogg +0 -0
  440. package/assets/sfx/impactos/metal_blunt_heavy_close_05.ogg +0 -0
  441. package/assets/sfx/impactos/metal_blunt_light_close_01.ogg +0 -0
  442. package/assets/sfx/impactos/metal_blunt_light_close_02.ogg +0 -0
  443. package/assets/sfx/impactos/metal_blunt_light_close_03.ogg +0 -0
  444. package/assets/sfx/impactos/metal_blunt_light_close_04.ogg +0 -0
  445. package/assets/sfx/impactos/metal_blunt_light_close_05.ogg +0 -0
  446. package/assets/sfx/impactos/metal_blunt_medium_close_01.ogg +0 -0
  447. package/assets/sfx/impactos/metal_blunt_medium_close_02.ogg +0 -0
  448. package/assets/sfx/impactos/metal_blunt_medium_close_03.ogg +0 -0
  449. package/assets/sfx/impactos/metal_blunt_medium_close_04.ogg +0 -0
  450. package/assets/sfx/impactos/metal_blunt_medium_close_05.ogg +0 -0
  451. package/assets/sfx/impactos/metal_bullet_close_01.ogg +0 -0
  452. package/assets/sfx/impactos/metal_bullet_close_02.ogg +0 -0
  453. package/assets/sfx/impactos/metal_bullet_close_03.ogg +0 -0
  454. package/assets/sfx/impactos/metal_bullet_close_04.ogg +0 -0
  455. package/assets/sfx/impactos/metal_bullet_close_05.ogg +0 -0
  456. package/assets/sfx/impactos/metal_bullet_close_06.ogg +0 -0
  457. package/assets/sfx/impactos/metal_bullet_close_21.ogg +0 -0
  458. package/assets/sfx/impactos/metal_bullet_close_22.ogg +0 -0
  459. package/assets/sfx/impactos/metal_bullet_close_23.ogg +0 -0
  460. package/assets/sfx/impactos/metal_bullet_close_24.ogg +0 -0
  461. package/assets/sfx/impactos/metal_bullet_close_25.ogg +0 -0
  462. package/assets/sfx/impactos/metal_bullet_close_26.ogg +0 -0
  463. package/assets/sfx/impactos/metal_bullet_close_27.ogg +0 -0
  464. package/assets/sfx/impactos/metal_bullet_close_28.ogg +0 -0
  465. package/assets/sfx/impactos/metal_bullet_close_29.ogg +0 -0
  466. package/assets/sfx/impactos/metal_bullet_close_30.ogg +0 -0
  467. package/assets/sfx/impactos/metal_bullet_close_31.ogg +0 -0
  468. package/assets/sfx/impactos/metal_bullet_close_32.ogg +0 -0
  469. package/assets/sfx/impactos/metal_bullet_close_33.ogg +0 -0
  470. package/assets/sfx/impactos/metal_bullet_close_34.ogg +0 -0
  471. package/assets/sfx/impactos/metal_fall_close_01.ogg +0 -0
  472. package/assets/sfx/impactos/metal_fall_close_02.ogg +0 -0
  473. package/assets/sfx/impactos/metal_fall_close_03.ogg +0 -0
  474. package/assets/sfx/impactos/metal_fall_close_04.ogg +0 -0
  475. package/assets/sfx/impactos/metal_fall_close_05.ogg +0 -0
  476. package/assets/sfx/impactos/metal_fall_close_06.ogg +0 -0
  477. package/assets/sfx/impactos/metal_fall_close_07.ogg +0 -0
  478. package/assets/sfx/impactos/metal_fall_close_08.ogg +0 -0
  479. package/assets/sfx/impactos/metal_fall_close_09.ogg +0 -0
  480. package/assets/sfx/impactos/metal_fall_close_10.ogg +0 -0
  481. package/assets/sfx/impactos/metal_thin_close_01.ogg +0 -0
  482. package/assets/sfx/impactos/metal_thin_close_02.ogg +0 -0
  483. package/assets/sfx/impactos/metal_thin_close_03.ogg +0 -0
  484. package/assets/sfx/impactos/metal_thin_close_04.ogg +0 -0
  485. package/assets/sfx/impactos/metal_thin_close_05.ogg +0 -0
  486. package/assets/sfx/impactos/metal_thin_close_06.ogg +0 -0
  487. package/assets/sfx/impactos/metal_thin_close_07.ogg +0 -0
  488. package/assets/sfx/impactos/metal_thin_close_08.ogg +0 -0
  489. package/assets/sfx/impactos/metal_thin_close_09.ogg +0 -0
  490. package/assets/sfx/impactos/metal_thin_close_10.ogg +0 -0
  491. package/assets/sfx/impactos/metal_thin_close_11.ogg +0 -0
  492. package/assets/sfx/impactos/metal_thin_close_12.ogg +0 -0
  493. package/assets/sfx/impactos/metal_thin_close_13.ogg +0 -0
  494. package/assets/sfx/impactos/metal_thin_close_14.ogg +0 -0
  495. package/assets/sfx/impactos/metal_thin_close_15.ogg +0 -0
  496. package/assets/sfx/impactos/metal_thin_close_16.ogg +0 -0
  497. package/assets/sfx/impactos/metal_thin_close_17.ogg +0 -0
  498. package/assets/sfx/impactos/metal_thin_close_18.ogg +0 -0
  499. package/assets/sfx/impactos/metal_thin_close_19.ogg +0 -0
  500. package/assets/sfx/impactos/metal_thin_close_20.ogg +0 -0
  501. package/assets/sfx/impactos/metal_thin_close_21.ogg +0 -0
  502. package/assets/sfx/impactos/metal_thin_close_22.ogg +0 -0
  503. package/assets/sfx/impactos/metal_thin_close_23.ogg +0 -0
  504. package/assets/sfx/impactos/metal_thin_close_24.ogg +0 -0
  505. package/assets/sfx/impactos/metal_thin_close_25.ogg +0 -0
  506. package/assets/sfx/impactos/metal_thin_close_26.ogg +0 -0
  507. package/assets/sfx/impactos/paper_tear_close_01.ogg +0 -0
  508. package/assets/sfx/impactos/paper_tear_close_02.ogg +0 -0
  509. package/assets/sfx/impactos/plastic_hit_close_01.ogg +0 -0
  510. package/assets/sfx/impactos/plastic_hit_close_02.ogg +0 -0
  511. package/assets/sfx/impactos/plastic_hit_close_03.ogg +0 -0
  512. package/assets/sfx/impactos/plastic_hit_close_04.ogg +0 -0
  513. package/assets/sfx/impactos/ricochet_metal_close_21.ogg +0 -0
  514. package/assets/sfx/impactos/ricochet_metal_close_22.ogg +0 -0
  515. package/assets/sfx/impactos/ricochet_metal_close_23.ogg +0 -0
  516. package/assets/sfx/impactos/ricochet_metal_close_24.ogg +0 -0
  517. package/assets/sfx/impactos/ricochet_metal_close_25.ogg +0 -0
  518. package/assets/sfx/impactos/ricochet_metal_close_26.ogg +0 -0
  519. package/assets/sfx/impactos/ricochet_metal_close_27.ogg +0 -0
  520. package/assets/sfx/impactos/ricochet_metal_close_28.ogg +0 -0
  521. package/assets/sfx/impactos/rubble_falling_close_01.ogg +0 -0
  522. package/assets/sfx/impactos/rubble_falling_close_02.ogg +0 -0
  523. package/assets/sfx/impactos/rubble_falling_close_03.ogg +0 -0
  524. package/assets/sfx/impactos/rubble_falling_close_04.ogg +0 -0
  525. package/assets/sfx/impactos/rubble_falling_close_05.ogg +0 -0
  526. package/assets/sfx/impactos/rubble_falling_close_06.ogg +0 -0
  527. package/assets/sfx/impactos/rubble_falling_close_07.ogg +0 -0
  528. package/assets/sfx/impactos/rubble_falling_close_08.ogg +0 -0
  529. package/assets/sfx/impactos/rubble_falling_close_09.ogg +0 -0
  530. package/assets/sfx/impactos/soft_bullet_close_01.ogg +0 -0
  531. package/assets/sfx/impactos/soft_bullet_close_02.ogg +0 -0
  532. package/assets/sfx/impactos/soft_bullet_close_03.ogg +0 -0
  533. package/assets/sfx/impactos/soft_bullet_close_04.ogg +0 -0
  534. package/assets/sfx/impactos/soft_bullet_close_05.ogg +0 -0
  535. package/assets/sfx/impactos/soft_bullet_close_06.ogg +0 -0
  536. package/assets/sfx/impactos/soft_bullet_close_07.ogg +0 -0
  537. package/assets/sfx/impactos/soft_bullet_close_08.ogg +0 -0
  538. package/assets/sfx/impactos/soft_bullet_close_09.ogg +0 -0
  539. package/assets/sfx/impactos/soft_bullet_close_10.ogg +0 -0
  540. package/assets/sfx/impactos/soil_bullet_close_21.ogg +0 -0
  541. package/assets/sfx/impactos/soil_bullet_close_22.ogg +0 -0
  542. package/assets/sfx/impactos/soil_bullet_close_23.ogg +0 -0
  543. package/assets/sfx/impactos/wood_blunt_heavy_close_01.ogg +0 -0
  544. package/assets/sfx/impactos/wood_blunt_heavy_close_02.ogg +0 -0
  545. package/assets/sfx/impactos/wood_blunt_heavy_close_03.ogg +0 -0
  546. package/assets/sfx/impactos/wood_blunt_heavy_close_04.ogg +0 -0
  547. package/assets/sfx/impactos/wood_blunt_heavy_close_05.ogg +0 -0
  548. package/assets/sfx/impactos/wood_blunt_light_close_01.ogg +0 -0
  549. package/assets/sfx/impactos/wood_blunt_light_close_02.ogg +0 -0
  550. package/assets/sfx/impactos/wood_blunt_light_close_03.ogg +0 -0
  551. package/assets/sfx/impactos/wood_blunt_light_close_04.ogg +0 -0
  552. package/assets/sfx/impactos/wood_blunt_light_close_05.ogg +0 -0
  553. package/assets/sfx/impactos/wood_blunt_medium_close_01.ogg +0 -0
  554. package/assets/sfx/impactos/wood_blunt_medium_close_02.ogg +0 -0
  555. package/assets/sfx/impactos/wood_blunt_medium_close_03.ogg +0 -0
  556. package/assets/sfx/impactos/wood_blunt_medium_close_04.ogg +0 -0
  557. package/assets/sfx/impactos/wood_blunt_medium_close_05.ogg +0 -0
  558. package/assets/sfx/impactos/wood_fall_close_01.ogg +0 -0
  559. package/assets/sfx/impactos/wood_fall_close_02.ogg +0 -0
  560. package/assets/sfx/impactos/wood_fall_close_03.ogg +0 -0
  561. package/assets/sfx/impactos/wood_fall_close_04.ogg +0 -0
  562. package/assets/sfx/impactos/wood_fall_close_05.ogg +0 -0
  563. package/assets/sfx/impactos/wood_fall_close_06.ogg +0 -0
  564. package/assets/sfx/impactos/wood_fall_close_07.ogg +0 -0
  565. package/assets/sfx/impactos/wood_fall_close_08.ogg +0 -0
  566. package/assets/sfx/impactos/wood_fall_close_09.ogg +0 -0
  567. package/assets/sfx/impactos/wood_hit_close_01.ogg +0 -0
  568. package/assets/sfx/impactos/wood_hit_close_02.ogg +0 -0
  569. package/assets/sfx/impactos/wood_hit_close_03.ogg +0 -0
  570. package/assets/sfx/impactos/wood_hit_close_04.ogg +0 -0
  571. package/assets/sfx/impactos/wood_hit_close_05.ogg +0 -0
  572. package/assets/sfx/impactos/wood_hit_close_06.ogg +0 -0
  573. package/assets/sfx/impactos/wood_hit_close_07.ogg +0 -0
  574. package/assets/sfx/impactos/wood_hit_close_08.ogg +0 -0
  575. package/assets/sfx/impactos/wood_hit_close_09.ogg +0 -0
  576. package/assets/sfx/impactos/wood_hit_close_10.ogg +0 -0
  577. package/assets/sfx/impactos/wood_hit_close_11.ogg +0 -0
  578. package/assets/sfx/impactos/wood_hit_close_12.ogg +0 -0
  579. package/assets/sfx/impactos/wood_hit_close_13.ogg +0 -0
  580. package/assets/sfx/impactos/wood_hit_close_14.ogg +0 -0
  581. package/assets/sfx/impactos/wood_hit_close_21.ogg +0 -0
  582. package/assets/sfx/impactos/wood_hit_close_22.ogg +0 -0
  583. package/assets/sfx/impactos/wood_hit_close_23.ogg +0 -0
  584. package/assets/sfx/impactos/wood_hit_close_24.ogg +0 -0
  585. package/assets/sfx/impactos/wood_hit_close_25.ogg +0 -0
  586. package/assets/sfx/impactos/wood_hit_close_26.ogg +0 -0
  587. package/assets/sfx/impactos/wood_hit_close_27.ogg +0 -0
  588. package/assets/sfx/itens-portas/backpack_open_shut_01.ogg +0 -0
  589. package/assets/sfx/itens-portas/backpack_open_shut_02.ogg +0 -0
  590. package/assets/sfx/itens-portas/backpack_open_shut_03.ogg +0 -0
  591. package/assets/sfx/itens-portas/backpack_open_shut_04.ogg +0 -0
  592. package/assets/sfx/itens-portas/backpack_open_shut_05.ogg +0 -0
  593. package/assets/sfx/itens-portas/backpack_open_shut_06.ogg +0 -0
  594. package/assets/sfx/itens-portas/book_open_shut_01.ogg +0 -0
  595. package/assets/sfx/itens-portas/book_open_shut_02.ogg +0 -0
  596. package/assets/sfx/itens-portas/book_open_shut_03.ogg +0 -0
  597. package/assets/sfx/itens-portas/book_open_shut_04.ogg +0 -0
  598. package/assets/sfx/itens-portas/book_open_shut_05.ogg +0 -0
  599. package/assets/sfx/itens-portas/book_open_shut_06.ogg +0 -0
  600. package/assets/sfx/itens-portas/book_open_shut_07.ogg +0 -0
  601. package/assets/sfx/itens-portas/book_open_shut_08.ogg +0 -0
  602. package/assets/sfx/itens-portas/book_open_shut_09.ogg +0 -0
  603. package/assets/sfx/itens-portas/book_open_shut_10.ogg +0 -0
  604. package/assets/sfx/itens-portas/book_open_shut_11.ogg +0 -0
  605. package/assets/sfx/itens-portas/door_creak_01.ogg +0 -0
  606. package/assets/sfx/itens-portas/door_creak_02.ogg +0 -0
  607. package/assets/sfx/itens-portas/door_creak_03.ogg +0 -0
  608. package/assets/sfx/itens-portas/door_creak_06.ogg +0 -0
  609. package/assets/sfx/itens-portas/door_creak_07.ogg +0 -0
  610. package/assets/sfx/itens-portas/door_glass_sliding_01.ogg +0 -0
  611. package/assets/sfx/itens-portas/door_glass_sliding_02.ogg +0 -0
  612. package/assets/sfx/itens-portas/door_glass_sliding_03.ogg +0 -0
  613. package/assets/sfx/itens-portas/door_glass_sliding_04.ogg +0 -0
  614. package/assets/sfx/itens-portas/door_knock_01.ogg +0 -0
  615. package/assets/sfx/itens-portas/door_lock_unlock_01.ogg +0 -0
  616. package/assets/sfx/itens-portas/door_lock_unlock_02.ogg +0 -0
  617. package/assets/sfx/itens-portas/door_lock_unlock_03.ogg +0 -0
  618. package/assets/sfx/itens-portas/door_lock_unlock_04.ogg +0 -0
  619. package/assets/sfx/itens-portas/door_lock_unlock_05.ogg +0 -0
  620. package/assets/sfx/itens-portas/door_lock_unlock_06.ogg +0 -0
  621. package/assets/sfx/itens-portas/door_lock_unlock_07.ogg +0 -0
  622. package/assets/sfx/itens-portas/door_lock_unlock_08.ogg +0 -0
  623. package/assets/sfx/itens-portas/door_lock_unlock_09.ogg +0 -0
  624. package/assets/sfx/itens-portas/door_lock_unlock_10.ogg +0 -0
  625. package/assets/sfx/itens-portas/door_lock_unlock_11.ogg +0 -0
  626. package/assets/sfx/itens-portas/door_locked_rattle_01.ogg +0 -0
  627. package/assets/sfx/itens-portas/door_locked_rattle_02.ogg +0 -0
  628. package/assets/sfx/itens-portas/door_locked_rattle_03.ogg +0 -0
  629. package/assets/sfx/itens-portas/door_metal_open_shut_01.ogg +0 -0
  630. package/assets/sfx/itens-portas/door_metal_open_shut_02.ogg +0 -0
  631. package/assets/sfx/itens-portas/door_metal_open_shut_03.ogg +0 -0
  632. package/assets/sfx/itens-portas/door_metal_open_shut_04.ogg +0 -0
  633. package/assets/sfx/itens-portas/door_metal_open_shut_05.ogg +0 -0
  634. package/assets/sfx/itens-portas/door_metal_open_shut_06.ogg +0 -0
  635. package/assets/sfx/itens-portas/door_metal_open_shut_07.ogg +0 -0
  636. package/assets/sfx/itens-portas/door_slam_wood_01.ogg +0 -0
  637. package/assets/sfx/itens-portas/door_slam_wood_02.ogg +0 -0
  638. package/assets/sfx/itens-portas/door_slam_wood_03.ogg +0 -0
  639. package/assets/sfx/itens-portas/door_slam_wood_04.ogg +0 -0
  640. package/assets/sfx/itens-portas/door_wood_open_01.ogg +0 -0
  641. package/assets/sfx/itens-portas/door_wood_open_02.ogg +0 -0
  642. package/assets/sfx/itens-portas/door_wood_open_03.ogg +0 -0
  643. package/assets/sfx/itens-portas/door_wood_open_04.ogg +0 -0
  644. package/assets/sfx/itens-portas/door_wood_shut_01.ogg +0 -0
  645. package/assets/sfx/itens-portas/door_wood_shut_02.ogg +0 -0
  646. package/assets/sfx/itens-portas/door_wood_shut_03.ogg +0 -0
  647. package/assets/sfx/itens-portas/door_wood_shut_04.ogg +0 -0
  648. package/assets/sfx/itens-portas/door_wood_shut_05.ogg +0 -0
  649. package/assets/sfx/itens-portas/door_wood_shut_06.ogg +0 -0
  650. package/assets/sfx/itens-portas/door_wood_shut_07.ogg +0 -0
  651. package/assets/sfx/itens-portas/door_wood_shut_08.ogg +0 -0
  652. package/assets/sfx/itens-portas/drawer_open_01.ogg +0 -0
  653. package/assets/sfx/itens-portas/drawer_open_02.ogg +0 -0
  654. package/assets/sfx/itens-portas/drawer_shut_01.ogg +0 -0
  655. package/assets/sfx/itens-portas/drawer_shut_02.ogg +0 -0
  656. package/assets/sfx/itens-portas/item_drop_bag_01.ogg +0 -0
  657. package/assets/sfx/itens-portas/item_drop_bag_02.ogg +0 -0
  658. package/assets/sfx/itens-portas/item_drop_glass_01.ogg +0 -0
  659. package/assets/sfx/itens-portas/item_drop_metal_01.ogg +0 -0
  660. package/assets/sfx/itens-portas/item_drop_metal_02.ogg +0 -0
  661. package/assets/sfx/itens-portas/item_drop_metal_03.ogg +0 -0
  662. package/assets/sfx/itens-portas/item_drop_metal_04.ogg +0 -0
  663. package/assets/sfx/itens-portas/item_drop_metal_05.ogg +0 -0
  664. package/assets/sfx/itens-portas/item_drop_paper_01.ogg +0 -0
  665. package/assets/sfx/itens-portas/item_pickup_coins_01.ogg +0 -0
  666. package/assets/sfx/itens-portas/item_pickup_coins_02.ogg +0 -0
  667. package/assets/sfx/itens-portas/item_pickup_generic_01.ogg +0 -0
  668. package/assets/sfx/itens-portas/item_pickup_generic_02.ogg +0 -0
  669. package/assets/sfx/itens-portas/item_pickup_generic_03.ogg +0 -0
  670. package/assets/sfx/itens-portas/item_pickup_generic_04.ogg +0 -0
  671. package/assets/sfx/itens-portas/item_pickup_leather_01.ogg +0 -0
  672. package/assets/sfx/itens-portas/item_pickup_leather_02.ogg +0 -0
  673. package/assets/sfx/itens-portas/item_pickup_leather_03.ogg +0 -0
  674. package/assets/sfx/itens-portas/item_pickup_leather_04.ogg +0 -0
  675. package/assets/sfx/itens-portas/item_pickup_leather_05.ogg +0 -0
  676. package/assets/sfx/itens-portas/item_setdown_01.ogg +0 -0
  677. package/assets/sfx/itens-portas/item_setdown_02.ogg +0 -0
  678. package/assets/sfx/itens-portas/keys_jingle_01.ogg +0 -0
  679. package/assets/sfx/itens-portas/keys_jingle_02.ogg +0 -0
  680. package/assets/sfx/itens-portas/keys_jingle_03.ogg +0 -0
  681. package/assets/sfx/itens-portas/keys_jingle_04.ogg +0 -0
  682. package/assets/sfx/itens-portas/keys_jingle_05.ogg +0 -0
  683. package/assets/sfx/itens-portas/keys_jingle_06.ogg +0 -0
  684. package/assets/sfx/itens-portas/keys_jingle_07.ogg +0 -0
  685. package/assets/sfx/itens-portas/lever_pull_01.ogg +0 -0
  686. package/assets/sfx/itens-portas/lever_pull_02.ogg +0 -0
  687. package/assets/sfx/itens-portas/lever_pull_03.ogg +0 -0
  688. package/assets/sfx/itens-portas/lever_pull_04.ogg +0 -0
  689. package/assets/sfx/itens-portas/lever_pull_05.ogg +0 -0
  690. package/assets/sfx/itens-portas/lever_pull_06.ogg +0 -0
  691. package/assets/sfx/itens-portas/metal_latch_01.ogg +0 -0
  692. package/assets/sfx/itens-portas/metal_latch_02.ogg +0 -0
  693. package/assets/sfx/itens-portas/plates_hit_01.ogg +0 -0
  694. package/assets/sfx/itens-portas/plates_hit_02.ogg +0 -0
  695. package/assets/sfx/itens-portas/plates_hit_03.ogg +0 -0
  696. package/assets/sfx/itens-portas/plates_hit_04.ogg +0 -0
  697. package/assets/sfx/itens-portas/plates_hit_05.ogg +0 -0
  698. package/assets/sfx/itens-portas/plates_hit_06.ogg +0 -0
  699. package/assets/sfx/itens-portas/plates_hit_07.ogg +0 -0
  700. package/assets/sfx/itens-portas/plates_hit_08.ogg +0 -0
  701. package/assets/sfx/itens-portas/plates_hit_09.ogg +0 -0
  702. package/assets/sfx/itens-portas/plates_hit_10.ogg +0 -0
  703. package/assets/sfx/itens-portas/plates_slide_01.ogg +0 -0
  704. package/assets/sfx/itens-portas/plates_slide_02.ogg +0 -0
  705. package/assets/sfx/itens-portas/plates_slide_03.ogg +0 -0
  706. package/assets/sfx/itens-portas/plates_slide_04.ogg +0 -0
  707. package/assets/sfx/itens-portas/saw_wood_01.ogg +0 -0
  708. package/assets/sfx/itens-portas/switch_click_01.ogg +0 -0
  709. package/assets/sfx/itens-portas/switch_click_02.ogg +0 -0
  710. package/assets/sfx/itens-portas/switch_click_03.ogg +0 -0
  711. package/assets/sfx/itens-portas/switch_click_04.ogg +0 -0
  712. package/assets/sfx/itens-portas/toilet_flush_01.ogg +0 -0
  713. package/assets/sfx/itens-portas/tools_handling_01.ogg +0 -0
  714. package/assets/sfx/itens-portas/tools_handling_02.ogg +0 -0
  715. package/assets/sfx/itens-portas/tools_handling_03.ogg +0 -0
  716. package/assets/sfx/itens-portas/tools_handling_04.ogg +0 -0
  717. package/assets/sfx/itens-portas/tools_handling_05.ogg +0 -0
  718. package/assets/sfx/itens-portas/tools_handling_06.ogg +0 -0
  719. package/assets/sfx/itens-portas/tools_handling_07.ogg +0 -0
  720. package/assets/sfx/itens-portas/tools_handling_08.ogg +0 -0
  721. package/assets/sfx/itens-portas/tools_handling_09.ogg +0 -0
  722. package/assets/sfx/itens-portas/tools_handling_10.ogg +0 -0
  723. package/assets/sfx/itens-portas/tools_handling_11.ogg +0 -0
  724. package/assets/sfx/itens-portas/tools_handling_12.ogg +0 -0
  725. package/assets/sfx/itens-portas/tools_handling_13.ogg +0 -0
  726. package/assets/sfx/itens-portas/tools_handling_14.ogg +0 -0
  727. package/assets/sfx/itens-portas/tools_handling_15.ogg +0 -0
  728. package/assets/sfx/itens-portas/tools_handling_16.ogg +0 -0
  729. package/assets/sfx/itens-portas/water_drip_01.ogg +0 -0
  730. package/assets/sfx/itens-portas/water_drip_02.ogg +0 -0
  731. package/assets/sfx/itens-portas/water_drip_03.ogg +0 -0
  732. package/assets/sfx/itens-portas/water_drip_04.ogg +0 -0
  733. package/assets/sfx/itens-portas/water_faucet_01.ogg +0 -0
  734. package/assets/sfx/itens-portas/water_faucet_02.ogg +0 -0
  735. package/assets/sfx/itens-portas/water_faucet_03.ogg +0 -0
  736. package/assets/sfx/itens-portas/water_faucet_04.ogg +0 -0
  737. package/assets/sfx/itens-portas/water_faucet_05.ogg +0 -0
  738. package/assets/sfx/itens-portas/water_faucet_06.ogg +0 -0
  739. package/assets/sfx/itens-portas/water_faucet_07.ogg +0 -0
  740. package/assets/sfx/itens-portas/water_faucet_08.ogg +0 -0
  741. package/assets/sfx/itens-portas/water_faucet_09.ogg +0 -0
  742. package/assets/sfx/itens-portas/water_faucet_10.ogg +0 -0
  743. package/assets/sfx/manifest.json +48 -0
  744. package/assets/sfx/personagem/axe_chop_01.ogg +0 -0
  745. package/assets/sfx/personagem/axe_chop_02.ogg +0 -0
  746. package/assets/sfx/personagem/blunt_hit_metal_01.ogg +0 -0
  747. package/assets/sfx/personagem/blunt_hit_metal_02.ogg +0 -0
  748. package/assets/sfx/personagem/blunt_hit_metal_03.ogg +0 -0
  749. package/assets/sfx/personagem/blunt_hit_metal_04.ogg +0 -0
  750. package/assets/sfx/personagem/blunt_hit_metal_05.ogg +0 -0
  751. package/assets/sfx/personagem/body_fall_01.ogg +0 -0
  752. package/assets/sfx/personagem/body_fall_02.ogg +0 -0
  753. package/assets/sfx/personagem/body_fall_03.ogg +0 -0
  754. package/assets/sfx/personagem/body_fall_04.ogg +0 -0
  755. package/assets/sfx/personagem/body_fall_05.ogg +0 -0
  756. package/assets/sfx/personagem/cloth_rustle_01.ogg +0 -0
  757. package/assets/sfx/personagem/cloth_rustle_02.ogg +0 -0
  758. package/assets/sfx/personagem/cloth_rustle_03.ogg +0 -0
  759. package/assets/sfx/personagem/cloth_rustle_04.ogg +0 -0
  760. package/assets/sfx/personagem/cloth_rustle_05.ogg +0 -0
  761. package/assets/sfx/personagem/cloth_rustle_06.ogg +0 -0
  762. package/assets/sfx/personagem/cloth_rustle_07.ogg +0 -0
  763. package/assets/sfx/personagem/cloth_rustle_08.ogg +0 -0
  764. package/assets/sfx/personagem/cloth_rustle_09.ogg +0 -0
  765. package/assets/sfx/personagem/cloth_rustle_10.ogg +0 -0
  766. package/assets/sfx/personagem/cloth_rustle_11.ogg +0 -0
  767. package/assets/sfx/personagem/cloth_rustle_12.ogg +0 -0
  768. package/assets/sfx/personagem/cloth_rustle_13.ogg +0 -0
  769. package/assets/sfx/personagem/cloth_rustle_14.ogg +0 -0
  770. package/assets/sfx/personagem/drink_gulp_01.ogg +0 -0
  771. package/assets/sfx/personagem/drink_gulp_02.ogg +0 -0
  772. package/assets/sfx/personagem/drink_gulp_03.ogg +0 -0
  773. package/assets/sfx/personagem/footstep_carpet_alt_01.ogg +0 -0
  774. package/assets/sfx/personagem/footstep_carpet_alt_02.ogg +0 -0
  775. package/assets/sfx/personagem/footstep_carpet_alt_03.ogg +0 -0
  776. package/assets/sfx/personagem/footstep_carpet_alt_04.ogg +0 -0
  777. package/assets/sfx/personagem/footstep_carpet_alt_05.ogg +0 -0
  778. package/assets/sfx/personagem/footstep_concrete_alt_01.ogg +0 -0
  779. package/assets/sfx/personagem/footstep_concrete_alt_02.ogg +0 -0
  780. package/assets/sfx/personagem/footstep_concrete_alt_03.ogg +0 -0
  781. package/assets/sfx/personagem/footstep_concrete_alt_04.ogg +0 -0
  782. package/assets/sfx/personagem/footstep_concrete_alt_05.ogg +0 -0
  783. package/assets/sfx/personagem/footstep_concrete_run_01.ogg +0 -0
  784. package/assets/sfx/personagem/footstep_concrete_run_02.ogg +0 -0
  785. package/assets/sfx/personagem/footstep_concrete_run_03.ogg +0 -0
  786. package/assets/sfx/personagem/footstep_concrete_run_04.ogg +0 -0
  787. package/assets/sfx/personagem/footstep_concrete_run_05.ogg +0 -0
  788. package/assets/sfx/personagem/footstep_concrete_walk_01.ogg +0 -0
  789. package/assets/sfx/personagem/footstep_concrete_walk_02.ogg +0 -0
  790. package/assets/sfx/personagem/footstep_concrete_walk_03.ogg +0 -0
  791. package/assets/sfx/personagem/footstep_concrete_walk_04.ogg +0 -0
  792. package/assets/sfx/personagem/footstep_concrete_walk_05.ogg +0 -0
  793. package/assets/sfx/personagem/footstep_dirt_run_01.ogg +0 -0
  794. package/assets/sfx/personagem/footstep_dirt_run_02.ogg +0 -0
  795. package/assets/sfx/personagem/footstep_dirt_run_03.ogg +0 -0
  796. package/assets/sfx/personagem/footstep_dirt_run_04.ogg +0 -0
  797. package/assets/sfx/personagem/footstep_dirt_run_05.ogg +0 -0
  798. package/assets/sfx/personagem/footstep_dirt_walk_01.ogg +0 -0
  799. package/assets/sfx/personagem/footstep_dirt_walk_02.ogg +0 -0
  800. package/assets/sfx/personagem/footstep_dirt_walk_03.ogg +0 -0
  801. package/assets/sfx/personagem/footstep_dirt_walk_04.ogg +0 -0
  802. package/assets/sfx/personagem/footstep_dirt_walk_05.ogg +0 -0
  803. package/assets/sfx/personagem/footstep_generic_alt_01.ogg +0 -0
  804. package/assets/sfx/personagem/footstep_generic_alt_02.ogg +0 -0
  805. package/assets/sfx/personagem/footstep_generic_alt_03.ogg +0 -0
  806. package/assets/sfx/personagem/footstep_generic_alt_04.ogg +0 -0
  807. package/assets/sfx/personagem/footstep_generic_alt_05.ogg +0 -0
  808. package/assets/sfx/personagem/footstep_generic_alt_06.ogg +0 -0
  809. package/assets/sfx/personagem/footstep_generic_alt_07.ogg +0 -0
  810. package/assets/sfx/personagem/footstep_generic_alt_08.ogg +0 -0
  811. package/assets/sfx/personagem/footstep_generic_alt_09.ogg +0 -0
  812. package/assets/sfx/personagem/footstep_generic_alt_10.ogg +0 -0
  813. package/assets/sfx/personagem/footstep_grass_alt2_01.ogg +0 -0
  814. package/assets/sfx/personagem/footstep_grass_alt2_02.ogg +0 -0
  815. package/assets/sfx/personagem/footstep_grass_alt2_03.ogg +0 -0
  816. package/assets/sfx/personagem/footstep_grass_alt2_04.ogg +0 -0
  817. package/assets/sfx/personagem/footstep_grass_alt_01.ogg +0 -0
  818. package/assets/sfx/personagem/footstep_grass_alt_02.ogg +0 -0
  819. package/assets/sfx/personagem/footstep_grass_alt_03.ogg +0 -0
  820. package/assets/sfx/personagem/footstep_grass_alt_04.ogg +0 -0
  821. package/assets/sfx/personagem/footstep_grass_alt_05.ogg +0 -0
  822. package/assets/sfx/personagem/footstep_grass_run_01.ogg +0 -0
  823. package/assets/sfx/personagem/footstep_grass_run_02.ogg +0 -0
  824. package/assets/sfx/personagem/footstep_grass_run_03.ogg +0 -0
  825. package/assets/sfx/personagem/footstep_grass_run_04.ogg +0 -0
  826. package/assets/sfx/personagem/footstep_grass_run_05.ogg +0 -0
  827. package/assets/sfx/personagem/footstep_grass_walk_01.ogg +0 -0
  828. package/assets/sfx/personagem/footstep_grass_walk_02.ogg +0 -0
  829. package/assets/sfx/personagem/footstep_grass_walk_03.ogg +0 -0
  830. package/assets/sfx/personagem/footstep_grass_walk_04.ogg +0 -0
  831. package/assets/sfx/personagem/footstep_grass_walk_05.ogg +0 -0
  832. package/assets/sfx/personagem/footstep_hard_alt_01.ogg +0 -0
  833. package/assets/sfx/personagem/footstep_hard_alt_02.ogg +0 -0
  834. package/assets/sfx/personagem/footstep_hard_alt_03.ogg +0 -0
  835. package/assets/sfx/personagem/footstep_hard_alt_04.ogg +0 -0
  836. package/assets/sfx/personagem/footstep_hard_alt_05.ogg +0 -0
  837. package/assets/sfx/personagem/footstep_hard_alt_06.ogg +0 -0
  838. package/assets/sfx/personagem/footstep_hard_alt_07.ogg +0 -0
  839. package/assets/sfx/personagem/footstep_hard_alt_08.ogg +0 -0
  840. package/assets/sfx/personagem/footstep_hard_alt_09.ogg +0 -0
  841. package/assets/sfx/personagem/footstep_metal_run_01.ogg +0 -0
  842. package/assets/sfx/personagem/footstep_metal_run_02.ogg +0 -0
  843. package/assets/sfx/personagem/footstep_metal_run_03.ogg +0 -0
  844. package/assets/sfx/personagem/footstep_metal_run_04.ogg +0 -0
  845. package/assets/sfx/personagem/footstep_metal_run_05.ogg +0 -0
  846. package/assets/sfx/personagem/footstep_metal_walk_01.ogg +0 -0
  847. package/assets/sfx/personagem/footstep_metal_walk_02.ogg +0 -0
  848. package/assets/sfx/personagem/footstep_metal_walk_03.ogg +0 -0
  849. package/assets/sfx/personagem/footstep_metal_walk_04.ogg +0 -0
  850. package/assets/sfx/personagem/footstep_metal_walk_05.ogg +0 -0
  851. package/assets/sfx/personagem/footstep_snow_alt_01.ogg +0 -0
  852. package/assets/sfx/personagem/footstep_snow_alt_02.ogg +0 -0
  853. package/assets/sfx/personagem/footstep_snow_alt_03.ogg +0 -0
  854. package/assets/sfx/personagem/footstep_snow_alt_04.ogg +0 -0
  855. package/assets/sfx/personagem/footstep_snow_alt_05.ogg +0 -0
  856. package/assets/sfx/personagem/footstep_snow_run_01.ogg +0 -0
  857. package/assets/sfx/personagem/footstep_snow_run_02.ogg +0 -0
  858. package/assets/sfx/personagem/footstep_snow_run_03.ogg +0 -0
  859. package/assets/sfx/personagem/footstep_snow_run_04.ogg +0 -0
  860. package/assets/sfx/personagem/footstep_snow_run_05.ogg +0 -0
  861. package/assets/sfx/personagem/footstep_snow_walk_01.ogg +0 -0
  862. package/assets/sfx/personagem/footstep_snow_walk_02.ogg +0 -0
  863. package/assets/sfx/personagem/footstep_snow_walk_03.ogg +0 -0
  864. package/assets/sfx/personagem/footstep_snow_walk_04.ogg +0 -0
  865. package/assets/sfx/personagem/footstep_snow_walk_05.ogg +0 -0
  866. package/assets/sfx/personagem/footstep_wood_alt_01.ogg +0 -0
  867. package/assets/sfx/personagem/footstep_wood_alt_02.ogg +0 -0
  868. package/assets/sfx/personagem/footstep_wood_alt_03.ogg +0 -0
  869. package/assets/sfx/personagem/footstep_wood_alt_04.ogg +0 -0
  870. package/assets/sfx/personagem/footstep_wood_alt_05.ogg +0 -0
  871. package/assets/sfx/personagem/footstep_wood_run_01.ogg +0 -0
  872. package/assets/sfx/personagem/footstep_wood_run_02.ogg +0 -0
  873. package/assets/sfx/personagem/footstep_wood_run_03.ogg +0 -0
  874. package/assets/sfx/personagem/footstep_wood_run_04.ogg +0 -0
  875. package/assets/sfx/personagem/footstep_wood_run_05.ogg +0 -0
  876. package/assets/sfx/personagem/footstep_wood_walk_01.ogg +0 -0
  877. package/assets/sfx/personagem/footstep_wood_walk_02.ogg +0 -0
  878. package/assets/sfx/personagem/footstep_wood_walk_03.ogg +0 -0
  879. package/assets/sfx/personagem/footstep_wood_walk_04.ogg +0 -0
  880. package/assets/sfx/personagem/footstep_wood_walk_05.ogg +0 -0
  881. package/assets/sfx/personagem/frying_pan_hit_01.ogg +0 -0
  882. package/assets/sfx/personagem/frying_pan_hit_02.ogg +0 -0
  883. package/assets/sfx/personagem/frying_pan_hit_03.ogg +0 -0
  884. package/assets/sfx/personagem/grab_01.ogg +0 -0
  885. package/assets/sfx/personagem/kick_hit_01.ogg +0 -0
  886. package/assets/sfx/personagem/kick_hit_02.ogg +0 -0
  887. package/assets/sfx/personagem/kick_hit_03.ogg +0 -0
  888. package/assets/sfx/personagem/kick_hit_04.ogg +0 -0
  889. package/assets/sfx/personagem/kick_hit_05.ogg +0 -0
  890. package/assets/sfx/personagem/knife_draw_01.ogg +0 -0
  891. package/assets/sfx/personagem/knife_draw_02.ogg +0 -0
  892. package/assets/sfx/personagem/knife_draw_03.ogg +0 -0
  893. package/assets/sfx/personagem/knife_scrape_01.ogg +0 -0
  894. package/assets/sfx/personagem/knife_slash_01.ogg +0 -0
  895. package/assets/sfx/personagem/knife_slash_02.ogg +0 -0
  896. package/assets/sfx/personagem/land_concrete_01.ogg +0 -0
  897. package/assets/sfx/personagem/land_concrete_02.ogg +0 -0
  898. package/assets/sfx/personagem/land_dirt_01.ogg +0 -0
  899. package/assets/sfx/personagem/land_dirt_02.ogg +0 -0
  900. package/assets/sfx/personagem/land_grass_01.ogg +0 -0
  901. package/assets/sfx/personagem/land_grass_02.ogg +0 -0
  902. package/assets/sfx/personagem/land_metal_01.ogg +0 -0
  903. package/assets/sfx/personagem/land_metal_02.ogg +0 -0
  904. package/assets/sfx/personagem/land_snow_01.ogg +0 -0
  905. package/assets/sfx/personagem/land_snow_02.ogg +0 -0
  906. package/assets/sfx/personagem/land_wood_01.ogg +0 -0
  907. package/assets/sfx/personagem/land_wood_02.ogg +0 -0
  908. package/assets/sfx/personagem/player_breath_run_01.ogg +0 -0
  909. package/assets/sfx/personagem/player_breath_run_02.ogg +0 -0
  910. package/assets/sfx/personagem/player_breath_run_03.ogg +0 -0
  911. package/assets/sfx/personagem/player_breath_run_04.ogg +0 -0
  912. package/assets/sfx/personagem/player_breath_run_05.ogg +0 -0
  913. package/assets/sfx/personagem/player_death_female_01.ogg +0 -0
  914. package/assets/sfx/personagem/player_death_female_02.ogg +0 -0
  915. package/assets/sfx/personagem/player_death_female_03.ogg +0 -0
  916. package/assets/sfx/personagem/player_death_female_04.ogg +0 -0
  917. package/assets/sfx/personagem/player_death_female_05.ogg +0 -0
  918. package/assets/sfx/personagem/player_death_female_06.ogg +0 -0
  919. package/assets/sfx/personagem/player_death_female_07.ogg +0 -0
  920. package/assets/sfx/personagem/player_death_female_08.ogg +0 -0
  921. package/assets/sfx/personagem/player_death_male_01.ogg +0 -0
  922. package/assets/sfx/personagem/player_death_male_02.ogg +0 -0
  923. package/assets/sfx/personagem/player_death_male_03.ogg +0 -0
  924. package/assets/sfx/personagem/player_death_male_04.ogg +0 -0
  925. package/assets/sfx/personagem/player_death_male_05.ogg +0 -0
  926. package/assets/sfx/personagem/player_death_male_06.ogg +0 -0
  927. package/assets/sfx/personagem/player_death_male_07.ogg +0 -0
  928. package/assets/sfx/personagem/player_death_male_08.ogg +0 -0
  929. package/assets/sfx/personagem/player_effort_01.ogg +0 -0
  930. package/assets/sfx/personagem/player_effort_02.ogg +0 -0
  931. package/assets/sfx/personagem/player_effort_03.ogg +0 -0
  932. package/assets/sfx/personagem/player_effort_04.ogg +0 -0
  933. package/assets/sfx/personagem/player_hurt_female_01.ogg +0 -0
  934. package/assets/sfx/personagem/player_hurt_female_02.ogg +0 -0
  935. package/assets/sfx/personagem/player_hurt_female_03.ogg +0 -0
  936. package/assets/sfx/personagem/player_hurt_female_04.ogg +0 -0
  937. package/assets/sfx/personagem/player_hurt_female_05.ogg +0 -0
  938. package/assets/sfx/personagem/player_hurt_female_06.ogg +0 -0
  939. package/assets/sfx/personagem/player_hurt_male_01.ogg +0 -0
  940. package/assets/sfx/personagem/player_hurt_male_02.ogg +0 -0
  941. package/assets/sfx/personagem/player_hurt_male_03.ogg +0 -0
  942. package/assets/sfx/personagem/player_hurt_male_04.ogg +0 -0
  943. package/assets/sfx/personagem/player_hurt_male_05.ogg +0 -0
  944. package/assets/sfx/personagem/player_hurt_male_06.ogg +0 -0
  945. package/assets/sfx/personagem/punch_hit_alt_01.ogg +0 -0
  946. package/assets/sfx/personagem/punch_hit_alt_02.ogg +0 -0
  947. package/assets/sfx/personagem/punch_hit_alt_03.ogg +0 -0
  948. package/assets/sfx/personagem/punch_hit_alt_04.ogg +0 -0
  949. package/assets/sfx/personagem/punch_hit_alt_05.ogg +0 -0
  950. package/assets/sfx/personagem/punch_hit_alt_06.ogg +0 -0
  951. package/assets/sfx/personagem/punch_hit_alt_07.ogg +0 -0
  952. package/assets/sfx/personagem/punch_hit_alt_08.ogg +0 -0
  953. package/assets/sfx/personagem/punch_hit_alt_09.ogg +0 -0
  954. package/assets/sfx/personagem/punch_hit_alt_10.ogg +0 -0
  955. package/assets/sfx/personagem/punch_hit_body_01.ogg +0 -0
  956. package/assets/sfx/personagem/punch_hit_body_02.ogg +0 -0
  957. package/assets/sfx/personagem/punch_hit_body_03.ogg +0 -0
  958. package/assets/sfx/personagem/punch_hit_body_04.ogg +0 -0
  959. package/assets/sfx/personagem/punch_hit_body_05.ogg +0 -0
  960. package/assets/sfx/personagem/punch_hit_body_06.ogg +0 -0
  961. package/assets/sfx/personagem/punch_hit_face_01.ogg +0 -0
  962. package/assets/sfx/personagem/punch_hit_face_02.ogg +0 -0
  963. package/assets/sfx/personagem/punch_hit_face_03.ogg +0 -0
  964. package/assets/sfx/personagem/punch_hit_face_04.ogg +0 -0
  965. package/assets/sfx/personagem/punch_hit_face_05.ogg +0 -0
  966. package/assets/sfx/personagem/punch_swing_01.ogg +0 -0
  967. package/assets/sfx/personagem/punch_swing_02.ogg +0 -0
  968. package/assets/sfx/personagem/punch_swing_03.ogg +0 -0
  969. package/assets/sfx/personagem/punch_swing_04.ogg +0 -0
  970. package/assets/sfx/personagem/punch_swing_05.ogg +0 -0
  971. package/assets/sfx/personagem/punch_swing_06.ogg +0 -0
  972. package/assets/sfx/personagem/punch_swing_07.ogg +0 -0
  973. package/assets/sfx/personagem/punch_swing_08.ogg +0 -0
  974. package/assets/sfx/personagem/scream_01.ogg +0 -0
  975. package/assets/sfx/personagem/scream_02.ogg +0 -0
  976. package/assets/sfx/personagem/scream_03.ogg +0 -0
  977. package/assets/sfx/personagem/scream_04.ogg +0 -0
  978. package/assets/sfx/personagem/slap_01.ogg +0 -0
  979. package/assets/sfx/personagem/swing_whoosh_alt_01.ogg +0 -0
  980. package/assets/sfx/personagem/swing_whoosh_alt_02.ogg +0 -0
  981. package/assets/sfx/personagem/swing_whoosh_alt_03.ogg +0 -0
  982. package/assets/sfx/personagem/swing_whoosh_alt_04.ogg +0 -0
  983. package/assets/sfx/personagem/swing_whoosh_alt_05.ogg +0 -0
  984. package/assets/sfx/personagem/swing_whoosh_alt_06.ogg +0 -0
  985. package/assets/sfx/personagem/swing_whoosh_alt_07.ogg +0 -0
  986. package/assets/sfx/personagem/swing_whoosh_alt_08.ogg +0 -0
  987. package/assets/sfx/personagem/swing_whoosh_alt_09.ogg +0 -0
  988. package/assets/sfx/personagem/swing_whoosh_alt_10.ogg +0 -0
  989. package/assets/sfx/personagem/swing_whoosh_alt_11.ogg +0 -0
  990. package/assets/sfx/personagem/swing_whoosh_alt_12.ogg +0 -0
  991. package/assets/sfx/personagem/swing_whoosh_alt_13.ogg +0 -0
  992. package/assets/sfx/personagem/swing_whoosh_alt_14.ogg +0 -0
  993. package/assets/sfx/personagem/swing_whoosh_alt_15.ogg +0 -0
  994. package/assets/sfx/personagem/swing_whoosh_alt_16.ogg +0 -0
  995. package/assets/sfx/personagem/swing_whoosh_alt_17.ogg +0 -0
  996. package/assets/sfx/personagem/swing_whoosh_alt_18.ogg +0 -0
  997. package/assets/sfx/personagem/swing_whoosh_alt_19.ogg +0 -0
  998. package/assets/sfx/personagem/swing_whoosh_alt_20.ogg +0 -0
  999. package/assets/sfx/personagem/swing_whoosh_alt_21.ogg +0 -0
  1000. package/assets/sfx/personagem/swing_whoosh_alt_22.ogg +0 -0
  1001. package/assets/sfx/personagem/swing_whoosh_alt_23.ogg +0 -0
  1002. package/assets/sfx/personagem/swing_whoosh_alt_24.ogg +0 -0
  1003. package/assets/sfx/personagem/swing_whoosh_alt_25.ogg +0 -0
  1004. package/assets/sfx/personagem/swing_whoosh_alt_26.ogg +0 -0
  1005. package/assets/sfx/personagem/swing_whoosh_alt_27.ogg +0 -0
  1006. package/assets/sfx/personagem/swing_whoosh_alt_28.ogg +0 -0
  1007. package/assets/sfx/personagem/swing_whoosh_alt_29.ogg +0 -0
  1008. package/assets/sfx/personagem/swing_whoosh_alt_30.ogg +0 -0
  1009. package/assets/sfx/personagem/swing_whoosh_alt_31.ogg +0 -0
  1010. package/assets/sfx/personagem/swing_whoosh_alt_32.ogg +0 -0
  1011. package/assets/sfx/personagem/swing_whoosh_alt_33.ogg +0 -0
  1012. package/assets/sfx/personagem/swing_whoosh_alt_34.ogg +0 -0
  1013. package/assets/sfx/personagem/swing_whoosh_alt_35.ogg +0 -0
  1014. package/assets/sfx/personagem/swing_whoosh_alt_36.ogg +0 -0
  1015. package/assets/sfx/personagem/swing_whoosh_alt_37.ogg +0 -0
  1016. package/assets/sfx/personagem/swing_whoosh_alt_38.ogg +0 -0
  1017. package/assets/sfx/personagem/swing_whoosh_alt_39.ogg +0 -0
  1018. package/assets/sfx/personagem/swing_whoosh_alt_40.ogg +0 -0
  1019. package/assets/sfx/personagem/swing_whoosh_alt_41.ogg +0 -0
  1020. package/assets/sfx/personagem/swing_whoosh_alt_42.ogg +0 -0
  1021. package/assets/sfx/personagem/swing_whoosh_alt_43.ogg +0 -0
  1022. package/assets/sfx/personagem/zombie_creature_01.ogg +0 -0
  1023. package/assets/sfx/personagem/zombie_creature_02.ogg +0 -0
  1024. package/assets/sfx/personagem/zombie_creature_03.ogg +0 -0
  1025. package/assets/sfx/personagem/zombie_death_01.ogg +0 -0
  1026. package/assets/sfx/personagem/zombie_death_02.ogg +0 -0
  1027. package/assets/sfx/personagem/zombie_death_03.ogg +0 -0
  1028. package/assets/sfx/personagem/zombie_death_04.ogg +0 -0
  1029. package/assets/sfx/personagem/zombie_death_05.ogg +0 -0
  1030. package/assets/sfx/personagem/zombie_death_06.ogg +0 -0
  1031. package/assets/sfx/personagem/zombie_death_07.ogg +0 -0
  1032. package/assets/sfx/personagem/zombie_death_08.ogg +0 -0
  1033. package/assets/sfx/personagem/zombie_groan_01.ogg +0 -0
  1034. package/assets/sfx/personagem/zombie_groan_02.ogg +0 -0
  1035. package/assets/sfx/personagem/zombie_groan_03.ogg +0 -0
  1036. package/assets/sfx/personagem/zombie_groan_04.ogg +0 -0
  1037. package/assets/sfx/personagem/zombie_groan_05.ogg +0 -0
  1038. package/assets/sfx/personagem/zombie_groan_06.ogg +0 -0
  1039. package/assets/sfx/personagem/zombie_groan_07.ogg +0 -0
  1040. package/assets/sfx/personagem/zombie_groan_08.ogg +0 -0
  1041. package/assets/sfx/personagem/zombie_groan_09.ogg +0 -0
  1042. package/assets/sfx/personagem/zombie_groan_10.ogg +0 -0
  1043. package/assets/sfx/personagem/zombie_groan_11.ogg +0 -0
  1044. package/assets/sfx/veiculos/car_door_open_01.ogg +0 -0
  1045. package/assets/sfx/veiculos/car_door_shut_01.ogg +0 -0
  1046. package/assets/sfx/veiculos/car_gear_shift_01.ogg +0 -0
  1047. package/assets/sfx/veiculos/car_trunk_shut_01.ogg +0 -0
  1048. package/assets/sfx/veiculos/car_window_01.ogg +0 -0
  1049. package/assets/sfx/veiculos/car_window_02.ogg +0 -0
  1050. package/assets/sfx/veiculos/engine_loop_car_high_01.ogg +0 -0
  1051. package/assets/sfx/veiculos/engine_loop_car_idle_01.ogg +0 -0
  1052. package/assets/sfx/veiculos/engine_start_run_stop_01.ogg +0 -0
  1053. package/assets/sfx/veiculos/engine_start_run_stop_02.ogg +0 -0
  1054. package/dist/bank-Dsj1VAht.d.ts +391 -0
  1055. package/dist/chunk-JV5XXCQE.js +180 -0
  1056. package/dist/chunk-JV5XXCQE.js.map +1 -0
  1057. package/dist/{chunk-C2K7XN2K.js → chunk-UUWKSG4J.js} +36 -165
  1058. package/dist/chunk-UUWKSG4J.js.map +1 -0
  1059. package/dist/fitted.d.ts +89 -0
  1060. package/dist/fitted.js +139 -0
  1061. package/dist/fitted.js.map +1 -0
  1062. package/dist/index.d.ts +28 -3
  1063. package/dist/index.global.js +106 -4
  1064. package/dist/index.global.js.map +1 -1
  1065. package/dist/index.js +80 -13
  1066. package/dist/index.js.map +1 -1
  1067. package/dist/{locale-BJMhMT0G.d.ts → locale-YHyJwN2P.d.ts} +104 -482
  1068. package/dist/testing.d.ts +3 -2
  1069. package/dist/testing.js +2 -1
  1070. package/package.json +6 -2
  1071. package/dist/chunk-C2K7XN2K.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/falloff.ts","../src/data/game-sfx.json","../src/recipes/noise-class.ts","../src/library/crowd_rumble.json","../src/library/engine_saw.json","../src/library/horn.json","../src/library/radio_static.json","../src/library/rotor_blades.json","../src/library/siren.json","../src/library/index.ts","../src/data/mix-profiles.json","../src/mix.ts","../src/recipe.ts","../src/data/voice-groups.json","../src/voices.ts","../src/bank.ts","../src/listener.ts","../src/rng.ts","../src/plan.ts","../src/webaudio/noise.ts","../src/webaudio/chain.ts","../src/webaudio/context.ts","../src/loops.ts","../src/webaudio/nodes.ts","../src/webaudio/realize-loop.ts","../src/webaudio/engine-loop.ts","../src/sample.ts","../src/webaudio/sample-loop.ts","../src/webaudio/engine-noise.ts","../src/webaudio/engine-queue.ts","../src/webaudio/realize-game.ts","../src/webaudio/realize-layered.ts","../src/webaudio/realize-weapon.ts","../src/webaudio/realize.ts","../src/variation.ts","../src/webaudio/sample-store.ts","../src/webaudio/realize-sample.ts","../src/webaudio/engine.ts","../src/bench/locale.ts","../src/bench/module.ts","../src/catalog.ts","../src/measure/calibration.ts","../src/measure/analyze.ts","../src/measure/criteria.ts","../src/manifest.ts","../src/kit-samples.ts","../src/local-pack.ts","../src/user-samples.ts","../src/bench/sound-check-locale.ts","../src/bench/sound-check.ts"],"sourcesContent":["import type { Falloff } from './recipe'\n\n/** The distance curves of the team routines, by name. Each recipe carries its own; these are the values to copy. */\nexport const DISTANCE_CURVES = {\n /** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */\n game_sfx: { model: 'inverse_square', k: 0.004, cutoffK: 0.01, minGain: 0.01 },\n /** The game's `grito`: `1 / (1 + d² × 0.006)`, silent below 0.02 (jogo L62129–62130). */\n game_scream: { model: 'inverse_square', k: 0.006, minGain: 0.02 },\n /** The game's `voz`: `1 / (1 + d² × 0.01)`, silent below 0.02 (jogo L62146–62147). */\n game_voice: { model: 'inverse_square', k: 0.01, minGain: 0.02 },\n /** The game's `boom`: `1.4 / (1 + d² × 0.002)`, never silent (jogo L68280). */\n game_boom: { model: 'inverse_square', k: 0.002, scale: 1.4 },\n /** The art scene's `outAt`: `vol / (1 + d² × 0.008)` (cena L1320). */\n art_scene: { model: 'inverse_square', k: 0.008 },\n /** The game's animal calls: `max(0, 1 − d / 70) × 0.25`, silent at or below 0.005 (jogo L66627–66628). */\n animals: { model: 'linear', range: 70, scale: 0.25, minGain: 0.005 },\n} as const satisfies Readonly<Record<string, Falloff>>\n\nexport type DistanceCurveName = keyof typeof DISTANCE_CURVES\n\n/** The level at `distance` for a sound at `volume`, before the recipe's envelope. */\nexport function falloffGain(falloff: Falloff | undefined, volume: number, distance: number): number {\n if (!falloff || falloff.model === 'none') return volume\n if (falloff.model === 'linear') {\n const level = Math.max(0, 1 - distance / falloff.range) * volume\n return falloff.scale === undefined ? level : level * falloff.scale\n }\n const level = volume / (1 + distance * distance * falloff.k)\n return falloff.scale === undefined ? level : falloff.scale * level\n}\n\n/** Whether a level is too quiet to play: below `minGain` (the game's `att < 0.01`), or at or below it for `linear` (the animal calls' `v <= 0.005`). */\nexport function isSilent(falloff: Falloff | undefined, gain: number): boolean {\n if (!falloff || falloff.model === 'none' || falloff.minGain === undefined) return false\n return falloff.model === 'linear' ? gain <= falloff.minGain : gain < falloff.minGain\n}\n\n/** What every lowpass cutoff is divided by at `distance` (1 when the curve has no muffling). */\nexport function cutoffDivisor(falloff: Falloff | undefined, distance: number): number {\n if (!falloff || falloff.model !== 'inverse_square' || falloff.cutoffK === undefined) return 1\n return 1 + distance * falloff.cutoffK\n}\n","{\n \"sources\": [\"jogo:L62089-62107\"],\n \"note\": \"The game's sfx table P: [lowpass cutoff Hz, peak gain, seconds]. Played as a noise burst with the game's distance curve (falloff game_sfx) and a 0.05 s tail. Team names in `team`.\",\n \"classes\": [\n { \"id\": \"pistol\", \"team\": \"pistola\", \"bus\": \"weapons\", \"cutoff\": 1800, \"gain\": 0.9, \"seconds\": 0.18 },\n { \"id\": \"shotgun\", \"team\": \"escopeta\", \"bus\": \"weapons\", \"cutoff\": 900, \"gain\": 1.2, \"seconds\": 0.35 },\n { \"id\": \"rifle\", \"team\": \"fuzil\", \"bus\": \"weapons\", \"cutoff\": 1400, \"gain\": 1.1, \"seconds\": 0.28 },\n { \"id\": \"long_rifle\", \"team\": \"rifle\", \"bus\": \"weapons\", \"cutoff\": 1100, \"gain\": 1.3, \"seconds\": 0.45 },\n { \"id\": \"impact\", \"team\": \"impacto\", \"bus\": \"world\", \"cutoff\": 2500, \"gain\": 0.25, \"seconds\": 0.05 },\n { \"id\": \"flesh\", \"team\": \"carne\", \"bus\": \"world\", \"cutoff\": 600, \"gain\": 0.35, \"seconds\": 0.08 },\n { \"id\": \"step\", \"team\": \"passo\", \"bus\": \"world\", \"cutoff\": 400, \"gain\": 0.08, \"seconds\": 0.05 },\n { \"id\": \"glass\", \"team\": \"vidro\", \"bus\": \"world\", \"cutoff\": 5000, \"gain\": 0.5, \"seconds\": 0.3 },\n { \"id\": \"wood\", \"team\": \"madeira\", \"bus\": \"world\", \"cutoff\": 700, \"gain\": 0.5, \"seconds\": 0.2 },\n { \"id\": \"reload\", \"team\": \"recarga\", \"bus\": \"weapons\", \"cutoff\": 3000, \"gain\": 0.15, \"seconds\": 0.06 },\n { \"id\": \"empty\", \"team\": \"vazio\", \"bus\": \"weapons\", \"cutoff\": 4000, \"gain\": 0.12, \"seconds\": 0.03 },\n { \"id\": \"explosion\", \"team\": \"explosao\", \"bus\": \"world\", \"cutoff\": 200, \"gain\": 1.6, \"seconds\": 1.4 }\n ],\n \"fallback\": { \"id\": \"unknown\", \"team\": \"(any other name)\", \"bus\": \"world\", \"cutoff\": 1000, \"gain\": 0.5, \"seconds\": 0.1 }\n}\n","import { DISTANCE_CURVES } from '../falloff'\nimport type { BusId, SoundBank, SoundRecipe } from '../recipe'\nimport gameSfxJson from '../data/game-sfx.json'\n\n/** One row of the game's `sfx` table (jogo L62096–62100): lowpass cutoff, peak gain and seconds of a noise burst. */\nexport type NoiseClass = {\n readonly id: string\n /** The name in the team code (`pistola`, `vidro`...). */\n readonly team: string\n readonly bus: BusId\n readonly cutoff: number\n readonly gain: number\n readonly seconds: number\n}\n\ntype GameSfxTable = { readonly sources: readonly string[]; readonly classes: readonly NoiseClass[]; readonly fallback: NoiseClass }\n\nconst GAME_SFX = gameSfxJson as unknown as GameSfxTable\n\n/** The 12 game classes, in the table's order. */\nexport const GAME_SFX_CLASSES: readonly NoiseClass[] = GAME_SFX.classes\n/** What the game plays for a name it does not know: `[1000, 0.5, 0.1]`. */\nexport const GAME_SFX_FALLBACK: NoiseClass = GAME_SFX.fallback\n\n/**\n * A class as a recipe: noise from a random point, the class lowpass (muffled by distance), the peak set at once and an exponential fall to 0.001 over\n * the class seconds, stopped 0.05 s later; the game's distance curve, silent below 0.01. Built in the game's `sfx` order (`burst`).\n */\nexport function noiseClassRecipe(row: NoiseClass, id = `sfx_${row.id}`): SoundRecipe {\n return {\n id,\n bus: row.bus,\n order: 'burst',\n duration: row.seconds,\n tail: 0.05,\n layers: [\n {\n source: { kind: 'noise', offset: 'random' },\n filters: { mode: 'serial', bank: [{ type: 'lowpass', frequency: { set: row.cutoff } }] },\n envelope: [\n [0, row.gain, 'set'],\n ['1d', 0.001, 'exp', 'fixed'],\n ],\n },\n ],\n falloff: DISTANCE_CURVES.game_sfx,\n sources: [...GAME_SFX.sources.map((source) => `${source} ${row.team}`)],\n }\n}\n\n/** The game's classes as a bank (`sfx_pistol`... and `sfx_unknown`). Subject banks pick their own classes from `GAME_SFX_CLASSES`. */\nexport const GAME_SFX_BANK: SoundBank = { id: 'game_sfx', sounds: [...GAME_SFX_CLASSES, GAME_SFX_FALLBACK].map((row) => noiseClassRecipe(row)) }\n","{\n \"id\": \"crowd_rumble\",\n \"bus\": \"ambience\",\n \"order\": \"game_loop\",\n \"source\": { \"kind\": \"noise\", \"loop\": true },\n \"filters\": { \"mode\": \"serial\", \"bank\": [{ \"type\": \"lowpass\", \"frequency\": { \"set\": 160 } }] },\n \"smoothing\": { \"volume\": 0.15, \"frequency\": 0.08 },\n \"startAbove\": 0.002,\n \"sources\": [\"jogo:L62116 horda: noise through a 160 Hz lowpass\", \"jogo:L70424 level min(0.16, near × 0.0016)\", \"temporary home until the crowd package (Q12)\"]\n}\n","{\n \"id\": \"engine_saw\",\n \"bus\": \"world\",\n \"order\": \"game_loop\",\n \"source\": { \"kind\": \"osc\", \"wave\": \"sawtooth\", \"loop\": true },\n \"filters\": { \"mode\": \"serial\", \"bank\": [{ \"type\": \"lowpass\", \"frequency\": { \"set\": 400 } }] },\n \"smoothing\": { \"volume\": 0.15, \"frequency\": 0.08 },\n \"startAbove\": 0.002,\n \"sources\": [\n \"jogo:L62115 motor: sawtooth through a 400 Hz lowpass\",\n \"jogo:L70421 level 0.035 + speed × 0.003, frequency 38 + speed × 7 (the host drives `set`)\",\n \"temporary home until the vehicles package (Q12)\"\n ]\n}\n","{\n \"id\": \"horn\",\n \"bus\": \"world\",\n \"order\": \"chord\",\n \"duration\": 0.6,\n \"tail\": 0.02,\n \"layers\": [\n { \"source\": { \"kind\": \"osc\", \"wave\": \"square\", \"frequency\": { \"set\": 415 } }, \"envelope\": [[0, 0.08, \"set\"], [0.6, 0.0001, \"set\", \"fixed\"]] },\n { \"source\": { \"kind\": \"osc\", \"wave\": \"square\", \"frequency\": { \"set\": 523 } }, \"envelope\": [[0, 0.08, \"set\"], [0.6, 0.0001, \"set\", \"fixed\"]] }\n ],\n \"falloff\": { \"model\": \"none\" },\n \"sources\": [\"jogo:L70272-70276 buzina: squares at 415 and 523 Hz, 0.08 for 0.6 s\", \"temporary home until the vehicles package (Q12)\"]\n}\n","{\n \"id\": \"radio_static\",\n \"bus\": \"world\",\n \"order\": \"static\",\n \"duration\": 0.6,\n \"layers\": [\n {\n \"source\": { \"kind\": \"noise\", \"offset\": \"random\" },\n \"filters\": { \"mode\": \"serial\", \"bank\": [{ \"type\": \"bandpass\", \"frequency\": { \"set\": 1800 }, \"q\": 0.8 }] },\n \"envelope\": [[0, 0.06, \"set\"], [\"1d\", 0.001, \"exp\", \"fixed\"]]\n }\n ],\n \"falloff\": { \"model\": \"none\" },\n \"sources\": [\"jogo:L69998-70004 chiado: noise through a 1800 Hz bandpass (Q 0.8), 0.06 falling over 0.6 s\", \"temporary home until the props or radio package (Q12)\"]\n}\n","{\n \"id\": \"rotor_blades\",\n \"bus\": \"world\",\n \"order\": \"game_loop\",\n \"source\": { \"kind\": \"noise\", \"loop\": true },\n \"filters\": { \"mode\": \"serial\", \"bank\": [{ \"type\": \"lowpass\", \"frequency\": { \"set\": 300 } }] },\n \"modulators\": [{ \"target\": \"gain\", \"rate\": 11, \"depth\": 0.5, \"base\": 0.5 }],\n \"smoothing\": { \"volume\": 0.15, \"frequency\": 0.08 },\n \"startAbove\": 0.002,\n \"sources\": [\n \"jogo:L62116-62120 rotor: noise through a 300 Hz lowpass, blade beat as an 11 Hz LFO of 0.5 on a 0.5 gain stage\",\n \"jogo:L70426 level min(0.5, 30 / (distance + 10))\",\n \"temporary home until the vehicles package (Q12)\"\n ]\n}\n","{\n \"id\": \"siren\",\n \"bus\": \"world\",\n \"order\": \"siren\",\n \"duration\": 9,\n \"tail\": 0.2,\n \"layers\": [\n {\n \"wet\": 1.5,\n \"source\": { \"kind\": \"osc\", \"wave\": \"sine\", \"frequency\": { \"set\": 850 } },\n \"modulators\": [{ \"target\": \"frequency\", \"rate\": 0.18, \"depth\": 280 }],\n \"filters\": { \"mode\": \"serial\", \"bank\": [{ \"type\": \"lowpass\", \"frequency\": { \"set\": 1400 } }] },\n \"envelope\": [[0, 0.0001, \"set\", \"fixed\"], [2, 0.035, \"exp\"], [6, 0.035, \"set\"], [9, 0.0001, \"exp\", \"fixed\"]]\n }\n ],\n \"falloff\": { \"model\": \"none\" },\n \"sources\": [\"cena:L1369 siren: 850 Hz sine swept ±280 Hz at 0.18 Hz, 1400 Hz lowpass, 0.035 for 9 s, reverb send 1.5\", \"temporary home until the vehicles package (Q12)\"]\n}\n","// Sounds whose subject has no package yet (Q12): they move to vehicles, crowd and props in Phases 7 and 8 and stay here as re-exports.\nimport type { LoopRecipe, SoundBank, SoundRecipe } from '../recipe'\nimport crowdRumble from './crowd_rumble.json'\nimport engineSaw from './engine_saw.json'\nimport horn from './horn.json'\nimport radioStatic from './radio_static.json'\nimport rotorBlades from './rotor_blades.json'\nimport siren from './siren.json'\n\nexport const LIBRARY_SOUNDS: readonly SoundRecipe[] = [horn, radioStatic, siren] as unknown as readonly SoundRecipe[]\nexport const LIBRARY_LOOPS: readonly LoopRecipe[] = [engineSaw, rotorBlades, crowdRumble] as unknown as readonly LoopRecipe[]\nexport const LIBRARY_BANK: SoundBank = { id: 'library', sounds: LIBRARY_SOUNDS, loops: LIBRARY_LOOPS }\n","[\n {\n \"id\": \"game\",\n \"master\": 0.5,\n \"noise\": {\n \"seconds\": 1.5,\n \"create\": \"lazy\"\n },\n \"sources\": [\n \"jogo:L62077-62081 master 0.5 to the output\",\n \"jogo:L62082-62088 noise 1.5 s made by the first sound that needs it\"\n ]\n },\n {\n \"id\": \"art_scene\",\n \"master\": 0.85,\n \"compressor\": {\n \"threshold\": -12,\n \"ratio\": 5\n },\n \"reverb\": {\n \"seconds\": 2.2,\n \"decay\": 3.4,\n \"wet\": 0.4\n },\n \"noise\": {\n \"seconds\": 2,\n \"create\": \"eager\"\n },\n \"sources\": [\n \"cena:L1308 compressor -12 dB, ratio 5\",\n \"cena:L1309 master 0.85\",\n \"cena:L1310 convolver, impulse 2.2 s of (1 - i/len)^3.4\",\n \"cena:L1311 wet 0.4\",\n \"cena:L1312 noise 2 s made with the chain\"\n ]\n },\n {\n \"id\": \"kit\",\n \"master\": 0.85,\n \"compressor\": {\n \"threshold\": -12,\n \"ratio\": 5\n },\n \"reverb\": {\n \"seconds\": 2.2,\n \"decay\": 3.4,\n \"wet\": 0.4\n },\n \"noise\": {\n \"seconds\": 2,\n \"create\": \"eager\"\n },\n \"sources\": [\n \"sdk: the art scene chain (cena L1308-L1312) with a limiter after the compressor: the page has none, and a blast with its debris and a fire catching reached +7 dBFS\"\n ],\n \"limiter\": {\n \"ceiling\": -1,\n \"knee\": -6\n }\n }\n]\n","import mixProfilesJson from './data/mix-profiles.json'\nimport type { BusId } from './recipe'\n\nexport type BusSetting = { readonly gain?: number; readonly muted?: boolean }\n\n/**\n * A mixing chain. `master` → (compressor) → (limiter) → output; with `reverb`, a wet bus → convolver (an impulse from the engine's seed) → master. `noise` is\n * the shared noise buffer: its length, and whether it is made with the chain (`eager`, the art scene) or by the first sound that needs it (`lazy`,\n * the game). Buses sit under the master and have no node until one is changed.\n */\nexport type MixProfile = {\n readonly id: string\n readonly master: number\n readonly compressor?: { readonly threshold: number; readonly ratio: number; readonly knee?: number; readonly attack?: number; readonly release?: number }\n readonly reverb?: { readonly seconds: number; readonly decay: number; readonly wet: number }\n /**\n * A last stage after the compressor that keeps every peak under `ceiling` dBFS: below `knee` dBFS the sound passes untouched, above it the peak\n * bends smoothly toward the ceiling (a soft clipper, no lookahead and no delay), so a blast with its debris and a fire catching all at once never\n * clips the output. `range` is the loudest input it shapes, as a factor of full scale (default 4, +12 dB); louder is held at the ceiling.\n */\n readonly limiter?: { readonly ceiling: number; readonly knee: number; readonly range?: number }\n readonly noise: { readonly seconds: number; readonly create: 'lazy' | 'eager' }\n readonly buses?: Readonly<Partial<Record<BusId, BusSetting>>>\n readonly sources: readonly string[]\n}\n\n/** The two team chains: `game` (master 0.5, jogo L62080) and `art_scene` (compressor and reverb, cena L1305–1313). */\nexport const MIX_PROFILES: Readonly<Record<string, MixProfile>> = Object.fromEntries(\n (mixProfilesJson as unknown as readonly MixProfile[]).map((profile) => [profile.id, profile]),\n)\n/** Q1: the kit plays through the art scene chain (compressor and reverb) with a limiter at the end (`kit`); `mix: 'art_scene'` is the page as it was, `mix: 'game'` the game's. */\nexport const DEFAULT_MIX = 'kit'\n\n/** A profile by id from `profiles`, or the profile itself. */\nexport function resolveMix(mix: string | MixProfile, profiles: Readonly<Record<string, MixProfile>> = MIX_PROFILES): MixProfile {\n if (typeof mix !== 'string') return mix\n const profile = profiles[mix]\n if (!profile) throw new Error(`game-audio: unknown mix profile \"${mix}\" (known: ${Object.keys(profiles).join(', ')})`)\n return profile\n}\n\n/** The gain a bus plays at: 0 when muted, its gain (default 1) otherwise. */\nexport function busGain(setting: BusSetting | undefined): number {\n if (!setting) return 1\n return setting.muted ? 0 : (setting.gain ?? 1)\n}\n","/**\n * Sound recipes are data. A recipe says which nodes a sound has and which numbers drive them; ranges are drawn when the sound is planned, in\n * the order the fields are written (see `planSound`), so a recipe ported from a team routine draws its random numbers in the routine's order.\n */\n\nexport const BUS_IDS = ['weapons', 'voices', 'world', 'ambience', 'weather', 'ui'] as const\nexport type BusId = (typeof BUS_IDS)[number]\n\n/** A named number: from `PlayOptions.params` or the recipe's `vars`, times `scale`, plus `add`. */\nexport type ParamRef = { readonly param: string; readonly scale?: number; readonly add?: number }\n\n/** A number, a `[min, max]` drawn uniformly (`min + random × (max − min)`), or a named number. */\nexport type Range = number | readonly [min: number, max: number] | ParamRef\n\n/** Seconds from the layer start: a range, the layer `'duration'`, or `'0.6d'` (0.6 × the layer duration). */\nexport type Time = Range | 'duration' | `${number}d`\n\nexport type Curve = 'linear' | 'exp'\n\n/**\n * How an AudioParam moves:\n * - `{ set }` assigns `.value`;\n * - `{ set, to, curve, over }` assigns `.value`, then ramps to `to` at `over`;\n * - `{ from }` calls `setValueAtTime(from)` at the start; with `to`, `curve` and `over` it then ramps to `to` (`'from'` is the value drawn for `from`: the art scene ramps a tone back to its own start when it gives no end).\n */\nexport type Automation =\n | { readonly set: Range; readonly to?: Range | 'from'; readonly curve?: Curve; readonly over?: Time }\n | { readonly from: Range; readonly to?: Range | 'from'; readonly curve?: Curve; readonly over?: Time }\n\n/**\n * One gain point: time (seconds, or `'0.6d'`), value and how it is reached (`set` = `setValueAtTime`, or a ramp). The value is multiplied by the\n * layer level (volume, distance and layer gain) except when the fourth item is `'fixed'` (the floor a ramp falls to, such as 0.001).\n */\nexport type EnvelopePoint =\n | readonly [time: number | `${number}d`, value: number, curve: 'set' | Curve]\n | readonly [time: number | `${number}d`, value: number, curve: 'set' | Curve, fixed: 'fixed']\nexport type Envelope = readonly EnvelopePoint[]\n\nexport type FilterSpec = {\n readonly type: BiquadFilterType\n readonly frequency: Automation\n readonly q?: Range\n /** The BiquadFilter gain (shelf and peaking types). */\n readonly gain?: Range\n /** A gain node after the filter, for a parallel bank where each band has its own level (the game's scream formants). */\n readonly level?: Range\n}\n\nexport type FilterBank = { readonly mode: 'serial' | 'parallel'; readonly bank: readonly FilterSpec[] }\n\n/** An LFO. `depth` is absolute, or a factor of the source start frequency. With `base`, gain modulation goes through its own gain stage (the game rotor). */\nexport type Modulator = {\n readonly target: 'gain' | 'frequency'\n /** Left out, the oscillator keeps its default (sine) and no type is set. */\n readonly wave?: OscillatorType\n readonly rate: Range\n readonly depth: Range | { readonly scaleOf: 'frequency'; readonly factor: number }\n readonly base?: number\n}\n\n/**\n * Noise from the engine's seeded buffer. `offset` is where playback starts in it: `'random'` (random × `offsetScale`, default 1), `'fit'`\n * (random × (buffer length − duration)) or seconds. `loop` sets the source to loop (the art scene sets it on every noise source).\n */\nexport type NoiseSource = {\n readonly kind: 'noise'\n readonly offset?: 'random' | 'fit' | number\n readonly offsetScale?: number\n readonly loop?: boolean\n}\n\nexport type OscSource = { readonly kind: 'osc'; readonly wave: OscillatorType; readonly frequency: Automation }\n\n/** The art scene's `voice`: an oscillator with vibrato through formant bands, plus a band of breath noise, summed and boosted. */\nexport type FormantVoiceSource = {\n readonly kind: 'formant_voice'\n readonly wave: OscillatorType\n readonly frequency: Automation\n /** Vibrato rate, and depth as a factor of the start frequency. */\n readonly vibrato: { readonly rate: Range; readonly depth: number }\n readonly formants: readonly { readonly frequency: Range; readonly q: number }[]\n readonly breath: { readonly frequency: Range; readonly q: number; readonly gain: Range }\n readonly mix: number\n}\n\nexport type LayerSource = NoiseSource | OscSource | FormantVoiceSource\n\nexport type Layer = {\n /** Start, seconds after the sound starts. */\n readonly at?: Range\n /** Overrides the recipe duration for this layer. */\n readonly duration?: Range\n /** Seconds the source keeps running after the duration (the `+ 0.05` of the team routines). Default: the recipe's, else 0.05. */\n readonly tail?: number\n /** The layer played `count` times, `spacing` seconds apart (the game's animal calls). */\n readonly repeat?: { readonly count: number; readonly spacing: number }\n /** Layer level before distance. Default 1. */\n readonly gain?: Range\n /** Send to the reverb, 0..1 or more (the art scene uses up to 1.2). */\n readonly wet?: number\n readonly source: LayerSource\n readonly filters?: FilterBank\n readonly modulators?: readonly Modulator[]\n readonly envelope: Envelope\n}\n\n/**\n * Distance falloff of a sound's level:\n * - `inverse_square`: `volume / (1 + d² × k)`; `cutoffK` also divides every lowpass cutoff by `1 + d × cutoffK` (the game's muffling);\n * - `linear`: `max(0, 1 − d / range)`, silent at or below `minGain`;\n * - `none`: no distance.\n * `scale` multiplies the level (the game's boom is 1.4 at the source), and below `minGain` the sound is not played.\n */\nexport type Falloff =\n | { readonly model: 'inverse_square'; readonly k: number; readonly minGain?: number; readonly cutoffK?: number; readonly scale?: number }\n | { readonly model: 'linear'; readonly range: number; readonly minGain?: number; readonly scale?: number }\n | { readonly model: 'none' }\n\n/**\n * The order the realizer creates and wires the nodes in. Each one is the order of the team routine it reproduces, so the trace of the SDK\n * matches the trace of the team code node for node:\n * - `layered` (default): the art scene's `sNoise`, `sTone` and `voice`; every layer has its own output stage (distance gain, pan, reverb send);\n * - `burst`: the game's `sfx` (jogo L62089);\n * - `scream`: the game's `grito` (L62128);\n * - `groan`: the game's `voz` (L62143);\n * - `boom`: the game's `boom` (L68278);\n * - `static`: the game's `chiado` (L69998);\n * - `chord`: the game's `buzina` (L70272);\n * - `calls`: the game's `bichoSom` (L66625);\n * - `siren`: the art scene's `siren` (L1369);\n * - `weapon`: the weapon audio of the kit (`weapons-three`): per layer a filtered noise burst or an oscillator, then its own gain, chained to the bus.\n * Every order but `layered` puts the level into the envelope and connects straight to the bus.\n */\nexport const BUILD_ORDERS = ['layered', 'burst', 'scream', 'groan', 'boom', 'static', 'chord', 'calls', 'siren', 'weapon'] as const\nexport type BuildOrder = (typeof BUILD_ORDERS)[number]\n\nexport type SoundRecipe = {\n readonly id: string\n readonly bus: BusId\n readonly order?: BuildOrder\n /** Named numbers drawn first, in the order written; layers read them with `{ param }`. */\n readonly vars?: Readonly<Record<string, Range>>\n readonly duration?: Range\n readonly tail?: number\n readonly layers: readonly Layer[]\n readonly falloff?: Falloff\n /** Stereo pan from the listener (the art scene's `panFor`). Only the `layered` order has an output stage to pan. */\n readonly pan?: boolean\n /** Voice group for the limiter (`undead_voice`...). */\n readonly group?: string\n /** Limiter priority; default from the bus (weapons > voices > world > ambience). */\n readonly priority?: number\n /**\n * The team routine creates nodes before it checks the level (the game's `bichoSom` creates its gain and filter first): a silent sound is kept as\n * a plan with `silent: true` so the realizer repeats those nodes. Off by default.\n */\n readonly keepSilent?: boolean\n /** Where the numbers come from: `\"jogo:L62128\"`, `\"cena:L1342\"`, or `\"sdk\"` for values the kit chose. */\n readonly sources: readonly string[]\n}\n\n/**\n * The order the loop realizer creates the nodes in:\n * - `game_loop`: the game's `loopSet` (L62109): gain and filter first, nodes created the first time the volume passes `startAbove`, gain from 0;\n * - `chain_loop`: the art scene's loops in `initAudio` (L1314–1316): source, filters, gain at its starting volume, created when the loop opens.\n */\nexport type LoopOrder = 'game_loop' | 'chain_loop'\n\nexport type LoopRecipe = {\n readonly id: string\n readonly bus: BusId\n readonly order?: LoopOrder\n /** An oscillator loop may leave the frequency out: it starts at the default and `set({ frequency })` glides it (the game's motor). */\n readonly source: (NoiseSource & { readonly loop: true }) | { readonly kind: 'osc'; readonly wave: OscillatorType; readonly frequency?: Automation; readonly loop: true }\n readonly filters?: FilterBank\n readonly modulators?: readonly Modulator[]\n /** `setTargetAtTime` time constants (jogo L62125–62126: 0.15 for the volume, 0.08 for the frequency). */\n readonly smoothing?: { readonly volume: number; readonly frequency: number }\n /** Nodes are created the first time the volume reaches this (jogo L62112: 0.002). */\n readonly startAbove?: number\n /** Volume the gain starts at when the loop opens (`chain_loop`). */\n readonly volume?: number\n /**\n * Distance falloff of the loop, applied each time `set` gives a `position` (an engine, a fire, a skid heard from where it is). Left out, the loop is\n * heard at the listener, as the team loops are. `cutoffK` also lowers the first filter's cutoff with the distance, as it does for one-shots.\n */\n readonly falloff?: Falloff\n /** Stereo pan from the listener, from the `position` of each `set` (a panner after the gain). Off by default. */\n readonly pan?: boolean\n readonly sources: readonly string[]\n}\n\n/**\n * One id that plays one of several recipes (the takes of a footstep, of a punch): `play(id)` draws a variant, never the one it played last time (unless\n * `repeat`), and plays it at a rate drawn from `rate` (1.04 is 4% higher and 4% shorter; see `retunePlan`), so ten footsteps never sound like one.\n */\nexport type SoundSet = {\n readonly id: string\n /** Recipe ids, at least one. */\n readonly variants: readonly string[]\n /** `[min, max]` of the playback rate (pitch and speed together). Default `[1, 1]`. */\n readonly rate?: readonly [min: number, max: number]\n /** Allow the same variant twice in a row (default false). */\n readonly repeat?: boolean\n}\n\nexport type SoundBank = {\n readonly id: string\n readonly sounds?: readonly SoundRecipe[]\n readonly loops?: readonly LoopRecipe[]\n readonly sets?: readonly SoundSet[]\n /** Sounds played from recorded files (see `sample.ts`). A sample and a recipe may share an id: the sample plays once its files are loaded. */\n readonly samples?: readonly SampleSound[]\n /**\n * Ids of this bank that play the takes of a sample sound registered by another bank (a manifest's file id), resolved when the id is looked up, so\n * the order the banks register in does not matter. A sample of the alias's own id, when one is registered, wins.\n */\n readonly sampleAliases?: readonly SampleAlias[]\n}\n\n/**\n * One id answered by the takes of another sample sound (`file`): `engine_car_low` by `engine_loop_car_idle`. The other numbers replace the file's;\n * `offset` and `duration` trim every take (one recording holding the start, the run and the stop gives each its own id). The recipe or loop of `id`\n * stays as the fallback while the files load or where they are missing.\n */\nexport type SampleAlias = {\n readonly id: string\n readonly file: string\n readonly offset?: number\n readonly duration?: number\n readonly loop?: SampleSound['loop']\n readonly baseFrequency?: number\n readonly gain?: number\n readonly pitch?: number\n readonly falloff?: Falloff\n}\n\n// ----- sounds from recorded files (planned by `planSample` in sample.ts; the types live here so the bank has them without an import cycle)\n\n/** One take: a file and its own trim (linear gain, default 1). */\nexport type SampleRef = {\n readonly url: string\n readonly gain?: number\n /** Seconds into the file the take starts at (default 0). A looping take starts there the first time round. */\n readonly offset?: number\n /** Seconds of the file the take plays (default to its end); a trimmed one-shot fades out over its last 40 ms, so the cut does not click. */\n readonly duration?: number\n}\n\n/** Where a sound happens: a closed room rings short and dense, the open field long and thin. */\nexport type SampleEnvironment = 'indoor' | 'outdoor'\n\n/** Where the near take hands over to the far one: all near up to `from` metres, all far from `to`, an equal-power crossfade between. */\nexport type SampleCrossover = { readonly from: number; readonly to: number }\n\nexport type SampleTail = {\n readonly indoor?: readonly SampleRef[]\n readonly outdoor?: readonly SampleRef[]\n /** Level of the tail against the dry take (default 0.6). */\n readonly gain?: number\n /** Seconds after the start (default 0: the tail file carries its own pre-delay). */\n readonly at?: number\n}\n\n/**\n * A set of takes for a strength of the action (criterion C7: a light blow, a heavy one, a car at 10 or 60 km/h): from `from` (0..1) up, these takes\n * replace `close` and `far`. The tier played is the last one whose `from` is at or below `PlayOptions.intensity`.\n */\nexport type SampleTier = {\n readonly name: string\n readonly from: number\n readonly close: readonly SampleRef[]\n readonly far?: readonly SampleRef[]\n}\n\nexport type SampleSound = {\n readonly id: string\n readonly bus: BusId\n /** The takes heard near; at least one (the criteria ask four for a sound heard all the time). */\n readonly close: readonly SampleRef[]\n /** The takes heard far; without them the near take plays at every distance (muffled by the lowpass). */\n readonly far?: readonly SampleRef[]\n /** Takes by strength (light, medium, heavy), in rising `from`; without `intensity` the near takes above play. */\n readonly tiers?: readonly SampleTier[]\n /** Default `{ from: 30, to: 80 }`. */\n readonly crossover?: SampleCrossover\n readonly tail?: SampleTail\n /** ± fraction of the playback rate drawn per play (default 0.04: ±4 %, inside the 3–5 % of the criteria). 0 plays every take at its pitch. */\n readonly pitch?: number\n /** Level of the sound (default 1). */\n readonly gain?: number\n /** Default `{ model: 'inverse_square', k: 0.002, minGain: 0.002 }`: a recorded take already sounds near or far, so the curve is gentler than a recipe's. */\n readonly falloff?: Falloff\n /** The lowpass cutoff is `20000 / (1 + d × cutoffK)` Hz (default 0.01: 10 kHz at 100 m). 0 turns the distance lowpass off. */\n readonly cutoffK?: number\n /** Stereo pan from the listener (default true). */\n readonly pan?: boolean\n readonly group?: string\n readonly priority?: number\n /**\n * At most `voices` plays of this sound ring at once: a new one fades the oldest out in `fade` seconds (default 0.03) at its own start. Rapid fire\n * then stays shot by shot instead of a wall of overlapping takes (criterion C9). Without it every play rings to its end.\n */\n readonly choke?: { readonly voices: number; readonly fade?: number }\n /**\n * A continuous sound (fire, rain, an engine idling) that `engine.loop(id)` plays: the near takes chained without a seam, each crossed into the next\n * in `crossfade` seconds (default 0.25, equal power), never the same take twice in a row. While the files load, the recipe loop of `fallback`\n * (or of the same id) plays. `play(id)` still plays one take as a one-shot.\n */\n readonly loop?: boolean | { readonly crossfade?: number }\n /**\n * The frequency the recording of a loop sounds at (an engine's firing frequency at the RPM it was recorded at): `set({ frequency })` then plays\n * the takes at `frequency / baseFrequency`, gliding, as an oscillator loop follows it. Without it the loop keeps the pitch of its files.\n */\n readonly baseFrequency?: number\n /** A recipe id the engine plays while the files are not loaded yet (or failed): the synthesized sound stays as the fallback. */\n readonly fallback?: string\n /** Where each file came from: `\"freesound:123456 autor CC0\"`, or `\"sdk\"` for files the kit made. */\n readonly sources: readonly string[]\n /** The licence of the files when one is declared (a local pack's entry); the sound panel lists those that are not CC0 / CC-BY. */\n readonly license?: string\n}\n","{\n \"undead_voice\": {\n \"maxConcurrent\": 5,\n \"cooldown\": 0.25,\n \"maxDistance\": 40,\n \"sources\": [\n \"cena:L1342 `AU.groans > 4` refuses, so five play at once\",\n \"jogo:L66986 one groan every 0.25 s (`groanBudget`), only nearer than 40 m\",\n \"jogo:L70472 the budget counts down by the frame time\"\n ]\n },\n \"fire_ignite\": {\n \"maxConcurrent\": 2,\n \"cooldown\": 0.15,\n \"sources\": [\n \"sdk: many parts catching at once (a blast sets a shelf alight) are one or two ignitions, not forty\"\n ]\n },\n \"fire_crackle\": {\n \"maxConcurrent\": 4,\n \"sources\": [\n \"sdk: the crackles of every fire share four voices\"\n ]\n }\n}\n","import voiceGroupsJson from './data/voice-groups.json'\nimport type { BusId } from './recipe'\n\n/**\n * Rules for a group of voices (`undead_voice`...). A request passes when every rule passes:\n * - `maxConcurrent`: at most this many of the group play at once (`steal` replaces the group's oldest instead of refusing);\n * - `cooldown`: seconds after an accepted voice before the next one (the game's `groanBudget`, jogo L66986 and L70472);\n * - `maxDistance`: only voices nearer than this (the game's `d < 40`).\n */\nexport type VoiceGroup = {\n readonly maxConcurrent?: number\n readonly cooldown?: number\n readonly maxDistance?: number\n readonly steal?: boolean\n readonly sources?: readonly string[]\n}\n\n/** `undead_voice`: the art scene's five at once with the game's 0.25 s cooldown and 40 m. */\nexport const VOICE_GROUPS: Readonly<Record<string, VoiceGroup>> = voiceGroupsJson\n\n/** Q7: weapons > voices > world > ambience; the interface above all, weather with the ambience. */\nexport const BUS_PRIORITY: Readonly<Record<BusId, number>> = { ui: 5, weapons: 4, voices: 3, world: 2, weather: 1, ambience: 1 }\nexport const DEFAULT_MAX_VOICES = 32\n\nexport function busPriority(bus: BusId): number {\n return BUS_PRIORITY[bus]\n}\n\nexport type VoiceRequest = {\n readonly group?: string\n readonly priority: number\n /** Planned level; the global cap drops the lowest `priority × gain`. */\n readonly gain: number\n readonly distance?: number\n /** Seconds the voice lasts. */\n readonly length: number\n}\n\nexport type VoiceRefusal = 'cooldown' | 'distance' | 'group_full' | 'global_full'\n\nexport type VoiceDecision =\n | { readonly accepted: true; readonly id: number; readonly evicted: readonly number[] }\n | { readonly accepted: false; readonly reason: VoiceRefusal }\n\nexport type VoiceStats = { readonly active: number; readonly peak: number; readonly dropped: number; readonly maxVoices: number }\n\nexport type VoiceManager = {\n request(request: VoiceRequest): VoiceDecision\n /** Ends a voice early (stopped by the host). */\n release(id: number): void\n /** Sets how long an accepted voice lasts (the engine admits a voice before its random length is drawn). */\n setLength(id: number, seconds: number): void\n /** Moves time on: cooldowns count down and finished voices leave. Returns the ids that ended. */\n advance(dt: number): number[]\n setGroup(id: string, group: VoiceGroup | undefined): void\n stats(): VoiceStats\n}\n\nexport type VoiceManagerOptions = {\n /** Default `VOICE_GROUPS`. */\n readonly groups?: Readonly<Record<string, VoiceGroup>>\n readonly maxVoices?: number\n}\n\ntype ActiveVoice = { readonly id: number; readonly group?: string; readonly score: number; remaining: number }\n\n/** The voice limiter: per-group rules, a global cap and priority dropping. Pure and time-driven (`advance`), so goldens script it frame by frame. */\nexport function createVoiceManager(options: VoiceManagerOptions = {}): VoiceManager {\n const groups = new Map(Object.entries(options.groups ?? VOICE_GROUPS))\n const maxVoices = options.maxVoices ?? DEFAULT_MAX_VOICES\n const budgets = new Map<string, number>()\n let voices: ActiveVoice[] = []\n let nextId = 1\n let peak = 0\n let dropped = 0\n\n const refuse = (reason: VoiceRefusal): VoiceDecision => {\n dropped += 1\n return { accepted: false, reason }\n }\n\n const groupCheck = (request: VoiceRequest, evicted: number[]): VoiceRefusal | undefined => {\n const group = request.group === undefined ? undefined : groups.get(request.group)\n if (!group) return undefined\n if (group.maxDistance !== undefined && !((request.distance ?? 0) < group.maxDistance)) return 'distance'\n if (group.cooldown !== undefined && (budgets.get(request.group as string) ?? 0) > 0) return 'cooldown'\n const members = voices.filter((voice) => voice.group === request.group)\n if (group.maxConcurrent === undefined || members.length < group.maxConcurrent) return undefined\n if (!group.steal) return 'group_full'\n evicted.push((members[0] as ActiveVoice).id)\n return undefined\n }\n\n return {\n request(request) {\n const evicted: number[] = []\n const refusal = groupCheck(request, evicted)\n if (refusal) return refuse(refusal)\n const score = request.priority * request.gain\n const remaining = voices.filter((voice) => !evicted.includes(voice.id))\n if (remaining.length >= maxVoices) {\n const lowest = remaining.reduce((low, voice) => (voice.score < low.score ? voice : low))\n if (score <= lowest.score) return refuse('global_full')\n evicted.push(lowest.id)\n dropped += 1\n }\n const group = request.group === undefined ? undefined : groups.get(request.group)\n if (group?.cooldown !== undefined) budgets.set(request.group as string, group.cooldown)\n const id = nextId++\n voices = [...voices.filter((voice) => !evicted.includes(voice.id)), { id, ...(request.group === undefined ? {} : { group: request.group }), score, remaining: request.length }]\n peak = Math.max(peak, voices.length)\n return { accepted: true, id, evicted }\n },\n release(id) {\n voices = voices.filter((voice) => voice.id !== id)\n },\n setLength(id, seconds) {\n const voice = voices.find((entry) => entry.id === id)\n if (voice) voice.remaining = seconds\n },\n advance(dt) {\n for (const [group, budget] of budgets) budgets.set(group, budget - dt)\n const ended: number[] = []\n for (const voice of voices) {\n voice.remaining -= dt\n if (voice.remaining <= 0) ended.push(voice.id)\n }\n if (ended.length > 0) voices = voices.filter((voice) => voice.remaining > 0)\n return ended\n },\n setGroup(id, group) {\n if (group) groups.set(id, group)\n else groups.delete(id)\n },\n stats: () => ({ active: voices.length, peak, dropped, maxVoices }),\n }\n}\n","import type { LoopRecipe, SampleAlias, SampleRef, SoundBank, SoundRecipe, SoundSet } from './recipe'\nimport type { SampleSound } from './sample'\n\nexport type DeepPartial<TValue> = TValue extends readonly unknown[] ? TValue : TValue extends object ? { readonly [Key in keyof TValue]?: DeepPartial<TValue[Key]> } : TValue\n\n/** Every sound and loop the engine knows, by id. Banks register in order; a later bank replaces an earlier recipe with the same id. */\nexport type SoundRegistry = {\n register(bank: SoundBank): void\n /** Merged into the recipe by id (objects merge, arrays such as `layers` are replaced); an unknown id is ignored. */\n patch(id: string, patch: DeepPartial<SoundRecipe> | DeepPartial<LoopRecipe> | DeepPartial<SampleSound>): void\n remove(id: string): void\n /** Drops only the sample sound of an id; a recipe or loop of the same id stays. */\n removeSample(id: string): void\n sound(id: string): SoundRecipe | undefined\n loop(id: string): LoopRecipe | undefined\n /** The set an id names (`SoundBank.sets`), if any; a recipe with the same id wins in `play`. */\n set(id: string): SoundSet | undefined\n /** The sample sound of an id: its own, or the takes of the sound a bank's `sampleAliases` points it at (once that one is registered). */\n sample(id: string): SampleSound | undefined\n soundIds(): string[]\n setIds(): string[]\n loopIds(): string[]\n /** Every id `sample` answers, aliases whose file is registered included. */\n sampleIds(): string[]\n /** Which bank each id came from. */\n bankOf(id: string): string | undefined\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n// keys keep their place, so a patched range is still drawn where it was\nfunction mergeRecords(base: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue\n const current = merged[key]\n merged[key] = isPlainObject(current) && isPlainObject(value) ? mergeRecords(current, value) : value\n }\n return merged\n}\n\nconst trimmed = (refs: readonly SampleRef[], alias: SampleAlias): SampleRef[] =>\n refs.map((ref) => ({\n ...ref,\n ...(alias.offset === undefined ? {} : { offset: alias.offset }),\n ...(alias.duration === undefined ? {} : { duration: alias.duration }),\n }))\n\n/** The sample an alias names: the file's takes and numbers, with the alias's id and its own numbers; the recipe of the alias id is the fallback. */\nexport function aliasSample(alias: SampleAlias, file: SampleSound): SampleSound {\n const { tiers: _tiers, fallback: _fallback, choke: _choke, ...rest } = file\n return {\n ...rest,\n id: alias.id,\n close: trimmed(file.close, alias),\n ...(file.far ? { far: trimmed(file.far, alias) } : {}),\n ...(alias.loop === undefined ? {} : { loop: alias.loop }),\n ...(alias.baseFrequency === undefined ? {} : { baseFrequency: alias.baseFrequency }),\n ...(alias.gain === undefined ? {} : { gain: alias.gain }),\n ...(alias.pitch === undefined ? {} : { pitch: alias.pitch }),\n ...(alias.falloff ? { falloff: alias.falloff } : {}),\n fallback: alias.id,\n sources: [...file.sources, `alias: ${alias.id} → ${alias.file}`],\n }\n}\n\nexport function createSoundRegistry(banks: readonly SoundBank[] = []): SoundRegistry {\n const sounds = new Map<string, SoundRecipe>()\n const loops = new Map<string, LoopRecipe>()\n const sets = new Map<string, SoundSet>()\n const samples = new Map<string, SampleSound>()\n const owners = new Map<string, string>()\n const aliases = new Map<string, SampleAlias>()\n // the sample of each alias, made on its first lookup; any change to the samples makes them again\n const derived = new Map<string, SampleSound>()\n const resolveAlias = (id: string): SampleSound | undefined => {\n const alias = aliases.get(id)\n if (!alias) return undefined\n const cached = derived.get(id)\n if (cached) return cached\n const file = samples.get(alias.file)\n if (!file) return undefined\n const sample = aliasSample(alias, file)\n derived.set(id, sample)\n return sample\n }\n const registry: SoundRegistry = {\n register(bank) {\n for (const sound of bank.sounds ?? []) {\n sounds.set(sound.id, sound)\n owners.set(sound.id, bank.id)\n }\n for (const loop of bank.loops ?? []) {\n loops.set(loop.id, loop)\n owners.set(loop.id, bank.id)\n }\n for (const set of bank.sets ?? []) {\n if (set.variants.length === 0) throw new Error(`sound set ${set.id} has no variant`)\n sets.set(set.id, set)\n owners.set(set.id, bank.id)\n }\n for (const sample of bank.samples ?? []) {\n samples.set(sample.id, sample)\n owners.set(sample.id, bank.id)\n }\n for (const alias of bank.sampleAliases ?? []) {\n aliases.set(alias.id, alias)\n if (!owners.has(alias.id)) owners.set(alias.id, bank.id)\n }\n derived.clear()\n },\n patch(id, patch) {\n const sound = sounds.get(id)\n if (sound) sounds.set(id, mergeRecords(sound, patch as Record<string, unknown>) as SoundRecipe)\n const loop = loops.get(id)\n if (loop) loops.set(id, mergeRecords(loop, patch as Record<string, unknown>) as LoopRecipe)\n const sample = samples.get(id)\n if (sample) samples.set(id, mergeRecords(sample, patch as Record<string, unknown>) as SampleSound)\n derived.clear()\n },\n remove(id) {\n sounds.delete(id)\n loops.delete(id)\n sets.delete(id)\n samples.delete(id)\n aliases.delete(id)\n owners.delete(id)\n derived.clear()\n },\n removeSample(id) {\n samples.delete(id)\n aliases.delete(id)\n if (!sounds.has(id) && !loops.has(id) && !sets.has(id)) owners.delete(id)\n derived.clear()\n },\n sound: (id) => sounds.get(id),\n loop: (id) => loops.get(id),\n set: (id) => sets.get(id),\n sample: (id) => samples.get(id) ?? resolveAlias(id),\n soundIds: () => [...sounds.keys()],\n setIds: () => [...sets.keys()],\n loopIds: () => [...loops.keys()],\n sampleIds: () => [...samples.keys(), ...[...aliases.keys()].filter((id) => !samples.has(id) && resolveAlias(id) !== undefined)],\n bankOf: (id) => owners.get(id),\n }\n for (const bank of banks) registry.register(bank)\n return registry\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\n/** Where the ears are. `yaw` turns around y like a three.js camera: the right ear points at `(cos yaw, 0, −sin yaw)`. */\nexport type Listener = { readonly position: Vec3; readonly yaw: number }\n\nexport type DistanceMode = 'xz' | '3d'\n\nexport const DEFAULT_LISTENER: Listener = { position: [0, 0, 0], yaw: 0 }\n\n/** The art scene clamps the pan to ±0.85 and never divides by less than 2 m (cena L1319). */\nexport const PAN_LIMIT = 0.85\nexport const PAN_MIN_DISTANCE = 2\n\n/** Distance from the listener: on the ground (`xz`, the teams' choice) or in 3D. */\nexport function listenerDistance(listener: Listener, position: Vec3, mode: DistanceMode = 'xz'): number {\n const dx = position[0] - listener.position[0]\n const dz = position[2] - listener.position[2]\n if (mode === 'xz') return Math.hypot(dx, dz)\n return Math.hypot(dx, position[1] - listener.position[1], dz)\n}\n\n/** The art scene's `panFor`: the side the sound is on, −0.85 (left) to 0.85 (right). No HRTF, for cost. */\nexport function panFor(listener: Listener, position: Vec3): number {\n const rightX = Math.cos(listener.yaw)\n const rightZ = -Math.sin(listener.yaw)\n const dx = position[0] - listener.position[0]\n const dz = position[2] - listener.position[2]\n const distance = Math.hypot(dx, dz) || 1\n const pan = (dx * rightX + dz * rightZ) / Math.max(distance, PAN_MIN_DISTANCE)\n return pan < -PAN_LIMIT ? -PAN_LIMIT : pan > PAN_LIMIT ? PAN_LIMIT : pan\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; floats in [0, 1). The same generator the golden tool seeds `Math.random` with, so a team routine and its recipe draw the same numbers. */\nexport function createRng(seed: number): () => number {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** The seed of the stream called `name` (or numbered `name`): one seed gives each channel its own sequence, so one subject's sounds never shift another's. */\nexport function streamSeed(seed: number, name: string | number): number {\n const label = String(name)\n let hash = FNV_OFFSET\n for (let index = 0; index < label.length; index++) hash = Math.imul(hash ^ label.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function streamFor(seed: number, name: string | number): () => number {\n return createRng(streamSeed(seed, name))\n}\n\n/** `min + random × (max − min)`: the form every team routine uses (`95 + Math.random() * 40`). */\nexport function drawBetween(random: () => number, min: number, max: number): number {\n return min + random() * (max - min)\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { cutoffDivisor, falloffGain, isSilent } from './falloff'\nimport { DEFAULT_LISTENER, listenerDistance, panFor } from './listener'\nimport type { DistanceMode, Listener } from './listener'\nimport type { Automation, BuildOrder, BusId, Curve, Envelope, FilterSpec, Layer, LayerSource, Modulator, Range, SoundRecipe, Time } from './recipe'\nimport { createRng } from './rng'\nimport { busPriority } from './voices'\n\n/** How an AudioParam moves, with every number resolved and every time in seconds from the layer start. */\nexport type PlannedAutomation = {\n /** Assigned to `.value`. */\n readonly value?: number\n /** `setValueAtTime(from)` at the layer start. */\n readonly from?: number\n /** Ramp target, reached `at` seconds after the layer start. */\n readonly to?: number\n readonly curve?: Curve\n readonly at?: number\n}\n\nexport type PlannedFilter = {\n readonly type: BiquadFilterType\n readonly frequency: PlannedAutomation\n readonly q?: number\n readonly gain?: number\n readonly level?: number\n}\n\nexport type PlannedModulator = {\n readonly target: 'gain' | 'frequency'\n readonly wave?: OscillatorType\n readonly rate: number\n readonly depth: number\n readonly base?: number\n}\n\nexport type PlannedSource =\n | { readonly kind: 'noise'; readonly offset: number; readonly loop: boolean }\n | { readonly kind: 'osc'; readonly wave: OscillatorType; readonly frequency: PlannedAutomation }\n | {\n readonly kind: 'formant_voice'\n readonly wave: OscillatorType\n readonly frequency: PlannedAutomation\n readonly vibrato: { readonly rate: number; readonly depth: number }\n readonly formants: readonly { readonly frequency: number; readonly q: number }[]\n readonly breath: { readonly frequency: number; readonly q: number; readonly gain: number; readonly offset: number }\n readonly mix: number\n }\n\nexport type PlannedEnvelopePoint = { readonly time: number; readonly value: number; readonly curve: 'set' | Curve }\n\nexport type PlannedLayer = {\n readonly at: number\n readonly duration: number\n readonly tail: number\n /** Layer gain × the sound's level: in the envelope for every order but `layered`, in the output stage for `layered`. */\n readonly level: number\n readonly wet?: number\n readonly source: PlannedSource\n readonly filters?: { readonly mode: 'serial' | 'parallel'; readonly bank: readonly PlannedFilter[] }\n readonly modulators: readonly PlannedModulator[]\n readonly envelope: readonly PlannedEnvelopePoint[]\n}\n\n/** A sound with every number decided: what the realizer builds, what goldens compare and what the bench sheet prints. */\nexport type SoundPlan = {\n readonly id: string\n readonly bus: BusId\n readonly order: BuildOrder\n readonly group?: string\n readonly priority: number\n /** The level from volume and distance, before layer gains. */\n readonly level: number\n readonly distance: number\n readonly pan?: number\n /** Too quiet to hear, kept only for a recipe with `keepSilent`. */\n readonly silent: boolean\n /** Seconds until the last source stops. */\n readonly length: number\n readonly layers: readonly PlannedLayer[]\n}\n\nexport type PlanInput = {\n /** Where the numbers are drawn from. Default: a fresh stream with seed 1. */\n readonly random?: () => number\n readonly volume?: number\n /** Distance in meters; overrides `position`. */\n readonly distance?: number\n readonly position?: Vec3\n readonly listener?: Listener\n readonly distanceMode?: DistanceMode\n readonly params?: Readonly<Record<string, number>>\n /** 0..1 from the host's occlusion callback: gain × (1 − 0.5 × o), lowpass cutoffs × (1 − 0.6 × o). */\n readonly occlusion?: number\n /** Length of the noise buffer, for `offset: 'fit'`. Default 1.5. */\n readonly noiseSeconds?: number\n}\n\nconst DEFAULT_TAIL = 0.05\nconst DEFAULT_NOISE_SECONDS = 1.5\nconst OCCLUSION_GAIN = 0.5\nconst OCCLUSION_CUTOFF = 0.6\n\ntype Scope = { readonly random: () => number; readonly params: Record<string, number> }\n\nfunction isParamRef(range: Range): range is Extract<Range, { readonly param: string }> {\n return typeof range === 'object' && !Array.isArray(range)\n}\n\nfunction draw(range: Range, scope: Scope): number {\n if (typeof range === 'number') return range\n if (isParamRef(range)) {\n const value = scope.params[range.param]\n if (value === undefined) throw new Error(`game-audio: the recipe reads the param \"${range.param}\", which was not given`)\n return value * (range.scale ?? 1) + (range.add ?? 0)\n }\n const [min, max] = range as readonly [number, number]\n return min + scope.random() * (max - min)\n}\n\n// a time is drawn now when it is a range; 'duration' and '0.6d' wait for the layer duration\ntype PendingTime = number | 'duration' | `${number}d`\n\nfunction drawTime(time: Time, scope: Scope): PendingTime {\n if (time === 'duration' || (typeof time === 'string' && time.endsWith('d'))) return time as PendingTime\n return draw(time as Range, scope)\n}\n\nfunction timeOf(time: PendingTime, duration: number): number {\n if (typeof time === 'number') return time\n if (time === 'duration') return duration\n return Number(time.slice(0, -1)) * duration\n}\n\ntype PendingAutomation = { value?: number; from?: number; to?: number; curve?: Curve; over?: PendingTime }\n\nfunction drawAutomation(automation: Automation, scope: Scope): PendingAutomation {\n const pending: PendingAutomation = {}\n for (const key of Object.keys(automation)) {\n if (key === 'set' && 'set' in automation) pending.value = draw(automation.set, scope)\n else if (key === 'from' && 'from' in automation) pending.from = draw(automation.from, scope)\n else if (key === 'to' && automation.to !== undefined) pending.to = automation.to === 'from' ? (pending.from ?? pending.value ?? 0) : draw(automation.to, scope)\n else if (key === 'curve') pending.curve = automation.curve\n else if (key === 'over' && automation.over !== undefined) pending.over = drawTime(automation.over, scope)\n }\n return pending\n}\n\nfunction finishAutomation(pending: PendingAutomation, duration: number): PlannedAutomation {\n if (pending.from !== undefined && pending.to === undefined) return { from: pending.from }\n if (pending.from !== undefined) return { from: pending.from, to: pending.to, curve: pending.curve ?? 'linear', at: timeOf(pending.over ?? 'duration', duration) }\n if (pending.to === undefined || pending.over === undefined) return { value: pending.value }\n return { value: pending.value, to: pending.to, curve: pending.curve ?? 'linear', at: timeOf(pending.over, duration) }\n}\n\nconst startFrequency = (automation: PendingAutomation): number => automation.from ?? automation.value ?? 0\n\ntype PendingFilter = { spec: FilterSpec; frequency: PendingAutomation; q?: number; gain?: number; level?: number }\n\nfunction drawFilter(spec: FilterSpec, scope: Scope): PendingFilter {\n const pending: PendingFilter = { spec, frequency: {} }\n for (const key of Object.keys(spec)) {\n if (key === 'frequency') pending.frequency = drawAutomation(spec.frequency, scope)\n else if (key === 'q' && spec.q !== undefined) pending.q = draw(spec.q, scope)\n else if (key === 'gain' && spec.gain !== undefined) pending.gain = draw(spec.gain, scope)\n else if (key === 'level' && spec.level !== undefined) pending.level = draw(spec.level, scope)\n }\n return pending\n}\n\ntype PendingModulator = { modulator: Modulator; rate: number; depth?: number }\n\nfunction drawModulator(modulator: Modulator, scope: Scope): PendingModulator {\n const pending: PendingModulator = { modulator, rate: 0 }\n for (const key of Object.keys(modulator)) {\n if (key === 'rate') pending.rate = draw(modulator.rate, scope)\n else if (key === 'depth' && !(typeof modulator.depth === 'object' && 'scaleOf' in modulator.depth)) pending.depth = draw(modulator.depth as Range, scope)\n }\n return pending\n}\n\ntype PendingVoice = { frequency: PendingAutomation; vibratoRate: number; formants: { frequency: number; q: number }[]; breath: { frequency: number; q: number; gain: number } }\n\nfunction drawVoice(source: Extract<LayerSource, { kind: 'formant_voice' }>, scope: Scope): PendingVoice {\n const pending: PendingVoice = { frequency: {}, vibratoRate: 0, formants: [], breath: { frequency: 0, q: source.breath.q, gain: 0 } }\n for (const key of Object.keys(source)) {\n if (key === 'frequency') pending.frequency = drawAutomation(source.frequency, scope)\n else if (key === 'vibrato') pending.vibratoRate = draw(source.vibrato.rate, scope)\n else if (key === 'formants') pending.formants = source.formants.map((formant) => ({ frequency: draw(formant.frequency, scope), q: formant.q }))\n else if (key === 'breath') pending.breath = { frequency: draw(source.breath.frequency, scope), q: source.breath.q, gain: draw(source.breath.gain, scope) }\n }\n return pending\n}\n\ntype LayerDefaults = { readonly duration?: number; readonly tail?: number; readonly noiseSeconds: number }\n\ntype PendingLayer = {\n at: number\n duration?: number\n gain: number\n automation?: PendingAutomation\n voice?: PendingVoice\n filters: PendingFilter[]\n modulators: PendingModulator[]\n}\n\nfunction drawLayer(layer: Layer, scope: Scope): PendingLayer {\n const pending: PendingLayer = { at: 0, gain: 1, filters: [], modulators: [] }\n for (const key of Object.keys(layer)) {\n if (key === 'at' && layer.at !== undefined) pending.at = draw(layer.at, scope)\n else if (key === 'duration' && layer.duration !== undefined) pending.duration = draw(layer.duration, scope)\n else if (key === 'gain' && layer.gain !== undefined) pending.gain = draw(layer.gain, scope)\n else if (key === 'source' && layer.source.kind === 'osc') pending.automation = drawAutomation(layer.source.frequency, scope)\n else if (key === 'source' && layer.source.kind === 'formant_voice') pending.voice = drawVoice(layer.source, scope)\n else if (key === 'filters' && layer.filters) pending.filters = layer.filters.bank.map((spec) => drawFilter(spec, scope))\n else if (key === 'modulators' && layer.modulators) pending.modulators = layer.modulators.map((modulator) => drawModulator(modulator, scope))\n }\n return pending\n}\n\n// the team code draws the noise start point when the source starts, after every other number of the layer\nfunction drawOffset(source: LayerSource, duration: number, scope: Scope, noiseSeconds: number): number {\n if (source.kind === 'formant_voice') return scope.random()\n if (source.kind !== 'noise' || source.offset === undefined) return 0\n if (typeof source.offset === 'number') return source.offset\n if (source.offset === 'fit') return scope.random() * Math.max(0, noiseSeconds - duration)\n return scope.random() * (source.offsetScale ?? 1)\n}\n\nfunction finishSource(layer: Layer, pending: PendingLayer, duration: number, offset: number): PlannedSource {\n const source = layer.source\n if (source.kind === 'noise') return { kind: 'noise', offset, loop: source.loop === true }\n if (source.kind === 'osc') return { kind: 'osc', wave: source.wave, frequency: finishAutomation(pending.automation ?? {}, duration) }\n const voice = pending.voice as PendingVoice\n return {\n kind: 'formant_voice',\n wave: source.wave,\n frequency: finishAutomation(voice.frequency, duration),\n vibrato: { rate: voice.vibratoRate, depth: startFrequency(voice.frequency) * source.vibrato.depth },\n formants: voice.formants,\n breath: { ...voice.breath, offset },\n mix: source.mix,\n }\n}\n\nfunction finishModulator(pending: PendingModulator, sourceFrequency: number): PlannedModulator {\n const { modulator } = pending\n const depth = typeof modulator.depth === 'object' && 'scaleOf' in modulator.depth ? sourceFrequency * modulator.depth.factor : (pending.depth ?? 0)\n return { target: modulator.target, ...(modulator.wave ? { wave: modulator.wave } : {}), rate: pending.rate, depth, ...(modulator.base === undefined ? {} : { base: modulator.base }) }\n}\n\nfunction finishEnvelope(envelope: Envelope, duration: number, level: number): PlannedEnvelopePoint[] {\n return envelope.map(([time, value, curve, fixed]) => ({ time: timeOf(time, duration), value: fixed === 'fixed' ? value : value * level, curve }))\n}\n\nfunction planLayer(layer: Layer, scope: Scope, defaults: LayerDefaults, levelInEnvelope: boolean, soundLevel: number): PlannedLayer[] {\n const pending = drawLayer(layer, scope)\n const duration = pending.duration ?? defaults.duration\n if (duration === undefined) throw new Error('game-audio: a layer needs a duration (its own or the recipe’s)')\n const offset = drawOffset(layer.source, duration, scope, defaults.noiseSeconds)\n const level = pending.gain * soundLevel\n const sourceFrequency = layer.source.kind === 'noise' ? 0 : startFrequency(pending.automation ?? pending.voice?.frequency ?? {})\n const planned: PlannedLayer = {\n at: pending.at,\n duration,\n tail: layer.tail ?? defaults.tail ?? DEFAULT_TAIL,\n level,\n ...(layer.wet === undefined ? {} : { wet: layer.wet }),\n source: finishSource(layer, pending, duration, offset),\n ...(layer.filters\n ? {\n filters: {\n mode: layer.filters.mode,\n bank: pending.filters.map(({ spec, frequency, q, gain, level: filterLevel }) => ({\n type: spec.type,\n frequency: finishAutomation(frequency, duration),\n ...(q === undefined ? {} : { q }),\n ...(gain === undefined ? {} : { gain }),\n ...(filterLevel === undefined ? {} : { level: filterLevel }),\n })),\n },\n }\n : {}),\n modulators: pending.modulators.map((modulator) => finishModulator(modulator, sourceFrequency)),\n envelope: finishEnvelope(layer.envelope, duration, levelInEnvelope ? level : 1),\n }\n if (!layer.repeat) return [planned]\n return Array.from({ length: layer.repeat.count }, (_, index) => ({ ...planned, at: planned.at + index * (layer.repeat?.spacing ?? 0) }))\n}\n\nfunction scaleAutomation(automation: PlannedAutomation, divisor: number): PlannedAutomation {\n const scale = (value: number | undefined): number | undefined => (value === undefined ? undefined : value / divisor)\n const scaled: Record<string, unknown> = { ...automation }\n for (const key of ['value', 'from', 'to'] as const) if (automation[key] !== undefined) scaled[key] = scale(automation[key])\n return scaled as PlannedAutomation\n}\n\n// distance muffling and occlusion lower every lowpass cutoff of the sound\nfunction muffle(layer: PlannedLayer, divisor: number): PlannedLayer {\n if (divisor === 1 || !layer.filters) return layer\n const bank = layer.filters.bank.map((filter) => (filter.type === 'lowpass' ? { ...filter, frequency: scaleAutomation(filter.frequency, divisor) } : filter))\n return { ...layer, filters: { ...layer.filters, bank } }\n}\n\nconst layerEnd = (layer: PlannedLayer): number => layer.at + layer.duration + layer.tail\n\n/**\n * Turns a recipe into a plan: pure, Node-safe, the same plan for the same `random`. Numbers are drawn in this order: `vars` (in the order written),\n * `duration`, then each layer in the order its fields are written, the noise start point last in its layer. A sound below its falloff's `minGain`\n * gives `null` (or a silent plan with `keepSilent`) before any number is drawn.\n */\nexport function planSound(recipe: SoundRecipe, input: PlanInput = {}): SoundPlan | null {\n const listener = input.listener ?? DEFAULT_LISTENER\n const distance = input.distance ?? (input.position ? listenerDistance(listener, input.position, input.distanceMode) : 0)\n const occlusion = Math.min(1, Math.max(0, input.occlusion ?? 0))\n const order = recipe.order ?? 'layered'\n const falloffLevel = falloffGain(recipe.falloff, input.volume ?? 1, distance)\n const level = occlusion > 0 ? falloffLevel * (1 - OCCLUSION_GAIN * occlusion) : falloffLevel\n const silent = isSilent(recipe.falloff, falloffLevel)\n const base = {\n id: recipe.id,\n bus: recipe.bus,\n order,\n ...(recipe.group === undefined ? {} : { group: recipe.group }),\n priority: recipe.priority ?? busPriority(recipe.bus),\n level,\n distance,\n ...(recipe.pan ? { pan: input.position ? panFor(listener, input.position) : 0 } : {}),\n }\n if (silent) return recipe.keepSilent ? { ...base, silent: true, length: 0, layers: [] } : null\n\n const scope: Scope = { random: input.random ?? createRng(1), params: { ...input.params } }\n for (const [name, range] of Object.entries(recipe.vars ?? {})) if (scope.params[name] === undefined) scope.params[name] = draw(range, scope)\n const defaults: LayerDefaults = {\n ...(recipe.duration === undefined ? {} : { duration: draw(recipe.duration, scope) }),\n ...(recipe.tail === undefined ? {} : { tail: recipe.tail }),\n noiseSeconds: input.noiseSeconds ?? DEFAULT_NOISE_SECONDS,\n }\n const divisor = cutoffDivisor(recipe.falloff, distance) / (1 - OCCLUSION_CUTOFF * occlusion)\n const layers = recipe.layers.flatMap((layer) => planLayer(layer, scope, defaults, order !== 'layered', level)).map((layer) => muffle(layer, divisor))\n return { ...base, silent: false, length: Math.max(0, ...layers.map(layerEnd)), layers }\n}\n","/** `length` samples of white noise, `random × 2 − 1`, drawn in order (jogo L62086, cena L1312). */\nexport function fillNoise(random: () => number, length: number): Float32Array {\n const samples = new Float32Array(length)\n for (let index = 0; index < length; index++) samples[index] = random() * 2 - 1\n return samples\n}\n\n/**\n * A reverb impulse: per channel, noise times `(1 − i / length)^decay` (cena L1310). `length` is `sampleRate × seconds` as the art scene computes it,\n * which is not always whole (48000 × 2.2 = 105600.00000000001): the loop runs while `i < length`, so one more number is drawn than the buffer holds,\n * exactly like the team code. The power is `exp(decay × log(base))`, which every engine computes the same.\n */\nexport function fillImpulse(random: () => number, options: { readonly channels: number; readonly length: number; readonly decay: number }): Float32Array[] {\n const size = Math.floor(options.length)\n return Array.from({ length: options.channels }, () => {\n const samples = new Float32Array(size)\n for (let index = 0; index < options.length; index++) {\n const value = (random() * 2 - 1) * Math.exp(options.decay * Math.log(1 - index / options.length))\n if (index < size) samples[index] = value\n }\n return samples\n })\n}\n\n/** An AudioBuffer holding the samples (one channel per array). */\nexport function bufferOf(context: AudioContext, channels: readonly Float32Array[], requestedLength: number): AudioBuffer {\n const buffer = context.createBuffer(channels.length, requestedLength, context.sampleRate)\n channels.forEach((samples, channel) => buffer.getChannelData(channel).set(samples))\n return buffer\n}\n","import type { MixProfile } from '../mix'\nimport { bufferOf, fillImpulse } from './noise'\n\nexport type MixChain = { readonly master: GainNode; readonly wet?: GainNode; disconnect(): void }\n\nconst LIMITER_POINTS = 4097\n\n/**\n * The limiter's curve over inputs `-range..range` (full scale 1): untouched up to the knee, then `knee + (ceiling − knee) × tanh((|x| − knee) / (ceiling − knee))`,\n * which leaves the knee with the same slope and never passes the ceiling.\n */\nexport function limiterCurve(ceilingDb: number, kneeDb: number, range: number, points = LIMITER_POINTS): Float32Array<ArrayBuffer> {\n const ceiling = 10 ** (ceilingDb / 20)\n const knee = Math.min(10 ** (kneeDb / 20), ceiling)\n const curve = new Float32Array(new ArrayBuffer(points * 4))\n for (let i = 0; i < points; i++) {\n const x = ((i / (points - 1)) * 2 - 1) * range\n const a = Math.abs(x)\n const y = a <= knee || ceiling === knee ? Math.min(a, ceiling) : knee + (ceiling - knee) * Math.tanh((a - knee) / (ceiling - knee))\n curve[i] = Math.sign(x) * y\n }\n return curve\n}\n\n/**\n * The mixing chain in the team order (cena L1308–1311; jogo L62080): compressor to the output, master into it (or straight to the output), then the\n * convolver with an impulse drawn from `random` and the wet bus into it, back into the master.\n */\nexport function buildChain(context: AudioContext, profile: MixProfile, random: () => number): MixChain {\n // the limiter is the last stage: a gain that brings `range` × full scale into the shaper's -1..1, and a curve that gives the level back, bent above the knee\n let limiter: { readonly input: GainNode; readonly shaper: WaveShaperNode } | undefined\n if (profile.limiter) {\n const range = profile.limiter.range ?? 4\n const input = context.createGain()\n input.gain.value = 1 / range\n const shaper = context.createWaveShaper()\n shaper.curve = limiterCurve(profile.limiter.ceiling, profile.limiter.knee, range)\n input.connect(shaper)\n shaper.connect(context.destination)\n limiter = { input, shaper }\n }\n const output: AudioNode = limiter?.input ?? context.destination\n let compressor: DynamicsCompressorNode | undefined\n if (profile.compressor) {\n compressor = context.createDynamicsCompressor()\n compressor.threshold.value = profile.compressor.threshold\n compressor.ratio.value = profile.compressor.ratio\n if (profile.compressor.knee !== undefined) compressor.knee.value = profile.compressor.knee\n if (profile.compressor.attack !== undefined) compressor.attack.value = profile.compressor.attack\n if (profile.compressor.release !== undefined) compressor.release.value = profile.compressor.release\n compressor.connect(output)\n }\n const master = context.createGain()\n master.gain.value = profile.master\n master.connect(compressor ?? output)\n if (!profile.reverb) {\n return {\n master,\n disconnect: () => {\n master.disconnect()\n compressor?.disconnect()\n limiter?.input.disconnect()\n limiter?.shaper.disconnect()\n },\n }\n }\n const convolver = context.createConvolver()\n const length = context.sampleRate * profile.reverb.seconds\n convolver.buffer = bufferOf(context, fillImpulse(random, { channels: 2, length, decay: profile.reverb.decay }), length)\n const wet = context.createGain()\n wet.gain.value = profile.reverb.wet\n wet.connect(convolver)\n convolver.connect(master)\n return {\n master,\n wet,\n disconnect: () => {\n wet.disconnect()\n convolver.disconnect()\n master.disconnect()\n compressor?.disconnect()\n limiter?.input.disconnect()\n limiter?.shaper.disconnect()\n },\n }\n}\n","type AudioContextConstructor = new () => AudioContext\n\n/** A new context from the page (`AudioContext` or the old `webkitAudioContext`), or `null` in Node and workers. */\nexport function globalContext(): AudioContext | null {\n const scope = globalThis as { AudioContext?: AudioContextConstructor; webkitAudioContext?: AudioContextConstructor }\n const Constructor = scope.AudioContext ?? scope.webkitAudioContext\n return Constructor ? new Constructor() : null\n}\n\n/** Browsers start a context suspended until a click or key; call from one. */\nexport function unlockContext(context: AudioContext): void {\n // an OfflineAudioContext (no `close`) is started by `startRendering`, never resumed\n if (context.state === 'suspended' && typeof context.close === 'function') void context.resume()\n}\n","import type { LoopRecipe } from './recipe'\n\n/** jogo L62112: a loop's nodes exist only once its volume reaches 0.002. */\nexport const LOOP_START_ABOVE = 0.002\n/** jogo L62125–62126: `setTargetAtTime` time constants. */\nexport const LOOP_SMOOTHING = { volume: 0.15, frequency: 0.08 } as const\n\n/** What the realizer does for one `set`: create the nodes first (once), then glide the volume and, for an oscillator, the frequency. */\nexport type LoopAction = { readonly create: boolean; readonly volume: number; readonly frequency?: number }\n\nexport type LoopState = {\n /** `null` while the loop has no nodes and the volume is still below the start threshold. */\n set(state: { readonly volume?: number; readonly frequency?: number }): LoopAction | null\n /** Whether the nodes exist. */\n readonly created: boolean\n /** The nodes were torn down (`stop`): the next audible `set` creates them again. */\n reset(): void\n}\n\n/**\n * The game's `loopSet` as state: nodes on the first volume at or above `startAbove`, then every `set` glides. The volume set last is kept, so a\n * `set` of only the frequency keeps the level. `chain_loop` recipes open with their nodes already made (`open` is true).\n */\nexport function createLoopState(recipe: LoopRecipe, open = false): LoopState {\n const startAbove = recipe.startAbove ?? LOOP_START_ABOVE\n let created = open\n let volume = recipe.volume ?? 0\n return {\n set(state) {\n volume = state.volume ?? volume\n const create = !created\n if (create && !(volume >= startAbove)) return null\n created = true\n const frequency = recipe.source.kind === 'osc' && state.frequency ? state.frequency : undefined\n return { create, volume, ...(frequency === undefined ? {} : { frequency }) }\n },\n get created() {\n return created\n },\n reset() {\n created = false\n },\n }\n}\n","import type { PlannedAutomation, PlannedEnvelopePoint, PlannedFilter } from '../plan'\n\n/** Where a plan is built: the context, the bus it plays into, the reverb send (if the mix has one), the shared noise and the start time. */\nexport type RealizeTarget = {\n readonly context: AudioContext\n readonly output: AudioNode\n readonly wet?: AudioNode\n /** The noise buffer; made on the first call when the mix makes it on demand. */\n readonly noise: () => AudioBuffer\n readonly time: number\n}\n\n/** What `realize` built: every scheduled source (so the voice can be cut short) and `stop`. */\nexport type RealizedVoice = { readonly sources: readonly AudioScheduledSourceNode[]; stop(): void }\n\n/** `.value = value`, or `setValueAtTime(from)` at `time`. */\nexport function assign(param: AudioParam, automation: PlannedAutomation, time: number): void {\n if (automation.value !== undefined) param.value = automation.value\n if (automation.from !== undefined) param.setValueAtTime(automation.from, time)\n}\n\nexport function ramp(param: AudioParam, curve: 'set' | 'linear' | 'exp', value: number, at: number): void {\n if (curve === 'set') param.setValueAtTime(value, at)\n else if (curve === 'exp') param.exponentialRampToValueAtTime(value, at)\n else param.linearRampToValueAtTime(value, at)\n}\n\n/** The ramp of an automation, if it has one. */\nexport function rampTo(param: AudioParam, automation: PlannedAutomation, time: number): void {\n if (automation.to !== undefined && automation.at !== undefined) ramp(param, automation.curve ?? 'linear', automation.to, time + automation.at)\n}\n\nexport function applyEnvelope(param: AudioParam, points: readonly PlannedEnvelopePoint[], time: number): void {\n for (const point of points) ramp(param, point.curve, point.value, time + point.time)\n}\n\n/** A noise source on the shared buffer (`loop` set only when asked, as the art scene's `nsrc` does). */\nexport function noiseSource(target: RealizeTarget, loop: boolean): AudioBufferSourceNode {\n const source = target.context.createBufferSource()\n source.buffer = target.noise()\n if (loop) source.loop = true\n return source\n}\n\n/** The art scene's `bq`: type, frequency, then Q and gain when given. The frequency ramp is left to the caller. */\nexport function filterNode(context: AudioContext, filter: PlannedFilter, time: number): BiquadFilterNode {\n const node = context.createBiquadFilter()\n node.type = filter.type\n assign(node.frequency, filter.frequency, time)\n if (filter.q !== undefined) node.Q.value = filter.q\n if (filter.gain !== undefined) node.gain.value = filter.gain\n return node\n}\n\nexport function gainNode(context: AudioContext, value: number): GainNode {\n const node = context.createGain()\n node.gain.value = value\n return node\n}\n\nexport function voiceOf(sources: readonly AudioScheduledSourceNode[]): RealizedVoice {\n return {\n sources,\n stop() {\n for (const source of sources) {\n try {\n source.stop()\n } catch {\n // already stopped\n }\n }\n },\n }\n}\n","// Loop nodes in the two team orders: the game's `loopSet` (jogo L62109–62127) and the art scene's loops in `initAudio` (cena L1314–1316).\nimport type { Automation, LoopRecipe, Range } from '../recipe'\nimport { filterNode, gainNode, noiseSource } from './nodes'\nimport type { RealizeTarget } from './nodes'\n\nexport type RealizedLoop = {\n readonly gain: GainNode\n /** The node wired to the bus: the panner when the recipe pans, else the gain. */\n readonly out: AudioNode\n readonly panner?: StereoPannerNode\n readonly source: AudioScheduledSourceNode\n readonly frequency?: AudioParam\n /** The first filter's cutoff, for `set({ cutoff })`. */\n readonly cutoff?: AudioParam\n stop(): void\n}\n\n// a panning loop goes gain → panner → bus; the others keep the team wiring (gain → bus)\nfunction outputStage(recipe: LoopRecipe, target: RealizeTarget, gain: GainNode): { out: AudioNode; panner?: StereoPannerNode } {\n if (!recipe.pan) {\n gain.connect(target.output)\n return { out: gain }\n }\n const panner = target.context.createStereoPanner()\n gain.connect(panner)\n panner.connect(target.output)\n return { out: panner, panner }\n}\n\n// loops take fixed numbers: a range or a param in a loop recipe reads as 0\nconst fixed = (range: Range | undefined): number => (typeof range === 'number' ? range : 0)\nconst fixedFrequency = (automation: Automation): number => fixed('set' in automation ? automation.set : automation.from)\n\nfunction sourceOf(recipe: LoopRecipe, target: RealizeTarget): { source: AudioScheduledSourceNode; frequency?: AudioParam } {\n if (recipe.source.kind === 'noise') return { source: noiseSource(target, true) }\n const oscillator = target.context.createOscillator()\n oscillator.type = recipe.source.wave\n if (recipe.source.frequency) oscillator.frequency.value = fixedFrequency(recipe.source.frequency)\n return { source: oscillator, frequency: oscillator.frequency }\n}\n\nfunction stopAll(sources: readonly AudioScheduledSourceNode[]): () => void {\n return () => {\n for (const source of sources) {\n try {\n source.stop()\n } catch {\n // already stopped\n }\n }\n }\n}\n\n/** `loopSet` on first use: gain from 0 and filter wired first, the source and filter set, an optional blade-beat stage, then the source starts. */\nexport function realizeGameLoop(recipe: LoopRecipe, target: RealizeTarget): RealizedLoop {\n const { context } = target\n const gain = context.createGain()\n const filters = (recipe.filters?.bank ?? []).map(() => context.createBiquadFilter())\n gain.gain.value = 0\n const last = filters.reduce<AudioNode | undefined>((previous, filter) => (previous ? previous.connect(filter) : filter), undefined)\n last?.connect(gain)\n const output = outputStage(recipe, target, gain)\n const { source, frequency } = sourceOf(recipe, target)\n recipe.filters?.bank.forEach((spec, index) => {\n const filter = filters[index] as BiquadFilterNode\n filter.type = spec.type\n filter.frequency.value = fixedFrequency(spec.frequency)\n if (spec.q !== undefined) filter.Q.value = fixed(spec.q)\n })\n const sources: AudioScheduledSourceNode[] = [source]\n for (const modulator of recipe.modulators ?? []) {\n const lfo = context.createOscillator()\n const depth = context.createGain()\n const stage = context.createGain()\n if (modulator.wave) lfo.type = modulator.wave\n lfo.frequency.value = fixed(modulator.rate)\n depth.gain.value = fixed(modulator.depth as Range)\n stage.gain.value = modulator.base ?? 0\n lfo.connect(depth)\n depth.connect(stage.gain)\n last?.disconnect()\n last?.connect(stage)\n stage.connect(gain)\n lfo.start()\n sources.push(lfo)\n }\n source.connect(filters[0] ?? gain)\n source.start()\n return { gain, ...output, source, ...(frequency ? { frequency } : {}), ...(filters[0] ? { cutoff: filters[0].frequency } : {}), stop: stopAll(sources) }\n}\n\n/** The art scene's loops: source, filters, gain at its starting volume, a gain LFO, wired, started. */\nexport function realizeChainLoop(recipe: LoopRecipe, target: RealizeTarget, volume: number): RealizedLoop {\n const { context } = target\n const { source, frequency } = sourceOf(recipe, target)\n const filters = (recipe.filters?.bank ?? []).map((spec) =>\n filterNode(context, { type: spec.type, frequency: { value: fixedFrequency(spec.frequency) }, ...(spec.q === undefined ? {} : { q: fixed(spec.q) }) }, target.time),\n )\n const gain = gainNode(context, volume)\n const lfos = (recipe.modulators ?? []).map((modulator) => {\n const lfo = context.createOscillator()\n if (modulator.wave) lfo.type = modulator.wave\n lfo.frequency.value = fixed(modulator.rate)\n const depth = gainNode(context, fixed(modulator.depth as Range))\n lfo.connect(depth)\n depth.connect(gain.gain)\n return lfo\n })\n let tail: AudioNode = source\n for (const filter of filters) tail = tail.connect(filter)\n tail.connect(gain)\n const output = outputStage(recipe, target, gain)\n source.start()\n for (const lfo of lfos) lfo.start()\n return { gain, ...output, source, ...(frequency ? { frequency } : {}), ...(filters[0] ? { cutoff: filters[0].frequency } : {}), stop: stopAll([source, ...lfos]) }\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { cutoffDivisor, falloffGain } from '../falloff'\nimport { listenerDistance, panFor } from '../listener'\nimport type { DistanceMode, Listener } from '../listener'\nimport { LOOP_SMOOTHING, createLoopState } from '../loops'\nimport type { BusId, LoopRecipe } from '../recipe'\nimport type { RealizeTarget } from './nodes'\nimport { realizeChainLoop, realizeGameLoop } from './realize-loop'\nimport type { RealizedLoop } from './realize-loop'\n\n/**\n * What one `set` changes. `volume` and `frequency` glide as in the team loops. `position` places the loop: with a recipe `falloff` the level falls\n * with the distance from the listener (and the cutoff with `cutoffK`), with `pan` it goes to the listener's side. `cutoff` glides the first filter\n * (an engine opening up under load, a skid getting brighter).\n */\nexport type LoopSet = { readonly volume?: number; readonly frequency?: number; readonly position?: Vec3; readonly cutoff?: number }\n\n/** A continuous sound: `set` glides the volume and, for an oscillator, the frequency; `stop` tears the nodes down. */\nexport type AudioLoopHandle = {\n set(state: LoopSet): void\n stop(): void\n}\n\nexport type LoopEntry = { rewire(): void; stop(): void; readonly created: boolean }\n\n/** What a loop needs from its engine. */\nexport type LoopHost = {\n ready(): AudioContext | null\n output(bus: BusId): AudioNode\n prepareNoise(): unknown\n noise(): AudioBuffer\n register(loop: LoopEntry): void\n unregister(loop: LoopEntry): void\n /** Where the ears are now, for a loop with a `falloff` or `pan`. */\n listener?(): Listener\n readonly distance?: DistanceMode\n}\n\nconst INERT: AudioLoopHandle = { set() {}, stop() {} }\n\n/** A `game_loop` makes its nodes on the first audible `set`; a `chain_loop` makes them when it opens, at `volume` (default the recipe's). */\nexport function createLoopHandle(recipe: LoopRecipe | undefined, host: LoopHost, volume?: number): AudioLoopHandle {\n if (!recipe) return INERT\n const loopRecipe = recipe\n const isChain = loopRecipe.order === 'chain_loop'\n const opening = volume ?? loopRecipe.volume ?? 0\n const smoothing = loopRecipe.smoothing ?? LOOP_SMOOTHING\n let state = createLoopState(loopRecipe)\n let nodes: RealizedLoop | undefined\n\n const entry: LoopEntry = {\n get created() {\n return nodes !== undefined\n },\n rewire() {\n nodes?.out.disconnect()\n nodes?.out.connect(host.output(loopRecipe.bus))\n },\n stop() {\n nodes?.stop()\n nodes?.out.disconnect()\n nodes = undefined\n state = createLoopState(loopRecipe)\n host.unregister(entry)\n },\n }\n\n const create = (context: AudioContext, startVolume: number): RealizedLoop => {\n if (loopRecipe.source.kind === 'noise') host.prepareNoise()\n const target: RealizeTarget = { context, output: host.output(loopRecipe.bus), noise: host.noise, time: context.currentTime }\n const made = isChain ? realizeChainLoop(loopRecipe, target, startVolume) : realizeGameLoop(loopRecipe, target)\n host.register(entry)\n return made\n }\n\n const open = (): void => {\n const context = host.ready()\n if (!context) return\n nodes = create(context, opening)\n state = createLoopState({ ...loopRecipe, volume: opening }, true)\n }\n if (isChain) open()\n\n let position: Vec3 | undefined\n let cutoff: number | undefined\n const placed = loopRecipe.falloff !== undefined || loopRecipe.pan === true\n return {\n set(next) {\n if (isChain && !nodes) open()\n const context = host.ready()\n if (!context) return\n position = next.position ?? position\n cutoff = next.cutoff ?? cutoff\n const action = state.set(next)\n if (!action) return\n nodes ??= create(context, 0)\n const listener = placed && position ? host.listener?.() : undefined\n const distance = listener && position ? listenerDistance(listener, position, host.distance) : 0\n const level = listener ? falloffGain(loopRecipe.falloff, action.volume, distance) : action.volume\n nodes.gain.gain.setTargetAtTime(level, context.currentTime, smoothing.volume)\n if (action.frequency !== undefined && nodes.frequency) nodes.frequency.setTargetAtTime(action.frequency, context.currentTime, smoothing.frequency)\n if (cutoff !== undefined && nodes.cutoff) nodes.cutoff.setTargetAtTime(cutoff / cutoffDivisor(loopRecipe.falloff, distance), context.currentTime, smoothing.frequency)\n if (listener && position && nodes.panner) nodes.panner.pan.setTargetAtTime(panFor(listener, position), context.currentTime, smoothing.frequency)\n },\n stop: entry.stop,\n }\n}\n","/**\n * Sounds made of recorded files (`.ogg`), as data. A `SampleSound` lists the takes of each layer: `close` (the sound as heard near, the only one\n * required), `far` (the same event heard from far away: a muffled bang with its echo) and the tail of the place it happens in (`indoor` / `outdoor`).\n * `planSample` decides, from a seeded stream, which take plays (round-robin: never the same take twice in a row), the pitch (± a fraction), how the\n * near and far layers cross over with the distance, the level, the pan and the distance lowpass. It is pure, so it runs in Node and in tests; the\n * WebAudio layer (`realizeSample`) plays the plan from decoded buffers.\n */\nimport type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { falloffGain, isSilent } from './falloff'\nimport { DEFAULT_LISTENER, listenerDistance, panFor } from './listener'\nimport type { DistanceMode, Listener } from './listener'\nimport type { BusId, Falloff, SampleCrossover, SampleEnvironment, SampleRef, SampleSound, SampleTier } from './recipe'\nimport { busPriority } from './voices'\n\nexport type { SampleCrossover, SampleEnvironment, SampleRef, SampleSound, SampleTail, SampleTier } from './recipe'\n\nexport const SAMPLE_ENVIRONMENTS = ['indoor', 'outdoor'] as const satisfies readonly SampleEnvironment[]\n\n/** The role of a layer in a plan. */\nexport type SampleLayerRole = 'close' | 'far' | 'tail'\n\nexport const DEFAULT_SAMPLE_FALLOFF: Falloff = { model: 'inverse_square', k: 0.002, minGain: 0.002 }\nexport const DEFAULT_CROSSOVER: SampleCrossover = { from: 30, to: 80 }\nexport const DEFAULT_SAMPLE_PITCH = 0.04\nexport const DEFAULT_TAIL_GAIN = 0.6\nexport const DEFAULT_SAMPLE_CUTOFF_K = 0.01\n/** The open lowpass: at or above it the realizer leaves the filter out. */\nexport const OPEN_CUTOFF = 20000\n/** A layer quieter than this is left out of the plan. */\nexport const LAYER_FLOOR = 0.001\n\n/** One file to play: which take, at what level (already times the sound level), rate and start. */\nexport type PlannedSampleLayer = {\n readonly role: SampleLayerRole\n readonly url: string\n /** Index of the take in its list. */\n readonly take: number\n readonly gain: number\n readonly rate: number\n readonly at: number\n /** Seconds into the file (the take's trim). */\n readonly offset?: number\n /** Seconds of the file played (the take's trim). */\n readonly duration?: number\n}\n\nexport type SamplePlan = {\n readonly kind: 'sample'\n readonly id: string\n readonly bus: BusId\n readonly level: number\n readonly distance: number\n readonly pan?: number\n /** Lowpass cutoff in Hz (`OPEN_CUTOFF` = no filter). */\n readonly cutoff: number\n /** Playback rate of every layer (the pitch drawn for this play). */\n readonly rate: number\n readonly environment: SampleEnvironment\n /** The tier played (`undefined` without tiers or intensity). */\n readonly tier?: string\n /** 0 = all near, 1 = all far. */\n readonly farMix: number\n readonly layers: readonly PlannedSampleLayer[]\n readonly priority: number\n readonly group?: string\n}\n\n/** The last take each sound layer played (`<id>/<role>` → index), so the next play never repeats it. Keep one per engine or channel. */\nexport type SampleMemory = Map<string, number>\n\nexport type SamplePlanInput = {\n readonly random: () => number\n readonly listener?: Listener\n readonly distanceMode?: DistanceMode\n readonly position?: Vec3\n /** Metres; overrides `position` for the distance (not for the pan). */\n readonly distance?: number\n readonly volume?: number\n /** Default `outdoor`. */\n readonly environment?: SampleEnvironment\n /** 0 (clear) to 1 (behind a wall): lowers the level and closes the lowpass. */\n readonly occlusion?: number\n /** Round-robin memory; without it each plan is drawn on its own (and may repeat). */\n readonly memory?: SampleMemory\n /** Limiter priority when the sound has none. */\n readonly priority?: number\n /** 0 (light) to 1 (heavy): picks the tier (see `SampleTier`). */\n readonly intensity?: number\n}\n\n/**\n * Round-robin without repeat: a take drawn among all but the last one played. With one take it is always 0; without `last` any take may come.\n * One random number per call.\n */\nexport function pickTake(count: number, last: number | undefined, random: () => number): number {\n if (count <= 1) return 0\n if (last === undefined || last < 0 || last >= count) return Math.min(count - 1, Math.floor(random() * count))\n const drawn = Math.min(count - 2, Math.floor(random() * (count - 1)))\n return drawn >= last ? drawn + 1 : drawn\n}\n\n/** 0 at or below `from`, 1 at or beyond `to`, linear between. */\nexport function farMixAt(crossover: SampleCrossover, distance: number): number {\n if (crossover.to <= crossover.from) return distance >= crossover.to ? 1 : 0\n const t = (distance - crossover.from) / (crossover.to - crossover.from)\n return t <= 0 ? 0 : t >= 1 ? 1 : t\n}\n\n/** Equal-power gains of the near and far layers for a far mix (so the crossover has no dip in loudness). */\nexport function crossGains(farMix: number): { readonly close: number; readonly far: number } {\n return { close: Math.cos((farMix * Math.PI) / 2), far: Math.sin((farMix * Math.PI) / 2) }\n}\n\n/** The distance lowpass, closed further behind a wall (an occluded sound loses its highs first). */\nexport function sampleCutoff(cutoffK: number, distance: number, occlusion = 0): number {\n const byDistance = cutoffK > 0 ? OPEN_CUTOFF / (1 + distance * cutoffK) : OPEN_CUTOFF\n const occluded = occlusion > 0 ? byDistance / (1 + occlusion * 9) : byDistance\n return Math.max(80, Math.min(OPEN_CUTOFF, occluded))\n}\n\n/** Every file a sound may play (to load before its first play). */\nexport function sampleUrls(sound: SampleSound): string[] {\n const tiers = (sound.tiers ?? []).flatMap((tier) => [...tier.close, ...(tier.far ?? [])])\n const all = [...sound.close, ...(sound.far ?? []), ...tiers, ...(sound.tail?.indoor ?? []), ...(sound.tail?.outdoor ?? [])].map((ref) => ref.url)\n return [...new Set(all)]\n}\n\n/** The tier for an intensity: the last whose `from` is at or below it. */\nexport function tierFor(sound: SampleSound, intensity: number | undefined): SampleTier | undefined {\n if (intensity === undefined || !sound.tiers) return undefined\n let chosen: SampleTier | undefined\n for (const tier of sound.tiers) if (tier.from <= intensity) chosen = tier\n return chosen ?? sound.tiers[0]\n}\n\n/**\n * The plan of one play, or `null` when the sound is too far to be heard. Random numbers, in order: the pitch, the near take, the far take, the\n * tail take (each drawn only when that layer has more than zero takes and is heard).\n */\nexport function planSample(sound: SampleSound, input: SamplePlanInput): SamplePlan | null {\n if (sound.close.length === 0) throw new Error(`sample sound ${sound.id} has no close take`)\n const listener = input.listener ?? DEFAULT_LISTENER\n const distance = input.distance ?? (input.position ? listenerDistance(listener, input.position, input.distanceMode) : 0)\n const falloff = sound.falloff ?? DEFAULT_SAMPLE_FALLOFF\n const occlusion = Math.max(0, Math.min(1, input.occlusion ?? 0))\n const level = falloffGain(falloff, (input.volume ?? 1) * (sound.gain ?? 1), distance) * (1 - 0.45 * occlusion)\n if (isSilent(falloff, level) || level <= 0) return null\n\n const pitch = sound.pitch ?? DEFAULT_SAMPLE_PITCH\n const rate = pitch > 0 ? 1 + (input.random() * 2 - 1) * pitch : 1\n const environment = input.environment ?? 'outdoor'\n const tier = tierFor(sound, input.intensity)\n const close = tier?.close.length ? tier.close : sound.close\n const far = tier?.far?.length ? tier.far : (sound.far ?? [])\n const farMix = far.length > 0 ? farMixAt(sound.crossover ?? DEFAULT_CROSSOVER, distance) : 0\n const gains = crossGains(farMix)\n const layers: PlannedSampleLayer[] = []\n const take = (role: SampleLayerRole, refs: readonly SampleRef[], gain: number, at: number): void => {\n if (refs.length === 0 || gain < LAYER_FLOOR) return\n const key = `${sound.id}/${tier && role !== 'tail' ? `${tier.name}/` : ''}${role}`\n const index = pickTake(refs.length, input.memory?.get(key), input.random)\n input.memory?.set(key, index)\n const ref = refs[index] as SampleRef\n layers.push({\n role,\n url: ref.url,\n take: index,\n gain: gain * (ref.gain ?? 1) * level,\n rate,\n at,\n ...(ref.offset === undefined ? {} : { offset: ref.offset }),\n ...(ref.duration === undefined ? {} : { duration: ref.duration }),\n })\n }\n take('close', close, gains.close, 0)\n take('far', far, gains.far, 0)\n const tails = sound.tail?.[environment] ?? []\n take('tail', tails, sound.tail?.gain ?? DEFAULT_TAIL_GAIN, sound.tail?.at ?? 0)\n\n const pan = (sound.pan ?? true) && input.position ? panFor(listener, input.position) : undefined\n return {\n kind: 'sample',\n id: sound.id,\n bus: sound.bus,\n level,\n distance,\n ...(pan === undefined ? {} : { pan }),\n cutoff: sampleCutoff(sound.cutoffK ?? DEFAULT_SAMPLE_CUTOFF_K, distance, occlusion),\n rate,\n environment,\n ...(tier ? { tier: tier.name } : {}),\n farMix,\n layers,\n priority: sound.priority ?? input.priority ?? busPriority(sound.bus),\n ...(sound.group ? { group: sound.group } : {}),\n }\n}\n","/**\n * A continuous sound played from files (fire, rain, an engine idling): `SampleSound.loop` turns a sample sound into a loop that `engine.loop(id)` plays.\n * The takes are chained without a seam: each one starts `crossfade` seconds before the last one ends, the two crossed with equal-power ramps, and\n * the next take is drawn by the round-robin (never the same twice in a row while there are two or more). A take shorter than two crossfades\n * loops on itself (`AudioBufferSourceNode.loop`). While the files are not decoded the recipe loop of the fallback (or of the same id) plays, and\n * the files take over when they are ready, at the volume the loop has then. A `position` in `set` places the loop (the sound's falloff and pan from\n * the listener), and with `baseFrequency` a `frequency` in `set` glides the rate of every take (an engine following its RPM).\n */\nimport type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { falloffGain } from '../falloff'\nimport { listenerDistance, panFor } from '../listener'\nimport type { DistanceMode, Listener } from '../listener'\nimport { DEFAULT_SAMPLE_FALLOFF, pickTake } from '../sample'\nimport type { BusId, SampleRef, SampleSound } from '../recipe'\nimport type { AudioLoopHandle, LoopEntry } from './engine-loop'\n\n/** The crossfade between two takes of a loop, in seconds, when `loop: true` gives none. */\nexport const DEFAULT_LOOP_CROSSFADE = 0.25\n/** Takes are scheduled until this far (seconds) past the clock, so a busy main thread (a heavy frame, a late timer) never leaves a gap. */\nconst LOOKAHEAD = 1.5\nconst VOLUME_SMOOTHING = 0.05\n/** Time constant of the rate glide (as the recipe loops' frequency). */\nconst RATE_SMOOTHING = 0.04\n/** The rate a loop may be pushed to by `frequency`, either way. */\nconst RATE_RANGE = [0.25, 4] as const\n\n/** The crossfade of a looping sample sound, or `undefined` when it does not loop. */\nexport function loopCrossfade(sound: SampleSound): number | undefined {\n if (!sound.loop) return undefined\n return sound.loop === true ? DEFAULT_LOOP_CROSSFADE : Math.max(0, sound.loop.crossfade ?? DEFAULT_LOOP_CROSSFADE)\n}\n\n/** Steps of the equal-power ramps (straight lines between points of the sine and cosine quarter). */\nexport const CROSSFADE_STEPS = 8\n\n/** The gain of an equal-power crossfade at `t` (0..1) for the take coming in; the take going out has the gain at `1 − t`. */\nexport const equalPowerIn = (t: number): number => Math.sin((Math.max(0, Math.min(1, t)) * Math.PI) / 2)\n\n// a quarter sine (in) or cosine (out) drawn as straight ramps, so it runs on any AudioParam (and on the recorder of the tests)\nconst ramp = (param: AudioParam, direction: 'in' | 'out', at: number, seconds: number): void => {\n const value = (t: number): number => (direction === 'in' ? equalPowerIn(t) : equalPowerIn(1 - t))\n param.setValueAtTime(value(0), at)\n for (let step = 1; step <= CROSSFADE_STEPS; step++) param.linearRampToValueAtTime(value(step / CROSSFADE_STEPS), at + (seconds * step) / CROSSFADE_STEPS)\n}\n\n/** What a sample loop needs from its engine. */\nexport type SampleLoopHost = {\n ready(): AudioContext | null\n /** The node sample voices of a bus go to (the limiter of the bus). */\n output(bus: BusId): AudioNode\n buffer(url: string): AudioBuffer | undefined\n isReady(sound: SampleSound): boolean\n /** Loads the files of the sound (resolves when they are decoded or failed). */\n load(sound: SampleSound): Promise<unknown>\n /** The recipe loop that plays while the files are not ready. */\n fallback(volume: number): AudioLoopHandle\n random(): number\n register(loop: LoopEntry): void\n unregister(loop: LoopEntry): void\n /** Whether a bus is muted now. */\n muted(bus: BusId): boolean\n /** Where the listener is, for a loop placed by `set({ position })`. */\n listener?(): Listener\n distance?: DistanceMode\n}\n\ntype Segment = { readonly source: AudioBufferSourceNode; readonly gain: GainNode; readonly end: number }\n\n/** The rate a loop with `baseFrequency` plays at for a frequency. */\nexport const loopRate = (sound: SampleSound, frequency: number): number =>\n sound.baseFrequency && sound.baseFrequency > 0 && frequency > 0 ? Math.max(RATE_RANGE[0], Math.min(RATE_RANGE[1], frequency / sound.baseFrequency)) : 1\n\n/** Plays a looping sample sound; falls back to the recipe loop while its files load. `volume` is the opening level (default 0, opened by `set`). */\nexport function createSampleLoopHandle(sound: SampleSound, host: SampleLoopHost, volume = 0): AudioLoopHandle {\n const crossfade = loopCrossfade(sound) ?? DEFAULT_LOOP_CROSSFADE\n let level = volume\n let stopped = false\n let fallback: AudioLoopHandle | undefined\n let master: GainNode | undefined\n let segments: Segment[] = []\n let last: number | undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n let panner: StereoPannerNode | undefined\n let rate = 1\n let position: Vec3 | undefined\n\n const entry: LoopEntry = {\n get created() {\n return master !== undefined\n },\n rewire() {\n const out = panner ?? master\n out?.disconnect()\n out?.connect(host.output(sound.bus))\n },\n stop() {\n stopped = true\n if (timer !== undefined) clearTimeout(timer)\n timer = undefined\n for (const segment of segments) {\n try {\n segment.source.stop()\n } catch {\n // already stopped\n }\n segment.source.disconnect()\n segment.gain.disconnect()\n }\n segments = []\n master?.disconnect()\n master = undefined\n panner?.disconnect()\n panner = undefined\n fallback?.stop()\n fallback = undefined\n host.unregister(entry)\n },\n }\n\n const nextTake = (): { readonly buffer: AudioBuffer; readonly ref: SampleRef } | undefined => {\n const takes = sound.close\n const take = pickTake(takes.length, last, host.random)\n last = take\n const ref = takes[take]\n const buffer = ref ? host.buffer(ref.url) : undefined\n return ref && buffer ? { buffer, ref } : undefined\n }\n\n // schedules one take from `at`; returns when the next one starts\n const schedule = (context: AudioContext, output: AudioNode, at: number, first: boolean): number | undefined => {\n const next = nextTake()\n if (!next) return undefined\n const { buffer, ref } = next\n const offset = Math.max(0, Math.min(ref.offset ?? 0, buffer.duration))\n const source = context.createBufferSource()\n source.buffer = buffer\n source.playbackRate.value = rate\n const gain = context.createGain()\n source.connect(gain)\n gain.connect(output)\n const fade = Math.min(crossfade, buffer.duration / 2)\n if (buffer.duration < 2 * crossfade || sound.close.length === 1) {\n // one take (or a take too short to cross): it loops on itself\n source.loop = true\n if (!first) ramp(gain.gain, 'in', at, Math.max(0.001, fade))\n source.start(at, offset)\n segments.push({ source, gain, end: Number.POSITIVE_INFINITY })\n return undefined\n }\n if (first) gain.gain.setValueAtTime(1, at)\n else ramp(gain.gain, 'in', at, fade)\n // a take crossed into the next one is timed at the rate it starts with (a rate that moves later shifts the seam a little)\n const end = at + (buffer.duration - offset) / rate\n ramp(gain.gain, 'out', end - fade, fade)\n source.start(at, offset)\n source.stop(end)\n segments.push({ source, gain, end })\n source.onended = () => {\n segments = segments.filter((segment) => segment.source !== source)\n source.disconnect()\n gain.disconnect()\n }\n return end - fade\n }\n\n const pump = (context: AudioContext, output: AudioNode, at: number, first: boolean): void => {\n if (stopped) return\n let next = schedule(context, output, at, first)\n // a late timer: catch up from the clock instead of stacking takes in the past\n while (next !== undefined && next < context.currentTime + LOOKAHEAD) next = schedule(context, output, Math.max(next, context.currentTime), false)\n if (next === undefined) return\n const wait = Math.max(0, (next - context.currentTime - LOOKAHEAD / 2) * 1000)\n timer = setTimeout(() => {\n timer = undefined\n pump(context, output, next, false)\n }, wait)\n }\n\n // the files play at the sound's own level (`SampleSound.gain`); the fallback recipe loop has its own\n const spatial = (): number => {\n if (!position || !host.listener) return 1\n return falloffGain(sound.falloff ?? DEFAULT_SAMPLE_FALLOFF, 1, listenerDistance(host.listener(), position, host.distance))\n }\n const fileLevel = (): number => level * (sound.gain ?? 1) * spatial()\n const place = (context: AudioContext): void => {\n if (panner && position && host.listener) panner.pan.setTargetAtTime(panFor(host.listener(), position), context.currentTime, VOLUME_SMOOTHING)\n }\n\n const startFiles = (): boolean => {\n if (stopped || master || !host.isReady(sound)) return master !== undefined\n const context = host.ready()\n if (!context) return false\n master = context.createGain()\n master.gain.setValueAtTime(fileLevel(), context.currentTime)\n if (sound.pan !== false && position && typeof context.createStereoPanner === 'function') {\n panner = context.createStereoPanner()\n if (host.listener) panner.pan.value = panFor(host.listener(), position)\n master.connect(panner)\n panner.connect(host.output(sound.bus))\n } else master.connect(host.output(sound.bus))\n host.register(entry)\n pump(context, master, context.currentTime, true)\n if (fallback) {\n fallback.set({ volume: 0 })\n const old = fallback\n fallback = undefined\n setTimeout(() => old.stop(), VOLUME_SMOOTHING * 6000)\n }\n return true\n }\n\n const ensure = (): void => {\n if (stopped || master) return\n if (startFiles()) return\n if (!fallback) {\n fallback = host.fallback(level)\n void host\n .load(sound)\n .then(() => {\n if (level > 0 || master) startFiles()\n })\n .catch(() => undefined)\n }\n }\n\n if (volume > 0) ensure()\n\n return {\n set(next) {\n if (stopped) return\n if (next.volume !== undefined) level = host.muted(sound.bus) ? 0 : Math.max(0, next.volume)\n if (next.position) position = next.position\n if (next.frequency !== undefined && sound.baseFrequency) rate = loopRate(sound, next.frequency)\n if (level > 0) ensure()\n const context = host.ready()\n if (master && context) {\n master.gain.setTargetAtTime(fileLevel(), context.currentTime, VOLUME_SMOOTHING)\n place(context)\n if (next.frequency !== undefined && sound.baseFrequency) for (const segment of segments) segment.source.playbackRate.setTargetAtTime(rate, context.currentTime, RATE_SMOOTHING)\n }\n fallback?.set(next.volume === undefined ? next : { ...next, volume: level })\n },\n stop: entry.stop,\n }\n}\n","import { bufferOf, fillNoise } from './noise'\n\n/** One noise buffer and the stream it is filled from. The samples are drawn before the sound that first needs them draws its own numbers. */\nexport type NoiseStore = { readonly random: () => number; samples?: Float32Array; buffer?: AudioBuffer; reset(): void }\n\nexport function createNoiseStore(random: () => number): NoiseStore {\n const store: NoiseStore = {\n random,\n reset() {\n store.samples = undefined\n store.buffer = undefined\n },\n }\n return store\n}\n\n/** Draws the samples (once): `sampleRate × seconds` of them, as the team code sizes its buffer. */\nexport function prepareNoise(store: NoiseStore, context: AudioContext, seconds: number): Float32Array {\n store.samples ??= fillNoise(store.random, Math.floor(context.sampleRate * seconds))\n return store.samples\n}\n\n/** The AudioBuffer (made on the first call, which is where the team code calls its `noise()`). */\nexport function noiseBuffer(store: NoiseStore, context: AudioContext, seconds: number): AudioBuffer {\n const samples = prepareNoise(store, context, seconds)\n store.buffer ??= bufferOf(context, [samples], context.sampleRate * seconds)\n return store.buffer\n}\n","import { DEFERRED_QUEUE_ID } from '@adatechnology/game-contracts'\nimport type { DeferredQueue } from '@adatechnology/game-contracts'\n\n/** A sound waiting to be built: `run` builds it, `drop` gives its voice back when it waited too long to still make sense. */\nexport type StartJob = { readonly queuedAt: number; run(): void; drop(): void }\n\nexport type StartQueueOptions = {\n /** Most milliseconds of main-thread work one task spends building voices (at least one voice is always built). Default 2. */\n readonly budgetMs?: number\n /** A voice still waiting after this many milliseconds is dropped instead of starting late. Default 250. */\n readonly maxLatencyMs?: number\n}\n\nexport type StartQueue = {\n push(job: Omit<StartJob, 'queuedAt'>): void\n clear(): void\n readonly size: number\n /** The same queue as a `DeferredQueue` for a shared frame budget. Asking for it changes nothing: the queue drains by itself until a budget attaches it. */\n deferredQueue?(): DeferredQueue\n}\n\nconst nowMs = (): number => (typeof performance === 'undefined' ? Date.now() : performance.now())\n\nfunction scheduleTask(task: () => void): void {\n if (typeof MessageChannel === 'undefined') {\n setTimeout(task, 0)\n return\n }\n const channel = new MessageChannel()\n channel.port1.onmessage = () => {\n channel.port1.close()\n task()\n }\n channel.port2.postMessage(0)\n}\n\n/** Builds voices in small timed slices between frames, so a burst (an explosion's debris, glass and metal) never lands inside one frame. */\n/** The queue this package makes always has its `deferredQueue`; a third-party `StartQueue` may leave it out. */\nexport type OwnStartQueue = StartQueue & { deferredQueue(): DeferredQueue }\n\nexport function createStartQueue(options: StartQueueOptions = {}): OwnStartQueue {\n const budgetMs = options.budgetMs ?? 2\n const maxLatencyMs = options.maxLatencyMs ?? 250\n let jobs: StartJob[] = []\n let scheduled = false\n // true once a frame budget owns the draining: nothing schedules a task by itself\n let attached = false\n\n const runNext = (): void => {\n const job = jobs.shift() as StartJob\n if (nowMs() - job.queuedAt > maxLatencyMs) job.drop()\n else job.run()\n }\n\n const drain = (): void => {\n scheduled = false\n if (attached) return\n const began = nowMs()\n while (jobs.length > 0) {\n runNext()\n if (nowMs() - began >= budgetMs) break\n }\n if (jobs.length > 0) schedule()\n }\n\n const schedule = (): void => {\n if (scheduled || attached) return\n scheduled = true\n scheduleTask(drain)\n }\n\n const queue: OwnStartQueue = {\n push(job) {\n jobs.push({ ...job, queuedAt: nowMs() })\n schedule()\n },\n clear() {\n for (const job of jobs) job.drop()\n jobs = []\n },\n get size() {\n return jobs.length\n },\n deferredQueue: () => deferredQueue,\n }\n\n const deferredQueue: DeferredQueue = {\n id: DEFERRED_QUEUE_ID.AUDIO_VOICES,\n pending: () => jobs.length,\n run(deadline, clock) {\n let ran = 0\n while (jobs.length > 0) {\n runNext()\n ran++\n if (clock() >= deadline) break\n }\n return ran\n },\n flush() {\n while (jobs.length > 0) runNext()\n },\n attach() {\n attached = true\n },\n detach() {\n attached = false\n if (jobs.length > 0) schedule()\n },\n }\n return queue\n}\n","// The game's routines (jogo.js), one builder each: the nodes are created, set and wired in the routine's own order, so the trace of a plan\n// matches the trace of the team function. The level is already in the envelope; every builder connects straight to the bus.\nimport type { PlannedFilter, PlannedLayer, SoundPlan } from '../plan'\nimport { applyEnvelope, assign, noiseSource, rampTo, voiceOf } from './nodes'\nimport type { RealizedVoice, RealizeTarget } from './nodes'\n\nconst end = (layer: PlannedLayer, start: number): number => start + layer.duration + layer.tail\nconst firstFilter = (layer: PlannedLayer): PlannedFilter | undefined => layer.filters?.bank[0]\nconst offsetOf = (layer: PlannedLayer): number => (layer.source.kind === 'noise' ? layer.source.offset : 0)\n\nfunction setFilter(node: BiquadFilterNode, filter: PlannedFilter | undefined, time: number): void {\n if (!filter) return\n node.type = filter.type\n assign(node.frequency, filter.frequency, time)\n if (filter.q !== undefined) node.Q.value = filter.q\n}\n\n/** `sfx` (L62089): gain to the bus first, then the noise, its lowpass, the envelope, and a random start in the noise. */\nexport function realizeBurst(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const gain = context.createGain()\n gain.connect(target.output)\n const source = noiseSource(target, layer.source.kind === 'noise' && layer.source.loop)\n const filter = context.createBiquadFilter()\n source.connect(filter)\n filter.connect(gain)\n setFilter(filter, firstFilter(layer), time)\n applyEnvelope(gain.gain, layer.envelope, time)\n source.start(time, offsetOf(layer))\n source.stop(end(layer, time))\n return voiceOf([source])\n}\n\n/** `grito` (L62128): noise through a parallel formant bank (each band with its own level), a gain LFO for roughness. */\nexport function realizeScream(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const source = noiseSource(target, layer.source.kind === 'noise' && layer.source.loop)\n const gain = context.createGain()\n gain.connect(target.output)\n for (const band of layer.filters?.bank ?? []) {\n const filter = context.createBiquadFilter()\n filter.type = band.type\n if (band.q !== undefined) filter.Q.value = band.q\n assign(filter.frequency, band.frequency, time)\n rampTo(filter.frequency, band.frequency, time)\n const level = context.createGain()\n level.gain.value = band.level ?? 1\n source.connect(filter)\n filter.connect(level)\n level.connect(gain)\n }\n const sources: AudioScheduledSourceNode[] = [source]\n const lfos = layer.modulators.map((modulator) => {\n const lfo = context.createOscillator()\n const depth = context.createGain()\n if (modulator.wave) lfo.type = modulator.wave\n lfo.frequency.value = modulator.rate\n depth.gain.value = modulator.depth\n lfo.connect(depth)\n depth.connect(gain.gain)\n return lfo\n })\n applyEnvelope(gain.gain, layer.envelope, time)\n source.start(time, offsetOf(layer))\n source.stop(end(layer, time))\n for (const lfo of lfos) {\n lfo.start(time)\n lfo.stop(end(layer, time))\n sources.push(lfo)\n }\n return voiceOf(sources)\n}\n\n/** `voz` (L62143): oscillator → bandpass → gain; the filter frequency is set after the pitch sweep. */\nexport function realizeGroan(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n const gain = context.createGain()\n const filter = context.createBiquadFilter()\n const band = firstFilter(layer)\n if (layer.source.kind === 'osc') oscillator.type = layer.source.wave\n if (band) {\n filter.type = band.type\n if (band.q !== undefined) filter.Q.value = band.q\n }\n if (layer.source.kind === 'osc') {\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n if (band) assign(filter.frequency, band.frequency, time)\n applyEnvelope(gain.gain, layer.envelope, time)\n oscillator.connect(filter)\n filter.connect(gain)\n gain.connect(target.output)\n oscillator.start(time)\n oscillator.stop(end(layer, time))\n return voiceOf([oscillator])\n}\n\n/** `boom` (L68278): one oscillator sweeping down into a gain. */\nexport function realizeBoom(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n const gain = context.createGain()\n if (layer.source.kind === 'osc') {\n oscillator.type = layer.source.wave\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n applyEnvelope(gain.gain, layer.envelope, time)\n oscillator.connect(gain)\n gain.connect(target.output)\n oscillator.start(time)\n oscillator.stop(end(layer, time))\n return voiceOf([oscillator])\n}\n\n/** `chiado` (L69998): gain, noise and bandpass created first, then set, then wired. */\nexport function realizeStatic(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const gain = context.createGain()\n const source = context.createBufferSource()\n const filter = context.createBiquadFilter()\n source.buffer = target.noise()\n setFilter(filter, firstFilter(layer), time)\n applyEnvelope(gain.gain, layer.envelope, time)\n source.connect(filter)\n filter.connect(gain)\n gain.connect(target.output)\n source.start(time, offsetOf(layer))\n source.stop(end(layer, time))\n return voiceOf([source])\n}\n\n/** `buzina` (L70272): one oscillator per layer into one gain with the first layer's envelope. */\nexport function realizeChord(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layers = plan.layers\n const oscillators = layers.map(() => context.createOscillator())\n const gain = context.createGain()\n // the team writes `o.type = o2.type = 'square'`, which assigns right to left\n for (let index = layers.length - 1; index >= 0; index--) {\n const source = (layers[index] as PlannedLayer).source\n if (source.kind === 'osc') (oscillators[index] as OscillatorNode).type = source.wave\n }\n layers.forEach((layer, index) => {\n if (layer.source.kind === 'osc') assign((oscillators[index] as OscillatorNode).frequency, layer.source.frequency, target.time + layer.at)\n })\n applyEnvelope(gain.gain, (layers[0] as PlannedLayer).envelope, target.time + (layers[0] as PlannedLayer).at)\n for (const oscillator of oscillators) oscillator.connect(gain)\n gain.connect(target.output)\n layers.forEach((layer, index) => (oscillators[index] as OscillatorNode).start(target.time + layer.at))\n layers.forEach((layer, index) => (oscillators[index] as OscillatorNode).stop(end(layer, target.time + layer.at)))\n return voiceOf(oscillators)\n}\n\n/**\n * `bichoSom` (L66625): gain and filter are created before the level is checked (a silent plan stops there), then each repeat is an oscillator\n * with its own envelope into the shared filter, whose frequency and Q are set again on every repeat.\n */\nexport function realizeCalls(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const gain = context.createGain()\n const filter = context.createBiquadFilter()\n if (plan.silent) return voiceOf([])\n const band = firstFilter(plan.layers[0] as PlannedLayer)\n if (band) filter.type = band.type\n filter.connect(gain)\n gain.connect(target.output)\n const oscillators = plan.layers.map((layer) => {\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n if (layer.source.kind === 'osc') {\n oscillator.type = layer.source.wave\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n if (band) {\n assign(filter.frequency, band.frequency, time)\n if (band.q !== undefined) filter.Q.value = band.q\n }\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n oscillator.connect(envelope)\n envelope.connect(filter)\n oscillator.start(time)\n oscillator.stop(end(layer, time))\n return oscillator\n })\n return voiceOf(oscillators)\n}\n","// The art scene's primitives (cena L1319–1328, L1369): `sNoise`, `sTone` and `voice`, each layer with its own output stage (`outAt`: distance\n// gain, pan, reverb send), and the siren straight to the bus. Built in the team's order so the traces match node for node.\nimport type { PlannedLayer, SoundPlan } from '../plan'\nimport { applyEnvelope, assign, filterNode, gainNode, noiseSource, rampTo, voiceOf } from './nodes'\nimport type { RealizedVoice, RealizeTarget } from './nodes'\n\nconst end = (layer: PlannedLayer, start: number): number => start + layer.duration + layer.tail\n\n/** `outAt`: the layer level, the stereo panner when the plan pans and the context has one, the bus, then the reverb send. */\nfunction outputStage(plan: SoundPlan, layer: PlannedLayer, target: RealizeTarget): GainNode {\n const { context } = target\n const level = gainNode(context, layer.level)\n let node: AudioNode = level\n if (plan.pan !== undefined && typeof context.createStereoPanner === 'function') {\n const panner = context.createStereoPanner()\n panner.pan.value = plan.pan\n level.connect(panner)\n node = panner\n }\n node.connect(target.output)\n if (layer.wet && target.wet) {\n const send = gainNode(context, layer.wet)\n node.connect(send)\n send.connect(target.wet)\n }\n return level\n}\n\nfunction realizeNoiseLayer(plan: SoundPlan, layer: PlannedLayer, target: RealizeTarget): AudioScheduledSourceNode[] {\n const { context } = target\n const time = target.time + layer.at\n const source = noiseSource(target, layer.source.kind === 'noise' && layer.source.loop)\n const filters = (layer.filters?.bank ?? []).map((filter) => {\n const node = filterNode(context, filter, time)\n rampTo(node.frequency, filter.frequency, time)\n return node\n })\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n let tail: AudioNode = source\n for (const filter of filters) tail = tail.connect(filter)\n tail.connect(envelope)\n envelope.connect(outputStage(plan, layer, target))\n source.start(time, layer.source.kind === 'noise' ? layer.source.offset : 0)\n source.stop(end(layer, time))\n return [source]\n}\n\nfunction realizeToneLayer(plan: SoundPlan, layer: PlannedLayer, target: RealizeTarget): AudioScheduledSourceNode[] {\n const { context } = target\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n if (layer.source.kind === 'osc') {\n oscillator.type = layer.source.wave\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n oscillator.connect(envelope)\n envelope.connect(outputStage(plan, layer, target))\n oscillator.start(time)\n oscillator.stop(end(layer, time))\n return [oscillator]\n}\n\nfunction realizeVoiceLayer(plan: SoundPlan, layer: PlannedLayer, target: RealizeTarget): AudioScheduledSourceNode[] {\n const source = layer.source\n if (source.kind !== 'formant_voice') return []\n const { context } = target\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n oscillator.type = source.wave\n assign(oscillator.frequency, source.frequency, time)\n rampTo(oscillator.frequency, source.frequency, time)\n const vibrato = context.createOscillator()\n vibrato.frequency.value = source.vibrato.rate\n const vibratoDepth = gainNode(context, source.vibrato.depth)\n vibrato.connect(vibratoDepth)\n vibratoDepth.connect(oscillator.frequency)\n const formants = source.formants.map((formant) => filterNode(context, { type: 'bandpass', frequency: { value: formant.frequency }, q: formant.q }, time))\n const breath = noiseSource(target, true)\n const breathBand = filterNode(context, { type: 'bandpass', frequency: { value: source.breath.frequency }, q: source.breath.q }, time)\n const breathLevel = gainNode(context, source.breath.gain)\n const mix = gainNode(context, source.mix)\n for (const formant of formants) oscillator.connect(formant)\n breath.connect(breathBand)\n breathBand.connect(breathLevel)\n for (const formant of formants) formant.connect(mix)\n breathLevel.connect(mix)\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n mix.connect(envelope)\n envelope.connect(outputStage(plan, layer, target))\n const stop = end(layer, time)\n oscillator.start(time)\n vibrato.start(time)\n breath.start(time, source.breath.offset)\n oscillator.stop(stop)\n vibrato.stop(stop)\n breath.stop(stop)\n return [oscillator, vibrato, breath]\n}\n\n/** Every layer in order, each with its own output stage. */\nexport function realizeLayered(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const sources = plan.layers.flatMap((layer) => {\n if (layer.source.kind === 'noise') return realizeNoiseLayer(plan, layer, target)\n if (layer.source.kind === 'osc') return realizeToneLayer(plan, layer, target)\n return realizeVoiceLayer(plan, layer, target)\n })\n return voiceOf(sources)\n}\n\n/** The siren: oscillator with a frequency LFO, envelope, lowpass, straight to the bus with a reverb send. */\nexport function realizeSiren(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const { context } = target\n const layer = plan.layers[0] as PlannedLayer\n const time = target.time + layer.at\n const oscillator = context.createOscillator()\n if (layer.source.kind === 'osc') {\n oscillator.type = layer.source.wave\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n const depths = layer.modulators.map((modulator) => {\n const lfo = context.createOscillator()\n if (modulator.wave) lfo.type = modulator.wave\n lfo.frequency.value = modulator.rate\n const depth = gainNode(context, modulator.depth)\n lfo.connect(depth)\n if (modulator.target === 'frequency') depth.connect(oscillator.frequency)\n return { lfo, depth, target: modulator.target }\n })\n const lfos = depths.map(({ lfo }) => lfo)\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n for (const { depth, target: modulated } of depths) if (modulated === 'gain') depth.connect(envelope.gain)\n const filters = (layer.filters?.bank ?? []).map((filter) => filterNode(context, filter, time))\n let tail: AudioNode = oscillator\n for (const filter of filters) tail = tail.connect(filter)\n tail.connect(envelope)\n envelope.connect(target.output)\n if (layer.wet && target.wet) {\n const send = gainNode(context, layer.wet)\n envelope.connect(send)\n send.connect(target.wet)\n }\n const stop = end(layer, time)\n oscillator.start(time)\n for (const lfo of lfos) lfo.start(time)\n oscillator.stop(stop)\n for (const lfo of lfos) lfo.stop(stop)\n return voiceOf([oscillator, ...lfos])\n}\n","// The weapon audio of the kit (`weapons-three`, first written against raw WebAudio): per layer, either a noise burst (source, filter, envelope gain)\n// or an oscillator (oscillator, envelope gain), created in that order and chained straight to the bus. The level is already in the envelope.\nimport type { PlannedLayer, SoundPlan } from '../plan'\nimport { applyEnvelope, assign, filterNode, noiseSource, rampTo, voiceOf } from './nodes'\nimport type { RealizedVoice, RealizeTarget } from './nodes'\n\nfunction noiseLayer(layer: PlannedLayer, target: RealizeTarget, time: number): AudioScheduledSourceNode {\n const { context } = target\n const source = noiseSource(target, layer.source.kind === 'noise' && layer.source.loop)\n const filters = (layer.filters?.bank ?? []).map((filter) => filterNode(context, filter, time))\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n let tail: AudioNode = source\n for (const filter of filters) tail = tail.connect(filter)\n tail.connect(envelope).connect(target.output)\n source.start(time, layer.source.kind === 'noise' ? layer.source.offset : 0)\n source.stop(time + layer.duration + layer.tail)\n return source\n}\n\nfunction toneLayer(layer: PlannedLayer, target: RealizeTarget, time: number): AudioScheduledSourceNode {\n const { context } = target\n const oscillator = context.createOscillator()\n if (layer.source.kind === 'osc') {\n oscillator.type = layer.source.wave\n assign(oscillator.frequency, layer.source.frequency, time)\n rampTo(oscillator.frequency, layer.source.frequency, time)\n }\n const envelope = context.createGain()\n applyEnvelope(envelope.gain, layer.envelope, time)\n oscillator.connect(envelope).connect(target.output)\n oscillator.start(time)\n oscillator.stop(time + layer.duration + layer.tail)\n return oscillator\n}\n\n/** One noise burst or one tone per layer, in the order written. */\nexport function realizeWeapon(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n const sources = plan.layers.map((layer) => {\n const time = target.time + layer.at\n return layer.source.kind === 'noise' ? noiseLayer(layer, target, time) : toneLayer(layer, target, time)\n })\n return voiceOf(sources)\n}\n","import type { SoundPlan } from '../plan'\nimport type { BuildOrder } from '../recipe'\nimport type { RealizedVoice, RealizeTarget } from './nodes'\nimport { realizeBoom, realizeBurst, realizeCalls, realizeChord, realizeGroan, realizeScream, realizeStatic } from './realize-game'\nimport { realizeLayered, realizeSiren } from './realize-layered'\nimport { realizeWeapon } from './realize-weapon'\n\nconst BUILDERS: Readonly<Record<BuildOrder, (plan: SoundPlan, target: RealizeTarget) => RealizedVoice>> = {\n layered: realizeLayered,\n burst: realizeBurst,\n scream: realizeScream,\n groan: realizeGroan,\n boom: realizeBoom,\n static: realizeStatic,\n chord: realizeChord,\n calls: realizeCalls,\n siren: realizeSiren,\n weapon: realizeWeapon,\n}\n\n/** Builds a plan's nodes on `target`, in the node order of the team routine its `order` names. */\nexport function realize(plan: SoundPlan, target: RealizeTarget): RealizedVoice {\n return BUILDERS[plan.order](plan, target)\n}\n","import type { PlannedAutomation, PlannedFilter, PlannedLayer, PlannedModulator, PlannedSource, SoundPlan } from './plan'\nimport type { SoundSet } from './recipe'\n\nconst tuneAutomation = (automation: PlannedAutomation, rate: number): PlannedAutomation => {\n const tuned: { -readonly [K in keyof PlannedAutomation]: PlannedAutomation[K] } = { ...automation }\n if (automation.value !== undefined) tuned.value = automation.value * rate\n if (automation.from !== undefined) tuned.from = automation.from * rate\n if (automation.to !== undefined) tuned.to = automation.to * rate\n if (automation.at !== undefined) tuned.at = automation.at / rate\n return tuned\n}\n\nconst tuneFilter = (filter: PlannedFilter, rate: number): PlannedFilter => ({ ...filter, frequency: tuneAutomation(filter.frequency, rate) })\n\nconst tuneSource = (source: PlannedSource, rate: number): PlannedSource => {\n switch (source.kind) {\n case 'noise':\n return source\n case 'osc':\n return { ...source, frequency: tuneAutomation(source.frequency, rate) }\n case 'formant_voice':\n return {\n ...source,\n frequency: tuneAutomation(source.frequency, rate),\n formants: source.formants.map((formant) => ({ ...formant, frequency: formant.frequency * rate })),\n breath: { ...source.breath, frequency: source.breath.frequency * rate },\n }\n }\n}\n\nconst tuneModulator = (modulator: PlannedModulator, rate: number): PlannedModulator => ({\n ...modulator,\n rate: modulator.rate * rate,\n ...(modulator.target === 'frequency' ? { depth: modulator.depth * rate } : {}),\n})\n\nconst tuneLayer = (layer: PlannedLayer, rate: number): PlannedLayer => ({\n ...layer,\n at: layer.at / rate,\n duration: layer.duration / rate,\n tail: layer.tail / rate,\n source: tuneSource(layer.source, rate),\n ...(layer.filters ? { filters: { ...layer.filters, bank: layer.filters.bank.map((filter) => tuneFilter(filter, rate)) } } : {}),\n modulators: layer.modulators.map((modulator) => tuneModulator(modulator, rate)),\n envelope: layer.envelope.map((point) => ({ ...point, time: point.time / rate })),\n})\n\n/**\n * A plan played faster or slower, as a tape would: every frequency (tones, filters, formants, LFOs) times `rate`, every time divided by it. Noise\n * has no pitch of its own, so its colour moves with its filters. `rate` 1 gives the plan back.\n */\nexport function retunePlan(plan: SoundPlan, rate: number): SoundPlan {\n if (rate === 1 || !(rate > 0)) return plan\n return { ...plan, length: plan.length / rate, layers: plan.layers.map((layer) => tuneLayer(layer, rate)) }\n}\n\n/** Remembers the last variant of each set, so the next draw never repeats it. */\nexport type SetPicker = {\n /** The variant to play and its rate, drawn from `random` (two numbers: the variant, then the rate). */\n pick(set: SoundSet, random: () => number): { readonly id: string; readonly rate: number }\n /** Forget the last variants (a fresh scene). */\n reset(): void\n}\n\nexport function createSetPicker(): SetPicker {\n const last = new Map<string, number>()\n return {\n pick(set, random) {\n const count = set.variants.length\n const previous = last.get(set.id)\n let index: number\n if (count === 1) index = 0\n else if (set.repeat || previous === undefined) index = Math.min(count - 1, Math.floor(random() * count))\n else {\n // one of the others: draw among count − 1 and skip the previous\n index = Math.min(count - 2, Math.floor(random() * (count - 1)))\n if (index >= previous) index += 1\n }\n last.set(set.id, index)\n const [min, max] = set.rate ?? [1, 1]\n const rate = min === max ? min : min + random() * (max - min)\n return { id: set.variants[index] as string, rate }\n },\n reset: () => last.clear(),\n }\n}\n","/**\n * Decoded sample buffers by url. Files load once (concurrent asks share the same promise), decode on the engine's context and stay until `clear`.\n * The bytes come from a `SampleLoader`: `fetch` by default, or anything else (a single-file page passes the files inlined as base64).\n */\n\n/** Gets the bytes of a file. */\nexport type SampleLoader = (url: string) => Promise<ArrayBuffer>\n\nexport type SampleStatus = 'none' | 'loading' | 'ready' | 'failed'\n\nexport type SampleLoadReport = { readonly loaded: readonly string[]; readonly failed: readonly { readonly url: string; readonly error: string }[] }\n\nexport type SampleStore = {\n status(url: string): SampleStatus\n /** The decoded buffer, once ready. */\n buffer(url: string): AudioBuffer | undefined\n /** Whether every url is ready. */\n ready(urls: readonly string[]): boolean\n load(urls: readonly string[], context: BaseAudioContext): Promise<SampleLoadReport>\n /** Seconds of the decoded file, or `undefined` while not ready. */\n seconds(url: string): number | undefined\n clear(): void\n}\n\n/** `fetch` relative to `baseUrl` (default the page). */\nexport function fetchLoader(baseUrl?: string): SampleLoader {\n return async (url) => {\n const target = baseUrl ? new URL(url, baseUrl).toString() : url\n const response = await fetch(target)\n if (!response.ok) throw new Error(`${response.status} ${response.statusText} for ${target}`)\n return response.arrayBuffer()\n }\n}\n\n/** Bytes of files given inline as base64 (or `data:` urls), by url. */\nexport function inlineLoader(files: Readonly<Record<string, string>>): SampleLoader {\n return async (url) => {\n const text = files[url]\n if (text === undefined) throw new Error(`no inline file for ${url}`)\n const base64 = text.startsWith('data:') ? text.slice(text.indexOf(',') + 1) : text\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index)\n return bytes.buffer\n }\n}\n\nconst decode = (context: BaseAudioContext, bytes: ArrayBuffer): Promise<AudioBuffer> =>\n new Promise((resolve, reject) => {\n // the callback form also covers old Safari, where decodeAudioData returns no promise\n const result = context.decodeAudioData(bytes, resolve, reject) as Promise<AudioBuffer> | undefined\n result?.catch?.(reject)\n })\n\nexport function createSampleStore(loader: SampleLoader = fetchLoader()): SampleStore {\n const buffers = new Map<string, AudioBuffer>()\n const pending = new Map<string, Promise<AudioBuffer>>()\n const failed = new Map<string, string>()\n let generation = 0\n\n const loadOne = (url: string, context: BaseAudioContext): Promise<AudioBuffer> => {\n const existing = buffers.get(url)\n if (existing) return Promise.resolve(existing)\n const inFlight = pending.get(url)\n if (inFlight) return inFlight\n const started = generation\n failed.delete(url)\n const promise = loader(url)\n .then((bytes) => decode(context, bytes))\n .then((buffer) => {\n if (started === generation) buffers.set(url, buffer)\n return buffer\n })\n .catch((error: unknown) => {\n if (started === generation) failed.set(url, error instanceof Error ? error.message : String(error))\n throw error\n })\n .finally(() => {\n if (pending.get(url) === promise) pending.delete(url)\n })\n pending.set(url, promise)\n return promise\n }\n\n return {\n status(url) {\n if (buffers.has(url)) return 'ready'\n if (pending.has(url)) return 'loading'\n if (failed.has(url)) return 'failed'\n return 'none'\n },\n buffer: (url) => buffers.get(url),\n ready: (urls) => urls.every((url) => buffers.has(url)),\n seconds: (url) => buffers.get(url)?.duration,\n async load(urls, context) {\n const results = await Promise.allSettled(urls.map((url) => loadOne(url, context)))\n const loaded: string[] = []\n const errors: { url: string; error: string }[] = []\n results.forEach((result, index) => {\n const url = urls[index] as string\n if (result.status === 'fulfilled') loaded.push(url)\n else errors.push({ url, error: result.reason instanceof Error ? result.reason.message : String(result.reason) })\n })\n return { loaded, failed: errors }\n },\n clear() {\n generation++\n buffers.clear()\n pending.clear()\n failed.clear()\n },\n }\n}\n","import { OPEN_CUTOFF } from '../sample'\nimport type { SamplePlan } from '../sample'\nimport { gainNode, voiceOf } from './nodes'\nimport type { RealizedVoice } from './nodes'\n\n/** Seconds a trimmed take fades out over at its cut. */\nexport const TRIM_FADE = 0.04\n\nexport type SampleTarget = {\n readonly context: BaseAudioContext\n readonly output: AudioNode\n readonly buffer: (url: string) => AudioBuffer | undefined\n readonly time: number\n}\n\n/** A sample voice can also be faded out (the choke of its sound). */\nexport type RealizedSampleVoice = RealizedVoice & { fade(at: number, seconds: number): void }\n\n/**\n * Builds a sample plan: each layer is a buffer source at the planned rate with its own gain, the layers meet in one voice gain (the choke fades it),\n * one lowpass (left out when open) and one stereo panner (when the plan has a pan), then the bus. A layer whose buffer is not loaded is skipped.\n */\nexport function realizeSample(plan: SamplePlan, target: SampleTarget): RealizedSampleVoice {\n const context = target.context\n let head: AudioNode = target.output\n if (plan.pan !== undefined && typeof context.createStereoPanner === 'function') {\n const panner = context.createStereoPanner()\n panner.pan.value = plan.pan\n panner.connect(head)\n head = panner\n }\n if (plan.cutoff < OPEN_CUTOFF) {\n const lowpass = context.createBiquadFilter()\n lowpass.type = 'lowpass'\n lowpass.frequency.value = plan.cutoff\n lowpass.Q.value = 0.7\n lowpass.connect(head)\n head = lowpass\n }\n const voice = context.createGain()\n voice.connect(head)\n head = voice\n const sources: AudioBufferSourceNode[] = []\n for (const layer of plan.layers) {\n const buffer = target.buffer(layer.url)\n if (!buffer) continue\n const source = context.createBufferSource()\n source.buffer = buffer\n source.playbackRate.value = layer.rate\n const gain = gainNode(context as AudioContext, layer.gain)\n source.connect(gain)\n gain.connect(head)\n const at = target.time + layer.at\n const offset = Math.max(0, Math.min(layer.offset ?? 0, buffer.duration))\n if (layer.duration === undefined) source.start(at, offset)\n else {\n // a take cut out of a longer file fades over its last 40 ms (of the clock: the rate shortens it)\n const duration = Math.max(0, Math.min(layer.duration, buffer.duration - offset))\n const end = at + duration / layer.rate\n const fade = Math.min(TRIM_FADE, (end - at) / 4)\n gain.gain.setValueAtTime(layer.gain, end - fade)\n gain.gain.linearRampToValueAtTime(0, end)\n source.start(at, offset, duration)\n }\n sources.push(source)\n }\n const realized = voiceOf(sources)\n return {\n ...realized,\n fade(at, seconds) {\n voice.gain.setValueAtTime(1, at)\n voice.gain.linearRampToValueAtTime(0, at + seconds)\n for (const source of sources) {\n try {\n source.stop(at + seconds)\n } catch {\n // already stopped\n }\n }\n },\n }\n}\n\n/** Seconds a sample plan lasts with its buffers (the longest layer, at its rate). */\nexport function sampleLength(plan: SamplePlan, seconds: (url: string) => number | undefined): number {\n let length = 0\n for (const layer of plan.layers) {\n const file = seconds(layer.url) ?? 0\n const played = layer.duration === undefined ? file - (layer.offset ?? 0) : Math.min(layer.duration, file - (layer.offset ?? 0))\n length = Math.max(length, layer.at + Math.max(0, played) / layer.rate)\n }\n return length\n}\n","import type { DeferredQueue, Vec3 } from '@adatechnology/game-contracts'\n\nimport { createSoundRegistry } from '../bank'\nimport type { SoundRegistry } from '../bank'\nimport { falloffGain, isSilent } from '../falloff'\nimport { DEFAULT_LISTENER, listenerDistance } from '../listener'\nimport type { DistanceMode, Listener } from '../listener'\nimport { DEFAULT_MIX, busGain, resolveMix } from '../mix'\nimport type { BusSetting, MixProfile } from '../mix'\nimport { planSound } from '../plan'\nimport type { PlanInput, SoundPlan } from '../plan'\nimport type { BusId, SoundBank, SoundRecipe } from '../recipe'\nimport { createRng, streamFor } from '../rng'\nimport { busPriority, createVoiceManager } from '../voices'\nimport type { VoiceGroup } from '../voices'\nimport { buildChain } from './chain'\nimport type { MixChain } from './chain'\nimport { globalContext, unlockContext } from './context'\nimport { createLoopHandle } from './engine-loop'\nimport type { AudioLoopHandle, LoopHost } from './engine-loop'\nimport { createSampleLoopHandle } from './sample-loop'\nimport { createNoiseStore, noiseBuffer, prepareNoise } from './engine-noise'\nimport type { NoiseStore } from './engine-noise'\nimport type { RealizedVoice } from './nodes'\nimport { createStartQueue } from './engine-queue'\nimport type { StartQueueOptions } from './engine-queue'\nimport { realize } from './realize'\nimport { createSetPicker, retunePlan } from '../variation'\nimport { planSample, sampleUrls } from '../sample'\nimport type { SampleEnvironment, SampleMemory, SamplePlan, SampleSound } from '../sample'\nimport { createSampleStore, fetchLoader } from './sample-store'\nimport type { SampleLoadReport, SampleLoader, SampleStatus } from './sample-store'\nimport { realizeSample, sampleLength } from './realize-sample'\nimport type { RealizedSampleVoice } from './realize-sample'\n\nexport type PlayOptions = {\n readonly position?: Vec3\n /** Meters; overrides `position` for the distance (not for the pan). */\n readonly distance?: number\n readonly volume?: number\n readonly params?: Readonly<Record<string, number>>\n /** This sound's own stream: same seed, same sound. */\n readonly seed?: number\n /** Seconds from now. */\n readonly delay?: number\n /** Built now instead of waiting in the engine's deferred start queue: for a sound that has to land on the frame the player sees it (a blow's\n * contact, a heel strike, a landing). The queue builds a voice on the next frame budget and drops it after its latency, which at a low frame\n * rate is late or silent. Default false. */\n readonly urgent?: boolean\n /** A named stream of the engine (`streamFor(seed, name)`), so one subject never shifts another's sounds. */\n readonly channel?: string\n /** The tail a sample sound plays (default the engine's, see `setEnvironment`). */\n readonly environment?: SampleEnvironment\n /** 0 (light) to 1 (heavy): the tier of takes a sample sound plays (criterion C7). */\n readonly intensity?: number\n /** 0 (clear) to 1 (behind a wall) for this play, over the engine's `occlusion` (a test bench puts a wall in between). Sample sounds only. */\n readonly occlusion?: number\n}\n\n/** A playing voice: a recipe (`kind: 'recipe'`, the plan of the synthesized sound) or files (`kind: 'sample'`). */\nexport type VoiceHandle =\n | { readonly id: number; readonly kind: 'recipe'; readonly plan: SoundPlan; stop(): void }\n | { readonly id: number; readonly kind: 'sample'; readonly plan: SamplePlan; stop(): void }\n\n/**\n * A voice that started, for measuring (criterion C1: the event against the start of the sound). Times are the context clock, in seconds:\n * `requestedAt` when `play` was called, `startAt` when the first sample of the sound leaves the engine; `outputLatency` is what the device adds\n * after that (`baseLatency + outputLatency` of the context, 0 when unknown).\n */\nexport type VoiceStartEvent = {\n readonly id: string\n readonly kind: 'recipe' | 'sample'\n /** The sample sound this recipe stood in for while its files were not loaded. */\n readonly fallbackOf?: string\n /** The bank the played id is registered in (`kit_samples`, `user_samples`, a recipe bank...). */\n readonly bank?: string\n readonly requestedAt: number\n readonly startAt: number\n readonly outputLatency: number\n readonly level: number\n readonly distance: number\n readonly pan?: number\n /** The files a sample voice plays, by layer. */\n readonly layers?: readonly { readonly role: string; readonly url: string; readonly take: number; readonly rate: number }[]\n /** The tier of takes a sample voice played (criterion C7). */\n readonly tier?: string\n}\n\nexport type SampleOptions = {\n /** Gets the bytes of a file (default `fetch`, relative to `baseUrl`). */\n readonly loader?: SampleLoader\n readonly baseUrl?: string\n /** Load a sound's files the first time it is played (default true); the fallback plays meanwhile. */\n readonly autoLoad?: boolean\n /**\n * The peak limiter every sample voice of a bus goes through before the bus (criteria C6 and C9: no sound and no burst goes over −1 dBFS): linear\n * up to `knee` (default 0.5, −6 dBFS), then bent smoothly to `ceiling` (default 0.891, −1 dBFS), with no delay. `false` leaves it out.\n */\n readonly limiter?: false | { readonly knee?: number; readonly ceiling?: number }\n}\n\n/** A subject's own random stream; `ownNoise` also gives it its own noise buffer, filled from that stream (the order `createWeaponAudio` uses). */\nexport type AudioChannel = {\n readonly random: () => number\n play(id: string, options?: PlayOptions): VoiceHandle | null\n plan(id: string, options?: PlayOptions): SoundPlan | null\n}\n\nexport type AudioStats = {\n readonly context: 'none' | AudioContextState\n readonly voices: number\n readonly peak: number\n readonly dropped: number\n readonly maxVoices: number\n readonly loops: number\n}\n\nexport type AudioEngineOptions = {\n /** Seeds the engine stream: the noise, the reverb impulse and every sound played without its own seed or channel. Default 1. */\n readonly seed?: number\n /** Default `art_scene` (Q1). */\n readonly mix?: string | MixProfile\n readonly profiles?: Readonly<Record<string, MixProfile>>\n readonly banks?: readonly SoundBank[]\n readonly maxVoices?: number\n readonly groups?: Readonly<Record<string, VoiceGroup>>\n readonly distance?: DistanceMode\n /** 0 (clear) to 1 (behind a wall) for a sound at a point; without it there is no occlusion (Q8). */\n readonly occlusion?: (point: Vec3) => number\n readonly createContext?: () => AudioContext | null\n /** Build voices in timed slices between frames instead of inside `play` (a sound starts a few ms late; a burst never costs a frame). Off by default. */\n readonly deferredStart?: StartQueueOptions\n /** Where sample sounds get their files. */\n readonly samples?: SampleOptions\n /** The tail sample sounds play when `play` names none (default `outdoor`). */\n readonly environment?: SampleEnvironment\n /** Called when a voice is built (recipe or sample): the measuring hook of the criteria. */\n readonly onVoiceStart?: (event: VoiceStartEvent) => void\n}\n\nexport type AudioEngine = {\n readonly registry: SoundRegistry\n register(bank: SoundBank): void\n /** Pure: the plan a sound would play with, from `options.seed` or the engine seed; draws nothing from the live streams. */\n plan(id: string, options?: PlayOptions): SoundPlan | null\n /** Pure: the plan a sample sound would play with (no round-robin memory), from `options.seed` or the engine seed. */\n planSample(id: string, options?: PlayOptions): SamplePlan | null\n /** Loads the files of these sample sounds (default all registered). Creates the context; resolves when every file is decoded or failed. */\n loadSamples(ids?: readonly string[]): Promise<SampleLoadReport>\n /** `ready` when every file of the sound is decoded. */\n sampleStatus(id: string): SampleStatus\n /** The tail sample sounds play from now on. */\n setEnvironment(environment: SampleEnvironment): void\n /** The node everything is mixed into before the speakers (to record or meter the whole output), or `null` before the context exists. */\n output(): AudioNode | null\n /** Another place files come from: urls `accepts` takes go to `loader`, the rest to the engine's own (a bench lends its calibration takes). */\n addSampleSource(accepts: (url: string) => boolean, loader: SampleLoader): void\n /** Follows every voice built from now on (as `onVoiceStart` does); returns the unsubscribe function. */\n watchVoices(listener: (event: VoiceStartEvent) => void): () => void\n play(id: string, options?: PlayOptions): VoiceHandle | null\n playPlan(plan: SoundPlan, options?: { readonly delay?: number }): VoiceHandle | null\n loop(id: string, options?: { readonly volume?: number }): AudioLoopHandle\n channel(options: { readonly seed?: number; readonly random?: () => number; readonly ownNoise?: boolean }): AudioChannel\n setListener(listener: Listener): void\n setBus(id: BusId, setting: BusSetting): void\n setMix(mix: string | MixProfile): void\n /** The master volume of the current chain and of any later one (0 to 1). */\n setMaster(gain: number): void\n /** Creates the context and the mixing chain if needed and resumes it; call from a click or a key. */\n unlock(): void\n /** Creates the context, the mixing chain (reverb impulse included) and the shared noise buffer now, so the first sound does not pay for them inside a frame. Returns false without a context. */\n warmUp(): boolean\n stats(): AudioStats\n /** RMS (0 to 1) of what a bus carries now, read from an analyser the first time you ask; sounds started before that do not reach it. 0 without a context. */\n level(bus: BusId): number\n /**\n * The voice start queue as a `DeferredQueue` for a shared frame budget (`budget.register` attaches it and the queue stops scheduling its own tasks), or `null`\n * without `deferredStart`. Asking for it changes nothing.\n */\n deferredQueue?(): DeferredQueue | null\n dispose(): void\n}\n\n/** The limiter's transfer curve over ±`range`: linear up to `knee`, then a tanh bend that never passes `ceiling`. */\nexport function limiterCurve(knee: number, ceiling: number, range: number, points = 2049): Float32Array<ArrayBuffer> {\n const curve = new Float32Array(points)\n const room = Math.max(1e-6, ceiling - knee)\n for (let index = 0; index < points; index++) {\n const value = ((index / (points - 1)) * 2 - 1) * range\n const size = Math.abs(value)\n const bent = size <= knee ? size : knee + room * Math.tanh((size - knee) / room)\n curve[index] = Math.sign(value) * bent\n }\n return curve\n}\n\ntype Admission = { readonly bus: BusId; readonly group?: string; readonly priority?: number }\n\nconst usesNoise = (recipe: SoundRecipe): boolean => recipe.layers.some((layer) => layer.source.kind !== 'osc')\nconst planUsesNoise = (plan: SoundPlan): boolean => plan.layers.some((layer) => layer.source.kind !== 'osc')\n\n/**\n * The sound engine: plans recipes and builds them on a lazily created AudioContext through one of the team mixing chains. Without an AudioContext\n * (Node, workers) every call except `plan` does nothing.\n */\nexport function createAudioEngine(options: AudioEngineOptions = {}): AudioEngine {\n const seed = options.seed ?? 1\n const registry = createSoundRegistry(options.banks)\n const voices = createVoiceManager({ ...(options.groups ? { groups: options.groups } : {}), ...(options.maxVoices === undefined ? {} : { maxVoices: options.maxVoices }) })\n const engineRandom = createRng(seed)\n const shared = createNoiseStore(engineRandom)\n const busSettings = new Map<BusId, BusSetting>()\n const busNodes = new Map<BusId, GainNode>()\n const meters = new Map<BusId, { readonly analyser: AnalyserNode; readonly data: Float32Array<ArrayBuffer> }>()\n const active = new Map<number, RealizedVoice>()\n const loops = new Set<{ rewire(): void; stop(): void; readonly created: boolean }>()\n const named = new Map<string, () => number>()\n let mix = resolveMix(options.mix ?? DEFAULT_MIX, options.profiles)\n let context: AudioContext | null = null\n let chain: MixChain | null = null\n let listener: Listener = DEFAULT_LISTENER\n let lastTime = 0\n let environment: SampleEnvironment = options.environment ?? 'outdoor'\n const sampleLimiters = new Map<BusId, AudioNode>()\n // recipes go straight to the bus (their traces match the team routines node for node); recorded files go through a limiter of their bus. It is a\n // waveshaper, not a compressor: a compressor of the browser looks 6 ms ahead, which C1 (≤ 20 ms from the event) cannot spare.\n const sampleOutput = (bus: BusId): AudioNode => {\n const setting = options.samples?.limiter\n if (setting === false || !context) return outputFor(bus)\n const existing = sampleLimiters.get(bus)\n if (existing) return existing\n const range = 4\n const input = context.createGain()\n input.gain.value = 1 / range\n const shaper = context.createWaveShaper()\n shaper.curve = limiterCurve(setting?.knee ?? 0.5, setting?.ceiling ?? 0.891, range)\n ensureBus(bus)\n input.connect(shaper)\n shaper.connect(outputFor(bus))\n sampleLimiters.set(bus, input)\n return input\n }\n const chokes = new Map<string, { readonly id: number; readonly voice: RealizedSampleVoice }[]>()\n // the voices of a choked sound still ringing (the limiter forgets the ones that ended)\n const choked = (id: string): { readonly id: number; readonly voice: RealizedSampleVoice }[] => {\n const list = (chokes.get(id) ?? []).filter((entry) => active.has(entry.id))\n chokes.set(id, list)\n return list\n }\n const watchers = new Set<(event: VoiceStartEvent) => void>()\n const announce = (event: VoiceStartEvent): void => {\n options.onVoiceStart?.(event)\n for (const watcher of watchers) watcher(event)\n }\n const sources: { readonly accepts: (url: string) => boolean; readonly loader: SampleLoader }[] = []\n const baseLoader = options.samples?.loader ?? fetchLoader(options.samples?.baseUrl)\n const sampleStore = createSampleStore((url) => (sources.find((source) => source.accepts(url))?.loader ?? baseLoader)(url))\n const memory: SampleMemory = new Map()\n const latencyOf = (audio: BaseAudioContext): number => {\n const live = audio as Partial<Pick<AudioContext, 'baseLatency' | 'outputLatency'>>\n return (live.baseLatency ?? 0) + (live.outputLatency ?? 0)\n }\n\n const outputFor = (bus: BusId): AudioNode => (busNodes.get(bus) ?? chain?.master) as AudioNode\n\n // a bus somebody asked the level of gets an analyser as soon as it has a node, so sounds started before the first reading are metered too\n const watched = new Set<BusId>()\n const meterOf = (bus: BusId): { readonly analyser: AnalyserNode; readonly data: Float32Array<ArrayBuffer> } | undefined => {\n const existing = meters.get(bus)\n if (existing) return existing\n const node = busNodes.get(bus)\n if (!context || !node || typeof context.createAnalyser !== 'function') return undefined\n const analyser = context.createAnalyser()\n analyser.fftSize = 1024\n node.connect(analyser)\n const made = { analyser, data: new Float32Array(analyser.fftSize) }\n meters.set(bus, made)\n return made\n }\n\n const ensureBus = (bus: BusId): void => {\n if (!context || !chain || busNodes.has(bus)) return\n const node = context.createGain()\n node.connect(chain.master)\n busNodes.set(bus, node)\n if (watched.has(bus)) meterOf(bus)\n }\n\n const ready = (): AudioContext | null => {\n if (context) return context\n const created = (options.createContext ?? globalContext)()\n if (!created) return null\n context = created\n chain = buildChain(created, mix, engineRandom)\n if (mix.noise.create === 'eager') noiseBuffer(shared, created, mix.noise.seconds)\n for (const [bus, setting] of Object.entries(mix.buses ?? {}) as [BusId, BusSetting][]) {\n busSettings.set(bus, { ...setting, ...busSettings.get(bus) })\n }\n for (const [bus, setting] of busSettings) {\n ensureBus(bus)\n ;(busNodes.get(bus) as GainNode).gain.value = busGain(setting)\n }\n lastTime = created.currentTime\n return created\n }\n\n const advance = (): void => {\n if (!context) return\n const elapsed = context.currentTime - lastTime\n lastTime = context.currentTime\n if (elapsed > 0) for (const id of voices.advance(elapsed)) active.delete(id)\n }\n\n const inputFor = (recipe: SoundRecipe, playOptions: PlayOptions, random: () => number): PlanInput => ({\n random,\n listener,\n noiseSeconds: mix.noise.seconds,\n ...(options.distance ? { distanceMode: options.distance } : {}),\n ...(playOptions.volume === undefined ? {} : { volume: playOptions.volume }),\n ...(playOptions.distance === undefined ? {} : { distance: playOptions.distance }),\n ...(playOptions.position ? { position: playOptions.position } : {}),\n ...(playOptions.params ? { params: playOptions.params } : {}),\n ...(options.occlusion && playOptions.position && recipe.falloff?.model !== 'none' ? { occlusion: options.occlusion(playOptions.position) } : {}),\n })\n\n const startQueue = options.deferredStart ? createStartQueue(options.deferredStart) : null\n\n const build = (plan: SoundPlan, store: NoiseStore, delay: number, requestedAt: number, fallbackOf?: string): RealizedVoice => {\n const audio = context as AudioContext\n const time = audio.currentTime + delay\n const realized = realize(plan, {\n context: audio,\n output: outputFor(plan.bus),\n ...(chain?.wet ? { wet: chain.wet } : {}),\n noise: () => noiseBuffer(store, audio, mix.noise.seconds),\n time,\n })\n const recipeBank = registry.bankOf(plan.id)\n announce({\n id: plan.id,\n kind: 'recipe',\n ...(fallbackOf ? { fallbackOf } : {}),\n ...(recipeBank ? { bank: recipeBank } : {}),\n requestedAt,\n startAt: time,\n outputLatency: latencyOf(audio),\n level: plan.level,\n distance: plan.distance,\n ...(plan.pan === undefined ? {} : { pan: plan.pan }),\n })\n return realized\n }\n\n // the voice a deferred sound is tracked by until it is built: `stop` cancels it or stops what was built\n const deferVoice = (plan: SoundPlan, store: NoiseStore, voiceId: number | undefined, delay: number, fallbackOf?: string): RealizedVoice => {\n const requestedAt = context?.currentTime ?? 0\n let built: RealizedVoice | null = null\n let cancelled = false\n const pending: RealizedVoice = {\n get sources() {\n return built?.sources ?? []\n },\n stop() {\n cancelled = true\n built?.stop()\n },\n }\n ;(startQueue as ReturnType<typeof createStartQueue>).push({\n run() {\n if (!cancelled && context) built = build(plan, store, delay, requestedAt, fallbackOf)\n },\n drop() {\n if (voiceId === undefined) return\n voices.release(voiceId)\n active.delete(voiceId)\n },\n })\n return pending\n }\n\n const start = (plan: SoundPlan, store: NoiseStore, voiceId: number | undefined, delay = 0, fallbackOf?: string, urgent = false): VoiceHandle | null => {\n const realized = startQueue && !urgent ? deferVoice(plan, store, voiceId, delay, fallbackOf) : build(plan, store, delay, context?.currentTime ?? 0, fallbackOf)\n if (voiceId === undefined) return null\n voices.setLength(voiceId, plan.length + delay)\n active.set(voiceId, realized)\n return {\n id: voiceId,\n kind: 'recipe',\n plan,\n stop() {\n realized.stop()\n voices.release(voiceId)\n active.delete(voiceId)\n },\n }\n }\n\n const admit = (recipe: Admission, gain: number, distance: number): number | null => {\n const decision = voices.request({ ...(recipe.group ? { group: recipe.group } : {}), priority: recipe.priority ?? busPriority(recipe.bus), gain, distance, length: 0 })\n if (!decision.accepted) return null\n for (const id of decision.evicted) {\n active.get(id)?.stop()\n active.delete(id)\n }\n return decision.id\n }\n\n // a set id (`SoundBank.sets`) plays one of its variants, never the last one, at a drawn rate; a recipe id plays itself at rate 1\n const picker = createSetPicker()\n const resolve = (id: string, random: () => number, chooser = picker): { readonly id: string; readonly rate: number } => {\n if (registry.sound(id)) return { id, rate: 1 }\n const set = registry.set(id)\n return set ? chooser.pick(set, random) : { id, rate: 1 }\n }\n\n const loadSounds = (sounds: readonly SampleSound[]): Promise<SampleLoadReport> => {\n const audio = ready()\n if (!audio) return Promise.resolve({ loaded: [], failed: sounds.flatMap(sampleUrls).map((url) => ({ url, error: 'no audio context' })) })\n return sampleStore.load([...new Set(sounds.flatMap(sampleUrls))], audio)\n }\n\n const sampleInput = (playOptions: PlayOptions, random: () => number, withMemory: boolean) => ({\n random,\n listener,\n environment: playOptions.environment ?? environment,\n ...(withMemory ? { memory } : {}),\n ...(options.distance ? { distanceMode: options.distance } : {}),\n ...(playOptions.volume === undefined ? {} : { volume: playOptions.volume }),\n ...(playOptions.intensity === undefined ? {} : { intensity: playOptions.intensity }),\n ...(playOptions.distance === undefined ? {} : { distance: playOptions.distance }),\n ...(playOptions.position ? { position: playOptions.position } : {}),\n ...(playOptions.occlusion !== undefined\n ? { occlusion: playOptions.occlusion }\n : options.occlusion && playOptions.position\n ? { occlusion: options.occlusion(playOptions.position) }\n : {}),\n })\n\n // undefined: the files are not ready and there is no fallback, so the recipe of the same id (if any) plays\n const playSample = (sample: SampleSound, playOptions: PlayOptions, random: () => number, store: NoiseStore): VoiceHandle | null | undefined => {\n if (busSettings.get(sample.bus)?.muted) return null\n if (!sampleStore.ready(sampleUrls(sample))) {\n if (options.samples?.autoLoad !== false && ready()) void loadSounds([sample]).catch(() => undefined)\n if (sample.fallback && sample.fallback !== sample.id) return playWith(sample.fallback, playOptions, random, store, sample.id)\n return registry.sound(sample.id) ? undefined : null\n }\n const plan = planSample(sample, sampleInput(playOptions, playOptions.seed === undefined ? random : createRng(playOptions.seed), true))\n if (!plan) return null\n const audio = ready()\n if (!audio) return null\n unlockContext(audio)\n advance()\n const voiceId = admit(plan, plan.level, plan.distance)\n if (voiceId === null) return null\n const requestedAt = audio.currentTime\n const time = requestedAt + (playOptions.delay ?? 0)\n const chokeList = sample.choke ? choked(sample.id) : undefined\n const realized = realizeSample(plan, { context: audio, output: sampleOutput(plan.bus), buffer: (url) => sampleStore.buffer(url), time })\n const sampleBank = registry.bankOf(plan.id)\n announce({\n id: plan.id,\n kind: 'sample',\n ...(sampleBank ? { bank: sampleBank } : {}),\n requestedAt,\n startAt: time,\n outputLatency: latencyOf(audio),\n level: plan.level,\n distance: plan.distance,\n ...(plan.pan === undefined ? {} : { pan: plan.pan }),\n layers: plan.layers.map((layer) => ({ role: layer.role, url: layer.url, take: layer.take, rate: layer.rate })),\n ...(plan.tier ? { tier: plan.tier } : {}),\n })\n voices.setLength(voiceId, sampleLength(plan, (url) => sampleStore.seconds(url)) + (playOptions.delay ?? 0))\n active.set(voiceId, realized)\n if (chokeList && sample.choke) {\n chokeList.push({ id: voiceId, voice: realized })\n while (chokeList.length > Math.max(1, sample.choke.voices)) {\n const oldest = chokeList.shift()\n if (!oldest) break\n oldest.voice.fade(time, sample.choke.fade ?? 0.03)\n voices.release(oldest.id)\n active.delete(oldest.id)\n }\n }\n return {\n id: voiceId,\n kind: 'sample',\n plan,\n stop() {\n realized.stop()\n voices.release(voiceId)\n active.delete(voiceId)\n },\n }\n }\n\n const playWith = (asked: string, playOptions: PlayOptions, streamRandom: () => number, store: NoiseStore, fallbackOf?: string): VoiceHandle | null => {\n const sample = fallbackOf === undefined ? registry.sample(asked) : undefined\n if (sample) {\n const played = playSample(sample, playOptions, streamRandom, store)\n if (played !== undefined) return played\n }\n const seeded = playOptions.seed === undefined ? null : createRng(playOptions.seed)\n const { id, rate } = resolve(asked, seeded ?? streamRandom)\n const random = seeded ?? streamRandom\n const recipe = registry.sound(id)\n if (!recipe || busSettings.get(recipe.bus)?.muted) return null\n const distance = playOptions.distance ?? (playOptions.position ? listenerDistance(listener, playOptions.position, options.distance) : 0)\n const level = falloffGain(recipe.falloff, playOptions.volume ?? 1, distance)\n const silent = isSilent(recipe.falloff, level)\n // a sound too quiet to play does not even start the context (the team routines return before touching it)\n if (silent && !recipe.keepSilent) return null\n const audio = ready()\n if (!audio) return null\n unlockContext(audio)\n advance()\n const voiceId = silent ? undefined : admit(recipe, level, distance)\n if (voiceId === null) return null\n if (!silent && usesNoise(recipe)) prepareNoise(store, audio, mix.noise.seconds)\n const plan = planSound(recipe, inputFor(recipe, playOptions, random))\n return plan ? start(retunePlan(plan, rate), store, voiceId, playOptions.delay, fallbackOf, playOptions.urgent) : null\n }\n\n const randomFor = (playOptions: PlayOptions): (() => number) => {\n if (playOptions.channel === undefined) return engineRandom\n const existing = named.get(playOptions.channel)\n if (existing) return existing\n const stream = streamFor(seed, playOptions.channel)\n named.set(playOptions.channel, stream)\n return stream\n }\n\n // pure: a set is drawn with a picker of its own, so planning never moves what `play` picks next\n const planWith = (asked: string, playOptions: PlayOptions, random: () => number): SoundPlan | null => {\n const { id, rate } = resolve(asked, random, createSetPicker())\n const recipe = registry.sound(id)\n const plan = recipe ? planSound(recipe, inputFor(recipe, playOptions, random)) : null\n return plan ? retunePlan(plan, rate) : null\n }\n\n const loopHost: LoopHost = {\n ready,\n output: outputFor,\n prepareNoise: () => context && prepareNoise(shared, context, mix.noise.seconds),\n noise: () => noiseBuffer(shared, context as AudioContext, mix.noise.seconds),\n register: (loop) => void loops.add(loop),\n unregister: (loop) => void loops.delete(loop),\n listener: () => listener,\n ...(options.distance ? { distance: options.distance } : {}),\n }\n\n return {\n registry,\n register: (bank) => registry.register(bank),\n plan: (id, playOptions = {}) => planWith(id, playOptions, createRng(playOptions.seed ?? seed)),\n planSample(id, playOptions = {}) {\n const sample = registry.sample(id)\n return sample ? planSample(sample, sampleInput(playOptions, createRng(playOptions.seed ?? seed), false)) : null\n },\n loadSamples(ids) {\n const chosen = (ids ?? registry.sampleIds()).map((id) => registry.sample(id)).filter((sample): sample is SampleSound => sample !== undefined)\n return loadSounds(chosen)\n },\n sampleStatus(id) {\n const sample = registry.sample(id)\n if (!sample) return 'none'\n const statuses = sampleUrls(sample).map((url) => sampleStore.status(url))\n if (statuses.every((status) => status === 'ready')) return 'ready'\n if (statuses.includes('failed')) return 'failed'\n if (statuses.includes('loading')) return 'loading'\n return statuses.includes('ready') ? 'loading' : 'none'\n },\n setEnvironment(next) {\n environment = next\n },\n output: () => chain?.master ?? null,\n addSampleSource(accepts, loader) {\n sources.push({ accepts, loader })\n },\n watchVoices(listener) {\n watchers.add(listener)\n return () => void watchers.delete(listener)\n },\n play: (id, playOptions = {}) => playWith(id, playOptions, randomFor(playOptions), shared),\n playPlan(plan, playOptions = {}) {\n const audio = ready()\n if (!audio) return null\n advance()\n const recipe = { id: plan.id, bus: plan.bus, layers: [], sources: [], priority: plan.priority, ...(plan.group ? { group: plan.group } : {}) }\n const voiceId = plan.silent ? undefined : admit(recipe, plan.level, plan.distance)\n if (voiceId === null) return null\n if (planUsesNoise(plan)) prepareNoise(shared, audio, mix.noise.seconds)\n return start(plan, shared, voiceId, playOptions.delay)\n },\n loop(id, loopOptions = {}) {\n const sample = registry.sample(id)\n if (!sample?.loop) return createLoopHandle(registry.loop(id), loopHost, loopOptions.volume)\n return createSampleLoopHandle(\n sample,\n {\n ready,\n output: sampleOutput,\n buffer: (url) => sampleStore.buffer(url),\n isReady: (sound) => sampleStore.ready(sampleUrls(sound)),\n load: (sound) => (options.samples?.autoLoad === false ? Promise.resolve() : loadSounds([sound])),\n fallback: (volume) => createLoopHandle(registry.loop(sample.fallback ?? sample.id) ?? registry.loop(sample.id), loopHost, volume),\n random: engineRandom,\n register: loopHost.register,\n unregister: loopHost.unregister,\n muted: (bus) => busSettings.get(bus)?.muted === true,\n listener: () => listener,\n ...(options.distance ? { distance: options.distance } : {}),\n },\n loopOptions.volume,\n )\n },\n channel(channelOptions) {\n const random = channelOptions.random ?? (channelOptions.seed === undefined ? engineRandom : createRng(channelOptions.seed))\n const store = channelOptions.ownNoise ? createNoiseStore(random) : shared\n return {\n random,\n play: (id, playOptions = {}) => playWith(id, playOptions, random, store),\n plan: (id, playOptions = {}) => planWith(id, playOptions, createRng(playOptions.seed ?? seed)),\n }\n },\n setListener(next) {\n listener = next\n },\n setBus(id, setting) {\n busSettings.set(id, { ...busSettings.get(id), ...setting })\n if (!context) return\n ensureBus(id)\n ;(busNodes.get(id) as GainNode).gain.value = busGain(busSettings.get(id))\n },\n setMix(next) {\n const previous = mix\n mix = resolveMix(next, options.profiles)\n if (!context || !chain) return\n const old = chain\n chain = buildChain(context, mix, engineRandom)\n if (mix.noise.seconds !== previous.noise.seconds) shared.reset()\n for (const node of busNodes.values()) {\n node.disconnect()\n node.connect(chain.master)\n }\n for (const loop of loops) loop.rewire()\n old.disconnect()\n },\n setMaster(gain) {\n mix = { ...mix, master: gain }\n if (chain) chain.master.gain.value = gain\n },\n unlock() {\n const audio = ready()\n if (audio) unlockContext(audio)\n },\n warmUp() {\n const audio = ready()\n if (!audio) return false\n noiseBuffer(shared, audio, mix.noise.seconds)\n return true\n },\n level(bus) {\n watched.add(bus)\n ensureBus(bus)\n const meter = meterOf(bus)\n if (!meter) return 0\n meter.analyser.getFloatTimeDomainData(meter.data)\n let sum = 0\n for (const sample of meter.data) sum += sample * sample\n return Math.sqrt(sum / meter.data.length)\n },\n deferredQueue: () => startQueue?.deferredQueue() ?? null,\n stats() {\n advance()\n const voiceStats = voices.stats()\n return {\n context: context ? context.state : 'none',\n voices: voiceStats.active,\n peak: voiceStats.peak,\n dropped: voiceStats.dropped,\n maxVoices: voiceStats.maxVoices,\n loops: [...loops].filter((loop) => loop.created).length,\n }\n },\n dispose() {\n // closing the context ends every voice; they only leave the limiter\n startQueue?.clear()\n for (const id of active.keys()) voices.release(id)\n for (const loop of [...loops]) loop.stop()\n active.clear()\n void context?.close()\n context = null\n chain = null\n busNodes.clear()\n meters.clear()\n shared.reset()\n sampleStore.clear()\n memory.clear()\n sampleLimiters.clear()\n chokes.clear()\n },\n }\n}\n","export type AudioBenchText = {\n readonly group: string\n readonly name: string\n readonly probe: string\n readonly controls: Readonly<Record<'sound' | 'distance' | 'bearing' | 'volume' | 'mix' | 'seed' | 'play' | 'voice_storm' | 'loop' | 'loop_level' | 'loop_pitch' | 'source', string>>\n readonly hints: Readonly<Record<'distance' | 'bearing' | 'mix' | 'seed' | 'voice_storm' | 'loop_pitch' | 'source', string>>\n readonly options: Readonly<Record<'none' | 'bench' | 'probe', string>>\n readonly layers: Readonly<Record<'reverb' | 'compressor' | 'panning' | 'muffling', string>>\n readonly metrics: Readonly<Record<'voices' | 'peak' | 'dropped' | 'loops' | 'context' | 'plan_length' | 'plan_level' | 'plan_pan' | 'level_weapons' | 'level_voices' | 'level_world' | 'level_ambience' | 'level_weather' | 'level_ui', string>>\n readonly scenarios: Readonly<Record<'panning' | 'distance' | 'determinism' | 'limiter', string>>\n readonly mixes: Readonly<Record<string, string>>\n /** Text of a sound or loop id when the game has one; the bench falls back to the id. */\n readonly sheet: Readonly<Record<'title' | 'level' | 'distance' | 'pan' | 'length' | 'silent' | 'layer' | 'none', string>>\n}\n\nconst EN: AudioBenchText = {\n group: 'Sound',\n name: 'Sound area',\n probe: 'Sound probe',\n controls: {\n sound: 'Sound',\n distance: 'Distance',\n bearing: 'Bearing',\n volume: 'Volume',\n mix: 'Mixing chain',\n seed: 'Seed',\n play: 'Play',\n voice_storm: 'Voice storm',\n loop: 'Loop',\n loop_level: 'Loop level',\n loop_pitch: 'Loop pitch',\n source: 'Source',\n },\n hints: {\n distance: 'Metres from the listener: the level falls and the sound is muffled with it.',\n bearing: 'Degrees from straight ahead, positive to the right: shows the panning.',\n mix: 'The game chain (master only) or the art scene chain (compressor and reverb).',\n seed: 'The same seed gives the same sound.',\n voice_storm: 'Twenty of the chosen sound at once: the voice limiter drops what its group and the global cap refuse.',\n loop_pitch: 'Frequency of an oscillator loop, in hertz (0 leaves it where it is).',\n source: 'Where the sound comes from: the distance and bearing set here, or the probe standing in the area.',\n },\n options: { none: 'None', bench: 'Bench settings', probe: 'The probe' },\n layers: { reverb: 'Reverb', compressor: 'Compressor', panning: 'Panning', muffling: 'Muffling by distance' },\n metrics: {\n voices: 'Voices playing',\n peak: 'Most voices at once',\n dropped: 'Voices dropped',\n loops: 'Loops running',\n context: 'Audio context',\n plan_length: 'Chosen sound: length',\n plan_level: 'Chosen sound: level',\n plan_pan: 'Chosen sound: pan',\n level_weapons: 'Level: weapons',\n level_voices: 'Level: voices',\n level_world: 'Level: world',\n level_ambience: 'Level: ambience',\n level_weather: 'Level: weather',\n level_ui: 'Level: interface',\n },\n scenarios: {\n panning: 'A sound to the right is heard on the right, one to the left on the left, one ahead in the middle',\n distance: 'The farther a sound, the quieter, until it is not played',\n determinism: 'The same seed gives the same sound plan, another seed another one',\n limiter: 'The voice limiter holds a storm of voices to its group rule and its global cap',\n },\n mixes: { game: 'Game', art_scene: 'Art scene', kit: 'Kit (art scene + limiter)' },\n sheet: { title: 'Sound plan', level: 'level', distance: 'distance', pan: 'pan', length: 'seconds', silent: 'too far to be heard', layer: 'layer', none: 'no sound chosen' },\n}\n\nconst PT_BR: AudioBenchText = {\n group: 'Som',\n name: 'Área de som',\n probe: 'Sonda de som',\n controls: {\n sound: 'Som',\n distance: 'Distância',\n bearing: 'Direção',\n volume: 'Volume',\n mix: 'Cadeia de mixagem',\n seed: 'Semente',\n play: 'Tocar',\n voice_storm: 'Tempestade de vozes',\n loop: 'Laço',\n loop_level: 'Nível do laço',\n loop_pitch: 'Altura do laço',\n source: 'Origem',\n },\n hints: {\n distance: 'Metros até o ouvinte: o nível cai e o som abafa junto.',\n bearing: 'Graus a partir da frente, positivo para a direita: mostra o pan.',\n mix: 'A cadeia do jogo (só o master) ou a da Cena de Arte (compressor e reverb).',\n seed: 'A mesma semente dá o mesmo som.',\n voice_storm: 'Vinte do som escolhido de uma vez: o limite de vozes derruba o que a regra do grupo e o teto global recusam.',\n loop_pitch: 'Frequência de um laço de oscilador, em hertz (0 deixa onde está).',\n source: 'De onde vem o som: a distância e a direção daqui, ou a sonda que está na área.',\n },\n options: { none: 'Nenhum', bench: 'Ajustes da bancada', probe: 'A sonda' },\n layers: { reverb: 'Reverb', compressor: 'Compressor', panning: 'Pan', muffling: 'Abafamento pela distância' },\n metrics: {\n voices: 'Vozes tocando',\n peak: 'Mais vozes de uma vez',\n dropped: 'Vozes derrubadas',\n loops: 'Laços ligados',\n context: 'Contexto de áudio',\n plan_length: 'Som escolhido: duração',\n plan_level: 'Som escolhido: nível',\n plan_pan: 'Som escolhido: pan',\n level_weapons: 'Nível: armas',\n level_voices: 'Nível: vozes',\n level_world: 'Nível: mundo',\n level_ambience: 'Nível: ambiente',\n level_weather: 'Nível: clima',\n level_ui: 'Nível: interface',\n },\n scenarios: {\n panning: 'Um som à direita sai à direita, à esquerda sai à esquerda, à frente sai no meio',\n distance: 'Quanto mais longe, mais baixo, até não tocar',\n determinism: 'A mesma semente dá o mesmo plano de som, outra semente dá outro',\n limiter: 'O limite de vozes segura uma tempestade de vozes na regra do grupo e no teto global',\n },\n mixes: { game: 'Jogo', art_scene: 'Cena de Arte', kit: 'Kit (Cena de Arte + limitador)' },\n sheet: { title: 'Plano do som', level: 'nível', distance: 'distância', pan: 'pan', length: 'segundos', silent: 'longe demais para ouvir', layer: 'camada', none: 'nenhum som escolhido' },\n}\n\nexport const audioBenchTextOf = (locale: string): AudioBenchText => (locale === 'en' ? EN : PT_BR)\n","import type { AreaPlacement, BenchChange, ChoiceOption, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\n\nimport { GAME_SFX_BANK } from '../recipes/noise-class'\nimport { LIBRARY_BANK } from '../library'\nimport { DISTANCE_CURVES } from '../falloff'\nimport { DEFAULT_MIX, MIX_PROFILES } from '../mix'\nimport type { MixProfile } from '../mix'\nimport { BUS_IDS } from '../recipe'\nimport type { BusId, Layer, SoundBank } from '../recipe'\nimport type { SoundPlan } from '../plan'\nimport { createVoiceManager } from '../voices'\nimport { createAudioEngine } from '../webaudio/engine'\nimport type { AudioEngine, VoiceHandle } from '../webaudio/engine'\nimport type { EngineSink } from '../webaudio/sink'\nimport type { AudioLoopHandle } from '../webaudio/engine-loop'\nimport { audioBenchTextOf } from './locale'\nimport type { AudioBenchText } from './locale'\n\n/**\n * Two probe sounds of the bench itself (a ping and a hiss), so panning, distance and the seed can be heard on something that has no subject. They are\n * made by the kit, not delivered by any team (`sdk` in the sources).\n */\nexport const BENCH_BANK: SoundBank = {\n id: 'audio_bench',\n sounds: [\n {\n id: 'bench_ping',\n bus: 'ui',\n pan: true,\n duration: 0.25,\n layers: [\n {\n gain: 0.5,\n wet: 0.3,\n source: { kind: 'osc', wave: 'sine', frequency: { from: 880 } },\n envelope: [\n [0, 0.0001, 'set', 'fixed'],\n [0.002, 1, 'exp'],\n ['1d', 0.0001, 'exp', 'fixed'],\n ],\n } satisfies Layer,\n ],\n falloff: DISTANCE_CURVES.art_scene,\n sources: ['sdk: bench probe, a 880 Hz ping through the art scene output stage'],\n },\n {\n id: 'bench_hiss',\n bus: 'ui',\n pan: true,\n duration: [0.3, 0.9],\n layers: [\n {\n gain: 0.4,\n source: { kind: 'noise', offset: 'random', offsetScale: 1.5, loop: true },\n filters: { mode: 'serial', bank: [{ type: 'highpass', frequency: { set: 3000 }, q: 0.7 }] },\n envelope: [\n [0, 0.0001, 'set', 'fixed'],\n [0.002, 1, 'exp'],\n ['1d', 0.0001, 'exp', 'fixed'],\n ],\n } satisfies Layer,\n ],\n falloff: DISTANCE_CURVES.art_scene,\n sources: ['sdk: bench probe, a highpass hiss of random length'],\n },\n ],\n}\n\nexport type AudioTestModuleOptions = {\n /** The engine to test (default: the one the host lends in `host.audio`, else a new one of the module's own). */\n engine?: AudioEngine\n /** Banks registered in the engine besides the bench's probes (default the game's noise classes and the library). */\n banks?: readonly SoundBank[]\n locale?: string\n /** Text of a sound or loop id (`sound.glass`) in the game's words; without it the bench shows the bank and the id. */\n translate?: (key: string, locale: string) => string | undefined\n seed?: number\n /** First sound chosen (default `bench_ping`). */\n sound?: string\n /**\n * Draws the thing the probe stands for, where the sound comes from with the `probe` source (for example a portable radio of `game-items-three`). The module\n * draws nothing of its own: without it the area has no probe and the sounds come from the bench settings.\n */\n probe?: (THREE: unknown) => unknown\n}\n\n/** What the scenarios use of the context the test room passes. */\nexport interface AudioScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type AudioTestModule = TestableModule<AudioScenarioLike> & {\n /** The engine in use: the host's when it lent one, the module's own otherwise. */\n readonly engine: AudioEngine\n /** The resolved plan of the chosen sound as text (the S3 view: every number decided). */\n sheet(): string\n /** Plays the chosen sound as the bench is set. */\n play(): VoiceHandle | null\n}\n\nconst DISTANCES = [0, 10, 40, 60, 120, 160] as const\nconst STORM = 20\nconst PROBE_ID = 'audio_probe'\nconst PROBE_AT: Vec3 = [0, 0, -10]\nconst NONE = 'none'\nconst DEFAULT_SOUND = 'bench_ping'\n\ntype Camera = { readonly position: { readonly x: number; readonly y: number; readonly z: number }; getWorldDirection(target: unknown): { readonly x: number; readonly z: number } }\ntype ThreeLike = { Vector3: new () => unknown }\ntype ProbeObject = { userData?: Record<string, unknown>; getWorldPosition(target: unknown): { readonly x: number; readonly y: number; readonly z: number }; traverse(visit: (object: ProbeObject) => void): void }\n\nconst variantOf = (profile: MixProfile, reverb: boolean, compressor: boolean): MixProfile => {\n const { reverb: wet, compressor: chain, ...rest } = profile\n return { ...rest, id: `${profile.id}${reverb ? '' : '+dry'}${compressor ? '' : '+open'}`, ...(wet && reverb ? { reverb: wet } : {}), ...(chain && compressor ? { compressor: chain } : {}) }\n}\n\n/**\n * The sound area of a test room, written against the generic contracts only: it plays any sound of an engine at a distance and bearing from the listener\n * (or from a probe standing in the area), runs loops, throws a storm of voices at the limiter, switches the mixing chain and its parts, reads the\n * level of each bus and prints the resolved plan. The engine is the host's (`host.audio`) when lent, else the module's own.\n */\nexport function createAudioTestModule(options: AudioTestModuleOptions = {}): AudioTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text: AudioBenchText = audioBenchTextOf(locale)\n const banks = [BENCH_BANK, ...(options.banks ?? [GAME_SFX_BANK, LIBRARY_BANK])]\n let engine: AudioEngine = options.engine ?? createAudioEngine({ seed: options.seed ?? 1, banks })\n for (const bank of banks) engine.register(bank)\n let host: ModuleHost | null = null\n let loop: AudioLoopHandle | undefined\n const state = {\n sound: options.sound ?? DEFAULT_SOUND,\n distance: 10,\n bearing: 0,\n volume: 1,\n mix: DEFAULT_MIX,\n seed: options.seed ?? 1,\n source: 'bench',\n loop: NONE,\n loopLevel: 0.1,\n loopPitch: 0,\n reverb: true,\n compressor: true,\n panning: true,\n muffling: true,\n }\n\n const nameOf = (id: string): string => {\n const translated = options.translate?.(`sound.${id}`, locale)\n if (translated) return translated\n const bank = engine.registry.bankOf(id)\n return bank ? `${bank} / ${id}` : id\n }\n const soundOptions = (): ChoiceOption[] => engine.registry.soundIds().map((id) => ({ id, name: nameOf(id) }))\n const loopOptions = (): ChoiceOption[] => [{ id: NONE, name: text.options.none }, ...engine.registry.loopIds().map((id) => ({ id, name: nameOf(id) }))]\n\n // the listener is the host camera; without a host (a test) it stands at the origin looking along -z\n const listener = (): { position: Vec3; yaw: number } => {\n const camera = host?.camera as Camera | undefined\n const three = host?.THREE as ThreeLike | undefined\n if (typeof camera?.getWorldDirection !== 'function' || typeof three?.Vector3 !== 'function' || !camera.position) return { position: [0, 0, 0], yaw: 0 }\n const direction = camera.getWorldDirection(new three.Vector3())\n return { position: [camera.position.x, camera.position.y, camera.position.z], yaw: Math.atan2(-direction.x, -direction.z) }\n }\n\n const probePosition = (): Vec3 | undefined => {\n const scene = host?.scene as ProbeObject | undefined\n const three = host?.THREE as ThreeLike | undefined\n if (typeof scene?.traverse !== 'function' || typeof three?.Vector3 !== 'function') return undefined\n let found: Vec3 | undefined\n scene.traverse((object) => {\n if (found || object.userData?.[PROBE_ID] !== true) return\n const at = object.getWorldPosition(new three.Vector3())\n found = [at.x, at.y, at.z]\n })\n return found\n }\n\n // `bearing` is degrees to the right of straight ahead\n const sourceAt = (ears: { position: Vec3; yaw: number }): Vec3 => {\n const probe = state.source === 'probe' ? probePosition() : undefined\n if (probe) return probe\n const bearing = (state.bearing * Math.PI) / 180\n const forward = [-Math.sin(ears.yaw), -Math.cos(ears.yaw)] as const\n const right = [Math.cos(ears.yaw), -Math.sin(ears.yaw)] as const\n return [ears.position[0] + state.distance * (forward[0] * Math.cos(bearing) + right[0] * Math.sin(bearing)), ears.position[1], ears.position[2] + state.distance * (forward[1] * Math.cos(bearing) + right[1] * Math.sin(bearing))]\n }\n\n const playOptions = (): { position?: Vec3; distance?: number; volume: number; seed: number } => {\n const ears = listener()\n engine.setListener(ears)\n const at = sourceAt(ears)\n const distance = Math.hypot(at[0] - ears.position[0], at[2] - ears.position[2])\n return { ...(state.panning ? { position: at } : { distance }), volume: state.volume, seed: state.seed }\n }\n\n // no muffling: the recipe's cutoff divisor is switched off for the one call\n const withMuffling = <T>(id: string, run: () => T): T => {\n const falloff = engine.registry.sound(id)?.falloff\n if (state.muffling || !falloff || falloff.model !== 'inverse_square' || falloff.cutoffK === undefined) return run()\n engine.registry.patch(id, { falloff: { cutoffK: 0 } })\n try {\n return run()\n } finally {\n engine.registry.patch(id, { falloff: { cutoffK: falloff.cutoffK } })\n }\n }\n\n const play = (): VoiceHandle | null => {\n engine.unlock()\n const chosen = state.sound\n return withMuffling(chosen, () => engine.play(chosen, playOptions()))\n }\n\n const plan = (): SoundPlan | null => {\n const chosen = state.sound\n return withMuffling(chosen, () => engine.plan(chosen, playOptions()))\n }\n\n const sheet = (): string => {\n const planned = plan()\n if (!planned) return `${text.sheet.title}: ${engine.registry.sound(state.sound) ? text.sheet.silent : text.sheet.none}`\n const head = `${text.sheet.title}: ${planned.id} (${planned.bus}) ${text.sheet.level} ${planned.level.toFixed(4)} ${text.sheet.distance} ${planned.distance.toFixed(1)} m` + `${planned.pan === undefined ? '' : ` ${text.sheet.pan} ${planned.pan.toFixed(3)}`} ${planned.length.toFixed(3)} ${text.sheet.length}`\n const layers = planned.layers.map((layer, index) => {\n const source = layer.source.kind === 'noise' ? `noise@${layer.source.offset.toFixed(4)}` : layer.source.kind === 'osc' ? `${layer.source.wave}@${layer.source.frequency.value ?? layer.source.frequency.from}` : layer.source.kind\n const filters = (layer.filters?.bank ?? []).map((filter) => `${filter.type}@${(filter.frequency.value ?? filter.frequency.from ?? 0).toFixed(1)}`).join(' ')\n const envelope = layer.envelope.map((point) => `${point.time.toFixed(3)}:${point.value.toPrecision(3)}`).join(' ')\n return ` ${text.sheet.layer} ${index + 1}: ${source} at ${layer.at.toFixed(3)} for ${layer.duration.toFixed(3)} ${filters} [${envelope}]`\n })\n return [head, ...layers].join('\\n')\n }\n\n const applyMix = (): void => {\n const profile = engine && MIX_PROFILES[state.mix]\n if (profile) engine.setMix(variantOf(profile, state.reverb, state.compressor))\n }\n\n const setLoop = (): void => {\n loop?.stop()\n loop = undefined\n if (state.loop === NONE) return\n engine.unlock()\n loop = engine.loop(state.loop)\n loop.set({ volume: state.loopLevel, ...(state.loopPitch > 0 ? { frequency: state.loopPitch } : {}) })\n }\n\n const storm = (): void => {\n engine.unlock()\n const base = playOptions()\n const chosen = state.sound\n for (let index = 0; index < STORM; index++) {\n const spread = base.position ? { position: [base.position[0] + (index - STORM / 2), base.position[1], base.position[2]] as Vec3 } : {}\n withMuffling(chosen, () => engine.play(chosen, { ...base, ...spread, seed: state.seed + index }))\n }\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') {\n if (change.id === 'reverb' || change.id === 'compressor') {\n state[change.id] = change.on\n applyMix()\n } else if (change.id === 'panning' || change.id === 'muffling') state[change.id] = change.on\n return\n }\n if (change.kind === 'action') {\n if (change.id === 'play') play()\n else if (change.id === 'voice_storm') storm()\n return\n }\n const { id, value } = change\n if (id === 'sound' && typeof value === 'string') state.sound = value\n else if (id === 'distance' && typeof value === 'string') state.distance = Number(value)\n else if (id === 'bearing' && typeof value === 'number') state.bearing = value\n else if (id === 'volume' && typeof value === 'number') state.volume = value\n else if (id === 'seed' && typeof value === 'number') state.seed = value\n else if (id === 'source' && typeof value === 'string') state.source = value\n else if (id === 'mix' && typeof value === 'string') {\n state.mix = value\n applyMix()\n } else if (id === 'loop' && typeof value === 'string') {\n state.loop = value\n setLoop()\n } else if (id === 'loop_level' && typeof value === 'number') {\n state.loopLevel = value\n loop?.set({ volume: value })\n } else if (id === 'loop_pitch' && typeof value === 'number') {\n state.loopPitch = value\n if (value > 0) loop?.set({ frequency: value })\n }\n }\n\n const items = (): TestableItem[] => {\n const probe = options.probe\n if (!probe) return []\n return [\n {\n id: PROBE_ID,\n name: text.probe,\n movable: false,\n build: (THREE) => {\n const root = probe(THREE) as { userData?: Record<string, unknown> }\n root.userData = root.userData ?? {}\n root.userData[PROBE_ID] = true\n return root\n },\n },\n ]\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'choice', id: 'sound', name: text.controls.sound, options: soundOptions(), default: state.sound },\n { kind: 'choice', id: 'source', name: text.controls.source, hint: text.hints.source, options: [{ id: 'bench', name: text.options.bench }, { id: 'probe', name: text.options.probe }], default: state.source },\n { kind: 'choice', id: 'distance', name: text.controls.distance, hint: text.hints.distance, options: DISTANCES.map((meters) => ({ id: String(meters), name: `${meters} m` })), default: String(state.distance) },\n { kind: 'number', id: 'bearing', name: text.controls.bearing, hint: text.hints.bearing, unit: '°', min: -180, max: 180, step: 15, default: state.bearing },\n { kind: 'number', id: 'volume', name: text.controls.volume, min: 0, max: 1, step: 0.05, default: state.volume },\n { kind: 'choice', id: 'mix', name: text.controls.mix, hint: text.hints.mix, options: Object.keys(MIX_PROFILES).map((id) => ({ id, name: text.mixes[id] ?? id })), default: state.mix },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: state.seed },\n { kind: 'action', id: 'play', name: text.controls.play },\n { kind: 'action', id: 'voice_storm', name: text.controls.voice_storm, hint: text.hints.voice_storm },\n { kind: 'choice', id: 'loop', name: text.controls.loop, options: loopOptions(), default: state.loop },\n { kind: 'number', id: 'loop_level', name: text.controls.loop_level, min: 0, max: 0.6, step: 0.01, default: state.loopLevel },\n { kind: 'number', id: 'loop_pitch', name: text.controls.loop_pitch, hint: text.hints.loop_pitch, unit: 'Hz', min: 0, max: 400, step: 5, default: state.loopPitch },\n ]\n\n const layers = (): ModuleLayer[] => (['reverb', 'compressor', 'panning', 'muffling'] as const).map((id) => ({ id, name: text.layers[id] }))\n\n const metrics = (): ModuleMetric[] => [\n { id: 'voices', name: text.metrics.voices, digits: 0, read: () => engine.stats().voices },\n { id: 'peak', name: text.metrics.peak, digits: 0, max: engine.stats().maxVoices > 0 && Number.isFinite(engine.stats().maxVoices) ? engine.stats().maxVoices : undefined, read: () => engine.stats().peak },\n { id: 'dropped', name: text.metrics.dropped, digits: 0, read: () => engine.stats().dropped },\n { id: 'loops', name: text.metrics.loops, digits: 0, read: () => engine.stats().loops },\n { id: 'context', name: text.metrics.context, read: () => engine.stats().context },\n { id: 'plan_length', name: text.metrics.plan_length, unit: 's', digits: 2, read: () => plan()?.length ?? 0 },\n { id: 'plan_level', name: text.metrics.plan_level, digits: 3, read: () => plan()?.level ?? 0 },\n { id: 'plan_pan', name: text.metrics.plan_pan, digits: 2, read: () => plan()?.pan ?? 0 },\n ...BUS_IDS.map((bus) => ({ id: `level_${bus}`, name: text.metrics[`level_${bus}` as keyof AudioBenchText['metrics']], digits: 3, read: () => engine.level(bus as BusId) })),\n ]\n\n const scenarios = (): Array<ModuleScenario<AudioScenarioLike>> => [\n {\n id: 'panning',\n name: text.scenarios.panning,\n run: ({ expect }) => {\n engine.setListener({ position: [0, 0, 0], yaw: 0 })\n const pan = (at: Vec3): number => engine.plan('bench_ping', { position: at })?.pan ?? Number.NaN\n expect(pan([10, 0, 0]) > 0.3, 'a sound to the right pans right', { pan: pan([10, 0, 0]) })\n expect(pan([-10, 0, 0]) < -0.3, 'a sound to the left pans left', { pan: pan([-10, 0, 0]) })\n expect(Math.abs(pan([0, 0, -10])) < 0.05, 'a sound ahead stays in the middle', { pan: pan([0, 0, -10]) })\n engine.setListener({ position: [0, 0, 0], yaw: Math.PI / 2 })\n expect(pan([0, 0, -10]) > 0.3, 'turning the listener left puts what was ahead on the right', { pan: pan([0, 0, -10]) })\n engine.setListener(listener())\n },\n },\n {\n id: 'distance',\n name: text.scenarios.distance,\n run: ({ expect }) => {\n const levels = [0, 10, 40, 100].map((meters) => engine.plan('bench_ping', { distance: meters })?.level ?? Number.NaN)\n expect(levels.every((level, index) => index === 0 || level < (levels[index - 1] as number)), 'the level falls with the distance', { levels })\n const far = engine.registry.sound('sfx_pistol') ? engine.plan('sfx_pistol', { distance: 400 }) : null\n expect(far === null, 'a game noise class is not played too far to be heard')\n },\n },\n {\n id: 'determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const a = engine.plan('bench_hiss', { seed: 5 })\n const b = engine.plan('bench_hiss', { seed: 5 })\n const c = engine.plan('bench_hiss', { seed: 6 })\n expect(JSON.stringify(a) === JSON.stringify(b), 'the same seed gives the same plan')\n expect(JSON.stringify(a) !== JSON.stringify(c), 'another seed gives another plan')\n },\n },\n {\n id: 'limiter',\n name: text.scenarios.limiter,\n run: ({ expect }) => {\n const voices = createVoiceManager({ maxVoices: 8 })\n const request = (group?: string) => voices.request({ ...(group ? { group } : {}), priority: 3, gain: 0.5, distance: 5, length: 1 })\n const grouped = Array.from({ length: STORM }, () => request('undead_voice')).filter((decision) => decision.accepted).length\n expect(grouped === 1, 'the group cooldown lets one voice of a storm through', { accepted: grouped })\n const plain = Array.from({ length: STORM }, () => request()).filter((decision) => decision.accepted).length\n expect(plain <= 8, 'the global cap holds the rest', { accepted: plain })\n },\n },\n ]\n\n const area = (): { placements: AreaPlacement[]; view: { eye: Vec3; target: Vec3 } } => ({\n placements: options.probe ? [{ item: PROBE_ID, position: PROBE_AT, asleep: true }] : [],\n view: { eye: [0, 1.7, 3], target: [0, 1.4, -10] },\n })\n\n const module: AudioTestModule = {\n id: 'audio_area',\n name: text.name,\n ground: { surface: 'concrete_slab' },\n group: text.group,\n get engine() {\n return engine\n },\n items: () => items(),\n area: () => area(),\n controls: () => controls(),\n layers: () => layers(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n sheet,\n play,\n attach(lent) {\n host = lent\n const shared = (lent.audio as EngineSink | undefined)?.engine\n if (shared && shared !== engine) {\n for (const bank of banks) shared.register(bank)\n engine = shared\n }\n // buses get their nodes now, so the level meters see every sound\n for (const bus of BUS_IDS) {\n engine.setBus(bus, {})\n engine.level(bus)\n }\n lent.bench?.patch('sound', { options: soundOptions() })\n lent.bench?.patch('loop', { options: loopOptions() })\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(() => {\n if (!shared) engine.setListener(listener())\n })\n return () => {\n off?.()\n offFrame()\n loop?.stop()\n loop = undefined\n host = null\n }\n },\n }\n return module\n}\n","/**\n * The sounds a game needs, by category, as the sound checklist lists them (generic, real-world names: a 9 mm pistol, a wooden door): the id a file\n * takes, its priority and the synthesized sound it replaces today (`current`, the A of an A/B). A sound is \"file\" once a bank registers a sample under\n * its id; \"synth\" while only `current` exists; \"missing\" when neither does. Data only: a game adds, renames or drops entries without touching the engine.\n */\n\nexport const SFX_CATEGORIES = ['armas', 'impactos', 'explosoes-fogo', 'personagem', 'veiculos', 'itens-portas', 'ambiente'] as const\nexport type SfxCategory = (typeof SFX_CATEGORIES)[number]\n\nexport type SfxPriority = 1 | 2 | 3\n\nexport type SfxEntry = {\n readonly id: string\n readonly category: SfxCategory\n readonly priority: SfxPriority\n /** The synthesized sound playing in its place today (a recipe id of some bank), if any. */\n readonly current?: string\n}\n\nconst entries = (category: SfxCategory, list: readonly (readonly [id: string, priority: SfxPriority, current?: string])[]): SfxEntry[] =>\n list.map(([id, priority, current]) => ({ id, category, priority, ...(current ? { current } : {}) }))\n\nexport const SFX_CATALOG: readonly SfxEntry[] = [\n ...entries('armas', [\n ['pistol_22lr', 2, 'sfx_pistol'],\n ['pistol_9mm', 1, 'sfx_pistol'],\n ['pistol_45', 1, 'sfx_pistol'],\n ['revolver_38_357', 2, 'sfx_pistol'],\n ['revolver_44_50ae', 3, 'sfx_pistol'],\n ['smg_9mm_auto', 1, 'sfx_pistol'],\n ['shotgun_12', 1, 'sfx_shotgun'],\n ['rifle_5_56', 1, 'sfx_rifle'],\n ['rifle_7_62x39', 1, 'sfx_rifle'],\n ['rifle_auto_burst', 1, 'sfx_rifle'],\n ['rifle_308_3006', 2, 'sfx_rifle'],\n ['sniper_338_300wm', 2, 'sfx_rifle'],\n ['antimateriel_50bmg', 3, 'sfx_rifle'],\n ['suppressed_pistol', 2],\n ['suppressed_rifle', 2],\n ['gunshot_far_pistol', 1],\n ['gunshot_far_rifle', 1],\n ['gunshot_far_shotgun', 1],\n ['gunshot_far_heavy', 2],\n ['gunshot_tail_indoor', 1],\n ['gunshot_tail_outdoor', 1],\n ['bullet_crack_by', 2],\n ['bullet_whiz', 2],\n ['ricochet_metal', 2, 'ping'],\n ['dry_fire', 1],\n ['mag_out', 1],\n ['mag_in', 1],\n ['slide_pull_release', 1],\n ['pump_cycle', 1],\n ['casing_drop_concreto_pistol', 1],\n ['casing_drop_concreto_rifle', 1],\n ['casing_drop_concreto_shell', 1],\n ['casing_drop_madeira_pistol', 1],\n ['casing_drop_madeira_rifle', 1],\n ['casing_drop_madeira_shell', 1],\n ['casing_drop_metal_pistol', 1],\n ['casing_drop_metal_rifle', 1],\n ['casing_drop_metal_shell', 1],\n ['casing_drop_terra_pistol', 1],\n ['casing_drop_terra_rifle', 1],\n ['casing_drop_terra_shell', 1],\n ['rocket_fire', 2],\n ['smg_45_auto', 2, 'sfx_pistol'],\n ['weapon_draw', 2],\n ['suppressor_attach', 3],\n ['suppressor_detach', 3],\n ['minigun_loop', 3],\n ['smg_5_7x28', 3],\n ['mg_belt_adjust', 3],\n ['mg_belt_box_attach', 3],\n ['mg_cover_open', 3],\n ['mg_cover_close', 3],\n ['weapon_holster', 3],\n ['scope_zoom', 3],\n ]),\n ...entries('impactos', [\n ['knife_hit_wall', 3],\n ['helmet_hit', 3],\n ['vest_hit', 3],\n ['headshot', 3],\n ['blood_squirt', 3],\n ]),\n ...entries('explosoes-fogo', [\n ['explosion_grenade', 1, 'boom'],\n ['explosion_big', 1, 'boom_big'],\n ['explosion_car', 2, 'boom_big'],\n ['explosion_far', 1],\n ['debris_rain_stone', 1],\n ['molotov_break_ignite', 1, 'glass_shatter'],\n ['fire_ignite', 1, 'hiss'],\n ['fire_loop_small', 1],\n ['fire_loop_large', 1],\n ['fire_extinguish', 2, 'hiss'],\n ['gas_leak_hiss', 2],\n ['structure_collapse', 2, 'crumble'],\n ['grenade_bounce', 1],\n ['c4_plant', 2],\n ['c4_beep', 2],\n ['c4_disarm', 2],\n ['c4_disarming_loop', 3],\n ['c4_remote_detonate', 3],\n ['smoke_grenade_hiss', 3],\n ['grenade_pin_pull', 3],\n ['electric_shock', 3],\n ['electric_spark', 3],\n ]),\n ...entries('personagem', [\n ['footstep_concrete_walk', 1, 'sfx_step'],\n ['footstep_wood_walk', 1, 'sfx_step'],\n ['footstep_dirt_walk', 1, 'sfx_step'],\n ['footstep_grass_walk', 1, 'sfx_step'],\n ['footstep_gravel_walk', 1, 'sfx_step'],\n ['land_concrete', 1, 'sfx_step'],\n ['punch_swing', 1],\n ['punch_hit_body', 1, 'sfx_flesh'],\n ['kick_hit', 1, 'sfx_flesh'],\n ['knife_stab', 1],\n ['blunt_hit', 1],\n ['bite', 1, 'sfx_flesh'],\n ['body_fall', 1],\n ['player_hurt', 2],\n ['footstep_tile_walk', 1, 'sfx_step'],\n ['footstep_water_walk', 1, 'sfx_step'],\n ['footstep_grate_walk', 2, 'sfx_step'],\n ['footstep_duct_walk', 3, 'sfx_step'],\n ['ladder_climb', 2],\n ['swim', 2],\n ['zombie_groan', 1],\n ['zombie_alert', 1],\n ['zombie_attack', 1],\n ['zombie_pain', 1],\n ['zombie_claw_hit', 1, 'sfx_flesh'],\n ['zombie_claw_miss', 2],\n ['swing_whoosh', 3],\n ['heartbeat_critical', 3],\n ['fall_water', 3],\n ['fall_damage', 3],\n ['fall_scream', 3],\n ['footstep_glass_walk', 3],\n ]),\n ...entries('veiculos', [\n ['engine_loop_car', 1],\n ['engine_start', 1],\n ['crash_light', 1, 'crash'],\n ['crash_heavy', 1, 'crash'],\n ['car_door_open', 1, 'latch'],\n ['car_door_close', 1, 'shut_metal'],\n ['horn_car', 2, 'horn'],\n ['tire_skid_asphalt', 2],\n ['jet_flyby', 3],\n ['helicopter_turbine', 3],\n ['tire_burnout', 3],\n ['handbrake_turn', 3],\n ['siren_police', 3],\n ]),\n ...entries('itens-portas', [\n ['item_pickup_metal', 1],\n ['can_open', 1],\n ['can_crush', 1],\n ['door_wood_open', 1, 'latch'],\n ['door_wood_close', 1, 'shut_wood'],\n ['door_creak', 1, 'creak_wood'],\n ['door_locked_rattle', 1, 'rattle'],\n ['drawer_open', 2, 'slide'],\n ['fridge_close', 2, 'shut_metal'],\n ['inventory_open', 3],\n ['inventory_close', 3],\n ['inventory_select', 3],\n ['inventory_place', 3],\n ['pickup_chime', 3],\n ['item_pickup_coins', 3],\n ['bandage_use', 3],\n ['bandage_refuse', 3],\n ['flashlight_toggle', 3],\n ['gear_draw', 3],\n ['gear_holster', 3],\n ['button_press', 3],\n ['lock_desk_open', 3],\n ['elevator_move_loop', 3],\n ['elevator_stop', 3],\n ['door_sliding', 3],\n ['door_kick', 3],\n ['door_wood_break', 3],\n ['gate_iron_open', 3],\n ['gate_iron_close', 3],\n ]),\n ...entries('ambiente', [\n ['rain_loop', 2],\n ['wind_loop', 2],\n ['thunder_near', 2],\n ['thunder_far', 2],\n ['water_splash', 2],\n ['helicopter_loop', 3],\n ['bird_flush', 3],\n ['dog_growl', 3],\n ['dog_whimper', 3],\n ['dog_howl', 3],\n ['zombie_dog_bark', 3],\n ['zombie_dog_howl_far', 3],\n ['insect_squash', 3],\n ['insect_crawl', 3],\n ['fan_loop', 3],\n ]),\n]\n\n/** The materials of the impact matrix, with the group whose synthesized sound plays for them today. */\nexport const SFX_MATERIALS = [\n ['steel', 'metal'],\n ['aluminium', 'metal'],\n ['wood', 'wood'],\n ['plywood', 'wood'],\n ['mdf', 'wood'],\n ['glass', 'glass'],\n ['tempered_glass', 'glass'],\n ['ceramic', 'glass'],\n ['concrete', 'masonry'],\n ['brick', 'masonry'],\n ['plaster', 'masonry'],\n ['plastic', 'soft'],\n ['fabric', 'soft'],\n ['paper', 'soft'],\n ['foliage', 'soft'],\n ['soil', 'soft'],\n ['flesh', 'soft'],\n] as const satisfies readonly (readonly [string, string])[]\nexport type SfxMaterial = (typeof SFX_MATERIALS)[number][0]\n\nexport const SFX_BLOWS = ['bullet', 'blunt', 'blade', 'break', 'drag'] as const\nexport type SfxBlow = (typeof SFX_BLOWS)[number]\n\n// the destruction renderer's synthesized sounds by material group (art scene keys), the A side of the matrix\nconst CURRENT_BY_GROUP: Readonly<Record<string, Readonly<Partial<Record<SfxBlow, string>>>>> = {\n metal: { bullet: 'clang', blunt: 'clang', blade: 'clang', break: 'clang', drag: 'drag_metal' },\n wood: { bullet: 'wood_hit', blunt: 'wood_hit', blade: 'wood_hit', break: 'crack', drag: 'drag_wood' },\n glass: { bullet: 'ping', blunt: 'ping', break: 'glass_shatter', drag: 'drag_glass' },\n masonry: { bullet: 'chip', blunt: 'chip', blade: 'chip', break: 'crumble', drag: 'drag_masonry' },\n soft: { bullet: 'thud', blunt: 'thud', blade: 'thud', break: 'thud', drag: 'drag_soft' },\n}\n\n/** The id a file of the matrix takes: `impact_<material>_<blow>` (`impact_concrete_bullet`). */\nexport const impactSoundId = (material: SfxMaterial, blow: SfxBlow): string => `impact_${material}_${blow}`\n\n/** The impact matrix as entries (the `impactos` category of the catalogue). */\nexport const SFX_IMPACTS: readonly SfxEntry[] = SFX_MATERIALS.flatMap(([material, group]) =>\n SFX_BLOWS.map((blow) => {\n const current = CURRENT_BY_GROUP[group]?.[blow]\n return { id: impactSoundId(material, blow), category: 'impactos' as const, priority: (['steel', 'wood', 'glass', 'concrete', 'brick', 'soil', 'flesh'].includes(material) && blow === 'bullet' ? 1 : 2) as SfxPriority, ...(current ? { current } : {}) }\n }),\n)\n\n/** Where an entry stands in an engine: a file registered (`file`), only the synthesized sound (`synth`), or nothing (`missing`). */\nexport type SfxState = 'file' | 'synth' | 'missing'\n\nexport function sfxState(entry: SfxEntry, has: { sample(id: string): unknown; sound(id: string): unknown }): SfxState {\n if (has.sample(entry.id)) return 'file'\n if ((entry.current && has.sound(entry.current)) || has.sound(entry.id)) return 'synth'\n return 'missing'\n}\n","/**\n * The calibration sound of the measuring harness: a sample sound made by the kit in code (no file, no licence), with every layer the criteria ask\n * for, so the harness can prove the whole file path (bytes → decode → plan → WebAudio) before any real file exists. Each take is a WAV built here:\n * an attack on the first sample (a click and a short noise burst over a low thump that decays), four near takes with their own pitch and noise, a far\n * take (darker, slower attack of the echo), light and heavy tiers and the two tails (a short dense room, a long thin field).\n */\nimport { createRng } from '../rng'\nimport type { SampleSound } from '../sample'\nimport type { SampleLoader } from '../webaudio/sample-store'\n\nexport const CALIBRATION_ID = 'calibration_shot'\nexport const CALIBRATION_RATE = 48000\n\n/** 16-bit PCM mono WAV bytes of the samples (clamped to ±1). */\nexport function encodeWav(samples: Float32Array, sampleRate = CALIBRATION_RATE): ArrayBuffer {\n const bytes = new ArrayBuffer(44 + samples.length * 2)\n const view = new DataView(bytes)\n const text = (at: number, value: string): void => {\n for (let index = 0; index < value.length; index++) view.setUint8(at + index, value.charCodeAt(index))\n }\n text(0, 'RIFF')\n view.setUint32(4, 36 + samples.length * 2, true)\n text(8, 'WAVE')\n text(12, 'fmt ')\n view.setUint32(16, 16, true)\n view.setUint16(20, 1, true)\n view.setUint16(22, 1, true)\n view.setUint32(24, sampleRate, true)\n view.setUint32(28, sampleRate * 2, true)\n view.setUint16(32, 2, true)\n view.setUint16(34, 16, true)\n text(36, 'data')\n view.setUint32(40, samples.length * 2, true)\n for (let index = 0; index < samples.length; index++) {\n const value = Math.max(-1, Math.min(1, samples[index] as number))\n view.setInt16(44 + index * 2, value < 0 ? value * 0x8000 : value * 0x7fff, true)\n }\n return bytes\n}\n\ntype Shot = { readonly seconds: number; readonly thump: number; readonly noise: number; readonly decay: number; readonly brightness: number; readonly gain: number; readonly seed: number; readonly attack?: number }\n\n/** One take: a thump (sine glide) and a noise burst, both decaying, smoothed by a one-pole lowpass (`brightness` 0..1), faded out at the end. */\nexport function shotSamples(shot: Shot, sampleRate = CALIBRATION_RATE): Float32Array {\n const random = createRng(shot.seed)\n const length = Math.round(shot.seconds * sampleRate)\n const samples = new Float32Array(length)\n let low = 0\n let phase = 0\n const attack = Math.max(1, Math.round((shot.attack ?? 0) * sampleRate))\n for (let index = 0; index < length; index++) {\n const time = index / sampleRate\n const envelope = Math.exp(-time / shot.decay) * Math.min(1, (index + 1) / attack)\n phase += (2 * Math.PI * shot.thump * (1 + 0.6 * Math.exp(-time * 30))) / sampleRate\n const noise = random() * 2 - 1\n low += shot.brightness * (noise - low)\n const fade = Math.min(1, (length - index) / (0.01 * sampleRate))\n samples[index] = shot.gain * envelope * fade * (0.55 * Math.sin(phase) + shot.noise * low)\n }\n return samples\n}\n\nconst TAKES: Readonly<Record<string, Shot>> = {\n 'close_1.wav': { seconds: 0.4, thump: 150, noise: 1, decay: 0.06, brightness: 0.9, gain: 0.85, seed: 1 },\n 'close_2.wav': { seconds: 0.4, thump: 160, noise: 1, decay: 0.065, brightness: 0.85, gain: 0.85, seed: 2 },\n 'close_3.wav': { seconds: 0.4, thump: 142, noise: 1, decay: 0.055, brightness: 0.95, gain: 0.85, seed: 3 },\n 'close_4.wav': { seconds: 0.4, thump: 170, noise: 1, decay: 0.07, brightness: 0.8, gain: 0.85, seed: 4 },\n 'far_1.wav': { seconds: 0.9, thump: 90, noise: 0.8, decay: 0.2, brightness: 0.08, gain: 0.7, seed: 5, attack: 0.004 },\n 'far_2.wav': { seconds: 0.9, thump: 95, noise: 0.8, decay: 0.22, brightness: 0.07, gain: 0.7, seed: 6, attack: 0.004 },\n 'light_1.wav': { seconds: 0.25, thump: 220, noise: 0.6, decay: 0.03, brightness: 0.6, gain: 0.35, seed: 7 },\n 'light_2.wav': { seconds: 0.25, thump: 230, noise: 0.6, decay: 0.03, brightness: 0.55, gain: 0.35, seed: 8 },\n 'heavy_1.wav': { seconds: 0.6, thump: 110, noise: 1.2, decay: 0.11, brightness: 0.95, gain: 0.95, seed: 9 },\n 'heavy_2.wav': { seconds: 0.6, thump: 105, noise: 1.2, decay: 0.12, brightness: 0.9, gain: 0.95, seed: 10 },\n 'tail_in.wav': { seconds: 0.5, thump: 0, noise: 1, decay: 0.08, brightness: 0.4, gain: 0.25, seed: 11, attack: 0.01 },\n 'tail_out.wav': { seconds: 2, thump: 0, noise: 1, decay: 0.45, brightness: 0.25, gain: 0.2, seed: 12, attack: 0.02 },\n 'loop_1.wav': { seconds: 0.6, thump: 0, noise: 1, decay: 100, brightness: 0.5, gain: 0.5, seed: 13, attack: 0.01 },\n 'loop_2.wav': { seconds: 0.6, thump: 0, noise: 1, decay: 100, brightness: 0.45, gain: 0.5, seed: 14, attack: 0.01 },\n 'loop_3.wav': { seconds: 0.6, thump: 0, noise: 1, decay: 100, brightness: 0.55, gain: 0.5, seed: 15, attack: 0.01 },\n}\n\nconst PREFIX = 'calibration/'\nconst url = (name: string): string => `${PREFIX}${name}`\n\n/** The calibration sound (weapons bus, every layer, fallback to the game's pistol noise class). */\nexport const CALIBRATION_SOUND: SampleSound = {\n id: CALIBRATION_ID,\n bus: 'weapons',\n close: ['close_1.wav', 'close_2.wav', 'close_3.wav', 'close_4.wav'].map((name) => ({ url: url(name) })),\n far: ['far_1.wav', 'far_2.wav'].map((name) => ({ url: url(name) })),\n tiers: [\n { name: 'light', from: 0, close: ['light_1.wav', 'light_2.wav'].map((name) => ({ url: url(name) })) },\n { name: 'medium', from: 0.34, close: ['close_1.wav', 'close_2.wav', 'close_3.wav', 'close_4.wav'].map((name) => ({ url: url(name) })) },\n { name: 'heavy', from: 0.67, close: ['heavy_1.wav', 'heavy_2.wav'].map((name) => ({ url: url(name) })) },\n ],\n tail: { indoor: [{ url: url('tail_in.wav') }], outdoor: [{ url: url('tail_out.wav') }] },\n pitch: 0.04,\n choke: { voices: 2 },\n fallback: 'sfx_pistol',\n sources: ['sdk: calibration takes synthesized by the harness (measure/calibration.ts), no file, no licence'],\n}\n\nexport const CALIBRATION_LOOP_ID = 'calibration_loop'\n\n/** A steady hiss in three 0.6 s takes, crossed in 0.15 s: the loop the harness checks for seams (no dip, no gap where two takes meet). */\nexport const CALIBRATION_LOOP_SOUND: SampleSound = {\n id: CALIBRATION_LOOP_ID,\n bus: 'ambience',\n close: ['loop_1.wav', 'loop_2.wav', 'loop_3.wav'].map((name) => ({ url: url(name) })),\n loop: { crossfade: 0.15 },\n sources: ['sdk: calibration takes synthesized by the harness (measure/calibration.ts), no file, no licence'],\n}\n\n/** Whether a url is one of the calibration takes. */\nexport const isCalibrationUrl = (url: string): boolean => url.startsWith(PREFIX)\n\n/** Bytes of the calibration takes (made on demand, the same for the same name). Falls through to `next` for any other url. */\nexport function calibrationLoader(next?: SampleLoader): SampleLoader {\n const made = new Map<string, ArrayBuffer>()\n return async (requested) => {\n if (!requested.startsWith(PREFIX)) {\n if (next) return next(requested)\n throw new Error(`not a calibration file: ${requested}`)\n }\n const name = requested.slice(PREFIX.length)\n const shot = TAKES[name]\n if (!shot) throw new Error(`no calibration take ${name}`)\n let bytes = made.get(name)\n if (!bytes) {\n bytes = encodeWav(shotSamples(shot))\n made.set(name, bytes)\n }\n // decodeAudioData detaches what it gets: every load gets its own copy\n return bytes.slice(0)\n }\n}\n","/**\n * Measurements of rendered sound (pure, on plain sample arrays), for the criteria C1–C9: when it starts, how loud and how bright it is, which side\n * it is on, how long it rings and how many separate hits a burst has.\n */\n\nexport type Channels = readonly Float32Array[]\n\n/** Linear amplitude to dBFS (−Infinity for 0). */\nexport const dbOf = (amplitude: number): number => (amplitude > 0 ? 20 * Math.log10(amplitude) : -Infinity)\n\nconst clampIndex = (channels: Channels, index: number): number => Math.max(0, Math.min(channels[0]?.length ?? 0, Math.round(index)))\n\n/** The loudest sample of every channel between two sample indexes (linear). */\nexport function peakOf(channels: Channels, start = 0, end = Number.POSITIVE_INFINITY): number {\n let peak = 0\n const from = clampIndex(channels, start)\n for (const channel of channels) {\n const to = Math.min(channel.length, end)\n for (let index = from; index < to; index++) {\n const value = Math.abs(channel[index] as number)\n if (value > peak) peak = value\n }\n }\n return peak\n}\n\n/** Index of the loudest sample (any channel) between two indexes. */\nexport function peakIndex(channels: Channels, start = 0, end = Number.POSITIVE_INFINITY): number {\n let peak = -1\n let at = -1\n const from = clampIndex(channels, start)\n for (const channel of channels) {\n const to = Math.min(channel.length, end)\n for (let index = from; index < to; index++) {\n const value = Math.abs(channel[index] as number)\n if (value > peak) {\n peak = value\n at = index\n }\n }\n }\n return at\n}\n\n/** First sample index at or after `start` whose amplitude (any channel) reaches `threshold`, or −1. */\nexport function onsetIndex(channels: Channels, start = 0, threshold = 0.001): number {\n const length = channels[0]?.length ?? 0\n for (let index = clampIndex(channels, start); index < length; index++) {\n for (const channel of channels) if (Math.abs(channel[index] as number) >= threshold) return index\n }\n return -1\n}\n\n/** RMS of all channels between two indexes, dBFS. */\nexport function rmsDb(channels: Channels, start: number, end: number): number {\n let sum = 0\n let count = 0\n const from = clampIndex(channels, start)\n for (const channel of channels) {\n const to = Math.min(channel.length, Math.round(end))\n for (let index = from; index < to; index++) {\n const value = channel[index] as number\n sum += value * value\n count++\n }\n }\n return count === 0 ? -Infinity : dbOf(Math.sqrt(sum / count))\n}\n\n/** Spectral centroid (Hz) of `size` samples from `start` (channels summed, Hann window, plain DFT): the brightness of the sound. */\nexport function centroidHz(channels: Channels, sampleRate: number, start: number, size = 2048): number {\n const from = clampIndex(channels, start)\n const frame = new Float64Array(size)\n for (const channel of channels) {\n for (let index = 0; index < size; index++) frame[index] = (frame[index] as number) + ((channel[from + index] as number | undefined) ?? 0)\n }\n for (let index = 0; index < size; index++) frame[index] = (frame[index] as number) * (0.5 - 0.5 * Math.cos((2 * Math.PI * index) / (size - 1)))\n let weighted = 0\n let total = 0\n const bins = size / 2\n for (let bin = 1; bin < bins; bin++) {\n let re = 0\n let im = 0\n const step = (2 * Math.PI * bin) / size\n for (let index = 0; index < size; index++) {\n const value = frame[index] as number\n re += value * Math.cos(step * index)\n im -= value * Math.sin(step * index)\n }\n const magnitude = Math.hypot(re, im)\n weighted += magnitude * ((bin * sampleRate) / size)\n total += magnitude\n }\n return total > 0 ? weighted / total : 0\n}\n\n/** Energy balance from −1 (all left) to 1 (all right) between two indexes. */\nexport function balanceOf(left: Float32Array, right: Float32Array, start: number, end: number): number {\n let l = 0\n let r = 0\n const to = Math.min(left.length, right.length, Math.round(end))\n for (let index = Math.max(0, Math.round(start)); index < to; index++) {\n l += (left[index] as number) ** 2\n r += (right[index] as number) ** 2\n }\n return l + r > 0 ? (r - l) / (r + l) : 0\n}\n\n/** Seconds from `start` to the last 10 ms window louder than `floorDb` (how long the sound rings, tail included). */\nexport function ringSeconds(channels: Channels, sampleRate: number, start: number, floorDb = -60): number {\n const window = Math.max(1, Math.round(sampleRate * 0.01))\n const length = channels[0]?.length ?? 0\n let last = clampIndex(channels, start)\n for (let index = last; index < length; index += window) {\n if (dbOf(peakOf(channels, index, index + window)) > floorDb) last = index + window\n }\n return (last - start) / sampleRate\n}\n\n/**\n * Separate hits in a burst: attacks of the 2 ms envelope, where it jumps to twice the mean of the 20 ms before it and reaches `threshold`, at least\n * 30 ms apart (so a rapid fire over a long tail still counts every shot).\n */\nexport function countHits(channels: Channels, sampleRate: number, threshold: number): number {\n const window = Math.max(1, Math.round(sampleRate * 0.002))\n const length = channels[0]?.length ?? 0\n const envelope: number[] = []\n for (let index = 0; index < length; index += window) envelope.push(peakOf(channels, index, index + window))\n const history = 10\n const refractory = Math.round(0.03 / 0.002)\n let hits = 0\n let quietUntil = -1\n for (let index = 0; index < envelope.length; index++) {\n const level = envelope[index] as number\n if (index < quietUntil || level < threshold) continue\n let sum = 0\n for (let back = Math.max(0, index - history); back < index; back++) sum += envelope[back] as number\n const before = index === 0 ? 0 : sum / Math.min(history, index)\n if (level >= 2 * before) {\n hits++\n quietUntil = index + refractory\n }\n }\n return hits\n}\n\n/** Peak of the last `seconds` of a file against its own peak, dB (≤ −40: it fades out, it does not end on a cut). */\nexport function endDropDb(channels: Channels, sampleRate: number, seconds = 0.005): number {\n const length = channels[0]?.length ?? 0\n const whole = peakOf(channels)\n if (whole === 0) return -Infinity\n return dbOf(peakOf(channels, length - Math.round(sampleRate * seconds), length) / whole)\n}\n","/**\n * The measuring harness of the sound criteria (C1–C10 of the sound checklist). Each criterion plays the sound through a real engine on an\n * `OfflineAudioContext` (the same mix, limiter and realizer the game uses, rendered faster than real time), and measures the rendered output: when it\n * starts against the event, how loud and bright it is at each distance, which side, how many takes, how it ends. Runs in a browser (or anything with\n * an `OfflineAudioContext`); C10 is the owner's ear, so it is left open with a recording to listen to (`recordOutput`).\n */\nimport type { MixProfile } from '../mix'\nimport type { SoundBank } from '../recipe'\nimport { createRng } from '../rng'\nimport { planSample, sampleUrls } from '../sample'\nimport type { SampleEnvironment, SampleSound } from '../sample'\nimport { createAudioEngine } from '../webaudio/engine'\nimport type { AudioEngine, PlayOptions, VoiceStartEvent } from '../webaudio/engine'\nimport type { SampleLoader } from '../webaudio/sample-store'\nimport { balanceOf, centroidHz, dbOf, endDropDb, onsetIndex, peakIndex, peakOf, ringSeconds, rmsDb } from './analyze'\nimport type { Channels } from './analyze'\n\nexport const CRITERIA = ['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10'] as const\nexport type CriterionId = (typeof CRITERIA)[number]\n\n/** The targets of the checklist, as numbers the harness compares with. */\nexport const CRITERIA_TARGETS = {\n /** C1: event to the first sample, and onset to the peak (one 60 fps frame). */\n syncMs: 20,\n peakAfterOnsetMs: 1000 / 60,\n /** C3: distances measured, metres. */\n distances: [1, 10, 50, 200] as readonly number[],\n /** C5: plays, distinct takes and the pitch range (fraction). */\n plays: 10,\n minTakes: 4,\n pitch: [0.03, 0.05] as const,\n /** C6: the highest peak, dBFS. */\n peakDb: -1,\n /** C8: the end of each file against its peak, dB. */\n endDropDb: -40,\n /** C9: a burst of rapid fire. */\n burst: 20,\n burstSpacing: 0.06,\n} as const\n\nexport type CriterionResult = {\n readonly id: CriterionId\n /** `null`: not decided by the harness (C10, the owner's ear). */\n readonly pass: boolean | null\n /** What was measured, short (the bench prints it). */\n readonly value: string\n readonly target: string\n readonly data?: Readonly<Record<string, unknown>>\n}\n\n/** One action of the game and the sound it must play (C2). */\nexport type ActionCheck = { readonly action: string; readonly play: string; readonly expect: string; readonly options?: PlayOptions }\n\nexport type MeasureOptions = {\n /** The sample sound measured. */\n readonly sound: string\n readonly banks: readonly SoundBank[]\n readonly loader: SampleLoader\n /** The mixing chain the game uses (default the engine's default). */\n readonly mix?: string | MixProfile\n readonly sampleRate?: number\n /** `new OfflineAudioContext(...)` by default. */\n readonly createOfflineContext?: (channels: number, length: number, sampleRate: number) => OfflineAudioContext\n /** The live context's `baseLatency` (s), added to the rendered delay for C1. */\n readonly baseLatency?: number\n /** The device's `outputLatency` (s), reported with C1 but not counted (it is the speakers', not the game's). */\n readonly outputLatency?: number\n /** C2: the actions to check (default the sound for itself). */\n readonly actions?: readonly ActionCheck[]\n /** C6: sound ids loudest first, the order the buses must keep (tiro > explosão > impacto > passo). */\n readonly loudnessOrder?: readonly string[]\n}\n\ntype Render = { readonly channels: Channels; readonly sampleRate: number; readonly events: readonly VoiceStartEvent[]; readonly handles: number }\n\nconst EVENT_AT = 0.2\n\nconst offlineFactory = (options: MeasureOptions) =>\n options.createOfflineContext ??\n ((channels: number, length: number, sampleRate: number): OfflineAudioContext => {\n const Constructor = (globalThis as { OfflineAudioContext?: new (channels: number, length: number, sampleRate: number) => OfflineAudioContext }).OfflineAudioContext\n if (!Constructor) throw new Error('no OfflineAudioContext here: the harness runs in a browser')\n return new Constructor(channels, length, sampleRate)\n })\n\n/** Renders what `act` plays on a fresh engine (files loaded first), `seconds` long. */\nasync function render(options: MeasureOptions, seconds: number, act: (engine: AudioEngine) => number, engineExtras: { occlusion?: () => number; environment?: SampleEnvironment } = {}): Promise<Render> {\n const sampleRate = options.sampleRate ?? 48000\n const context = offlineFactory(options)(2, Math.ceil(seconds * sampleRate), sampleRate)\n const events: VoiceStartEvent[] = []\n const engine = createAudioEngine({\n banks: options.banks,\n createContext: () => context as unknown as AudioContext,\n samples: { loader: options.loader, autoLoad: false },\n onVoiceStart: (event) => events.push(event),\n ...(options.mix ? { mix: options.mix } : {}),\n ...(engineExtras.occlusion ? { occlusion: engineExtras.occlusion } : {}),\n ...(engineExtras.environment ? { environment: engineExtras.environment } : {}),\n })\n const ids = [...new Set([options.sound, ...(options.actions ?? []).map((action) => action.play), ...(options.loudnessOrder ?? [])])].filter((id) => engine.registry.sample(id))\n const report = await engine.loadSamples(ids)\n if (report.failed.length > 0) throw new Error(`files did not load: ${report.failed.map((entry) => `${entry.url} (${entry.error})`).join(', ')}`)\n const handles = act(engine)\n const buffer = await context.startRendering()\n const channels = Array.from({ length: buffer.numberOfChannels }, (_, index) => buffer.getChannelData(index))\n return { channels, sampleRate, events, handles }\n}\n\nconst ms = (seconds: number): string => `${(seconds * 1000).toFixed(1)} ms`\nconst db = (value: number): string => (Number.isFinite(value) ? `${value.toFixed(1)} dB` : '−∞')\nconst decreasing = (values: readonly number[]): boolean => values.every((value, index) => index === 0 || value < (values[index - 1] as number))\n\nasync function c1(options: MeasureOptions): Promise<CriterionResult> {\n const result = await render(options, 1.2, (engine) => (engine.play(options.sound, { distance: 1, delay: EVENT_AT }) ? 1 : 0))\n const onset = onsetIndex(result.channels, 0, 0.001)\n const event = result.events.find((entry) => entry.id === options.sound)\n if (onset < 0 || !event) return { id: 'C1', pass: false, value: 'sem som', target: `≤ ${CRITERIA_TARGETS.syncMs} ms` }\n const delay = onset / result.sampleRate - EVENT_AT + (event.startAt - event.requestedAt - EVENT_AT) + (options.baseLatency ?? 0)\n const peak = peakIndex(result.channels, onset, onset + Math.round(result.sampleRate * 0.25))\n const toPeak = (peak - onset) / result.sampleRate\n const pass = delay <= CRITERIA_TARGETS.syncMs / 1000 && toPeak <= CRITERIA_TARGETS.peakAfterOnsetMs / 1000\n return {\n id: 'C1',\n pass,\n value: `${ms(delay)}, pico +${ms(toPeak)}`,\n target: `≤ ${CRITERIA_TARGETS.syncMs} ms; pico no quadro do contato`,\n data: { delay, toPeak, baseLatency: options.baseLatency ?? 0, outputLatency: options.outputLatency ?? 0 },\n }\n}\n\nasync function c2(options: MeasureOptions): Promise<CriterionResult> {\n const actions = options.actions ?? [{ action: options.sound, play: options.sound, expect: options.sound }]\n const result = await render(options, 0.5, (engine) => {\n let played = 0\n for (const action of actions) if (engine.play(action.play, { distance: 1, ...action.options })) played++\n return played\n })\n const wrong = actions.filter((action, index) => {\n const event = result.events[index]\n return !event || (event.fallbackOf ?? event.id) !== action.expect || event.kind !== 'sample'\n })\n return {\n id: 'C2',\n pass: wrong.length === 0,\n value: `${actions.length - wrong.length}/${actions.length} certas`,\n target: '100% das ações batem com a tabela (arquivo, não o substituto)',\n data: { wrong: wrong.map((action) => action.action), events: result.events.map((event) => `${event.kind}:${event.id}`) },\n }\n}\n\nasync function c3(options: MeasureOptions, sound: SampleSound): Promise<CriterionResult> {\n const levels: number[] = []\n const brightness: number[] = []\n for (const distance of CRITERIA_TARGETS.distances) {\n const result = await render(options, 1.2, (engine) => (engine.play(options.sound, { position: [0, 0, -distance], seed: 1, delay: EVENT_AT }) ? 1 : 0))\n const onset = onsetIndex(result.channels, 0, 1e-5)\n levels.push(onset < 0 ? -Infinity : rmsDb(result.channels, onset, onset + result.sampleRate * 0.3))\n brightness.push(onset < 0 ? 0 : centroidHz(result.channels, result.sampleRate, onset))\n }\n const far = planSample(sound, { random: createRng(1), distance: CRITERIA_TARGETS.distances.at(-1) as number })\n const switched = (far?.farMix ?? 0) === 1 && (far?.layers.some((layer) => layer.role === 'far') ?? false)\n const pass = decreasing(levels) && decreasing(brightness) && switched\n return {\n id: 'C3',\n pass,\n value: `${levels.map((level) => db(level)).join(' › ')}; ${brightness.map((hz) => `${Math.round(hz)} Hz`).join(' › ')}${switched ? '; longe = far' : '; sem camada far'}`,\n target: 'cai e escurece com a distância; troca para a versão de longe depois de ~50 m',\n data: { distances: CRITERIA_TARGETS.distances, levels, brightness, switched },\n }\n}\n\nasync function c4(options: MeasureOptions): Promise<CriterionResult> {\n const side = async (x: number): Promise<number> => {\n const result = await render(options, 0.8, (engine) => (engine.play(options.sound, { position: [x, 0, -2], seed: 1, delay: EVENT_AT }) ? 1 : 0))\n const [left, right] = result.channels as [Float32Array, Float32Array]\n return balanceOf(left, right, 0, left.length)\n }\n const right = await side(10)\n const left = await side(-10)\n const bright = async (occluded: boolean): Promise<number> => {\n const result = await render(options, 0.8, (engine) => (engine.play(options.sound, { position: [0, 0, -10], seed: 1, delay: EVENT_AT }) ? 1 : 0), occluded ? { occlusion: () => 1 } : {})\n const onset = onsetIndex(result.channels, 0, 1e-5)\n return onset < 0 ? 0 : centroidHz(result.channels, result.sampleRate, onset)\n }\n const clear = await bright(false)\n const wall = await bright(true)\n const pass = right > 0.2 && left < -0.2 && wall < clear * 0.7\n return {\n id: 'C4',\n pass,\n value: `dir ${right.toFixed(2)} esq ${left.toFixed(2)}; parede ${Math.round(wall)} Hz de ${Math.round(clear)} Hz`,\n target: 'lado certo; atrás da parede fica abafado',\n data: { right, left, clear, wall },\n }\n}\n\nasync function c5(options: MeasureOptions, sound: SampleSound): Promise<CriterionResult> {\n const result = await render(options, 0.3 * CRITERIA_TARGETS.plays + 1, (engine) => {\n let played = 0\n for (let index = 0; index < CRITERIA_TARGETS.plays; index++) if (engine.play(options.sound, { distance: 1, delay: 0.1 + index * 0.3 })) played++\n return played\n })\n const close = result.events.map((event) => event.layers?.find((layer) => layer.role === 'close'))\n const takes = close.map((layer) => layer?.url ?? '')\n const repeats = takes.filter((take, index) => index > 0 && take === takes[index - 1]).length\n const distinct = new Set(takes).size\n const rates = close.map((layer) => layer?.rate ?? 1)\n const spread = (Math.max(...rates) - Math.min(...rates)) / 2\n const pitch = sound.pitch ?? 0.04\n const pass = distinct >= CRITERIA_TARGETS.minTakes && repeats === 0 && pitch >= CRITERIA_TARGETS.pitch[0] && pitch <= CRITERIA_TARGETS.pitch[1] && spread > 0.01\n return {\n id: 'C5',\n pass,\n value: `${distinct} tomadas, ${repeats} repetições seguidas, tom ±${(pitch * 100).toFixed(0)}%`,\n target: `≥ ${CRITERIA_TARGETS.minTakes} variações, nunca a mesma duas vezes, tom ±3–5%`,\n data: { takes, rates },\n }\n}\n\nasync function c6(options: MeasureOptions): Promise<CriterionResult> {\n const peakAt = async (id: string): Promise<{ peak: number; rms: number }> => {\n const result = await render(options, 1.2, (engine) => (engine.play(id, { distance: 1, seed: 1, delay: EVENT_AT }) ? 1 : 0))\n const onset = onsetIndex(result.channels, 0, 1e-5)\n return { peak: dbOf(peakOf(result.channels)), rms: onset < 0 ? -Infinity : rmsDb(result.channels, onset, onset + result.sampleRate * 0.3) }\n }\n const own = await peakAt(options.sound)\n const order = options.loudnessOrder ?? []\n const loudness: number[] = []\n for (const id of order) loudness.push((await peakAt(id)).rms)\n const ordered = order.length < 2 || decreasing(loudness)\n const pass = own.peak <= CRITERIA_TARGETS.peakDb && ordered\n return {\n id: 'C6',\n pass,\n value: `pico ${db(own.peak)}, RMS ${db(own.rms)}${order.length > 1 ? `; ordem ${ordered ? 'ok' : 'errada'}` : ''}`,\n target: 'tiro > explosão > impacto > passo; pico ≤ −1 dBFS',\n data: { peak: own.peak, rms: own.rms, order, loudness },\n }\n}\n\nasync function c7(options: MeasureOptions, sound: SampleSound): Promise<CriterionResult> {\n if (!sound.tiers || sound.tiers.length < 2) return { id: 'C7', pass: false, value: 'sem camadas leve/médio/forte', target: 'muda de camada, não só de volume' }\n const at = async (intensity: number): Promise<{ tier: string; rms: number; files: string }> => {\n const result = await render(options, 1.2, (engine) => (engine.play(options.sound, { distance: 1, seed: 1, intensity, delay: EVENT_AT }) ? 1 : 0))\n const onset = onsetIndex(result.channels, 0, 1e-5)\n const event = result.events[0]\n return { tier: event?.tier ?? '', rms: onset < 0 ? -Infinity : rmsDb(result.channels, onset, onset + result.sampleRate * 0.3), files: event?.layers?.find((layer) => layer.role === 'close')?.url ?? '' }\n }\n const light = await at(0.1)\n const heavy = await at(0.9)\n const pass = light.tier !== heavy.tier && light.files !== heavy.files && heavy.rms > light.rms\n return {\n id: 'C7',\n pass,\n value: `${light.tier} ${db(light.rms)} → ${heavy.tier} ${db(heavy.rms)}`,\n target: 'golpe fraco x forte troca a camada (leve/médio/forte), não só o volume',\n data: { light, heavy },\n }\n}\n\nasync function c8(options: MeasureOptions, sound: SampleSound): Promise<CriterionResult> {\n const sampleRate = options.sampleRate ?? 48000\n const decoder = offlineFactory(options)(1, sampleRate, sampleRate)\n const drops: { url: string; drop: number }[] = []\n for (const url of sampleUrls(sound)) {\n const buffer = await decoder.decodeAudioData(await options.loader(url))\n drops.push({ url, drop: endDropDb([buffer.getChannelData(0)], buffer.sampleRate) })\n }\n const worst = drops.reduce((max, entry) => Math.max(max, entry.drop), -Infinity)\n const ring = async (environment: SampleEnvironment): Promise<number> => {\n const result = await render(options, 3, (engine) => (engine.play(options.sound, { distance: 1, seed: 1, environment, delay: EVENT_AT }) ? 1 : 0))\n return ringSeconds(result.channels, result.sampleRate, Math.round(EVENT_AT * result.sampleRate))\n }\n const indoor = await ring('indoor')\n const outdoor = await ring('outdoor')\n const hasTails = Boolean(sound.tail?.indoor?.length && sound.tail?.outdoor?.length)\n const pass = worst <= CRITERIA_TARGETS.endDropDb && hasTails && outdoor > indoor\n return {\n id: 'C8',\n pass,\n value: `fim ${db(worst)}; cauda dentro ${indoor.toFixed(2)} s, fora ${outdoor.toFixed(2)} s${hasTails ? '' : ' (sem as duas caudas)'}`,\n target: 'não corta seco; cauda de interior x exterior coerente',\n data: { drops, indoor, outdoor },\n }\n}\n\nasync function c9(options: MeasureOptions): Promise<CriterionResult> {\n const { burst, burstSpacing } = CRITERIA_TARGETS\n const first = 0.1\n const result = await render(options, burst * burstSpacing + 1.5, (engine) => {\n let played = 0\n for (let index = 0; index < burst; index++) if (engine.play(options.sound, { distance: 1, delay: first + index * burstSpacing })) played++\n return played\n })\n const peak = dbOf(peakOf(result.channels))\n // C9 reads: no pile-up (the level does not build up shot after shot) and no shot that vanishes (every slot carries its shot). RMS of each shot's slot:\n const slots: number[] = []\n for (let index = 0; index < burst; index++) {\n const at = Math.round((first + index * burstSpacing) * result.sampleRate)\n slots.push(rmsDb(result.channels, at, at + Math.round(burstSpacing * result.sampleRate)))\n }\n const sorted = [...slots].sort((a, b) => a - b)\n const median = sorted[Math.floor(sorted.length / 2)] as number\n const vanished = slots.filter((level) => level < median - 6).length\n const buildUp = slots.slice(-5).reduce((sum, level) => sum + level, 0) / 5 - (slots[0] as number)\n const pass = result.handles === burst && vanished === 0 && buildUp <= 6 && peak <= CRITERIA_TARGETS.peakDb\n return {\n id: 'C9',\n pass,\n value: `${result.handles}/${burst} tocaram, ${vanished} sumiram, acúmulo ${buildUp >= 0 ? '+' : ''}${buildUp.toFixed(1)} dB, pico ${db(peak)}`,\n target: 'rajada sem amontoar (acúmulo ≤ 6 dB) nem sumir; pico ≤ −1 dBFS',\n data: { handles: result.handles, slots, vanished, buildUp, peak },\n }\n}\n\n/** Runs the criteria (all by default) and returns one result each, in order. C10 is always open: it is the owner's ear on a recording. */\nexport async function measureCriteria(options: MeasureOptions, only: readonly CriterionId[] = CRITERIA): Promise<CriterionResult[]> {\n const probe = createAudioEngine({ banks: options.banks, createContext: () => null })\n const sound = probe.registry.sample(options.sound)\n if (!sound) throw new Error(`${options.sound} is not a sample sound of these banks`)\n const results: CriterionResult[] = []\n for (const id of only) {\n if (id === 'C1') results.push(await c1(options))\n else if (id === 'C2') results.push(await c2(options))\n else if (id === 'C3') results.push(await c3(options, sound))\n else if (id === 'C4') results.push(await c4(options))\n else if (id === 'C5') results.push(await c5(options, sound))\n else if (id === 'C6') results.push(await c6(options))\n else if (id === 'C7') results.push(await c7(options, sound))\n else if (id === 'C8') results.push(await c8(options, sound))\n else if (id === 'C9') results.push(await c9(options))\n else results.push({ id: 'C10', pass: null, value: 'gravar e ouvir', target: 'aprovado pelo ouvido do dono (print + gravação na 4280)' })\n }\n return results\n}\n\n/**\n * Records what the engine outputs while `act` plays, `seconds` long (the C10 recording): a `MediaRecorder` on a stream tapped from the master. Returns\n * `null` where there is no recorder or no context.\n */\nexport async function recordOutput(engine: AudioEngine, seconds: number, act: () => void): Promise<Blob | null> {\n engine.unlock()\n const output = engine.output()\n const Recorder = (globalThis as { MediaRecorder?: typeof MediaRecorder }).MediaRecorder\n const context = output?.context as AudioContext | undefined\n if (!output || !Recorder || !context || typeof context.createMediaStreamDestination !== 'function') return null\n const tap = context.createMediaStreamDestination()\n output.connect(tap)\n const recorder = new Recorder(tap.stream)\n const chunks: Blob[] = []\n recorder.ondataavailable = (event) => chunks.push(event.data)\n const done = new Promise<void>((resolve) => {\n recorder.onstop = () => resolve()\n })\n recorder.start()\n act()\n await new Promise((resolve) => setTimeout(resolve, seconds * 1000))\n recorder.stop()\n await done\n output.disconnect(tap)\n return new Blob(chunks, { type: recorder.mimeType || 'audio/webm' })\n}\n","/**\n * The manifest the converter (`scripts/sfx-convert.mjs`) writes next to the converted files: every sound id with its takes per layer, the file\n * facts the criteria check (rate, channels, peak, length) and where each file came from. `sampleBankFromManifest` turns it into a `SoundBank`\n * of `SampleSound`s, with the bus and the numbers of each sound given by the caller.\n */\nimport type { BusId, Falloff, SoundBank } from './recipe'\nimport type { SampleCrossover, SampleRef, SampleSound } from './sample'\n\n/** Licences the SDK accepts (the files are redistributed on npm): public domain or attribution only. */\nexport const SDK_LICENSES = ['CC0', 'CC-BY'] as const\nexport type SdkLicense = (typeof SDK_LICENSES)[number]\n\nexport type SfxFileEntry = {\n /** Path from the manifest's folder: `armas/pistol_9mm_close_01.ogg`. */\n readonly file: string\n readonly sampleRate: number\n readonly channels: number\n /** dBFS. */\n readonly peak: number\n readonly seconds: number\n readonly source: string\n readonly author: string\n readonly license: SdkLicense\n}\n\n/** The layers a file name can end in: `<id>_<layer>_<nn>` (`pistol_9mm_close_01`); a name without one is a `close` take. */\nexport const SFX_LAYERS = ['close', 'far', 'tail_in', 'tail_out'] as const\nexport type SfxLayer = (typeof SFX_LAYERS)[number]\n\nexport type SfxManifestSound = {\n readonly id: string\n readonly category: string\n readonly layers: Partial<Readonly<Record<SfxLayer, readonly SfxFileEntry[]>>>\n}\n\nexport type SfxManifest = {\n readonly version: 1\n readonly format: { readonly codec: 'vorbis'; readonly sampleRate: number; readonly channels: number; readonly peakDb: number }\n readonly sounds: readonly SfxManifestSound[]\n}\n\n/** The numbers of one sound that the files do not say (bus, curve, pitch...). */\nexport type SampleDefaults = {\n readonly bus: BusId\n readonly gain?: number\n readonly pitch?: number\n readonly crossover?: SampleCrossover\n readonly tailGain?: number\n readonly falloff?: Falloff\n readonly cutoffK?: number\n readonly group?: string\n readonly priority?: number\n readonly fallback?: string\n}\n\nexport type SampleBankOptions = {\n readonly id: string\n /** Prefix of every url (where the manifest's folder is served: `/sfx/`). Default ''. */\n readonly baseUrl?: string\n /** Numbers per sound id, or one function; a sound with neither is left out (it has no bus). */\n readonly sounds?: Readonly<Record<string, SampleDefaults>>\n readonly defaults?: (sound: { readonly id: string; readonly category: string }) => SampleDefaults | undefined\n}\n\n/** The strength suffixes of a sound id (`kick_hit_heavy`): takes of the tiers of `kick_hit`, from these intensities. */\nexport const SFX_TIERS: Readonly<Record<string, number>> = { light: 0, medium: 0.34, heavy: 0.67 }\n\n/** Splits a file name (no extension) into its sound id, layer and take number. */\nexport function parseSfxName(name: string): { readonly id: string; readonly layer: SfxLayer; readonly take: number } {\n const match = /^(.*?)(?:_(close|far|tail_in|tail_out))?(?:_(\\d+))?$/.exec(name)\n const id = match?.[1] || name\n const layer = (match?.[2] as SfxLayer | undefined) ?? 'close'\n const take = match?.[3] ? Number(match[3]) : 1\n return { id, layer, take }\n}\n\n/** The base id and tier of a sound id: `kick_hit_heavy` → `kick_hit`, `heavy`. */\nexport function splitTier(id: string): { readonly base: string; readonly tier?: string } {\n const match = /^(.*)_(light|medium|heavy)$/.exec(id)\n return match ? { base: match[1] as string, tier: match[2] as string } : { base: id }\n}\n\n/** What `sampleBankFromManifest` reads of a manifest: the sounds, their layers and where each file came from (any licence string). */\nexport type SfxManifestLike = {\n readonly sounds: readonly {\n readonly id: string\n readonly category: string\n readonly layers: Partial<Readonly<Record<SfxLayer, readonly { readonly file: string; readonly source: string; readonly author: string; readonly license: string }[]>>>\n }[]\n}\n\nconst refsOf = (entries: readonly { readonly file: string }[] | undefined, baseUrl: string): SampleRef[] => (entries ?? []).map((entry) => ({ url: `${baseUrl}${entry.file}` }))\n\n/** A bank of sample sounds from a manifest. */\nexport function sampleBankFromManifest(manifest: SfxManifestLike, options: SampleBankOptions): SoundBank {\n const baseUrl = options.baseUrl ?? ''\n const samples: SampleSound[] = []\n // `<id>_light`, `_medium`, `_heavy` are the tiers of `<id>`, gathered under it\n type Sound = SfxManifestLike['sounds'][number]\n const tiersOf = new Map<string, Sound[]>()\n for (const sound of manifest.sounds) {\n const { base, tier } = splitTier(sound.id)\n if (tier) tiersOf.set(base, [...(tiersOf.get(base) ?? []), sound])\n }\n const bases = new Map<string, Sound>()\n for (const sound of manifest.sounds) {\n if (!splitTier(sound.id).tier) bases.set(sound.id, sound)\n }\n for (const [base, tiers] of tiersOf) {\n if (!bases.has(base)) bases.set(base, { id: base, category: tiers[0]?.category ?? '', layers: { close: tiers[0]?.layers.close ?? [] } })\n }\n for (const sound of bases.values()) {\n const numbers = options.sounds?.[sound.id] ?? options.defaults?.(sound)\n const close = refsOf(sound.layers.close, baseUrl)\n if (!numbers || close.length === 0) continue\n const tiers = (tiersOf.get(sound.id) ?? [])\n .map((tier) => {\n const name = splitTier(tier.id).tier as string\n const tierFar = refsOf(tier.layers.far, baseUrl)\n return { name, from: SFX_TIERS[name] ?? 0, close: refsOf(tier.layers.close, baseUrl), ...(tierFar.length > 0 ? { far: tierFar } : {}) }\n })\n .sort((a, b) => a.from - b.from)\n const far = refsOf(sound.layers.far, baseUrl)\n const indoor = refsOf(sound.layers.tail_in, baseUrl)\n const outdoor = refsOf(sound.layers.tail_out, baseUrl)\n const files = [sound, ...(tiersOf.get(sound.id) ?? [])].flatMap((entry) => Object.values(entry.layers).flatMap((entries) => entries ?? []))\n samples.push({\n id: sound.id,\n bus: numbers.bus,\n close,\n ...(far.length > 0 ? { far } : {}),\n ...(tiers.length > 0 ? { tiers } : {}),\n ...(numbers.crossover ? { crossover: numbers.crossover } : {}),\n ...(indoor.length > 0 || outdoor.length > 0\n ? { tail: { ...(indoor.length > 0 ? { indoor } : {}), ...(outdoor.length > 0 ? { outdoor } : {}), ...(numbers.tailGain === undefined ? {} : { gain: numbers.tailGain }) } }\n : {}),\n ...(numbers.pitch === undefined ? {} : { pitch: numbers.pitch }),\n ...(numbers.gain === undefined ? {} : { gain: numbers.gain }),\n ...(numbers.falloff ? { falloff: numbers.falloff } : {}),\n ...(numbers.cutoffK === undefined ? {} : { cutoffK: numbers.cutoffK }),\n ...(numbers.group ? { group: numbers.group } : {}),\n ...(numbers.priority === undefined ? {} : { priority: numbers.priority }),\n ...(numbers.fallback ? { fallback: numbers.fallback } : {}),\n sources: files.map((file) => `${file.file}: ${file.source} ${file.author} ${file.license}`),\n })\n }\n return { id: options.id, samples }\n}\n","/**\n * The kit's own recorded sounds: the files in `assets/sfx/` (CC0 / CC-BY, credited in `assets/sfx/CREDITOS.md`) and the numbers each one plays\n * with. `kitSampleBank` turns the converter's manifest into a bank; `KIT_SAMPLE_ALIASES` lets a recipe id the kit already plays (`shut_wood`,\n * `rattle`...) be answered by the takes of a file id (`door_wood_shut`), so a sound that was synthesized becomes the recording with no change where\n * it is played: the recipe of the same id plays while the files load, and wherever they cannot be fetched (`file://`). `loadKitSamples` fetches the\n * manifest from where the folder is served and registers the bank on an engine.\n */\nimport { sampleBankFromManifest } from './manifest'\nimport type { SampleDefaults, SfxManifest, SfxManifestSound } from './manifest'\nimport type { BusId, SoundBank } from './recipe'\n\n/** The bus of a manifest category (the folder the file sits in). */\nexport const KIT_CATEGORY_BUS: Readonly<Record<string, BusId>> = {\n armas: 'weapons',\n impactos: 'world',\n 'explosoes-fogo': 'world',\n personagem: 'world',\n veiculos: 'world',\n 'itens-portas': 'world',\n ambiente: 'ambience',\n}\n\n/** Voice sounds go on the voices bus whatever folder they are in. */\nconst VOICE_IDS = /^(player_(hurt|death|effort|breath)|scream|zombie_)/\n\n/**\n * Recipe id → file id. The recipe keeps playing until the takes of the file id load. Hand-worked leaves (doors, drawers) of `game-destruction-three`\n * and the hand sounds of items.\n */\nexport const KIT_SAMPLE_ALIASES: Readonly<Record<string, string>> = {\n // a house door: the latch giving, the hinge, the leaf meeting the frame, a locked one shaken; a drawer on its runners\n latch: 'metal_latch',\n creak_wood: 'door_creak',\n shut_wood: 'door_wood_shut',\n rattle: 'door_locked_rattle',\n // a drawer stays on its recipe: the recorded runs (1 to 1.9 s) outlast a drawer's pull\n // an item taken in the hand (game-destruction-three grab_* keys)\n grab_hard: 'item_pickup_generic',\n grab_soft: 'item_pickup_leather',\n // the hand foley of the test room (game-audio FOLEY_BANK) whose id is not a file id: a wooden leaf shut and slammed, an item picked up by material.\n // The metal door stays on its recipe (two of its takes run 10 s), and so do the fridge, the microwave and paper (no file for them).\n door_wood_close: 'door_wood_shut',\n door_wood_slam: 'door_slam_wood',\n item_pickup_metal: 'item_pickup_generic',\n item_pickup_plastic: 'item_pickup_generic',\n item_pickup_glass: 'item_pickup_generic',\n item_pickup_wood: 'item_pickup_generic',\n item_pickup_fabric: 'item_pickup_leather',\n}\n\n/** The numbers of a sound the files do not say: the bus of its folder, a little pitch spread. */\nexport function kitSampleDefaults(sound: { readonly id: string; readonly category: string }): SampleDefaults | undefined {\n const bus = VOICE_IDS.test(sound.id) ? 'voices' : KIT_CATEGORY_BUS[sound.category]\n if (!bus) return undefined\n return { bus, pitch: sound.category === 'ambiente' || /_loop/.test(sound.id) ? 0 : 0.04 }\n}\n\nexport type KitSampleBankOptions = {\n /** Where the `assets/sfx/` folder is served (`./sfx/`). */\n readonly baseUrl?: string\n /** Recipe id → file id (default `KIT_SAMPLE_ALIASES`); `{}` adds none. */\n readonly aliases?: Readonly<Record<string, string>>\n readonly id?: string\n}\n\n/** The manifest with each alias as one more sound, holding the takes of its file id. */\nexport function withAliases(manifest: SfxManifest, aliases: Readonly<Record<string, string>>): SfxManifest {\n const byId = new Map(manifest.sounds.map((sound) => [sound.id, sound]))\n const extra: SfxManifestSound[] = []\n for (const [alias, target] of Object.entries(aliases)) {\n const sound = byId.get(target)\n if (sound && !byId.has(alias)) extra.push({ ...sound, id: alias })\n }\n return { ...manifest, sounds: [...manifest.sounds, ...extra] }\n}\n\n/** The bank of the kit's files. */\nexport function kitSampleBank(manifest: SfxManifest, options: KitSampleBankOptions = {}): SoundBank {\n return sampleBankFromManifest(withAliases(manifest, options.aliases ?? KIT_SAMPLE_ALIASES), {\n id: options.id ?? 'kit_samples',\n baseUrl: options.baseUrl ?? '',\n defaults: kitSampleDefaults,\n })\n}\n\nexport type LoadKitSamplesOptions = KitSampleBankOptions & {\n /** Gets the manifest (default `fetch` of `<baseUrl>manifest.json`). */\n readonly fetchManifest?: (url: string) => Promise<SfxManifest>\n /** Ids to load right away instead of on their first play (the sounds of the first seconds, so they are not the recipe). */\n readonly preload?: readonly string[]\n}\n\ntype Registers = { register(bank: SoundBank): void; loadSamples?(ids?: readonly string[]): Promise<unknown> }\n\n/** True when `url`, read against the page, is a `file://` one: `fetch` refuses that scheme and the browser logs an error for each try. */\nconst isFileUrl = (url: string): boolean => {\n const page = (globalThis as { location?: { href?: string } }).location?.href\n try {\n return new URL(url, page).protocol === 'file:'\n } catch {\n return false\n }\n}\n\nconst fetchJson = async (url: string): Promise<SfxManifest> => {\n // a page opened from disk keeps the recipes without asking: the refused fetch would only put an error in the console\n if (isFileUrl(url)) throw new Error(`${url}: file:// is not fetched`)\n const response = await fetch(url)\n if (!response.ok) throw new Error(`${url}: ${response.status}`)\n return (await response.json()) as SfxManifest\n}\n\n/**\n * Fetches the manifest and registers the bank on the engine. Resolves to the bank, or `null` when the manifest cannot be had (a page opened from\n * `file://`, the folder not served): the recipes keep playing, so that is not an error.\n */\nexport async function loadKitSamples(engine: Registers, options: LoadKitSamplesOptions = {}): Promise<SoundBank | null> {\n const baseUrl = options.baseUrl ?? ''\n let manifest: SfxManifest\n try {\n manifest = await (options.fetchManifest ?? fetchJson)(`${baseUrl}manifest.json`)\n } catch {\n return null\n }\n const bank = kitSampleBank(manifest, options)\n engine.register(bank)\n if (options.preload && engine.loadSamples) void engine.loadSamples(options.preload).catch(() => undefined)\n return bank\n}\n","/**\n * A local sound pack: files a project keeps in its own folders (never in the SDK, never published) mapped to the SDK's sound ids by a JSON config.\n * `parseLocalSoundPack` checks the config at the boundary; `localPackSamples` turns it into sample sounds whose urls are relative to a base the\n * consuming project chooses (`audio/`, `https://cdn.example/sfx/`). Each entry says its licence; anything but `CC0` / `CC-BY` is shown as\n * unlicensed by the sound panel. `applyLocalSoundPack` (local-pack-loader.ts) loads them in idle time and swaps each id in only once its files decode.\n */\nimport { SFX_CATALOG, SFX_IMPACTS } from './catalog'\nimport { kitSampleDefaults } from './kit-samples'\nimport { SDK_LICENSES } from './manifest'\nimport { BUS_IDS } from './recipe'\nimport type { BusId, SampleSound } from './recipe'\n\nexport const LOCAL_PACK_LICENSES = ['CC0', 'CC-BY', 'unknown', 'proprietary'] as const\nexport type LocalPackLicense = (typeof LOCAL_PACK_LICENSES)[number]\n\n/** Which sound an id plays when the SDK also has a recording for it: the pack's files (default) or the SDK's, the pack staying as the alternative. */\nexport const LOCAL_PACK_PREFERENCES = ['pack', 'sdk'] as const\nexport type LocalPackPreference = (typeof LOCAL_PACK_PREFERENCES)[number]\n\nexport type LocalSoundEntry = {\n /** Paths or urls of the takes, relative to the pack's base. */\n readonly files: readonly string[]\n readonly license: LocalPackLicense\n /** Default `pack`; `sdk` keeps the SDK recording when there is one (the pack's files are then not even fetched). */\n readonly prefer?: LocalPackPreference\n /** Bus of the sound (default the bus of its catalogue category). */\n readonly bus?: BusId\n readonly gain?: number\n /** 0–10: how well the files fit the id (a reviewer's note, shown by tools). */\n readonly score?: number\n readonly note?: string\n}\n\nexport type LocalSoundPack = {\n readonly version: 1\n /** Prefix of every file (a folder served next to the page, or a url); the consumer can override it. */\n readonly baseUrl?: string\n /** SDK sound id → its files. */\n readonly sounds: Readonly<Record<string, LocalSoundEntry>>\n}\n\nexport class LocalSoundPackError extends Error {\n readonly problems: readonly string[]\n constructor(problems: readonly string[]) {\n super(`invalid local sound pack: ${problems.join('; ')}`)\n this.name = 'LocalSoundPackError'\n this.problems = problems\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null && !Array.isArray(value)\nconst isLicense = (value: unknown): value is LocalPackLicense => (LOCAL_PACK_LICENSES as readonly unknown[]).includes(value)\nconst isBus = (value: unknown): value is BusId => (BUS_IDS as readonly unknown[]).includes(value)\n\nfunction entryProblems(id: string, entry: unknown): string[] {\n if (!isRecord(entry)) return [`${id}: not an object`]\n const problems: string[] = []\n const files = entry.files\n if (!Array.isArray(files) || files.length === 0 || !files.every((file) => typeof file === 'string' && file.length > 0)) problems.push(`${id}: files must be a non-empty list of paths`)\n if (!isLicense(entry.license)) problems.push(`${id}: license must be one of ${LOCAL_PACK_LICENSES.join(', ')}`)\n if (entry.prefer !== undefined && !(LOCAL_PACK_PREFERENCES as readonly unknown[]).includes(entry.prefer)) problems.push(`${id}: prefer must be pack or sdk`)\n if (entry.bus !== undefined && !isBus(entry.bus)) problems.push(`${id}: unknown bus ${String(entry.bus)}`)\n if (entry.gain !== undefined && (typeof entry.gain !== 'number' || entry.gain < 0)) problems.push(`${id}: gain must be a number ≥ 0`)\n if (entry.score !== undefined && (typeof entry.score !== 'number' || entry.score < 0 || entry.score > 10)) problems.push(`${id}: score must be 0–10`)\n return problems\n}\n\n/** Checks a parsed JSON config; every problem is reported at once. */\nexport function parseLocalSoundPack(value: unknown): LocalSoundPack {\n if (!isRecord(value)) throw new LocalSoundPackError(['the pack is not an object'])\n const problems: string[] = []\n if (value.version !== 1) problems.push('version must be 1')\n if (value.baseUrl !== undefined && typeof value.baseUrl !== 'string') problems.push('baseUrl must be a string')\n if (!isRecord(value.sounds)) problems.push('sounds must be an object of id → entry')\n else for (const [id, entry] of Object.entries(value.sounds)) problems.push(...entryProblems(id, entry))\n if (problems.length > 0) throw new LocalSoundPackError(problems)\n return value as LocalSoundPack\n}\n\n/** Whether the SDK may ship a file of this licence (public domain or attribution). */\nexport const isShippableLicense = (license: string | undefined): boolean => (SDK_LICENSES as readonly (string | undefined)[]).includes(license)\n\nconst CATALOG = new Map([...SFX_CATALOG, ...SFX_IMPACTS].map((entry) => [entry.id, entry]))\n\nconst busOf = (id: string, entry: LocalSoundEntry): BusId => {\n if (entry.bus) return entry.bus\n const category = CATALOG.get(id)?.category ?? ''\n return kitSampleDefaults({ id, category })?.bus ?? 'world'\n}\n\nexport type LocalPackSampleOptions = {\n /** Overrides the pack's `baseUrl`. */\n readonly baseUrl?: string\n}\n\n/** The pack as sample sounds, one per id, with the synthesized sound of the catalogue as the fallback. */\nexport function localPackSamples(pack: LocalSoundPack, options: LocalPackSampleOptions = {}): SampleSound[] {\n const baseUrl = options.baseUrl ?? pack.baseUrl ?? ''\n return Object.entries(pack.sounds).map(([id, entry]) => {\n const current = CATALOG.get(id)?.current\n const isLoop = /_loop(_|$)/.test(id)\n return {\n id,\n bus: busOf(id, entry),\n close: entry.files.map((file) => ({ url: `${baseUrl}${file}` })),\n pitch: isLoop ? 0 : 0.04,\n ...(isLoop ? { loop: true } : {}),\n ...(entry.gain === undefined ? {} : { gain: entry.gain }),\n ...(current ? { fallback: current } : {}),\n license: entry.license,\n sources: entry.files.map((file) => `local: ${file} ${entry.license}`),\n }\n })\n}\n","/**\n * The owner's own sounds, kept out of the kit. Files whose licence the kit cannot redistribute (game rips, paid libraries) never enter git or npm:\n * a list of picks (`user-sounds/picks.json`: sound id, the pack and the files in it) says which file answers which sound, the script `sfx:user`\n * converts those files from the owner's folder into `.sfx-local/` (ignored by git) with a manifest, and `loadUserSamples` registers them on an\n * engine from where that folder is served.\n *\n * Each pick has a role. `primary`: the kit has no recording of that sound, so the owner's file plays. `fallback`: the kit's recording plays first;\n * the owner's file is registered under the same id only when the kit has none loaded (its manifest could not be fetched). Every pick is also\n * registered under `user:<id>`, so a panel can play the owner's take next to the kit's.\n */\nimport { sampleBankFromManifest, splitTier } from './manifest'\nimport type { SfxLayer } from './manifest'\nimport { kitSampleDefaults } from './kit-samples'\nimport type { SoundBank } from './recipe'\n\nexport const USER_SAMPLES_BANK = 'user_samples'\nexport const KIT_SAMPLES_BANK = 'kit_samples'\n/** Prefix of the id each pick is also registered under. */\nexport const USER_SOUND_PREFIX = 'user:'\n\nexport type UserSoundRole = 'primary' | 'fallback'\n\n/** One sound the owner's files answer. */\nexport type UserSoundPick = {\n readonly id: string\n readonly role: UserSoundRole\n /** The kit category (`armas`, `personagem`...): the bus and the folder of the converted files. */\n readonly category: string\n readonly label: string\n /** The pack the files come from (a folder of the owner's sounds). */\n readonly pack: string\n /** Paths inside the pack (matched by their end, so the pack may be nested differently). */\n readonly files: readonly string[]\n /** 0–10: how well the files fit the sound (rate, clipping, band). */\n readonly score: number\n readonly loop?: boolean\n /** Who made the files, when the pack is not the list's `author`. */\n readonly author?: string\n /** Their licence, when not the list's `license`. */\n readonly license?: string\n}\n\nexport type UserSoundPicks = {\n readonly version: 1\n readonly author: string\n readonly license: string\n readonly picks: readonly UserSoundPick[]\n}\n\n/** One converted file, as `sfx:user` writes it. */\nexport type UserSfxFile = {\n readonly file: string\n readonly sampleRate: number\n readonly channels: number\n readonly peak: number\n readonly seconds: number\n readonly source: string\n readonly author: string\n readonly license: string\n}\n\nexport type UserSfxSound = {\n readonly id: string\n readonly category: string\n readonly role: UserSoundRole\n readonly label: string\n readonly layers: Partial<Readonly<Record<SfxLayer, readonly UserSfxFile[]>>>\n}\n\n/** The manifest `sfx:user` writes in `.sfx-local/manifest.json`. */\nexport type UserSfxManifest = {\n readonly version: 1\n readonly sounds: readonly UserSfxSound[]\n}\n\n/** Where a voice came from: the kit's recording, the owner's file, or the synthesized recipe. */\nexport type SoundSource = 'sdk' | 'user' | 'synth'\n\n/** The source of a started voice, from its kind and the bank its id is registered in. */\nexport function soundSourceOf(event: { readonly kind: 'recipe' | 'sample'; readonly bank?: string }): SoundSource {\n if (event.kind === 'recipe') return 'synth'\n return event.bank === USER_SAMPLES_BANK ? 'user' : 'sdk'\n}\n\nexport type UserSampleBankOptions = {\n readonly baseUrl?: string\n /** True for an id the kit already plays from a file: a `fallback` pick is then only registered under `user:<id>`. */\n readonly kitHas?: (id: string) => boolean\n}\n\nexport type UserSampleBankResult = {\n readonly bank: SoundBank\n /** Ids the owner's files now answer (primary picks, and fallbacks the kit lacks). */\n readonly playing: readonly string[]\n /** Fallback ids the kit answers, kept under `user:<id>`. */\n readonly behindKit: readonly string[]\n}\n\n/** The bank of the owner's converted files. */\nexport function userSampleBank(manifest: UserSfxManifest, options: UserSampleBankOptions = {}): UserSampleBankResult {\n const playing: string[] = []\n const behindKit: string[] = []\n const sounds: UserSfxSound[] = []\n for (const picked of manifest.sounds) {\n // a strength tier (`mag_seat_medium`) answers its base id (`mag_seat`), the id the kit's tiers are played by\n const sound = { ...picked, id: splitTier(picked.id).base }\n sounds.push({ ...sound, id: `${USER_SOUND_PREFIX}${sound.id}` })\n if (sound.role === 'fallback' && options.kitHas?.(sound.id)) {\n behindKit.push(sound.id)\n continue\n }\n sounds.push(sound)\n playing.push(sound.id)\n }\n const bank = sampleBankFromManifest(\n { sounds },\n {\n id: USER_SAMPLES_BANK,\n baseUrl: options.baseUrl ?? '',\n defaults: (sound) => kitSampleDefaults({ id: sound.id.replace(USER_SOUND_PREFIX, ''), category: sound.category }),\n },\n )\n return { bank, playing, behindKit }\n}\n\nexport type LoadUserSamplesOptions = UserSampleBankOptions & {\n readonly fetchManifest?: (url: string) => Promise<UserSfxManifest>\n}\n\ntype Registers = { register(bank: SoundBank): void; readonly registry?: { sample(id: string): unknown } }\n\nconst fetchManifestJson = async (url: string): Promise<UserSfxManifest> => {\n const page = (globalThis as { location?: { href?: string } }).location?.href\n if (new URL(url, page ?? 'http://localhost/').protocol === 'file:') throw new Error(`${url}: file:// is not fetched`)\n const response = await fetch(url)\n if (!response.ok) throw new Error(`${url}: ${response.status}`)\n return (await response.json()) as UserSfxManifest\n}\n\n/**\n * Fetches `<baseUrl>manifest.json` (default `./sfx-local/`) and registers the owner's files. Call it after the kit's bank loaded, so a fallback\n * pick stays behind the kit's recording. Resolves to `null` when the folder is not there (a machine without the owner's sounds): nothing changes.\n */\nexport async function loadUserSamples(engine: Registers, options: LoadUserSamplesOptions = {}): Promise<UserSampleBankResult | null> {\n const baseUrl = options.baseUrl ?? './sfx-local/'\n let manifest: UserSfxManifest\n try {\n manifest = await (options.fetchManifest ?? fetchManifestJson)(`${baseUrl}manifest.json`)\n } catch {\n return null\n }\n const kitHas = options.kitHas ?? ((id: string): boolean => Boolean(engine.registry?.sample(id)))\n const result = userSampleBank(manifest, { baseUrl, kitHas })\n engine.register(result.bank)\n return result\n}\n","import type { SfxBlow, SfxMaterial, SfxState } from '../catalog'\nimport type { CriterionId } from '../measure/criteria'\nimport type { SampleEnvironment } from '../sample'\nimport type { SoundSource } from '../user-samples'\n\ntype Strength = 'light' | 'medium' | 'heavy'\n\nexport type SoundCheckText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<\n Record<\n | 'category'\n | 'sound'\n | 'play'\n | 'play_user'\n | 'material'\n | 'blow'\n | 'strike'\n | 'distance'\n | 'bearing'\n | 'environment'\n | 'strength'\n | 'wall'\n | 'burst'\n | 'play_a'\n | 'play_b'\n | 'ab_cycle'\n | 'blind'\n | 'reveal'\n | 'prefer_a'\n | 'prefer_b'\n | 'measure'\n | 'record'\n | 'approve',\n string\n >\n >\n readonly hints: Readonly<Record<'play_user' | 'sound' | 'strike' | 'wall' | 'burst' | 'ab_cycle' | 'blind' | 'measure' | 'record' | 'approve', string>>\n readonly categories: Readonly<Record<string, string>>\n readonly blows: Readonly<Record<SfxBlow, string>>\n readonly materials: Readonly<Record<SfxMaterial, string>>\n readonly environments: Readonly<Record<SampleEnvironment, string>>\n readonly strengths: Readonly<Record<Strength, string>>\n readonly states: Readonly<Record<SfxState, string>>\n readonly criteria: Readonly<Record<CriterionId, string>>\n readonly metrics: Readonly<Record<'source' | 'chosen' | 'matrix' | 'last' | 'ab' | 'blind' | 'verdicts' | 'state' | 'count' | 'unlicensed', string>>\n readonly run: Readonly<Record<'idle' | 'measuring' | 'done' | 'failed' | 'recording' | 'recorded', string>>\n readonly words: Readonly<Record<'none' | 'hidden' | 'prefers' | 'approved' | 'local_file' | 'sdk_file' | 'synth', string>>\n /** Where the voice came from: the kit's file, the owner's file, the synthesized recipe. */\n readonly sources: Readonly<Record<SoundSource, string>>\n readonly probe: string\n readonly wall: string\n readonly scenarios: Readonly<Record<'pipeline' | 'criteria' | 'loop' | 'panel', string>>\n}\n\nconst PT: SoundCheckText = {\n group: 'Som',\n name: 'Painel de som (arquivos e C1–C10)',\n controls: {\n category: '1 · Categoria',\n sound: '1 · Som',\n play: '1 · ▶ Tocar',\n play_user: '1 · ▶ Tocar o seu',\n material: '2 · Material',\n blow: '2 · Golpe',\n strike: '2 · ▶ Tocar golpe',\n distance: '3 · Distância',\n bearing: '3 · Direção',\n environment: '3 · Lugar',\n strength: '3 · Força',\n wall: '3 · Atrás da parede',\n burst: '3 · Rajada 20×',\n play_a: '4 · ▶ A (atual)',\n play_b: '4 · ▶ B (novo)',\n ab_cycle: '4 · Alternar A/B',\n blind: '4 · Às cegas (X)',\n reveal: '4 · Revelar X',\n prefer_a: '4 · Prefiro A',\n prefer_b: '4 · Prefiro B',\n measure: '5 · Medir C1–C10',\n record: '5 · Gravar 3 s',\n approve: '5 · Aprovo (C10)',\n },\n hints: {\n play_user: 'Toca a sua gravação deste som (dos seus pacotes, fora do git), mesmo quando o SDK tem uma melhor e toca na frente.',\n sound: 'A = arquivo, S = sintetizado, F = faltando. O que tem arquivo toca o arquivo; o resto toca o som atual.',\n strike: 'Toca impact_<material>_<golpe>: o arquivo se existir, senão o som atual daquele material.',\n wall: 'Põe a parede de casa entre você e a fonte: o som fica abafado (C4).',\n burst: 'Vinte vezes a cada 60 ms, como uma rajada (C9).',\n ab_cycle: 'A, B, A, B, um por segundo.',\n blind: 'Toca A ou B sem dizer qual; depois revele.',\n measure: 'Mede o som escolhido no motor real (contexto offline): sincronia, som certo, distância, lado, variação, volume, força, cauda e rajada.',\n record: 'Grava 3 s da saída com o som tocando e baixa o arquivo (C10).',\n approve: 'Marca o C10 do som escolhido como aprovado pelo seu ouvido.',\n },\n categories: {\n armas: 'Armas',\n impactos: 'Impactos',\n 'explosoes-fogo': 'Explosões e fogo',\n personagem: 'Personagem',\n veiculos: 'Veículos',\n 'itens-portas': 'Itens e portas',\n ambiente: 'Ambiente',\n calibracao: 'Calibração (SDK)',\n },\n blows: { bullet: 'tiro', blunt: 'soco/chute', blade: 'faca', break: 'quebra', drag: 'arrasto/queda' },\n materials: {\n steel: 'aço',\n aluminium: 'alumínio',\n wood: 'madeira',\n plywood: 'compensado',\n mdf: 'MDF',\n glass: 'vidro',\n tempered_glass: 'vidro temperado',\n ceramic: 'cerâmica',\n concrete: 'concreto',\n brick: 'tijolo',\n plaster: 'gesso',\n plastic: 'plástico',\n fabric: 'tecido',\n paper: 'papelão',\n foliage: 'folhagem',\n soil: 'terra',\n flesh: 'carne',\n },\n environments: { indoor: 'interior', outdoor: 'exterior' },\n strengths: { light: 'leve', medium: 'médio', heavy: 'forte' },\n states: { file: 'A', synth: 'S', missing: 'F' },\n criteria: { C1: 'C1 Sincronia', C2: 'C2 Certo p/ ação', C3: 'C3 Distância', C4: 'C4 Posição', C5: 'C5 Variação', C6: 'C6 Volume', C7: 'C7 Intensidade', C8: 'C8 Cauda', C9: 'C9 Rajada', C10: 'C10 Escuta' },\n metrics: { source: '1 · Fonte do que tocou', chosen: '1 · Escolhido', matrix: '2 · Matriz', last: 'Último tocado', ab: '4 · A × B', blind: '4 · X', verdicts: '4 · Preferências', state: '5 · Medição', count: '1 · Catálogo', unlicensed: '1 · Arquivo sem licença' },\n run: { idle: 'parada', measuring: 'medindo…', done: 'pronta', failed: 'falhou', recording: 'gravando…', recorded: 'gravação baixada' },\n words: { none: '—', hidden: '? (revele)', prefers: 'prefere', approved: 'aprovado pelo dono', local_file: 'arquivo do pacote local', sdk_file: 'gravação do SDK', synth: 'síntese do SDK' },\n sources: { sdk: 'SDK', user: 'seu som', synth: 'sintetizado' },\n probe: 'Fonte do som',\n wall: 'Parede (oclusão)',\n scenarios: { pipeline: 'Arquivo → decodifica → toca (round-robin, cauda)', criteria: 'Critérios C1–C9 no som de calibração', loop: 'Loop de arquivo: emenda sem buraco (crossfade)', panel: 'Painel: categorias, matriz, A/B e parede' },\n}\n\nconst EN: SoundCheckText = {\n ...PT,\n group: 'Sound',\n name: 'Sound panel (files and C1–C10)',\n controls: {\n category: '1 · Category',\n sound: '1 · Sound',\n play: '1 · ▶ Play',\n play_user: '1 · ▶ Play yours',\n material: '2 · Material',\n blow: '2 · Blow',\n strike: '2 · ▶ Play blow',\n distance: '3 · Distance',\n bearing: '3 · Bearing',\n environment: '3 · Place',\n strength: '3 · Strength',\n wall: '3 · Behind the wall',\n burst: '3 · Burst 20×',\n play_a: '4 · ▶ A (current)',\n play_b: '4 · ▶ B (new)',\n ab_cycle: '4 · Alternate A/B',\n blind: '4 · Blind (X)',\n reveal: '4 · Reveal X',\n prefer_a: '4 · Prefer A',\n prefer_b: '4 · Prefer B',\n measure: '5 · Measure C1–C10',\n record: '5 · Record 3 s',\n approve: '5 · Approve (C10)',\n },\n hints: {\n play_user: 'Plays your own take of this sound (from your packs, kept out of git), even where the SDK has a better one that plays first.',\n sound: 'A = file, S = synthesized, F = missing. A file plays the file; the rest plays the current sound.',\n strike: 'Plays impact_<material>_<blow>: the file if there is one, else the current sound of that material.',\n wall: 'Puts the house wall between you and the source: the sound is muffled (C4).',\n burst: 'Twenty times every 60 ms, like a burst (C9).',\n ab_cycle: 'A, B, A, B, one a second.',\n blind: 'Plays A or B without saying which; reveal it after.',\n measure: 'Measures the chosen sound through the real engine (offline context): sync, right sound, distance, side, variation, level, strength, tail and burst.',\n record: 'Records 3 s of the output with the sound playing and downloads it (C10).',\n approve: 'Marks C10 of the chosen sound as approved by your ear.',\n },\n categories: { armas: 'Weapons', impactos: 'Impacts', 'explosoes-fogo': 'Explosions and fire', personagem: 'Character', veiculos: 'Vehicles', 'itens-portas': 'Items and doors', ambiente: 'Ambience', calibracao: 'Calibration (SDK)' },\n blows: { bullet: 'bullet', blunt: 'punch/kick', blade: 'knife', break: 'break', drag: 'drag/fall' },\n materials: {\n steel: 'steel',\n aluminium: 'aluminium',\n wood: 'wood',\n plywood: 'plywood',\n mdf: 'MDF',\n glass: 'glass',\n tempered_glass: 'tempered glass',\n ceramic: 'ceramic',\n concrete: 'concrete',\n brick: 'brick',\n plaster: 'plaster',\n plastic: 'plastic',\n fabric: 'fabric',\n paper: 'cardboard',\n foliage: 'foliage',\n soil: 'soil',\n flesh: 'flesh',\n },\n environments: { indoor: 'indoor', outdoor: 'outdoor' },\n strengths: { light: 'light', medium: 'medium', heavy: 'heavy' },\n criteria: { C1: 'C1 Sync', C2: 'C2 Right sound', C3: 'C3 Distance', C4: 'C4 Position', C5: 'C5 Variation', C6: 'C6 Level', C7: 'C7 Strength', C8: 'C8 Tail', C9: 'C9 Burst', C10: 'C10 Listening' },\n metrics: { source: '1 · Source of what played', chosen: '1 · Chosen', matrix: '2 · Matrix', last: 'Last played', ab: '4 · A × B', blind: '4 · X', verdicts: '4 · Preferences', state: '5 · Measurement', count: '1 · Catalogue', unlicensed: '1 · File without licence' },\n run: { idle: 'idle', measuring: 'measuring…', done: 'done', failed: 'failed', recording: 'recording…', recorded: 'recording downloaded' },\n words: { none: '—', hidden: '? (reveal)', prefers: 'prefers', approved: 'approved by the owner', local_file: 'local pack file', sdk_file: 'SDK recording', synth: 'SDK synthesis' },\n sources: { sdk: 'SDK', user: 'your sound', synth: 'synthesized' },\n probe: 'Sound source',\n wall: 'Wall (occlusion)',\n scenarios: { pipeline: 'File → decode → play (round-robin, tail)', criteria: 'Criteria C1–C9 on the calibration sound', loop: 'File loop: seamless joins (crossfade)', panel: 'Panel: categories, matrix, A/B and wall' },\n}\n\nexport const soundCheckTextOf = (locale: string): SoundCheckText => (locale.startsWith('en') ? EN : PT)\n","import type { AreaPlacement, BenchChange, ChoiceOption, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\n\nimport { SFX_BLOWS, SFX_CATALOG, SFX_CATEGORIES, SFX_IMPACTS, SFX_MATERIALS, impactSoundId, sfxState } from '../catalog'\nimport type { SfxBlow, SfxEntry, SfxMaterial, SfxState } from '../catalog'\nimport { CALIBRATION_ID, CALIBRATION_LOOP_ID, CALIBRATION_LOOP_SOUND, CALIBRATION_SOUND, calibrationLoader, isCalibrationUrl } from '../measure/calibration'\nimport { CRITERIA, measureCriteria, recordOutput } from '../measure/criteria'\nimport type { ActionCheck, CriterionId, CriterionResult } from '../measure/criteria'\nimport { isShippableLicense } from '../local-pack'\nimport type { LoopRecipe, SampleSound, SoundBank, SoundRecipe } from '../recipe'\nimport { GAME_SFX_BANK } from '../recipes/noise-class'\nimport { SAMPLE_ENVIRONMENTS } from '../sample'\nimport type { SampleEnvironment } from '../sample'\nimport { createAudioEngine } from '../webaudio/engine'\nimport type { AudioEngine, PlayOptions, VoiceHandle, VoiceStartEvent } from '../webaudio/engine'\nimport { fetchLoader } from '../webaudio/sample-store'\nimport type { SampleLoader } from '../webaudio/sample-store'\nimport type { EngineSink } from '../webaudio/sink'\nimport type { AudioScenarioLike } from './module'\nimport { USER_SOUND_PREFIX, soundSourceOf } from '../user-samples'\nimport { soundCheckTextOf } from './sound-check-locale'\nimport type { SoundCheckText } from './sound-check-locale'\n\nexport { soundCheckTextOf } from './sound-check-locale'\nexport type { SoundCheckText } from './sound-check-locale'\n\nexport const SOUND_STRENGTHS = { light: 0.1, medium: 0.5, heavy: 0.9 } as const\nexport type SoundStrength = keyof typeof SOUND_STRENGTHS\nexport const CALIBRATION_CATEGORY = 'calibracao'\n\nexport type SoundCheckModuleOptions = {\n /** Banks with sample sounds to try (the calibration sound is always there); registered in the host's engine when it lends one. */\n readonly banks?: readonly SoundBank[]\n /** Where the files of those banks come from (default `fetch`). */\n readonly loader?: SampleLoader\n /** The engine to use (default the host's in `host.audio`, else a new one). */\n readonly engine?: AudioEngine\n readonly locale?: string\n /** First sound chosen (default the calibration sound). */\n readonly sound?: string\n /** The sounds by category (default the kit's catalogue, `SFX_CATALOG` and the impact matrix). */\n readonly catalog?: readonly SfxEntry[]\n /** C2: the actions and the sounds they must play, per sound id. */\n readonly actions?: Readonly<Record<string, readonly ActionCheck[]>>\n /** C6: sound ids loudest first. */\n readonly loudnessOrder?: readonly string[]\n /** Draws the source of the sound in the area (a portable radio of the items catalogue, say). Without it no source is drawn. */\n readonly probe?: (THREE: unknown) => unknown\n /** Draws the wall that goes between the listener and the source (a house wall of the floorplan renderer). Without it no wall is drawn. */\n readonly wall?: (THREE: unknown) => unknown\n}\n\nexport type SoundCheckModule = TestableModule<AudioScenarioLike> & {\n readonly engine: AudioEngine\n /** Measures the chosen sound (every criterion) and keeps the results for the bench. */\n measure(): Promise<readonly CriterionResult[]>\n results(): readonly CriterionResult[]\n /** Every voice the engine started while the module was attached (the event log of C1/C2). */\n events(): readonly VoiceStartEvent[]\n /** Plays the chosen sound (its file when there is one, else the current sound). */\n play(): VoiceHandle | null\n /** The A/B pair of the chosen sound: the current (synthesized) id and the new (file) id. */\n pair(): { readonly a: string | null; readonly b: string | null }\n /** The preferences given (`sound → 'A' | 'B'`). */\n verdicts(): Readonly<Record<string, 'A' | 'B'>>\n /** The sounds whose C10 the owner approved. */\n approvals(): readonly string[]\n}\n\nconst CALIBRATION_BANK: SoundBank = { id: 'calibration', samples: [CALIBRATION_SOUND, CALIBRATION_LOOP_SOUND] }\nconst DISTANCES = [1, 10, 50, 200] as const\nconst PROBE_ID = 'sound_check_source'\nconst WALL_ID = 'sound_check_wall'\nconst EYE: Vec3 = [0, 1.7, 3]\n// the source is drawn at most this far (the arena is ~14 m); the sound plays at the real distance\nconst DRAWN_MAX = 11\nconst WALL_AT = -2.5\nconst LOG_LIMIT = 200\n\ntype Ears = { readonly position: Vec3; readonly yaw: number }\ntype Camera = { readonly position: { readonly x: number; readonly y: number; readonly z: number }; getWorldDirection(target: unknown): { readonly x: number; readonly z: number } }\ntype ThreeLike = { Vector3: new () => unknown }\ntype Placed = { userData?: Record<string, unknown>; visible?: boolean; position?: { set(x: number, y: number, z: number): void }; traverse(visit: (object: Placed) => void): void }\n\n/**\n * The sound panel of the test room, in the five blocks the owner approved: (1) the sounds of each category with their state (file, synthesized, missing),\n * (2) the material × blow matrix, (3) where and how it plays (distance, bearing, indoor or outdoor, strength, behind the house wall, a burst), (4) A/B of the\n * current sound against the new file (alternating and blind, with the preference kept) and (5) the measurement of C1–C10 with a 3 s recording and the\n * owner's approval for C10. It uses the host's engine (every bank of the room) and lends it the calibration takes.\n */\nexport function createSoundCheckModule(options: SoundCheckModuleOptions = {}): SoundCheckModule {\n const locale = options.locale ?? 'pt-BR'\n const text: SoundCheckText = soundCheckTextOf(locale)\n const ownBanks: SoundBank[] = [CALIBRATION_BANK, ...(options.banks ?? [])]\n const loader = calibrationLoader(options.loader ?? fetchLoader())\n const log: VoiceStartEvent[] = []\n const catalog: readonly SfxEntry[] = options.catalog ?? [...SFX_CATALOG, ...SFX_IMPACTS]\n let engine: AudioEngine = options.engine ?? createAudioEngine({ banks: [GAME_SFX_BANK, ...ownBanks], samples: { loader } })\n if (options.engine) for (const bank of ownBanks) engine.register(bank)\n let host: ModuleHost | null = null\n let results: CriterionResult[] = []\n let run: keyof SoundCheckText['run'] = 'idle'\n const verdicts: Record<string, 'A' | 'B'> = {}\n const approvals = new Set<string>()\n let blind: { readonly side: 'A' | 'B'; revealed: boolean } | null = null\n const chosen = {\n category: options.sound && options.sound !== CALIBRATION_ID ? (catalog.find((entry) => entry.id === options.sound)?.category ?? CALIBRATION_CATEGORY) : CALIBRATION_CATEGORY,\n sound: options.sound ?? CALIBRATION_ID,\n material: 'concrete' as SfxMaterial,\n blow: 'bullet' as SfxBlow,\n distance: 10,\n bearing: 0,\n environment: 'outdoor' as SampleEnvironment,\n strength: 'medium' as SoundStrength,\n wall: false,\n }\n\n const registry = () => engine.registry\n const entryOf = (id: string): SfxEntry | undefined => catalog.find((entry) => entry.id === id)\n const stateOf = (id: string): SfxState => {\n const entry = entryOf(id)\n if (entry) return sfxState(entry, registry())\n return registry().sample(id) ? 'file' : registry().sound(id) ? 'synth' : 'missing'\n }\n /** A = what plays today (the synthesized recipe), B = the file. */\n const pairOf = (id: string): { a: string | null; b: string | null } => {\n const entry = entryOf(id)\n const sample = registry().sample(id)\n const current = entry?.current ?? sample?.fallback ?? (registry().sound(id) ? id : undefined)\n return { a: current && registry().sound(current) ? current : null, b: sample ? id : null }\n }\n\n const soundsOf = (category: string): string[] => {\n if (category === CALIBRATION_CATEGORY) return registry().sampleIds().filter((id) => !entryOf(id))\n return catalog.filter((entry) => entry.category === category).map((entry) => entry.id)\n }\n const sourceOfId = (id: string): string => {\n const state = stateOf(id)\n if (state !== 'file') return text.states[state]\n const own = registry().sample(`${USER_SOUND_PREFIX}${id}`) ? ' +seu' : ''\n return `${text.states.file} ${text.sources[soundSourceOf({ kind: 'sample', bank: registry().bankOf(id) })]}${own}`\n }\n const label = (id: string): string => {\n const entry = entryOf(id)\n return `${id}${entry ? ` · P${entry.priority}` : ''} · ${sourceOfId(id)}`\n }\n const soundOptions = (): ChoiceOption[] => soundsOf(chosen.category).map((id) => ({ id, name: label(id) }))\n\n // the listener is the host camera; without one it stands at the eye of the area, looking along −z\n const listener = (): Ears => {\n const camera = host?.camera as Camera | undefined\n const three = host?.THREE as ThreeLike | undefined\n if (typeof camera?.getWorldDirection !== 'function' || typeof three?.Vector3 !== 'function' || !camera.position) return { position: EYE, yaw: 0 }\n const direction = camera.getWorldDirection(new three.Vector3())\n return { position: [camera.position.x, camera.position.y, camera.position.z], yaw: Math.atan2(-direction.x, -direction.z) }\n }\n // `bearing` is degrees to the right of straight ahead\n const offset = (ears: Ears, distance: number): Vec3 => {\n const bearing = (chosen.bearing * Math.PI) / 180\n const forward = [-Math.sin(ears.yaw), -Math.cos(ears.yaw)] as const\n const right = [Math.cos(ears.yaw), -Math.sin(ears.yaw)] as const\n return [ears.position[0] + distance * (forward[0] * Math.cos(bearing) + right[0] * Math.sin(bearing)), ears.position[1], ears.position[2] + distance * (forward[1] * Math.cos(bearing) + right[1] * Math.sin(bearing))]\n }\n const playOptions = (extra: PlayOptions = {}): PlayOptions => {\n const ears = listener()\n engine.setListener(ears)\n return { position: offset(ears, chosen.distance), environment: chosen.environment, intensity: SOUND_STRENGTHS[chosen.strength], occlusion: chosen.wall ? 1 : 0, ...extra }\n }\n\n const playId = (id: string | null, extra: PlayOptions = {}): VoiceHandle | null => {\n if (!id) return null\n engine.unlock()\n return engine.play(id, playOptions(extra))\n }\n const preferred = (id: string): string | null => pairOf(id).b ?? pairOf(id).a ?? (registry().sound(id) ? id : null)\n const play = (): VoiceHandle | null => playId(preferred(chosen.sound))\n // B is the file: while its files load a sample sound plays its fallback, so B waits for them\n const playB = async (delay = 0): Promise<void> => {\n const { b } = pairOf(chosen.sound)\n if (!b) return\n if (engine.sampleStatus(b) !== 'ready') await engine.loadSamples([b])\n playId(b, { delay })\n }\n // the owner's take of the chosen sound (`user:<id>`), loaded first: it has no recipe to stand in while it loads\n const playUser = async (): Promise<void> => {\n const own = `${USER_SOUND_PREFIX}${chosen.sound}`\n if (!registry().sample(own)) return\n if (engine.sampleStatus(own) !== 'ready') await engine.loadSamples([own])\n playId(own)\n }\n const playA = (delay = 0): void => void playId(pairOf(chosen.sound).a, { delay })\n\n // the source and the wall drawn in the area follow the bench: the source at the bearing and distance (drawn at most DRAWN_MAX m), the wall only when asked\n const placeScenery = (): void => {\n const scene = host?.scene as Placed | undefined\n if (typeof scene?.traverse !== 'function') return\n const at = offset({ position: EYE, yaw: 0 }, Math.min(chosen.distance, DRAWN_MAX))\n scene.traverse((object) => {\n if (object.userData?.[PROBE_ID] === true) object.position?.set(at[0], 0, at[2])\n if (object.userData?.[WALL_ID] === true) object.visible = chosen.wall\n })\n }\n\n const measure = async (): Promise<readonly CriterionResult[]> => {\n run = 'measuring'\n try {\n engine.unlock()\n const context = (engine.output()?.context as AudioContext | undefined) ?? null\n // the measuring engines get every sound of this engine, so the fallbacks and the order of C6 are the room's\n const bank: SoundBank = {\n id: 'measured',\n sounds: registry().soundIds().map((id) => registry().sound(id)).filter((recipe): recipe is SoundRecipe => recipe !== undefined),\n loops: registry().loopIds().map((id) => registry().loop(id)).filter((recipe): recipe is LoopRecipe => recipe !== undefined),\n samples: registry().sampleIds().map((id) => registry().sample(id)).filter((sample): sample is SampleSound => sample !== undefined),\n }\n results = await measureCriteria({\n sound: chosen.sound,\n banks: [bank],\n loader,\n ...(context ? { baseLatency: context.baseLatency ?? 0, outputLatency: context.outputLatency ?? 0 } : {}),\n ...(options.actions?.[chosen.sound] ? { actions: options.actions[chosen.sound] as readonly ActionCheck[] } : {}),\n ...(options.loudnessOrder ? { loudnessOrder: options.loudnessOrder } : {}),\n })\n if (approvals.has(chosen.sound)) results = results.map((result) => (result.id === 'C10' ? { ...result, pass: true, value: text.words.approved } : result))\n run = 'done'\n } catch (error) {\n run = 'failed'\n results = [{ id: 'C1', pass: false, value: error instanceof Error ? error.message : String(error), target: '' }]\n }\n ;(globalThis as { __soundCheck?: unknown }).__soundCheck = { sound: chosen.sound, results }\n return results\n }\n\n const record = async (): Promise<void> => {\n run = 'recording'\n const blob = await recordOutput(engine, 3, () => {\n for (let index = 0; index < 4; index++) playId(preferred(chosen.sound), { delay: index * 0.6 })\n })\n const documentLike = (globalThis as { document?: Document }).document\n if (blob && documentLike && typeof URL.createObjectURL === 'function') {\n const link = documentLike.createElement('a')\n link.href = URL.createObjectURL(blob)\n link.download = `${chosen.sound}-${chosen.environment}-${chosen.distance}m.webm`\n link.click()\n run = 'recorded'\n } else run = blob ? 'recorded' : 'failed'\n }\n\n const approve = (): void => {\n approvals.add(chosen.sound)\n results = results.map((result) => (result.id === 'C10' ? { ...result, pass: true, value: text.words.approved } : result))\n host?.log(`${chosen.sound}: C10 ${text.words.approved}`, { sound: chosen.sound }, 'sound')\n }\n const prefer = (side: 'A' | 'B'): void => {\n verdicts[chosen.sound] = side\n const pair = pairOf(chosen.sound)\n host?.log(`${chosen.sound}: ${text.words.prefers} ${side}`, { sound: chosen.sound, prefers: side, a: pair.a, b: pair.b }, 'sound')\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'choice', id: 'category', name: text.controls.category, options: [...SFX_CATEGORIES, CALIBRATION_CATEGORY].map((id) => ({ id, name: text.categories[id] ?? id })), default: chosen.category },\n { kind: 'choice', id: 'sound', name: text.controls.sound, hint: text.hints.sound, options: soundOptions(), default: chosen.sound },\n { kind: 'action', id: 'play', name: text.controls.play },\n { kind: 'action', id: 'play_user', name: text.controls.play_user, hint: text.hints.play_user },\n { kind: 'choice', id: 'material', name: text.controls.material, options: SFX_MATERIALS.map(([id]) => ({ id, name: text.materials[id] })), default: chosen.material },\n { kind: 'choice', id: 'blow', name: text.controls.blow, options: SFX_BLOWS.map((id) => ({ id, name: text.blows[id] })), default: chosen.blow },\n { kind: 'action', id: 'strike', name: text.controls.strike, hint: text.hints.strike },\n { kind: 'choice', id: 'distance', name: text.controls.distance, options: DISTANCES.map((meters) => ({ id: String(meters), name: `${meters} m` })), default: String(chosen.distance) },\n { kind: 'number', id: 'bearing', name: text.controls.bearing, unit: '°', min: -180, max: 180, step: 15, default: chosen.bearing },\n { kind: 'choice', id: 'environment', name: text.controls.environment, options: SAMPLE_ENVIRONMENTS.map((id) => ({ id, name: text.environments[id] })), default: chosen.environment },\n { kind: 'choice', id: 'strength', name: text.controls.strength, options: (Object.keys(SOUND_STRENGTHS) as SoundStrength[]).map((id) => ({ id, name: text.strengths[id] })), default: chosen.strength },\n { kind: 'boolean', id: 'wall', name: text.controls.wall, hint: text.hints.wall, default: chosen.wall },\n { kind: 'action', id: 'burst', name: text.controls.burst, hint: text.hints.burst },\n { kind: 'action', id: 'play_a', name: text.controls.play_a },\n { kind: 'action', id: 'play_b', name: text.controls.play_b },\n { kind: 'action', id: 'ab_cycle', name: text.controls.ab_cycle, hint: text.hints.ab_cycle },\n { kind: 'action', id: 'blind', name: text.controls.blind, hint: text.hints.blind },\n { kind: 'action', id: 'reveal', name: text.controls.reveal },\n { kind: 'action', id: 'prefer_a', name: text.controls.prefer_a },\n { kind: 'action', id: 'prefer_b', name: text.controls.prefer_b },\n { kind: 'action', id: 'measure', name: text.controls.measure, hint: text.hints.measure },\n { kind: 'action', id: 'record', name: text.controls.record, hint: text.hints.record },\n { kind: 'action', id: 'approve', name: text.controls.approve, hint: text.hints.approve },\n ]\n\n const line = (id: CriterionId): string => {\n const result = results.find((entry) => entry.id === id)\n if (!result) return text.words.none\n return `${result.pass === null ? '◌' : result.pass ? '✓' : '✗'} ${result.value}`\n }\n const counts = (): string => {\n const states = catalog.map((entry) => sfxState(entry, registry()))\n const count = (state: SfxState): number => states.filter((each) => each === state).length\n return `${text.states.file} ${count('file')} · ${text.states.synth} ${count('synth')} · ${text.states.missing} ${count('missing')}`\n }\n // where the chosen id's sound comes from: a local pack's file, the SDK's recording, or its synthesis\n const sourceOf = (id: string): string => {\n const sample = registry().sample(id)\n if (!sample) return text.words.synth\n return sample.sources.some((source) => source.startsWith('local:')) ? text.words.local_file : text.words.sdk_file\n }\n // ids playing a file whose declared licence the SDK could not ship (a local pack's `unknown` / `proprietary`)\n const unlicensed = (): string => {\n const ids = registry()\n .sampleIds()\n .filter((id) => {\n const license = registry().sample(id)?.license\n return license !== undefined && !isShippableLicense(license)\n })\n return ids.length === 0 ? text.words.none : `${ids.length}: ${ids.join(', ')}`\n }\n const strikeId = (): string => impactSoundId(chosen.material, chosen.blow)\n const lastLine = (): string => {\n const last = log.at(-1)\n if (!last) return text.words.none\n const files = last.layers?.map((layer) => layer.url.split('/').pop()).join('+') ?? ''\n return `${last.kind}:${last.fallbackOf ? `${last.fallbackOf}→` : ''}${last.id}${last.tier ? `/${last.tier}` : ''} ${files}`.trim()\n }\n /** Who answered the last voice: the SDK's file, the owner's file or the synthesized recipe, with the file played. */\n const sourceLine = (): string => {\n const last = log.at(-1)\n if (!last) return text.words.none\n const file = last.layers?.find((layer) => layer.role === 'close')?.url.split('/').pop() ?? last.id\n return `${text.sources[soundSourceOf(last)]} · ${last.id.replace(USER_SOUND_PREFIX, '')} · ${file}`\n }\n\n const metrics = (): ModuleMetric[] => [\n { id: 'source', name: text.metrics.source, read: sourceLine },\n { id: 'count', name: text.metrics.count, read: counts },\n { id: 'unlicensed', name: text.metrics.unlicensed, read: unlicensed },\n { id: 'chosen', name: text.metrics.chosen, read: () => `${label(chosen.sound)}${registry().sample(chosen.sound) ? ` (${engine.sampleStatus(chosen.sound)})` : ''} · ${sourceOf(chosen.sound)}` },\n { id: 'matrix', name: text.metrics.matrix, read: () => `${strikeId()} · ${text.states[stateOf(strikeId())]}${pairOf(strikeId()).a ? ` · A=${pairOf(strikeId()).a}` : ''}` },\n { id: 'ab', name: text.metrics.ab, read: () => `A ${pairOf(chosen.sound).a ?? text.words.none} · B ${pairOf(chosen.sound).b ?? text.words.none}` },\n { id: 'blind_state', name: text.metrics.blind, read: () => (!blind ? text.words.none : blind.revealed ? `X = ${blind.side}` : text.words.hidden) },\n { id: 'verdicts', name: text.metrics.verdicts, read: () => Object.entries(verdicts).map(([id, side]) => `${id} ${text.words.prefers} ${side}`).join('; ') || text.words.none },\n { id: 'last', name: text.metrics.last, read: lastLine },\n { id: 'state', name: text.metrics.state, read: () => text.run[run] },\n ...CRITERIA.map((id) => ({ id: `criterion_${id.toLowerCase()}`, name: text.criteria[id], read: () => line(id) })),\n ]\n\n const act = (id: string): void => {\n if (id === 'play') play()\n else if (id === 'play_user') void playUser()\n else if (id === 'strike') playId(preferred(strikeId()))\n else if (id === 'burst') for (let index = 0; index < 20; index++) playId(preferred(chosen.sound), { delay: index * 0.06 })\n else if (id === 'play_a') playA()\n else if (id === 'play_b') void playB()\n else if (id === 'ab_cycle') {\n playA(0)\n void playB(1).then(() => {\n playA(2)\n return playB(3)\n })\n } else if (id === 'blind') {\n const side = Math.random() < 0.5 ? 'A' : 'B'\n blind = { side, revealed: false }\n if (side === 'A') playA()\n else void playB()\n } else if (id === 'reveal' && blind) blind.revealed = true\n else if (id === 'prefer_a') prefer('A')\n else if (id === 'prefer_b') prefer('B')\n else if (id === 'measure') void measure()\n else if (id === 'record') void record()\n else if (id === 'approve') approve()\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') return act(change.id)\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'category' && typeof value === 'string') {\n chosen.category = value\n const first = soundsOf(value)[0]\n if (first) chosen.sound = first\n host?.bench?.patch('sound', { options: soundOptions(), value: chosen.sound })\n results = []\n } else if (id === 'sound' && typeof value === 'string') {\n chosen.sound = value\n results = []\n if (registry().sample(value)) void engine.loadSamples([value])\n } else if (id === 'material' && typeof value === 'string') chosen.material = value as SfxMaterial\n else if (id === 'blow' && typeof value === 'string') chosen.blow = value as SfxBlow\n else if (id === 'distance' && typeof value === 'string') chosen.distance = Number(value)\n else if (id === 'bearing' && typeof value === 'number') chosen.bearing = value\n else if (id === 'environment' && (value === 'indoor' || value === 'outdoor')) chosen.environment = value\n else if (id === 'strength' && typeof value === 'string' && value in SOUND_STRENGTHS) chosen.strength = value as SoundStrength\n else if (id === 'wall' && typeof value === 'boolean') chosen.wall = value\n placeScenery()\n }\n\n const items = (): TestableItem[] => {\n const marked = (id: string, name: string, build: (THREE: unknown) => unknown): TestableItem => ({\n id,\n name,\n movable: false,\n build: (THREE) => {\n const root = build(THREE) as { userData?: Record<string, unknown> }\n root.userData = root.userData ?? {}\n root.userData[id] = true\n return root\n },\n })\n return [...(options.probe ? [marked(PROBE_ID, text.probe, options.probe)] : []), ...(options.wall ? [marked(WALL_ID, text.wall, options.wall)] : [])]\n }\n\n const area = (): { placements: AreaPlacement[]; view: { eye: Vec3; target: Vec3 } } => ({\n placements: [\n ...(options.probe ? [{ item: PROBE_ID, position: offset({ position: EYE, yaw: 0 }, Math.min(chosen.distance, DRAWN_MAX)), asleep: true }] : []),\n ...(options.wall ? [{ item: WALL_ID, position: [0, 0, WALL_AT] as Vec3, asleep: true }] : []),\n ],\n view: { eye: EYE, target: [0, 1.2, -8] },\n })\n\n const scenarios = (): Array<ModuleScenario<AudioScenarioLike>> => [\n {\n id: 'sample_pipeline',\n name: text.scenarios.pipeline,\n run: async ({ expect }) => {\n const report = await engine.loadSamples([CALIBRATION_ID])\n expect(report.failed.length === 0 && engine.sampleStatus(CALIBRATION_ID) === 'ready', 'the calibration files load and decode', { failed: report.failed })\n // the voices of these six plays, watched on their own: the bench log keeps only its last LOG_LIMIT voices, so after a room full of sounds an\n // index into it no longer points at these\n const started: VoiceStartEvent[] = []\n const offStarted = engine.watchVoices((event) => void started.push(event))\n const handles = Array.from({ length: 6 }, (_, index) => engine.play(CALIBRATION_ID, { distance: 2, environment: index % 2 === 0 ? 'indoor' : 'outdoor' }))\n offStarted()\n expect(handles.every((handle) => handle?.kind === 'sample'), 'it plays the files, not the fallback', { kinds: handles.map((handle) => handle?.kind) })\n const events = started.filter((event) => event.id === CALIBRATION_ID)\n const takes = events.map((event) => event.layers?.find((layer) => layer.role === 'close')?.url)\n expect(takes.length === 6 && takes.every((take, index) => index === 0 || take !== takes[index - 1]), 'never the same take twice in a row', { takes })\n const tails = events.map((event) => event.layers?.find((layer) => layer.role === 'tail')?.url ?? '')\n expect(tails[0]?.endsWith('tail_in.wav') === true && tails[1]?.endsWith('tail_out.wav') === true, 'the tail follows the place', { tails })\n for (const handle of handles) handle?.stop()\n },\n },\n {\n id: 'sample_criteria',\n name: text.scenarios.criteria,\n run: async ({ expect }) => {\n const previous = chosen.sound\n chosen.sound = CALIBRATION_ID\n const measured = await measure()\n chosen.sound = previous\n for (const result of measured) if (result.id !== 'C10') expect(result.pass === true, `${result.id}: ${result.target}`, { value: result.value, data: result.data })\n },\n },\n {\n id: 'sample_loop',\n name: text.scenarios.loop,\n run: async ({ expect }) => {\n const report = await engine.loadSamples([CALIBRATION_LOOP_ID])\n expect(report.failed.length === 0, 'the loop takes load and decode', { failed: report.failed })\n engine.unlock()\n // read the bus once first: its analyser only hears what starts after\n engine.level('ambience')\n const loop = engine.loop(CALIBRATION_LOOP_ID, { volume: 0.8 })\n const wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms))\n // the seams are measured once the loop sounds: the context may still be resuming and the bus analyser filling (on a busy machine\n // the first reads come back 0 and read as a dip that is only the start)\n const started = performance.now()\n while (engine.level('ambience') < 0.01 && performance.now() - started < 2000) await wait(20)\n expect(performance.now() - started < 2000, 'the loop starts within 2 s', { ms: Math.round(performance.now() - started) })\n await wait(200)\n const levels: number[] = []\n // 2.4 s: four seams of 0.6 s takes\n for (let index = 0; index < 60; index++) {\n levels.push(engine.level('ambience'))\n await wait(40)\n }\n loop.stop()\n const sorted = [...levels].sort((a, b) => a - b)\n const median = sorted[Math.floor(sorted.length / 2)] ?? 0\n const lowest = sorted[0] ?? 0\n const dip = lowest > 0 && median > 0 ? 20 * Math.log10(lowest / median) : -Infinity\n expect(median > 0.01, 'the loop sounds', { median })\n expect(dip >= -6, 'no seam: the level never dips more than 6 dB where two takes cross', { dip: Number(dip.toFixed(1)), lowest, median, levels: levels.map((level) => Number(level.toFixed(3))) })\n await wait(200)\n expect(engine.level('ambience') < median / 4, 'stop silences it', { after: engine.level('ambience') })\n },\n },\n {\n id: 'sound_panel',\n name: text.scenarios.panel,\n run: ({ expect }) => {\n const categories = SFX_CATEGORIES.map((category) => soundsOf(category).length)\n expect(categories.every((count) => count > 0), 'every category lists its sounds', { categories })\n expect(soundsOf('impactos').length >= SFX_MATERIALS.length * SFX_BLOWS.length, 'the matrix has every material × blow')\n const pair = pairOf(CALIBRATION_ID)\n expect(pair.a === 'sfx_pistol' && pair.b === CALIBRATION_ID, 'A is the synthesized sound and B the file', pair)\n const clear = engine.planSample(CALIBRATION_ID, { position: [0, 1.6, -10], occlusion: 0, seed: 1 })\n const walled = engine.planSample(CALIBRATION_ID, { position: [0, 1.6, -10], occlusion: 1, seed: 1 })\n expect((walled?.cutoff ?? Infinity) < (clear?.cutoff ?? 0) / 5, 'behind the wall the sound is muffled', { clear: clear?.cutoff, walled: walled?.cutoff })\n },\n },\n ]\n\n return {\n id: 'sound_check_area',\n name: text.name,\n group: text.group,\n ground: { surface: 'concrete_slab' },\n get engine() {\n return engine\n },\n items: () => items(),\n area: () => area(),\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n measure,\n results: () => results,\n events: () => log,\n play,\n pair: () => pairOf(chosen.sound),\n verdicts: () => ({ ...verdicts }),\n approvals: () => [...approvals],\n // the engine (and its context) is made on the first play or measure, not when the room loads the module\n attach(lent) {\n host = lent\n const shared = options.engine ? undefined : (lent.audio as EngineSink | undefined)?.engine\n if (shared && shared !== engine) {\n for (const bank of ownBanks) shared.register(bank)\n shared.addSampleSource(isCalibrationUrl, loader)\n engine = shared\n }\n const offVoices = engine.watchVoices((event) => {\n log.push(event)\n // the log keeps the last voices only (a burst a second would grow it for ever)\n if (log.length > LOG_LIMIT) log.splice(0, log.length - LOG_LIMIT)\n })\n lent.bench?.patch('sound', { options: soundOptions() })\n const off = lent.bench?.onChange(onChange)\n placeScenery()\n return () => {\n off?.()\n offVoices()\n host = null\n }\n },\n }\n}\n"],"mappings":"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","names":["level","fixed","ramp","end","end","outputStage","url","end","limiterCurve","url","listener","layers","url","end","left","right","url","entries","url","url","EN","DISTANCES","PROBE_ID","sourceOf","ms"]}