@drop-ai/core 0.2.0 → 0.3.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 (301) hide show
  1. package/README.md +655 -237
  2. package/dist/actions/ActionRegistry.d.ts.map +1 -1
  3. package/dist/actions/ActionRegistry.js +7 -2
  4. package/dist/actions/ActionRegistry.js.map +1 -1
  5. package/dist/actions/types.d.ts +7 -1
  6. package/dist/actions/types.d.ts.map +1 -1
  7. package/dist/analysis/AudioAnalyzer.d.ts +71 -0
  8. package/dist/analysis/AudioAnalyzer.d.ts.map +1 -0
  9. package/dist/analysis/AudioAnalyzer.js +569 -0
  10. package/dist/analysis/AudioAnalyzer.js.map +1 -0
  11. package/dist/audio/AudioEngine.d.ts +14 -1
  12. package/dist/audio/AudioEngine.d.ts.map +1 -1
  13. package/dist/audio/AudioEngine.js +115 -35
  14. package/dist/audio/AudioEngine.js.map +1 -1
  15. package/dist/audio/Auditioner.d.ts +104 -0
  16. package/dist/audio/Auditioner.d.ts.map +1 -0
  17. package/dist/audio/Auditioner.js +239 -0
  18. package/dist/audio/Auditioner.js.map +1 -0
  19. package/dist/audio/BWFMetadata.d.ts +116 -0
  20. package/dist/audio/BWFMetadata.d.ts.map +1 -0
  21. package/dist/audio/BWFMetadata.js +394 -0
  22. package/dist/audio/BWFMetadata.js.map +1 -0
  23. package/dist/audio/ChannelSplitter.d.ts +37 -0
  24. package/dist/audio/ChannelSplitter.d.ts.map +1 -0
  25. package/dist/audio/ChannelSplitter.js +82 -0
  26. package/dist/audio/ChannelSplitter.js.map +1 -0
  27. package/dist/audio/ExportAnalyzer.d.ts +39 -0
  28. package/dist/audio/ExportAnalyzer.d.ts.map +1 -0
  29. package/dist/audio/ExportAnalyzer.js +76 -0
  30. package/dist/audio/ExportAnalyzer.js.map +1 -0
  31. package/dist/audio/LufsNormalizer.d.ts +37 -0
  32. package/dist/audio/LufsNormalizer.d.ts.map +1 -0
  33. package/dist/audio/LufsNormalizer.js +217 -0
  34. package/dist/audio/LufsNormalizer.js.map +1 -0
  35. package/dist/audio/OfflineExporter.d.ts +1 -6
  36. package/dist/audio/OfflineExporter.d.ts.map +1 -1
  37. package/dist/audio/OfflineExporter.js +31 -10
  38. package/dist/audio/OfflineExporter.js.map +1 -1
  39. package/dist/audio/RoutingGraph.d.ts +134 -0
  40. package/dist/audio/RoutingGraph.d.ts.map +1 -0
  41. package/dist/audio/RoutingGraph.js +547 -0
  42. package/dist/audio/RoutingGraph.js.map +1 -0
  43. package/dist/audio/SampleRateConverter.d.ts +21 -0
  44. package/dist/audio/SampleRateConverter.d.ts.map +1 -0
  45. package/dist/audio/SampleRateConverter.js +84 -0
  46. package/dist/audio/SampleRateConverter.js.map +1 -0
  47. package/dist/audio/SilencePadding.d.ts +29 -0
  48. package/dist/audio/SilencePadding.d.ts.map +1 -0
  49. package/dist/audio/SilencePadding.js +86 -0
  50. package/dist/audio/SilencePadding.js.map +1 -0
  51. package/dist/audio/SourceCache.d.ts +13 -16
  52. package/dist/audio/SourceCache.d.ts.map +1 -1
  53. package/dist/audio/SourceCache.js +21 -33
  54. package/dist/audio/SourceCache.js.map +1 -1
  55. package/dist/audio/engine/Declick.d.ts +98 -0
  56. package/dist/audio/engine/Declick.d.ts.map +1 -0
  57. package/dist/audio/engine/Declick.js +204 -0
  58. package/dist/audio/engine/Declick.js.map +1 -0
  59. package/dist/audio/engine/DiskIO.d.ts +172 -0
  60. package/dist/audio/engine/DiskIO.d.ts.map +1 -0
  61. package/dist/audio/engine/DiskIO.js +384 -0
  62. package/dist/audio/engine/DiskIO.js.map +1 -0
  63. package/dist/audio/engine/LatencyCompensator.d.ts +46 -0
  64. package/dist/audio/engine/LatencyCompensator.d.ts.map +1 -0
  65. package/dist/audio/engine/LatencyCompensator.js +84 -0
  66. package/dist/audio/engine/LatencyCompensator.js.map +1 -0
  67. package/dist/audio/engine/MultiTrackRecorder.d.ts +146 -0
  68. package/dist/audio/engine/MultiTrackRecorder.d.ts.map +1 -0
  69. package/dist/audio/engine/MultiTrackRecorder.js +359 -0
  70. package/dist/audio/engine/MultiTrackRecorder.js.map +1 -0
  71. package/dist/audio/engine/PlaylistEngine.d.ts.map +1 -1
  72. package/dist/audio/engine/PlaylistEngine.js +9 -2
  73. package/dist/audio/engine/PlaylistEngine.js.map +1 -1
  74. package/dist/audio/engine/PunchRecordManager.d.ts +113 -0
  75. package/dist/audio/engine/PunchRecordManager.d.ts.map +1 -0
  76. package/dist/audio/engine/PunchRecordManager.js +191 -0
  77. package/dist/audio/engine/PunchRecordManager.js.map +1 -0
  78. package/dist/audio/engine/RoutingGraph.d.ts +135 -0
  79. package/dist/audio/engine/RoutingGraph.d.ts.map +1 -0
  80. package/dist/audio/engine/RoutingGraph.js +436 -0
  81. package/dist/audio/engine/RoutingGraph.js.map +1 -0
  82. package/dist/audio/engine/SidechainRouter.d.ts +139 -0
  83. package/dist/audio/engine/SidechainRouter.d.ts.map +1 -0
  84. package/dist/audio/engine/SidechainRouter.js +292 -0
  85. package/dist/audio/engine/SidechainRouter.js.map +1 -0
  86. package/dist/audio/engine/XrunTracker.d.ts +71 -0
  87. package/dist/audio/engine/XrunTracker.d.ts.map +1 -0
  88. package/dist/audio/engine/XrunTracker.js +118 -0
  89. package/dist/audio/engine/XrunTracker.js.map +1 -0
  90. package/dist/audio/export/CDMarkerExporter.d.ts +62 -0
  91. package/dist/audio/export/CDMarkerExporter.d.ts.map +1 -0
  92. package/dist/audio/export/CDMarkerExporter.js +164 -0
  93. package/dist/audio/export/CDMarkerExporter.js.map +1 -0
  94. package/dist/audio/export/ExportGraphBuilder.d.ts +121 -0
  95. package/dist/audio/export/ExportGraphBuilder.d.ts.map +1 -0
  96. package/dist/audio/export/ExportGraphBuilder.js +522 -0
  97. package/dist/audio/export/ExportGraphBuilder.js.map +1 -0
  98. package/dist/audio/export/ExportPresetManager.d.ts +87 -0
  99. package/dist/audio/export/ExportPresetManager.d.ts.map +1 -0
  100. package/dist/audio/export/ExportPresetManager.js +306 -0
  101. package/dist/audio/export/ExportPresetManager.js.map +1 -0
  102. package/dist/commands/handlers/RegionHandler.d.ts.map +1 -1
  103. package/dist/commands/handlers/RegionHandler.js +25 -1
  104. package/dist/commands/handlers/RegionHandler.js.map +1 -1
  105. package/dist/commands/handlers/TrackHandler.js +1 -1
  106. package/dist/commands/handlers/TrackHandler.js.map +1 -1
  107. package/dist/commands/impl/FreezeTrackCommand.d.ts.map +1 -1
  108. package/dist/commands/impl/FreezeTrackCommand.js +37 -36
  109. package/dist/commands/impl/FreezeTrackCommand.js.map +1 -1
  110. package/dist/commands/impl/SetRegionTimeDomainCommand.d.ts.map +1 -1
  111. package/dist/commands/impl/SetRegionTimeDomainCommand.js +3 -3
  112. package/dist/commands/impl/SetRegionTimeDomainCommand.js.map +1 -1
  113. package/dist/commands/impl/ToggleLoopCommand.d.ts +1 -0
  114. package/dist/commands/impl/ToggleLoopCommand.d.ts.map +1 -1
  115. package/dist/commands/impl/ToggleLoopCommand.js +10 -0
  116. package/dist/commands/impl/ToggleLoopCommand.js.map +1 -1
  117. package/dist/commands/impl/TrimRegionCommand.d.ts +14 -1
  118. package/dist/commands/impl/TrimRegionCommand.d.ts.map +1 -1
  119. package/dist/commands/impl/TrimRegionCommand.js +138 -33
  120. package/dist/commands/impl/TrimRegionCommand.js.map +1 -1
  121. package/dist/commands/impl/TrimRegionToPlayheadCommand.d.ts +27 -0
  122. package/dist/commands/impl/TrimRegionToPlayheadCommand.d.ts.map +1 -0
  123. package/dist/commands/impl/TrimRegionToPlayheadCommand.js +69 -0
  124. package/dist/commands/impl/TrimRegionToPlayheadCommand.js.map +1 -0
  125. package/dist/commands/impl/TrimRegionToRangeCommand.d.ts +28 -0
  126. package/dist/commands/impl/TrimRegionToRangeCommand.d.ts.map +1 -0
  127. package/dist/commands/impl/TrimRegionToRangeCommand.js +69 -0
  128. package/dist/commands/impl/TrimRegionToRangeCommand.js.map +1 -0
  129. package/dist/commands/impl/TrimToAdjacentRegionCommand.d.ts +27 -0
  130. package/dist/commands/impl/TrimToAdjacentRegionCommand.d.ts.map +1 -0
  131. package/dist/commands/impl/TrimToAdjacentRegionCommand.js +77 -0
  132. package/dist/commands/impl/TrimToAdjacentRegionCommand.js.map +1 -0
  133. package/dist/commands/types.d.ts +19 -0
  134. package/dist/commands/types.d.ts.map +1 -1
  135. package/dist/commands/types.js +21 -0
  136. package/dist/commands/types.js.map +1 -1
  137. package/dist/domain/Crossfade.d.ts +78 -0
  138. package/dist/domain/Crossfade.d.ts.map +1 -0
  139. package/dist/domain/Crossfade.js +216 -0
  140. package/dist/domain/Crossfade.js.map +1 -0
  141. package/dist/domain/ExportConfig.d.ts +98 -1
  142. package/dist/domain/ExportConfig.d.ts.map +1 -1
  143. package/dist/domain/ExportConfig.js +154 -1
  144. package/dist/domain/ExportConfig.js.map +1 -1
  145. package/dist/domain/ExportPreset.d.ts +62 -0
  146. package/dist/domain/ExportPreset.d.ts.map +1 -0
  147. package/dist/domain/ExportPreset.js +79 -0
  148. package/dist/domain/ExportPreset.js.map +1 -0
  149. package/dist/domain/ImportStatus.d.ts +40 -0
  150. package/dist/domain/ImportStatus.d.ts.map +1 -0
  151. package/dist/domain/ImportStatus.js +86 -0
  152. package/dist/domain/ImportStatus.js.map +1 -0
  153. package/dist/domain/Playlist.d.ts +72 -0
  154. package/dist/domain/Playlist.d.ts.map +1 -1
  155. package/dist/domain/Playlist.js +231 -6
  156. package/dist/domain/Playlist.js.map +1 -1
  157. package/dist/domain/Region.d.ts +76 -0
  158. package/dist/domain/Region.d.ts.map +1 -1
  159. package/dist/domain/Region.js +234 -1
  160. package/dist/domain/Region.js.map +1 -1
  161. package/dist/domain/Route.d.ts +43 -3
  162. package/dist/domain/Route.d.ts.map +1 -1
  163. package/dist/domain/Route.js +92 -6
  164. package/dist/domain/Route.js.map +1 -1
  165. package/dist/domain/Session.d.ts +31 -0
  166. package/dist/domain/Session.d.ts.map +1 -1
  167. package/dist/domain/Session.js +70 -0
  168. package/dist/domain/Session.js.map +1 -1
  169. package/dist/domain/Source.d.ts +145 -1
  170. package/dist/domain/Source.d.ts.map +1 -1
  171. package/dist/domain/Source.js +144 -1
  172. package/dist/domain/Source.js.map +1 -1
  173. package/dist/domain/ThawList.d.ts +37 -0
  174. package/dist/domain/ThawList.d.ts.map +1 -0
  175. package/dist/domain/ThawList.js +73 -0
  176. package/dist/domain/ThawList.js.map +1 -0
  177. package/dist/domain/Track.d.ts +93 -1
  178. package/dist/domain/Track.d.ts.map +1 -1
  179. package/dist/domain/Track.js +136 -0
  180. package/dist/domain/Track.js.map +1 -1
  181. package/dist/domain/TriggerBox.d.ts +123 -0
  182. package/dist/domain/TriggerBox.d.ts.map +1 -0
  183. package/dist/domain/TriggerBox.js +430 -0
  184. package/dist/domain/TriggerBox.js.map +1 -0
  185. package/dist/domain/VCATrack.d.ts +64 -1
  186. package/dist/domain/VCATrack.d.ts.map +1 -1
  187. package/dist/domain/VCATrack.js +128 -1
  188. package/dist/domain/VCATrack.js.map +1 -1
  189. package/dist/domain/VideoExportConfig.d.ts +117 -0
  190. package/dist/domain/VideoExportConfig.d.ts.map +1 -0
  191. package/dist/domain/VideoExportConfig.js +244 -0
  192. package/dist/domain/VideoExportConfig.js.map +1 -0
  193. package/dist/domain/VideoExportStatus.d.ts +89 -0
  194. package/dist/domain/VideoExportStatus.d.ts.map +1 -0
  195. package/dist/domain/VideoExportStatus.js +192 -0
  196. package/dist/domain/VideoExportStatus.js.map +1 -0
  197. package/dist/domain/VideoMetadata.d.ts +46 -0
  198. package/dist/domain/VideoMetadata.d.ts.map +1 -0
  199. package/dist/domain/VideoMetadata.js +2 -0
  200. package/dist/domain/VideoMetadata.js.map +1 -0
  201. package/dist/domain/index.d.ts +5 -0
  202. package/dist/domain/index.d.ts.map +1 -1
  203. package/dist/domain/index.js +5 -0
  204. package/dist/domain/index.js.map +1 -1
  205. package/dist/domain/temporal/TempoMap.d.ts +199 -2
  206. package/dist/domain/temporal/TempoMap.d.ts.map +1 -1
  207. package/dist/domain/temporal/TempoMap.js +464 -30
  208. package/dist/domain/temporal/TempoMap.js.map +1 -1
  209. package/dist/index.d.ts +43 -1
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +32 -1
  212. package/dist/index.js.map +1 -1
  213. package/dist/lib/ThawList.d.ts +100 -0
  214. package/dist/lib/ThawList.d.ts.map +1 -0
  215. package/dist/lib/ThawList.js +153 -0
  216. package/dist/lib/ThawList.js.map +1 -0
  217. package/dist/midi/MidiFileParser.d.ts +33 -0
  218. package/dist/midi/MidiFileParser.d.ts.map +1 -0
  219. package/dist/midi/MidiFileParser.js +246 -0
  220. package/dist/midi/MidiFileParser.js.map +1 -0
  221. package/dist/midi/MidiFileWriter.d.ts +31 -0
  222. package/dist/midi/MidiFileWriter.d.ts.map +1 -0
  223. package/dist/midi/MidiFileWriter.js +160 -0
  224. package/dist/midi/MidiFileWriter.js.map +1 -0
  225. package/dist/midi/MidiImporter.d.ts +37 -0
  226. package/dist/midi/MidiImporter.d.ts.map +1 -0
  227. package/dist/midi/MidiImporter.js +62 -0
  228. package/dist/midi/MidiImporter.js.map +1 -0
  229. package/dist/plugins/PluginPresetManager.d.ts +86 -0
  230. package/dist/plugins/PluginPresetManager.d.ts.map +1 -0
  231. package/dist/plugins/PluginPresetManager.js +140 -0
  232. package/dist/plugins/PluginPresetManager.js.map +1 -0
  233. package/dist/processing/IO.d.ts +15 -1
  234. package/dist/processing/IO.d.ts.map +1 -1
  235. package/dist/processing/IO.js +29 -1
  236. package/dist/processing/IO.js.map +1 -1
  237. package/dist/processing/InternalSend.d.ts +104 -0
  238. package/dist/processing/InternalSend.d.ts.map +1 -0
  239. package/dist/processing/InternalSend.js +175 -0
  240. package/dist/processing/InternalSend.js.map +1 -0
  241. package/dist/processing/MeterDSP.d.ts +166 -0
  242. package/dist/processing/MeterDSP.d.ts.map +1 -0
  243. package/dist/processing/MeterDSP.js +754 -0
  244. package/dist/processing/MeterDSP.js.map +1 -0
  245. package/dist/processing/Panner.d.ts +145 -0
  246. package/dist/processing/Panner.d.ts.map +1 -0
  247. package/dist/processing/Panner.js +281 -0
  248. package/dist/processing/Panner.js.map +1 -0
  249. package/dist/processing/PluginInsert.d.ts +56 -1
  250. package/dist/processing/PluginInsert.d.ts.map +1 -1
  251. package/dist/processing/PluginInsert.js +180 -2
  252. package/dist/processing/PluginInsert.js.map +1 -1
  253. package/dist/processing/Processor.d.ts +38 -0
  254. package/dist/processing/Processor.d.ts.map +1 -1
  255. package/dist/processing/Processor.js +60 -1
  256. package/dist/processing/Processor.js.map +1 -1
  257. package/dist/processing/SurroundPanner.d.ts +122 -0
  258. package/dist/processing/SurroundPanner.d.ts.map +1 -0
  259. package/dist/processing/SurroundPanner.js +376 -0
  260. package/dist/processing/SurroundPanner.js.map +1 -0
  261. package/dist/processing/TruePeakLimiter.d.ts +34 -0
  262. package/dist/processing/TruePeakLimiter.d.ts.map +1 -0
  263. package/dist/processing/TruePeakLimiter.js +144 -0
  264. package/dist/processing/TruePeakLimiter.js.map +1 -0
  265. package/dist/storage/ExportPresetStorage.d.ts +33 -0
  266. package/dist/storage/ExportPresetStorage.d.ts.map +1 -0
  267. package/dist/storage/ExportPresetStorage.js +121 -0
  268. package/dist/storage/ExportPresetStorage.js.map +1 -0
  269. package/dist/storage/SessionArchive.d.ts +73 -0
  270. package/dist/storage/SessionArchive.d.ts.map +1 -0
  271. package/dist/storage/SessionArchive.js +211 -0
  272. package/dist/storage/SessionArchive.js.map +1 -0
  273. package/dist/storage/SessionTemplate.d.ts +74 -5
  274. package/dist/storage/SessionTemplate.d.ts.map +1 -1
  275. package/dist/storage/SessionTemplate.js +247 -53
  276. package/dist/storage/SessionTemplate.js.map +1 -1
  277. package/dist/utils/BwfMetadataWriter.d.ts +42 -0
  278. package/dist/utils/BwfMetadataWriter.d.ts.map +1 -0
  279. package/dist/utils/BwfMetadataWriter.js +131 -0
  280. package/dist/utils/BwfMetadataWriter.js.map +1 -0
  281. package/dist/utils/FilenameTemplate.d.ts +40 -0
  282. package/dist/utils/FilenameTemplate.d.ts.map +1 -0
  283. package/dist/utils/FilenameTemplate.js +78 -0
  284. package/dist/utils/FilenameTemplate.js.map +1 -0
  285. package/dist/utils/Logger.d.ts +28 -0
  286. package/dist/utils/Logger.d.ts.map +1 -0
  287. package/dist/utils/Logger.js +46 -0
  288. package/dist/utils/Logger.js.map +1 -0
  289. package/dist/utils/Mp4ChapterGenerator.d.ts +17 -0
  290. package/dist/utils/Mp4ChapterGenerator.d.ts.map +1 -0
  291. package/dist/utils/Mp4ChapterGenerator.js +33 -0
  292. package/dist/utils/Mp4ChapterGenerator.js.map +1 -0
  293. package/dist/utils/OggEncoder.d.ts +20 -20
  294. package/dist/utils/OggEncoder.d.ts.map +1 -1
  295. package/dist/utils/OggEncoder.js +114 -50
  296. package/dist/utils/OggEncoder.js.map +1 -1
  297. package/dist/utils/TocGenerator.d.ts +17 -0
  298. package/dist/utils/TocGenerator.d.ts.map +1 -0
  299. package/dist/utils/TocGenerator.js +47 -0
  300. package/dist/utils/TocGenerator.js.map +1 -0
  301. package/package.json +7 -8
@@ -0,0 +1,292 @@
1
+ import { Signal } from '../../lib/Signal';
2
+ /**
3
+ * SidechainRouter manages the actual audio signal routing for sidechain connections.
4
+ *
5
+ * Ardour reference: libs/ardour/sidechain.cc
6
+ *
7
+ * In the Web Audio context, sidechain routing works by:
8
+ * 1. Tapping the source track's audio output (pre or post fader)
9
+ * 2. Optionally applying a high-pass filter
10
+ * 3. Feeding it into the target processor's sidechain input
11
+ *
12
+ * The router maintains a buffer-per-config that holds the latest audio block
13
+ * from the source track, available for the target processor to read.
14
+ */
15
+ export class SidechainRouter {
16
+ /**
17
+ * @param sampleRate - The audio sample rate (e.g. 44100, 48000)
18
+ */
19
+ constructor(sampleRate = 44100) {
20
+ this._configs = new Map();
21
+ /** Buffer storage: configId -> latest audio block from source */
22
+ this._sidechainBuffers = new Map();
23
+ /** HPF filter state per config (one state per channel, keyed by configId) */
24
+ this._filterStates = new Map();
25
+ this.routingChanged = new Signal();
26
+ this._sampleRate = sampleRate;
27
+ }
28
+ // ─── Configuration Management ──────────────────────────────────────────────
29
+ /**
30
+ * Register a sidechain configuration.
31
+ * Initialises the buffer and filter state for the new config.
32
+ */
33
+ addConfig(config) {
34
+ this._configs.set(config.id, config);
35
+ // Initialise an empty buffer
36
+ this._sidechainBuffers.set(config.id, {
37
+ data: [],
38
+ blockSize: 0,
39
+ valid: false,
40
+ });
41
+ // Initialise filter states (start with 2 channels; will resize as needed)
42
+ this._rebuildFilterState(config);
43
+ // Listen for filter parameter changes so we can recompute coefficients
44
+ config.filterChanged.connect(() => {
45
+ this._rebuildFilterState(config);
46
+ });
47
+ this.routingChanged.emit();
48
+ }
49
+ /**
50
+ * Remove a sidechain configuration and clean up its resources.
51
+ */
52
+ removeConfig(configId) {
53
+ if (!this._configs.has(configId)) {
54
+ return;
55
+ }
56
+ this._configs.delete(configId);
57
+ this._sidechainBuffers.delete(configId);
58
+ this._filterStates.delete(configId);
59
+ this.routingChanged.emit();
60
+ }
61
+ /**
62
+ * Get config by ID.
63
+ */
64
+ getConfig(configId) {
65
+ return this._configs.get(configId);
66
+ }
67
+ /**
68
+ * Get all configs targeting a specific track.
69
+ */
70
+ getConfigsForTarget(trackId) {
71
+ const result = [];
72
+ for (const config of this._configs.values()) {
73
+ if (config.targetTrackId === trackId) {
74
+ result.push(config);
75
+ }
76
+ }
77
+ return result;
78
+ }
79
+ /**
80
+ * Get all configs sourcing from a specific track.
81
+ */
82
+ getConfigsForSource(trackId) {
83
+ const result = [];
84
+ for (const config of this._configs.values()) {
85
+ if (config.sourceTrackId === trackId) {
86
+ result.push(config);
87
+ }
88
+ }
89
+ return result;
90
+ }
91
+ // ─── Audio Routing ─────────────────────────────────────────────────────────
92
+ /**
93
+ * Called by the audio engine when a source track produces audio.
94
+ * Stores the audio block for later retrieval by target processors.
95
+ *
96
+ * For every config that sources from the given trackId, we copy the
97
+ * audio data into the config's sidechain buffer.
98
+ *
99
+ * @param trackId - The source track that just produced audio
100
+ * @param audioData - Per-channel audio data (e.g. [leftChannel, rightChannel])
101
+ * @param blockSize - Number of samples per channel in this block
102
+ */
103
+ feedSourceAudio(trackId, audioData, blockSize) {
104
+ for (const config of this._configs.values()) {
105
+ if (config.sourceTrackId !== trackId || !config.enabled) {
106
+ continue;
107
+ }
108
+ const numChannels = audioData.length;
109
+ let buffer = this._sidechainBuffers.get(config.id);
110
+ // Allocate or resize the buffer if needed
111
+ if (!buffer ||
112
+ buffer.data.length !== numChannels ||
113
+ buffer.blockSize !== blockSize) {
114
+ buffer = {
115
+ data: new Array(numChannels)
116
+ .fill(null)
117
+ .map(() => new Float32Array(blockSize)),
118
+ blockSize,
119
+ valid: false,
120
+ };
121
+ this._sidechainBuffers.set(config.id, buffer);
122
+ }
123
+ // Copy source audio into the sidechain buffer
124
+ for (let ch = 0; ch < numChannels; ch++) {
125
+ buffer.data[ch].set(audioData[ch].subarray(0, blockSize));
126
+ }
127
+ buffer.valid = true;
128
+ }
129
+ }
130
+ /**
131
+ * Called by the target processor to get the sidechain input.
132
+ * Returns the latest audio block from the source track (with optional HPF applied),
133
+ * or null if no valid data is available.
134
+ *
135
+ * @param configId - The sidechain configuration ID
136
+ * @returns Per-channel audio data, or null if unavailable
137
+ */
138
+ getSidechainInput(configId) {
139
+ const config = this._configs.get(configId);
140
+ if (!config || !config.enabled) {
141
+ return null;
142
+ }
143
+ const buffer = this._sidechainBuffers.get(configId);
144
+ if (!buffer || !buffer.valid || buffer.data.length === 0) {
145
+ return null;
146
+ }
147
+ // If HPF is enabled, apply it to a copy of the buffer
148
+ if (config.sidechainFilterEnabled) {
149
+ return this._applyHPF(configId, buffer.data);
150
+ }
151
+ // Return copies so the caller can't mutate our internal buffers
152
+ return buffer.data.map((ch) => new Float32Array(ch));
153
+ }
154
+ // ─── HPF (High-Pass Filter) ────────────────────────────────────────────────
155
+ /**
156
+ * Apply a 2nd-order Butterworth high-pass filter to the sidechain signal.
157
+ * Processes in-place on copies of the input channels.
158
+ *
159
+ * The Butterworth HPF transfer function is implemented as a Direct Form I
160
+ * biquad filter: y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2]
161
+ */
162
+ _applyHPF(configId, inputChannels) {
163
+ const numChannels = inputChannels.length;
164
+ let states = this._filterStates.get(configId);
165
+ // Ensure we have a filter state per channel
166
+ if (!states || states.length !== numChannels) {
167
+ const config = this._configs.get(configId);
168
+ if (!config) {
169
+ return inputChannels.map((ch) => new Float32Array(ch));
170
+ }
171
+ states = new Array(numChannels)
172
+ .fill(null)
173
+ .map(() => computeHPFCoefficients(config.sidechainFilterFrequency, this._sampleRate));
174
+ this._filterStates.set(configId, states);
175
+ }
176
+ const output = [];
177
+ for (let ch = 0; ch < numChannels; ch++) {
178
+ const input = inputChannels[ch];
179
+ const out = new Float32Array(input.length);
180
+ const state = states[ch];
181
+ for (let i = 0; i < input.length; i++) {
182
+ const x = input[i];
183
+ // Direct Form I biquad
184
+ const y = state.b0 * x +
185
+ state.b1 * state.x1 +
186
+ state.b2 * state.x2 -
187
+ state.a1 * state.y1 -
188
+ state.a2 * state.y2;
189
+ // Shift delay line
190
+ state.x2 = state.x1;
191
+ state.x1 = x;
192
+ state.y2 = state.y1;
193
+ state.y1 = y;
194
+ out[i] = y;
195
+ }
196
+ output.push(out);
197
+ }
198
+ return output;
199
+ }
200
+ /**
201
+ * Rebuild the filter state for a given config.
202
+ * Called when the config is added or its filter parameters change.
203
+ */
204
+ _rebuildFilterState(config) {
205
+ const buffer = this._sidechainBuffers.get(config.id);
206
+ const numChannels = buffer ? Math.max(buffer.data.length, 2) : 2;
207
+ const states = new Array(numChannels)
208
+ .fill(null)
209
+ .map(() => computeHPFCoefficients(config.sidechainFilterFrequency, this._sampleRate));
210
+ this._filterStates.set(config.id, states);
211
+ }
212
+ // ─── Lifecycle ─────────────────────────────────────────────────────────────
213
+ /**
214
+ * Reset all buffers and filter states.
215
+ * Typically called when transport stops or seeks.
216
+ */
217
+ reset() {
218
+ for (const [configId, buffer] of this._sidechainBuffers.entries()) {
219
+ for (const ch of buffer.data) {
220
+ ch.fill(0);
221
+ }
222
+ buffer.valid = false;
223
+ // Reset filter delay lines while preserving coefficients
224
+ const states = this._filterStates.get(configId);
225
+ if (states) {
226
+ for (const state of states) {
227
+ state.x1 = 0;
228
+ state.x2 = 0;
229
+ state.y1 = 0;
230
+ state.y2 = 0;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ /**
236
+ * Update the sample rate. Recomputes all HPF filter coefficients.
237
+ */
238
+ setSampleRate(sampleRate) {
239
+ this._sampleRate = sampleRate;
240
+ for (const config of this._configs.values()) {
241
+ this._rebuildFilterState(config);
242
+ }
243
+ }
244
+ }
245
+ // ─── Helper Functions ──────────────────────────────────────────────────────────
246
+ /**
247
+ * Compute the biquad filter coefficients for a 2nd-order Butterworth high-pass filter.
248
+ *
249
+ * Derivation from the analogue Butterworth prototype:
250
+ * H(s) = s^2 / (s^2 + sqrt(2)*s + 1)
251
+ *
252
+ * Bilinear transform with pre-warping:
253
+ * omega_c = 2 * pi * frequency / sampleRate
254
+ * K = tan(omega_c / 2)
255
+ * norm = 1 / (1 + sqrt(2)*K + K^2)
256
+ *
257
+ * b0 = norm
258
+ * b1 = -2 * norm
259
+ * b2 = norm
260
+ * a1 = 2 * (K^2 - 1) * norm
261
+ * a2 = (1 - sqrt(2)*K + K^2) * norm
262
+ *
263
+ * The returned state has zeroed delay lines, ready for immediate use.
264
+ *
265
+ * @param frequency - HPF cutoff frequency in Hz
266
+ * @param sampleRate - Audio sample rate in Hz
267
+ * @returns A BiquadFilterState with computed coefficients and zeroed state
268
+ */
269
+ export function computeHPFCoefficients(frequency, sampleRate) {
270
+ // Clamp frequency to a safe range: above 0 and below Nyquist
271
+ const nyquist = sampleRate / 2;
272
+ const freq = Math.max(1, Math.min(frequency, nyquist * 0.99));
273
+ const omega = (2 * Math.PI * freq) / sampleRate;
274
+ const K = Math.tan(omega / 2);
275
+ const K2 = K * K;
276
+ const sqrt2 = Math.SQRT2;
277
+ const norm = 1 / (1 + sqrt2 * K + K2);
278
+ return {
279
+ // Delay line state (zeroed)
280
+ x1: 0,
281
+ x2: 0,
282
+ y1: 0,
283
+ y2: 0,
284
+ // Coefficients
285
+ b0: norm,
286
+ b1: -2 * norm,
287
+ b2: norm,
288
+ a1: 2 * (K2 - 1) * norm,
289
+ a2: (1 - sqrt2 * K + K2) * norm,
290
+ };
291
+ }
292
+ //# sourceMappingURL=SidechainRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SidechainRouter.js","sourceRoot":"","sources":["../../../src/audio/engine/SidechainRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { Signal } from '../../lib/Signal';
2
+ export interface XrunEvent {
3
+ timestamp: number;
4
+ frame: number;
5
+ type: 'underrun' | 'overrun';
6
+ duration?: number;
7
+ }
8
+ /**
9
+ * XrunTracker - Tracks buffer underrun/overrun events during recording
10
+ * and playback. Provides signals for real-time notification and
11
+ * query methods for post-session analysis.
12
+ */
13
+ export declare class XrunTracker {
14
+ private _events;
15
+ private _isTracking;
16
+ private _totalXruns;
17
+ /** Signal emitted whenever an xrun is detected */
18
+ readonly xrunDetected: Signal<XrunEvent>;
19
+ /**
20
+ * Start tracking xrun events.
21
+ * Clears any previously recorded events.
22
+ */
23
+ startTracking(): void;
24
+ /**
25
+ * Stop tracking xrun events.
26
+ */
27
+ stopTracking(): void;
28
+ /**
29
+ * Record an xrun event.
30
+ * Only records if tracking is active.
31
+ * @param frame - The session frame position where the xrun occurred
32
+ * @param type - Whether this was an underrun or overrun
33
+ * @param duration - Optional estimated glitch duration in samples
34
+ */
35
+ reportXrun(frame: number, type: 'underrun' | 'overrun', duration?: number): void;
36
+ /**
37
+ * Get all recorded xrun events.
38
+ */
39
+ getEvents(): XrunEvent[];
40
+ /**
41
+ * Get all xrun events that occurred at or after the given frame.
42
+ */
43
+ getEventsSince(frame: number): XrunEvent[];
44
+ /**
45
+ * Get the total number of xruns recorded (persists across reset of events).
46
+ */
47
+ getTotalCount(): number;
48
+ /**
49
+ * Get the most recent xrun event, if any.
50
+ */
51
+ getLastEvent(): XrunEvent | undefined;
52
+ /**
53
+ * Check if any xruns have been recorded.
54
+ */
55
+ hasXruns(): boolean;
56
+ /**
57
+ * Reset all tracked events and counters.
58
+ */
59
+ reset(): void;
60
+ /**
61
+ * Get a summary of all recorded xrun events.
62
+ */
63
+ getSummary(): {
64
+ total: number;
65
+ underruns: number;
66
+ overruns: number;
67
+ firstFrame?: number;
68
+ lastFrame?: number;
69
+ };
70
+ }
71
+ //# sourceMappingURL=XrunTracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XrunTracker.d.ts","sourceRoot":"","sources":["../../../src/audio/engine/XrunTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,WAAW,SAAS;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAAa;IAEhC,kDAAkD;IAClD,SAAgB,YAAY,EAAE,MAAM,CAAC,SAAS,CAAC,CAA2B;IAE1E;;;OAGG;IACH,aAAa,IAAI,IAAI;IAIrB;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;;;;;OAMG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAehF;;OAEG;IACH,SAAS,IAAI,SAAS,EAAE;IAIxB;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAI1C;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,YAAY,IAAI,SAAS,GAAG,SAAS;IAMrC;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,UAAU,IAAI;QACV,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACtB;CA6BJ"}
@@ -0,0 +1,118 @@
1
+ import { Signal } from '../../lib/Signal';
2
+ /**
3
+ * XrunTracker - Tracks buffer underrun/overrun events during recording
4
+ * and playback. Provides signals for real-time notification and
5
+ * query methods for post-session analysis.
6
+ */
7
+ export class XrunTracker {
8
+ constructor() {
9
+ this._events = [];
10
+ this._isTracking = false;
11
+ this._totalXruns = 0;
12
+ /** Signal emitted whenever an xrun is detected */
13
+ this.xrunDetected = new Signal();
14
+ }
15
+ /**
16
+ * Start tracking xrun events.
17
+ * Clears any previously recorded events.
18
+ */
19
+ startTracking() {
20
+ this._isTracking = true;
21
+ }
22
+ /**
23
+ * Stop tracking xrun events.
24
+ */
25
+ stopTracking() {
26
+ this._isTracking = false;
27
+ }
28
+ /**
29
+ * Record an xrun event.
30
+ * Only records if tracking is active.
31
+ * @param frame - The session frame position where the xrun occurred
32
+ * @param type - Whether this was an underrun or overrun
33
+ * @param duration - Optional estimated glitch duration in samples
34
+ */
35
+ reportXrun(frame, type, duration) {
36
+ if (!this._isTracking)
37
+ return;
38
+ const event = {
39
+ timestamp: Date.now(),
40
+ frame,
41
+ type,
42
+ duration,
43
+ };
44
+ this._events.push(event);
45
+ this._totalXruns++;
46
+ this.xrunDetected.emit(event);
47
+ }
48
+ /**
49
+ * Get all recorded xrun events.
50
+ */
51
+ getEvents() {
52
+ return [...this._events];
53
+ }
54
+ /**
55
+ * Get all xrun events that occurred at or after the given frame.
56
+ */
57
+ getEventsSince(frame) {
58
+ return this._events.filter(e => e.frame >= frame);
59
+ }
60
+ /**
61
+ * Get the total number of xruns recorded (persists across reset of events).
62
+ */
63
+ getTotalCount() {
64
+ return this._totalXruns;
65
+ }
66
+ /**
67
+ * Get the most recent xrun event, if any.
68
+ */
69
+ getLastEvent() {
70
+ return this._events.length > 0
71
+ ? this._events[this._events.length - 1]
72
+ : undefined;
73
+ }
74
+ /**
75
+ * Check if any xruns have been recorded.
76
+ */
77
+ hasXruns() {
78
+ return this._events.length > 0;
79
+ }
80
+ /**
81
+ * Reset all tracked events and counters.
82
+ */
83
+ reset() {
84
+ this._events = [];
85
+ this._totalXruns = 0;
86
+ }
87
+ /**
88
+ * Get a summary of all recorded xrun events.
89
+ */
90
+ getSummary() {
91
+ let underruns = 0;
92
+ let overruns = 0;
93
+ let firstFrame;
94
+ let lastFrame;
95
+ for (const event of this._events) {
96
+ if (event.type === 'underrun') {
97
+ underruns++;
98
+ }
99
+ else {
100
+ overruns++;
101
+ }
102
+ if (firstFrame === undefined || event.frame < firstFrame) {
103
+ firstFrame = event.frame;
104
+ }
105
+ if (lastFrame === undefined || event.frame > lastFrame) {
106
+ lastFrame = event.frame;
107
+ }
108
+ }
109
+ return {
110
+ total: this._events.length,
111
+ underruns,
112
+ overruns,
113
+ firstFrame,
114
+ lastFrame,
115
+ };
116
+ }
117
+ }
118
+ //# sourceMappingURL=XrunTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XrunTracker.js","sourceRoot":"","sources":["../../../src/audio/engine/XrunTracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAS1C;;;;GAIG;AACH,MAAM,OAAO,WAAW;IAAxB;QACY,YAAO,GAAgB,EAAE,CAAC;QAC1B,gBAAW,GAAY,KAAK,CAAC;QAC7B,gBAAW,GAAW,CAAC,CAAC;QAEhC,kDAAkD;QAClC,iBAAY,GAAsB,IAAI,MAAM,EAAa,CAAC;IA0H9E,CAAC;IAxHG;;;OAGG;IACH,aAAa;QACT,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,YAAY;QACR,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAC,KAAa,EAAE,IAA4B,EAAE,QAAiB;QACrE,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAE9B,MAAM,KAAK,GAAc;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,KAAK;YACL,IAAI;YACJ,QAAQ;SACX,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,SAAS;QACL,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,KAAa;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,aAAa;QACT,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,YAAY;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAC1B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;YACvC,CAAC,CAAC,SAAS,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,QAAQ;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,UAAU;QAON,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,UAA8B,CAAC;QACnC,IAAI,SAA6B,CAAC;QAElC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC5B,SAAS,EAAE,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACJ,QAAQ,EAAE,CAAC;YACf,CAAC;YAED,IAAI,UAAU,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC;gBACvD,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;YAC7B,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,EAAE,CAAC;gBACrD,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;YAC5B,CAAC;QACL,CAAC;QAED,OAAO;YACH,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC1B,SAAS;YACT,QAAQ;YACR,UAAU;YACV,SAAS;SACZ,CAAC;IACN,CAAC;CACJ"}
@@ -0,0 +1,62 @@
1
+ import { CDMarker } from '../../domain/CDMarker';
2
+ /**
3
+ * CD Marker Exporter
4
+ *
5
+ * Generates industry-standard marker/chapter files from CDMarker data.
6
+ * Supports CUE sheets, cdrdao TOC files, and Nero-style MP4 chapter files.
7
+ *
8
+ * Ardour reference: libs/ardour/export_handler.cc
9
+ */
10
+ export declare class CDMarkerExporter {
11
+ /**
12
+ * Generate a CUE sheet from CD markers.
13
+ *
14
+ * CUE format reference: https://en.wikipedia.org/wiki/Cue_sheet_(computing)
15
+ * Time format: MM:SS:FF where FF = CD frames (75 fps)
16
+ *
17
+ * @param markers Array of CDMarker instances
18
+ * @param filename Audio filename referenced in the CUE sheet
19
+ * @param sampleRate Sample rate of the audio
20
+ * @param albumTitle Optional album title
21
+ * @param albumPerformer Optional album performer
22
+ */
23
+ static generateCUE(markers: CDMarker[], filename: string, sampleRate: number, albumTitle?: string, albumPerformer?: string): string;
24
+ /**
25
+ * Generate a cdrdao-compatible TOC (Table of Contents) file.
26
+ *
27
+ * TOC format reference: cdrdao(1) man page
28
+ *
29
+ * @param markers Array of CDMarker instances
30
+ * @param filename Audio filename
31
+ * @param sampleRate Sample rate of the audio
32
+ */
33
+ static generateTOC(markers: CDMarker[], filename: string, sampleRate: number): string;
34
+ /**
35
+ * Generate Nero-style MP4 chapter metadata.
36
+ *
37
+ * Format: CHAPTERXX=HH:MM:SS.mmm / CHAPTERXXNAME=Title
38
+ * This format is understood by ffmpeg via -i chapters.txt.
39
+ *
40
+ * @param markers Array of CDMarker instances
41
+ * @param sampleRate Sample rate of the audio
42
+ */
43
+ static generateMP4Chapters(markers: CDMarker[], sampleRate: number): string;
44
+ /**
45
+ * Convert a sample-frame position to CD time format MM:SS:FF.
46
+ * CD frames run at 75 fps (Red Book standard).
47
+ *
48
+ * @param frames Position in audio sample frames
49
+ * @param sampleRate Audio sample rate (e.g. 44100)
50
+ * @returns Time string in MM:SS:FF format
51
+ */
52
+ static framesToCDTime(frames: number, sampleRate: number): string;
53
+ /**
54
+ * Convert a sample-frame position to HH:MM:SS.mmm timestamp.
55
+ *
56
+ * @param frames Position in audio sample frames
57
+ * @param sampleRate Audio sample rate
58
+ * @returns Time string in HH:MM:SS.mmm format
59
+ */
60
+ static framesToTimestamp(frames: number, sampleRate: number): string;
61
+ }
62
+ //# sourceMappingURL=CDMarkerExporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CDMarkerExporter.d.ts","sourceRoot":"","sources":["../../../src/audio/export/CDMarkerExporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD;;;;;;;GAOG;AACH,qBAAa,gBAAgB;IACzB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,WAAW,CACd,OAAO,EAAE,QAAQ,EAAE,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAmB,EAC/B,cAAc,GAAE,MAAW,GAC5B,MAAM;IAiCT;;;;;;;;OAQG;IACH,MAAM,CAAC,WAAW,CACd,OAAO,EAAE,QAAQ,EAAE,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACnB,MAAM;IA2DT;;;;;;;;OAQG;IACH,MAAM,CAAC,mBAAmB,CACtB,OAAO,EAAE,QAAQ,EAAE,EACnB,UAAU,EAAE,MAAM,GACnB,MAAM;IAgBT;;;;;;;OAOG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAajE;;;;;;OAMG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAcvE"}