@libraz/libsonare 1.7.2 → 1.8.1

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 (303) hide show
  1. package/NOTICE +178 -0
  2. package/README.md +26 -203
  3. package/dist/_chain_config.d.ts +14 -0
  4. package/dist/_chain_config.d.ts.map +1 -0
  5. package/dist/_effects_common.d.ts +7 -0
  6. package/dist/_effects_common.d.ts.map +1 -0
  7. package/dist/_feature_validation.d.ts +8 -0
  8. package/dist/_feature_validation.d.ts.map +1 -0
  9. package/dist/_fft_options.d.ts +24 -0
  10. package/dist/_fft_options.d.ts.map +1 -0
  11. package/dist/align_take.d.ts +50 -0
  12. package/dist/align_take.d.ts.map +1 -0
  13. package/dist/analysis.d.ts +29 -5840
  14. package/dist/analysis.d.ts.map +1 -0
  15. package/dist/analysis.js +874 -722
  16. package/dist/analysis.js.map +1 -1
  17. package/dist/analysis_helpers.d.ts +9 -0
  18. package/dist/analysis_helpers.d.ts.map +1 -0
  19. package/dist/audio.d.ts +163 -0
  20. package/dist/audio.d.ts.map +1 -0
  21. package/dist/clip_page_streamer.d.ts +133 -0
  22. package/dist/clip_page_streamer.d.ts.map +1 -0
  23. package/dist/codes.d.ts +44 -0
  24. package/dist/codes.d.ts.map +1 -0
  25. package/dist/effects_mastering.d.ts +23 -0
  26. package/dist/effects_mastering.d.ts.map +1 -0
  27. package/dist/effects_note_ops.d.ts +502 -0
  28. package/dist/effects_note_ops.d.ts.map +1 -0
  29. package/dist/effects_percussive.d.ts +185 -0
  30. package/dist/effects_percussive.d.ts.map +1 -0
  31. package/dist/effects_separation.d.ts +65 -0
  32. package/dist/effects_separation.d.ts.map +1 -0
  33. package/dist/effects_spectral.d.ts +28 -0
  34. package/dist/effects_spectral.d.ts.map +1 -0
  35. package/dist/effects_timepitch.d.ts +134 -0
  36. package/dist/effects_timepitch.d.ts.map +1 -0
  37. package/dist/effects_voice_change.d.ts +53 -0
  38. package/dist/effects_voice_change.d.ts.map +1 -0
  39. package/dist/errors.d.ts +51 -0
  40. package/dist/errors.d.ts.map +1 -0
  41. package/dist/feature_core.d.ts +341 -0
  42. package/dist/feature_core.d.ts.map +1 -0
  43. package/dist/feature_decompose.d.ts +278 -0
  44. package/dist/feature_decompose.d.ts.map +1 -0
  45. package/dist/feature_inverse.d.ts +128 -0
  46. package/dist/feature_inverse.d.ts.map +1 -0
  47. package/dist/feature_loudness.d.ts +66 -0
  48. package/dist/feature_loudness.d.ts.map +1 -0
  49. package/dist/feature_music.d.ts +307 -0
  50. package/dist/feature_music.d.ts.map +1 -0
  51. package/dist/feature_pitch.d.ts +108 -0
  52. package/dist/feature_pitch.d.ts.map +1 -0
  53. package/dist/feature_resample.d.ts +16 -0
  54. package/dist/feature_resample.d.ts.map +1 -0
  55. package/dist/feature_spectral.d.ts +137 -0
  56. package/dist/feature_spectral.d.ts.map +1 -0
  57. package/dist/feature_spectrogram.d.ts +198 -0
  58. package/dist/feature_spectrogram.d.ts.map +1 -0
  59. package/dist/features.d.ts +10 -0
  60. package/dist/features.d.ts.map +1 -0
  61. package/dist/hrtf/default.shrf +0 -0
  62. package/dist/index.d.ts +74 -7431
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +4173 -1621
  65. package/dist/index.js.map +1 -1
  66. package/dist/instrument_types.d.ts +517 -0
  67. package/dist/instrument_types.d.ts.map +1 -0
  68. package/dist/live_audio.d.ts +35 -0
  69. package/dist/live_audio.d.ts.map +1 -0
  70. package/dist/mastering_chain.d.ts +213 -0
  71. package/dist/mastering_chain.d.ts.map +1 -0
  72. package/dist/mastering_core.d.ts +483 -0
  73. package/dist/mastering_core.d.ts.map +1 -0
  74. package/dist/mastering_dynamics.d.ts +80 -0
  75. package/dist/mastering_dynamics.d.ts.map +1 -0
  76. package/dist/metering.d.ts +287 -0
  77. package/dist/metering.d.ts.map +1 -0
  78. package/dist/mixer.d.ts +464 -0
  79. package/dist/mixer.d.ts.map +1 -0
  80. package/dist/mixing_assistant.d.ts +62 -0
  81. package/dist/mixing_assistant.d.ts.map +1 -0
  82. package/dist/mixing_oneshot.d.ts +40 -0
  83. package/dist/mixing_oneshot.d.ts.map +1 -0
  84. package/dist/module_state.d.ts +15 -0
  85. package/dist/module_state.d.ts.map +1 -0
  86. package/dist/opfs_clip_pages.d.ts +28 -0
  87. package/dist/opfs_clip_pages.d.ts.map +1 -0
  88. package/dist/playback_renderer.d.ts +128 -0
  89. package/dist/playback_renderer.d.ts.map +1 -0
  90. package/dist/polyphony.d.ts +202 -0
  91. package/dist/polyphony.d.ts.map +1 -0
  92. package/dist/project.d.ts +8 -0
  93. package/dist/project.d.ts.map +1 -0
  94. package/dist/project_class.d.ts +562 -0
  95. package/dist/project_class.d.ts.map +1 -0
  96. package/dist/project_internal.d.ts +194 -0
  97. package/dist/project_internal.d.ts.map +1 -0
  98. package/dist/project_synth.d.ts +74 -0
  99. package/dist/project_synth.d.ts.map +1 -0
  100. package/dist/project_types.d.ts +654 -0
  101. package/dist/project_types.d.ts.map +1 -0
  102. package/dist/public_types.d.ts +185 -0
  103. package/dist/public_types.d.ts.map +1 -0
  104. package/dist/public_types_acoustic.d.ts +215 -0
  105. package/dist/public_types_acoustic.d.ts.map +1 -0
  106. package/dist/public_types_mastering.d.ts +528 -0
  107. package/dist/public_types_mastering.d.ts.map +1 -0
  108. package/dist/public_types_mixing.d.ts +436 -0
  109. package/dist/public_types_mixing.d.ts.map +1 -0
  110. package/dist/public_types_music.d.ts +619 -0
  111. package/dist/public_types_music.d.ts.map +1 -0
  112. package/dist/public_types_playback.d.ts +165 -0
  113. package/dist/public_types_playback.d.ts.map +1 -0
  114. package/dist/public_types_realtime.d.ts +174 -0
  115. package/dist/public_types_realtime.d.ts.map +1 -0
  116. package/dist/public_types_repair.d.ts +424 -0
  117. package/dist/public_types_repair.d.ts.map +1 -0
  118. package/dist/public_types_spectral.d.ts +697 -0
  119. package/dist/public_types_spectral.d.ts.map +1 -0
  120. package/dist/quick_analysis.d.ts +445 -0
  121. package/dist/quick_analysis.d.ts.map +1 -0
  122. package/dist/realtime_engine.d.ts +893 -0
  123. package/dist/realtime_engine.d.ts.map +1 -0
  124. package/dist/realtime_voice_changer.d.ts +158 -0
  125. package/dist/realtime_voice_changer.d.ts.map +1 -0
  126. package/dist/repair_dereverb.d.ts +187 -0
  127. package/dist/repair_dereverb.d.ts.map +1 -0
  128. package/dist/repair_impulsive.d.ts +186 -0
  129. package/dist/repair_impulsive.d.ts.map +1 -0
  130. package/dist/repair_noise.d.ts +239 -0
  131. package/dist/repair_noise.d.ts.map +1 -0
  132. package/dist/repair_trim.d.ts +123 -0
  133. package/dist/repair_trim.d.ts.map +1 -0
  134. package/dist/sample_bank.d.ts +84 -0
  135. package/dist/sample_bank.d.ts.map +1 -0
  136. package/dist/scale.d.ts +10 -0
  137. package/dist/scale.d.ts.map +1 -0
  138. package/dist/schemas/mixer-scene.schema.json +393 -0
  139. package/dist/schemas/playback-renderer-config.schema.json +392 -0
  140. package/dist/sonare-analysis.d.ts +8 -0
  141. package/dist/sonare-analysis.js +2 -2
  142. package/dist/sonare-analysis.wasm +0 -0
  143. package/dist/sonare.d.ts +3945 -0
  144. package/dist/sonare.js +2 -2
  145. package/dist/sonare.wasm +0 -0
  146. package/dist/stream_analyzer.d.ts +163 -0
  147. package/dist/stream_analyzer.d.ts.map +1 -0
  148. package/dist/stream_types.d.ts +214 -0
  149. package/dist/stream_types.d.ts.map +1 -0
  150. package/dist/streaming_mixing.d.ts +6 -0
  151. package/dist/streaming_mixing.d.ts.map +1 -0
  152. package/dist/streaming_processors.d.ts +340 -0
  153. package/dist/streaming_processors.d.ts.map +1 -0
  154. package/dist/transcribe.d.ts +77 -0
  155. package/dist/transcribe.d.ts.map +1 -0
  156. package/dist/validation.d.ts +140 -0
  157. package/dist/validation.d.ts.map +1 -0
  158. package/dist/web_midi.d.ts +77 -0
  159. package/dist/web_midi.d.ts.map +1 -0
  160. package/dist/worker.d.ts +5 -48
  161. package/dist/worker.d.ts.map +1 -0
  162. package/dist/worker.js +94 -41
  163. package/dist/worker.js.map +1 -1
  164. package/dist/worker_client.d.ts +96 -0
  165. package/dist/worker_client.d.ts.map +1 -0
  166. package/dist/worker_protocol.d.ts +43 -0
  167. package/dist/worker_protocol.d.ts.map +1 -0
  168. package/dist/worklet/audio_types.d.ts +21 -0
  169. package/dist/worklet/audio_types.d.ts.map +1 -0
  170. package/dist/worklet/engine-automation.d.ts +29 -0
  171. package/dist/worklet/engine-automation.d.ts.map +1 -0
  172. package/dist/worklet/engine-capture-facade.d.ts +35 -0
  173. package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
  174. package/dist/worklet/engine-clips.d.ts +23 -0
  175. package/dist/worklet/engine-clips.d.ts.map +1 -0
  176. package/dist/worklet/engine-markers.d.ts +40 -0
  177. package/dist/worklet/engine-markers.d.ts.map +1 -0
  178. package/dist/worklet/engine-mixer-facade.d.ts +164 -0
  179. package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
  180. package/dist/worklet/engine-node.d.ts +83 -0
  181. package/dist/worklet/engine-node.d.ts.map +1 -0
  182. package/dist/worklet/engine-offline.d.ts +81 -0
  183. package/dist/worklet/engine-offline.d.ts.map +1 -0
  184. package/dist/worklet/engine-options.d.ts +12 -0
  185. package/dist/worklet/engine-options.d.ts.map +1 -0
  186. package/dist/worklet/engine-parameter-facade.d.ts +106 -0
  187. package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
  188. package/dist/worklet/engine-processor.d.ts +72 -0
  189. package/dist/worklet/engine-processor.d.ts.map +1 -0
  190. package/dist/worklet/engine-register.d.ts +2 -0
  191. package/dist/worklet/engine-register.d.ts.map +1 -0
  192. package/dist/worklet/engine-strips.d.ts +75 -0
  193. package/dist/worklet/engine-strips.d.ts.map +1 -0
  194. package/dist/worklet/engine-sync.d.ts +39 -0
  195. package/dist/worklet/engine-sync.d.ts.map +1 -0
  196. package/dist/worklet/engine-tempo-facade.d.ts +48 -0
  197. package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
  198. package/dist/worklet/engine.d.ts +418 -0
  199. package/dist/worklet/engine.d.ts.map +1 -0
  200. package/dist/worklet/guards.d.ts +53 -0
  201. package/dist/worklet/guards.d.ts.map +1 -0
  202. package/dist/worklet/messages.d.ts +710 -0
  203. package/dist/worklet/messages.d.ts.map +1 -0
  204. package/dist/worklet/mixer-processor.d.ts +46 -0
  205. package/dist/worklet/mixer-processor.d.ts.map +1 -0
  206. package/dist/worklet/playback-processor.d.ts +62 -0
  207. package/dist/worklet/playback-processor.d.ts.map +1 -0
  208. package/dist/worklet/protocol.d.ts +331 -0
  209. package/dist/worklet/protocol.d.ts.map +1 -0
  210. package/dist/worklet/voice-changer-processor.d.ts +41 -0
  211. package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
  212. package/dist/worklet.d.ts +16 -2515
  213. package/dist/worklet.d.ts.map +1 -0
  214. package/dist/worklet.js +3200 -541
  215. package/dist/worklet.js.map +1 -1
  216. package/package.json +23 -12
  217. package/src/_effects_common.ts +47 -0
  218. package/src/_feature_validation.ts +34 -0
  219. package/src/_fft_options.ts +39 -0
  220. package/src/align_take.ts +64 -0
  221. package/src/analysis.ts +56 -3
  222. package/src/analysis_helpers.ts +7 -0
  223. package/src/audio.ts +106 -3
  224. package/src/codes.ts +39 -2
  225. package/src/effects_mastering.ts +101 -22
  226. package/src/effects_note_ops.ts +683 -0
  227. package/src/effects_percussive.ts +217 -0
  228. package/src/effects_separation.ts +150 -0
  229. package/src/effects_spectral.ts +60 -0
  230. package/src/effects_timepitch.ts +388 -0
  231. package/src/errors.ts +23 -1
  232. package/src/feature_core.ts +127 -2
  233. package/src/feature_decompose.ts +633 -0
  234. package/src/feature_inverse.ts +454 -0
  235. package/src/feature_loudness.ts +125 -0
  236. package/src/feature_music.ts +107 -14
  237. package/src/feature_pitch.ts +96 -1
  238. package/src/feature_spectral.ts +16 -611
  239. package/src/feature_spectrogram.ts +63 -450
  240. package/src/features.ts +36 -22
  241. package/src/index.ts +288 -30
  242. package/src/instrument_types.ts +645 -0
  243. package/src/live_audio.ts +27 -1
  244. package/src/mastering_chain.ts +184 -0
  245. package/src/mastering_core.ts +441 -32
  246. package/src/mastering_dynamics.ts +22 -11
  247. package/src/metering.ts +67 -24
  248. package/src/mixer.ts +251 -22
  249. package/src/mixing_assistant.ts +138 -0
  250. package/src/mixing_oneshot.ts +10 -5
  251. package/src/module_state.ts +24 -2
  252. package/src/playback_renderer.ts +252 -0
  253. package/src/polyphony.ts +279 -0
  254. package/src/project.ts +61 -24
  255. package/src/project_class.ts +450 -27
  256. package/src/project_internal.ts +149 -42
  257. package/src/project_synth.ts +67 -1
  258. package/src/project_types.ts +271 -271
  259. package/src/public_types.ts +122 -3
  260. package/src/public_types_acoustic.ts +112 -3
  261. package/src/public_types_mastering.ts +275 -73
  262. package/src/public_types_mixing.ts +363 -1
  263. package/src/public_types_music.ts +312 -2
  264. package/src/public_types_playback.ts +196 -0
  265. package/src/public_types_realtime.ts +39 -7
  266. package/src/public_types_repair.ts +446 -0
  267. package/src/public_types_spectral.ts +491 -5
  268. package/src/quick_analysis.ts +203 -26
  269. package/src/realtime_engine.ts +773 -34
  270. package/src/realtime_voice_changer.ts +55 -1
  271. package/src/repair_dereverb.ts +299 -0
  272. package/src/repair_impulsive.ts +395 -0
  273. package/src/repair_noise.ts +425 -0
  274. package/src/repair_trim.ts +226 -0
  275. package/src/sample_bank.ts +113 -0
  276. package/src/sonare.js.d.ts +1158 -30
  277. package/src/stream_analyzer.ts +36 -4
  278. package/src/stream_types.ts +37 -0
  279. package/src/streaming_mixing.ts +1 -1
  280. package/src/streaming_processors.ts +202 -10
  281. package/src/transcribe.ts +89 -0
  282. package/src/validation.ts +285 -11
  283. package/src/web_midi.ts +1 -6
  284. package/src/worker.ts +18 -2
  285. package/src/worklet/audio_types.ts +37 -0
  286. package/src/worklet/engine-mixer-facade.ts +800 -32
  287. package/src/worklet/engine-node.ts +99 -29
  288. package/src/worklet/engine-offline.ts +14 -8
  289. package/src/worklet/engine-parameter-facade.ts +21 -0
  290. package/src/worklet/engine-processor.ts +332 -93
  291. package/src/worklet/engine-register.ts +32 -18
  292. package/src/worklet/engine-strips.ts +275 -9
  293. package/src/worklet/engine-sync.ts +20 -7
  294. package/src/worklet/engine.ts +394 -48
  295. package/src/worklet/guards.ts +195 -44
  296. package/src/worklet/messages.ts +229 -2
  297. package/src/worklet/mixer-processor.ts +117 -48
  298. package/src/worklet/playback-processor.ts +300 -0
  299. package/src/worklet/protocol.ts +82 -11
  300. package/src/worklet/voice-changer-processor.ts +17 -11
  301. package/src/worklet.ts +17 -0
  302. package/src/effects_transform.ts +0 -718
  303. package/src/mastering_repair.ts +0 -273
@@ -1,5 +1,13 @@
1
1
  import { panLawCode, panModeCode } from '../codes';
2
2
  import type { EqBand, PanLawInput, PanMode, RealtimeEngine } from '../index';
3
+ import type { InsertParamOverrideMap } from './engine-mixer-facade';
4
+ import {
5
+ emptyStripJson,
6
+ type InsertParamOverride,
7
+ insertParamOverrideKey,
8
+ replaceStripScene,
9
+ type StripJsonTarget,
10
+ } from './engine-mixer-facade';
3
11
  import type { SonareEngineInstrumentSyncMessage, SonareEngineSyncMessage } from './messages';
4
12
 
5
13
  /**
@@ -14,20 +22,80 @@ export interface EngineStripContext {
14
22
  postInstrumentSync(message: SonareEngineInstrumentSyncMessage): void;
15
23
  ensureTrackLane(target: string | number): number;
16
24
  resolveTargetId(target: string | number): number;
25
+ readStripJson(target: StripJsonTarget): string | undefined;
26
+ writeStripJson(target: StripJsonTarget, sceneJson: string): void;
27
+ readonly insertParamOverrides: InsertParamOverrideMap;
28
+ clearInsertAutomationLanes(target: StripJsonTarget): void;
17
29
  }
18
30
 
19
31
  function trackIdFor(ctx: EngineStripContext, target: string | number): number {
20
32
  return ctx.trackLaneIds[ctx.ensureTrackLane(target)];
21
33
  }
22
34
 
35
+ type SceneEntry = Record<string, unknown>;
36
+
37
+ /**
38
+ * Folds a setter's change into the strip's cached scene JSON, so the next
39
+ * syncMixer re-post replays it instead of reverting it on the worklet.
40
+ */
41
+ function mergeStripJson(
42
+ ctx: EngineStripContext,
43
+ target: StripJsonTarget,
44
+ update: (entry: SceneEntry) => void,
45
+ ): void {
46
+ const scene = JSON.parse(ctx.readStripJson(target) ?? emptyStripJson(target)) as {
47
+ strips: SceneEntry[];
48
+ buses: SceneEntry[];
49
+ };
50
+ update(target.kind === 'bus' ? scene.buses[0] : scene.strips[0]);
51
+ ctx.writeStripJson(target, JSON.stringify(scene));
52
+ }
53
+
54
+ function mergeEqBand(
55
+ ctx: EngineStripContext,
56
+ target: StripJsonTarget,
57
+ bandIndex: number,
58
+ bandJson: string,
59
+ ): void {
60
+ mergeStripJson(ctx, target, (entry) => {
61
+ const eq = (entry.eq ?? { enabled: true, bands: [] }) as { bands?: unknown[] };
62
+ const bands = eq.bands ?? [];
63
+ while (bands.length < bandIndex) {
64
+ bands.push({});
65
+ }
66
+ bands[bandIndex] = JSON.parse(bandJson);
67
+ entry.eq = { ...eq, bands };
68
+ });
69
+ }
70
+
71
+ function setInsertParamByName(
72
+ ctx: EngineStripContext,
73
+ target: StripJsonTarget,
74
+ insertIndex: number,
75
+ paramName: string,
76
+ value: number,
77
+ applyNative: () => void,
78
+ message: SonareEngineSyncMessage,
79
+ ): void {
80
+ applyNative();
81
+ // Keep the construction scene unchanged. Rewriting insert params here makes
82
+ // a later syncMixer rebuild stateful effects; the override is replayed after
83
+ // the scene on both engines instead.
84
+ const override: InsertParamOverride = { target, insertIndex, paramName, value };
85
+ ctx.insertParamOverrides.set(insertParamOverrideKey(override), override);
86
+ ctx.postSync(message);
87
+ }
88
+
23
89
  export function setTrackStripJson(
24
90
  ctx: EngineStripContext,
25
91
  trackId: number,
26
92
  sceneJson: string,
27
93
  trackStripJson: Map<number, string>,
28
- ): void {
29
- ctx.offlineEngine.setTrackStripJson(trackId, sceneJson);
94
+ ): { insertBaseResets: StripJsonTarget[]; constructionOverrides: InsertParamOverride[] } {
95
+ const target: StripJsonTarget = { kind: 'track', trackId };
96
+ const result = replaceStripScene(ctx, target, trackStripJson.get(trackId), sceneJson);
30
97
  trackStripJson.set(trackId, sceneJson);
98
+ return result;
31
99
  }
32
100
 
33
101
  export function setTrackStripEqBand(
@@ -39,6 +107,7 @@ export function setTrackStripEqBand(
39
107
  const trackId = trackIdFor(ctx, target);
40
108
  const bandJson = typeof band === 'string' ? band : JSON.stringify(band);
41
109
  ctx.offlineEngine.setTrackStripEqBandJson(trackId, bandIndex, bandJson);
110
+ mergeEqBand(ctx, { kind: 'track', trackId }, bandIndex, bandJson);
42
111
  ctx.postSync({ type: 'syncTrackStripEqBand', trackId, bandIndex, bandJson });
43
112
  }
44
113
 
@@ -68,8 +137,16 @@ export function setTrackStripInsertParamByName(
68
137
  value: number,
69
138
  ): void {
70
139
  const trackId = trackIdFor(ctx, target);
71
- ctx.offlineEngine.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);
72
- ctx.postSync({ type: 'syncTrackStripInsertParamByName', trackId, insertIndex, paramName, value });
140
+ setInsertParamByName(
141
+ ctx,
142
+ { kind: 'track', trackId },
143
+ insertIndex,
144
+ paramName,
145
+ value,
146
+ () =>
147
+ ctx.offlineEngine.restoreTrackStripInsertParamByName(trackId, insertIndex, paramName, value),
148
+ { type: 'syncTrackStripInsertParamByName', trackId, insertIndex, paramName, value },
149
+ );
73
150
  }
74
151
 
75
152
  export function setTrackStripPan(
@@ -79,6 +156,9 @@ export function setTrackStripPan(
79
156
  ): void {
80
157
  const trackId = trackIdFor(ctx, target);
81
158
  ctx.offlineEngine.setTrackStripPan(trackId, pan);
159
+ mergeStripJson(ctx, { kind: 'track', trackId }, (entry) => {
160
+ entry.pan = pan;
161
+ });
82
162
  ctx.postSync({ type: 'syncTrackStripPan', trackId, pan });
83
163
  }
84
164
 
@@ -90,6 +170,9 @@ export function setTrackStripPanLaw(
90
170
  const trackId = trackIdFor(ctx, target);
91
171
  const code = panLawCode(panLaw);
92
172
  ctx.offlineEngine.setTrackStripPanLaw(trackId, code);
173
+ mergeStripJson(ctx, { kind: 'track', trackId }, (entry) => {
174
+ entry.panLaw = code;
175
+ });
93
176
  ctx.postSync({ type: 'syncTrackStripPanLaw', trackId, panLaw: code });
94
177
  }
95
178
 
@@ -101,6 +184,9 @@ export function setTrackStripPanMode(
101
184
  const trackId = trackIdFor(ctx, target);
102
185
  const code = panModeCode(panMode);
103
186
  ctx.offlineEngine.setTrackStripPanMode(trackId, code);
187
+ mergeStripJson(ctx, { kind: 'track', trackId }, (entry) => {
188
+ entry.panMode = code;
189
+ });
104
190
  ctx.postSync({ type: 'syncTrackStripPanMode', trackId, panMode: code });
105
191
  }
106
192
 
@@ -112,6 +198,10 @@ export function setTrackStripDualPan(
112
198
  ): void {
113
199
  const trackId = trackIdFor(ctx, target);
114
200
  ctx.offlineEngine.setTrackStripDualPan(trackId, leftPan, rightPan);
201
+ mergeStripJson(ctx, { kind: 'track', trackId }, (entry) => {
202
+ entry.dualPanLeft = leftPan;
203
+ entry.dualPanRight = rightPan;
204
+ });
115
205
  ctx.postSync({ type: 'syncTrackStripDualPan', trackId, leftPan, rightPan });
116
206
  }
117
207
 
@@ -122,9 +212,26 @@ export function setTrackStripChannelDelaySamples(
122
212
  ): void {
123
213
  const trackId = trackIdFor(ctx, target);
124
214
  ctx.offlineEngine.setTrackStripChannelDelaySamples(trackId, delaySamples);
215
+ mergeStripJson(ctx, { kind: 'track', trackId }, (entry) => {
216
+ entry.channelDelaySamples = delaySamples;
217
+ });
125
218
  ctx.postSync({ type: 'syncTrackStripChannelDelaySamples', trackId, delaySamples });
126
219
  }
127
220
 
221
+ /**
222
+ * Records a master fader or pan value the parameter path applied, so a master
223
+ * strip re-post does not reset it; a track lane keeps these outside its strip.
224
+ */
225
+ export function cacheMasterStripScalar(
226
+ ctx: EngineStripContext,
227
+ field: 'faderDb' | 'pan',
228
+ value: number,
229
+ ): void {
230
+ mergeStripJson(ctx, { kind: 'master' }, (entry) => {
231
+ entry[field] = value;
232
+ });
233
+ }
234
+
128
235
  export function setMasterStripEqBand(
129
236
  ctx: EngineStripContext,
130
237
  bandIndex: number,
@@ -132,6 +239,7 @@ export function setMasterStripEqBand(
132
239
  ): void {
133
240
  const bandJson = typeof band === 'string' ? band : JSON.stringify(band);
134
241
  ctx.offlineEngine.setMasterStripEqBandJson(bandIndex, bandJson);
242
+ mergeEqBand(ctx, { kind: 'master' }, bandIndex, bandJson);
135
243
  ctx.postSync({ type: 'syncMasterStripEqBand', bandIndex, bandJson });
136
244
  }
137
245
 
@@ -151,8 +259,15 @@ export function setMasterStripInsertParamByName(
151
259
  paramName: string,
152
260
  value: number,
153
261
  ): void {
154
- ctx.offlineEngine.setMasterStripInsertParamByName(insertIndex, paramName, value);
155
- ctx.postSync({ type: 'syncMasterStripInsertParamByName', insertIndex, paramName, value });
262
+ setInsertParamByName(
263
+ ctx,
264
+ { kind: 'master' },
265
+ insertIndex,
266
+ paramName,
267
+ value,
268
+ () => ctx.offlineEngine.restoreMasterStripInsertParamByName(insertIndex, paramName, value),
269
+ { type: 'syncMasterStripInsertParamByName', insertIndex, paramName, value },
270
+ );
156
271
  }
157
272
 
158
273
  export function setBusStripInsertParamByName(
@@ -162,8 +277,86 @@ export function setBusStripInsertParamByName(
162
277
  paramName: string,
163
278
  value: number,
164
279
  ): void {
165
- ctx.offlineEngine.setBusStripInsertParamByName(busId, insertIndex, paramName, value);
166
- ctx.postSync({ type: 'syncBusStripInsertParamByName', busId, insertIndex, paramName, value });
280
+ setInsertParamByName(
281
+ ctx,
282
+ { kind: 'bus', busId },
283
+ insertIndex,
284
+ paramName,
285
+ value,
286
+ () => ctx.offlineEngine.restoreBusStripInsertParamByName(busId, insertIndex, paramName, value),
287
+ { type: 'syncBusStripInsertParamByName', busId, insertIndex, paramName, value },
288
+ );
289
+ }
290
+
291
+ export function setBusStripInsertBypassed(
292
+ ctx: EngineStripContext,
293
+ busId: number,
294
+ insertIndex: number,
295
+ bypassed: boolean,
296
+ resetOnBypass: boolean,
297
+ ): void {
298
+ ctx.offlineEngine.setBusStripInsertBypassed(busId, insertIndex, bypassed, resetOnBypass);
299
+ ctx.postSync({ type: 'syncBusStripInsertBypassed', busId, insertIndex, bypassed, resetOnBypass });
300
+ }
301
+
302
+ export function setBusStripEqBand(
303
+ ctx: EngineStripContext,
304
+ busId: number,
305
+ bandIndex: number,
306
+ band: EqBand | string,
307
+ ): void {
308
+ const bandJson = typeof band === 'string' ? band : JSON.stringify(band);
309
+ ctx.offlineEngine.setBusStripEqBandJson(busId, bandIndex, bandJson);
310
+ mergeEqBand(ctx, { kind: 'bus', busId }, bandIndex, bandJson);
311
+ ctx.postSync({ type: 'syncBusStripEqBand', busId, bandIndex, bandJson });
312
+ }
313
+
314
+ export function setBusStripPan(ctx: EngineStripContext, busId: number, pan: number): void {
315
+ ctx.offlineEngine.setBusStripPan(busId, pan);
316
+ mergeStripJson(ctx, { kind: 'bus', busId }, (entry) => {
317
+ entry.pan = pan;
318
+ });
319
+ ctx.postSync({ type: 'syncBusStripPan', busId, pan });
320
+ }
321
+
322
+ export function setBusStripPanLaw(
323
+ ctx: EngineStripContext,
324
+ busId: number,
325
+ panLaw: PanLawInput,
326
+ ): void {
327
+ const code = panLawCode(panLaw);
328
+ ctx.offlineEngine.setBusStripPanLaw(busId, code);
329
+ mergeStripJson(ctx, { kind: 'bus', busId }, (entry) => {
330
+ entry.panLaw = code;
331
+ });
332
+ ctx.postSync({ type: 'syncBusStripPanLaw', busId, panLaw: code });
333
+ }
334
+
335
+ export function setBusStripPanMode(
336
+ ctx: EngineStripContext,
337
+ busId: number,
338
+ panMode: PanMode | number,
339
+ ): void {
340
+ const code = panModeCode(panMode);
341
+ ctx.offlineEngine.setBusStripPanMode(busId, code);
342
+ mergeStripJson(ctx, { kind: 'bus', busId }, (entry) => {
343
+ entry.panMode = code;
344
+ });
345
+ ctx.postSync({ type: 'syncBusStripPanMode', busId, panMode: code });
346
+ }
347
+
348
+ export function setBusStripDualPan(
349
+ ctx: EngineStripContext,
350
+ busId: number,
351
+ leftPan: number,
352
+ rightPan: number,
353
+ ): void {
354
+ ctx.offlineEngine.setBusStripDualPan(busId, leftPan, rightPan);
355
+ mergeStripJson(ctx, { kind: 'bus', busId }, (entry) => {
356
+ entry.dualPanLeft = leftPan;
357
+ entry.dualPanRight = rightPan;
358
+ });
359
+ ctx.postSync({ type: 'syncBusStripDualPan', busId, leftPan, rightPan });
167
360
  }
168
361
 
169
362
  export function pushMidiNoteOn(
@@ -232,6 +425,77 @@ export function pushMidiCc(
232
425
  });
233
426
  }
234
427
 
428
+ export function pushMidiPitchBend(
429
+ ctx: EngineStripContext,
430
+ trackId: string | number,
431
+ group: number,
432
+ channel: number,
433
+ bend14: number,
434
+ renderFrame: number,
435
+ ): void {
436
+ const destinationId = ctx.resolveTargetId(trackId);
437
+ ctx.offlineEngine.pushMidiPitchBend(destinationId, group, channel, bend14, renderFrame);
438
+ ctx.postSync({
439
+ type: 'syncMidiPitchBend',
440
+ destinationId,
441
+ group,
442
+ channel,
443
+ data0: bend14,
444
+ data1: 0,
445
+ renderFrame,
446
+ });
447
+ }
448
+
449
+ export function pushMidiChannelPressure(
450
+ ctx: EngineStripContext,
451
+ trackId: string | number,
452
+ group: number,
453
+ channel: number,
454
+ pressure: number,
455
+ renderFrame: number,
456
+ ): void {
457
+ const destinationId = ctx.resolveTargetId(trackId);
458
+ ctx.offlineEngine.pushMidiChannelPressure(destinationId, group, channel, pressure, renderFrame);
459
+ ctx.postSync({
460
+ type: 'syncMidiChannelPressure',
461
+ destinationId,
462
+ group,
463
+ channel,
464
+ data0: pressure,
465
+ data1: 0,
466
+ renderFrame,
467
+ });
468
+ }
469
+
470
+ export function pushMidiPolyPressure(
471
+ ctx: EngineStripContext,
472
+ trackId: string | number,
473
+ group: number,
474
+ channel: number,
475
+ note: number,
476
+ pressure: number,
477
+ renderFrame: number,
478
+ ): void {
479
+ const destinationId = ctx.resolveTargetId(trackId);
480
+ ctx.offlineEngine.pushMidiPolyPressure(
481
+ destinationId,
482
+ group,
483
+ channel,
484
+ note,
485
+ pressure,
486
+ renderFrame,
487
+ );
488
+ ctx.postSync({
489
+ type: 'syncMidiPolyPressure',
490
+ destinationId,
491
+ group,
492
+ channel,
493
+ data0: note,
494
+ data1: pressure,
495
+ renderFrame,
496
+ });
497
+ }
498
+
235
499
  export function pushMidiUmp(
236
500
  ctx: EngineStripContext,
237
501
  trackId: string | number,
@@ -239,7 +503,7 @@ export function pushMidiUmp(
239
503
  renderFrame: number,
240
504
  ): void {
241
505
  const destinationId = ctx.resolveTargetId(trackId);
242
- ctx.offlineEngine.pushMidiUmp(destinationId, word0, renderFrame);
506
+ ctx.offlineEngine.pushMidiUmp(destinationId, [word0], renderFrame);
243
507
  ctx.postSync({ type: 'syncMidiUmp', destinationId, word0, renderFrame });
244
508
  }
245
509
 
@@ -276,6 +540,8 @@ export function setSf2Instrument(
276
540
  gain?: number;
277
541
  polyphony?: number;
278
542
  preferModelForModeledFamilies?: boolean;
543
+ clearBankRig?: boolean;
544
+ gsEfxRealization?: 'modern' | 'classic';
279
545
  },
280
546
  ): void {
281
547
  const destinationId = ctx.resolveTargetId(trackId);
@@ -11,25 +11,30 @@ import type { SonareEngineSyncTempoMessage } from './messages';
11
11
  * Builds the ordered mixer-lane descriptors for a sync message.
12
12
  *
13
13
  * Each declared track id is paired with its current send list and output bus
14
- * (both omitted when absent), defensively copying the send entries.
14
+ * (both omitted when absent) and source channel layout, defensively copying the
15
+ * send entries.
15
16
  *
16
17
  * @param trackLaneIds Lane order (track ids) declared on the engine.
17
18
  * @param trackSends Per-track send lists.
18
19
  * @param trackOutputBus Per-track output bus routing.
20
+ * @param trackSourceChannelLayout Per-track source channel layouts.
19
21
  * @returns Lane descriptors in lane order.
20
22
  */
21
23
  export function buildMixerLanes(
22
24
  trackLaneIds: readonly number[],
23
25
  trackSends: ReadonlyMap<number, EngineTrackSend[]>,
24
26
  trackOutputBus: ReadonlyMap<number, number>,
27
+ trackSourceChannelLayout: ReadonlyMap<number, number>,
25
28
  ): EngineTrackLane[] {
26
29
  return trackLaneIds.map((trackId) => {
27
30
  const sends = trackSends.get(trackId);
28
31
  const outputBusId = trackOutputBus.get(trackId);
32
+ const sourceChannelLayout = trackSourceChannelLayout.get(trackId);
29
33
  return {
30
34
  trackId,
31
35
  ...(sends && sends.length > 0 ? { sends: sends.map((send) => ({ ...send })) } : {}),
32
36
  ...(outputBusId !== undefined ? { outputBusId } : {}),
37
+ ...(sourceChannelLayout !== undefined ? { sourceChannelLayout } : {}),
33
38
  };
34
39
  });
35
40
  }
@@ -54,15 +59,23 @@ export function buildTempoSync(
54
59
  }
55
60
 
56
61
  /**
57
- * Resolves a target id from a string or number; non-numeric strings resolve to
58
- * 0, mirroring the engine's integer-id namespace.
62
+ * Resolves a target id given as a number, or as a string naming one.
63
+ *
64
+ * Both spellings reach one refusal. Reading the string with `Number.parseInt`
65
+ * stops at the first non-digit, so `"3.5"` resolves to `3` and `"5abc"` to `5`,
66
+ * and an unparseable name resolves to `0` -- all ids the caller never named.
67
+ * `0` is a legal destination, so the native check these feed cannot tell the
68
+ * substitution from a deliberate choice and never reports one.
59
69
  */
60
70
  export function resolveTargetId(target: string | number): number {
61
- if (typeof target === 'number') {
62
- return target;
71
+ // An empty or blank string is not a spelling of zero, which is what Number
72
+ // reads it as.
73
+ const value =
74
+ typeof target === 'number' ? target : target.trim() === '' ? Number.NaN : Number(target);
75
+ if (!Number.isInteger(value)) {
76
+ throw new RangeError(`target id must be an integer, got ${JSON.stringify(target)}`);
63
77
  }
64
- const parsed = Number.parseInt(target, 10);
65
- return Number.isFinite(parsed) ? parsed : 0;
78
+ return value;
66
79
  }
67
80
 
68
81
  /** Resolves a registered parameter name or passes through a numeric id. */