@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,384 @@
1
+ import { Declicker, DeclickAmp } from './Declick';
2
+ /** Default chunk size: 64k samples (~1.5s at 44100 Hz) */
3
+ const DEFAULT_CHUNK_SIZE = 65536;
4
+ /** Default peak buffer size for GUI visualization */
5
+ const DEFAULT_PEAK_BUFFER_SIZE = 1024;
6
+ /**
7
+ * DiskReader - Manages buffered playback I/O.
8
+ * Provides chunk-based reading with loop handling.
9
+ * Inspired by Ardour's DiskReader.
10
+ */
11
+ export class DiskReader {
12
+ /**
13
+ * @param channelCount - Number of audio channels (e.g. 2 for stereo)
14
+ * @param chunkSize - Size of the internal playback buffer per channel (default 64k)
15
+ */
16
+ constructor(channelCount, chunkSize) {
17
+ this._readPosition = 0;
18
+ this._writeOffset = 0; // How many valid samples are in _buffer
19
+ this._loopStart = -1;
20
+ this._loopEnd = -1;
21
+ this._declicker = null;
22
+ this._channelCount = channelCount;
23
+ this._chunkSize = chunkSize !== null && chunkSize !== void 0 ? chunkSize : DEFAULT_CHUNK_SIZE;
24
+ this._buffer = [];
25
+ for (let ch = 0; ch < channelCount; ch++) {
26
+ this._buffer.push(new Float32Array(this._chunkSize));
27
+ }
28
+ }
29
+ /**
30
+ * Set loop boundaries for loop playback.
31
+ * When reading reaches loopEnd, it wraps back to loopStart.
32
+ * Optionally enables a declicker for smooth loop transitions.
33
+ * @param start - Loop start frame (in source coordinates)
34
+ * @param end - Loop end frame (in source coordinates)
35
+ */
36
+ setLoop(start, end) {
37
+ this._loopStart = start;
38
+ this._loopEnd = end;
39
+ // Create a declicker for the loop boundary (~128 samples)
40
+ this._declicker = new Declicker(128);
41
+ }
42
+ /**
43
+ * Remove loop boundaries.
44
+ */
45
+ clearLoop() {
46
+ this._loopStart = -1;
47
+ this._loopEnd = -1;
48
+ this._declicker = null;
49
+ }
50
+ /**
51
+ * Fill the internal buffer from a source starting at the given frame.
52
+ * Handles loop wrapping if a loop is set.
53
+ * @param source - The audio buffer source to read from
54
+ * @param startFrame - The frame position in the source to start reading from
55
+ * @returns The number of frames actually read
56
+ */
57
+ async refill(source, startFrame) {
58
+ const srcLength = source.length;
59
+ const channels = Math.min(this._channelCount, source.numberOfChannels);
60
+ let framesRead = 0;
61
+ let srcPos = startFrame;
62
+ const hasLoop = this._loopStart >= 0 && this._loopEnd > this._loopStart;
63
+ // Clear buffers
64
+ for (let ch = 0; ch < this._channelCount; ch++) {
65
+ this._buffer[ch].fill(0);
66
+ }
67
+ while (framesRead < this._chunkSize) {
68
+ // Clamp source position
69
+ if (srcPos >= srcLength) {
70
+ if (hasLoop) {
71
+ srcPos = this._loopStart;
72
+ }
73
+ else {
74
+ break; // End of source, no loop
75
+ }
76
+ }
77
+ // Determine how many frames we can read in this segment
78
+ let framesToRead = this._chunkSize - framesRead;
79
+ // Don't read past source end
80
+ framesToRead = Math.min(framesToRead, srcLength - srcPos);
81
+ // Don't read past loop end
82
+ if (hasLoop && srcPos < this._loopEnd) {
83
+ framesToRead = Math.min(framesToRead, this._loopEnd - srcPos);
84
+ }
85
+ if (framesToRead <= 0)
86
+ break;
87
+ // Copy from source into internal buffer
88
+ for (let ch = 0; ch < channels; ch++) {
89
+ const srcData = source.getChannelData(ch);
90
+ const destData = this._buffer[ch];
91
+ for (let i = 0; i < framesToRead; i++) {
92
+ destData[framesRead + i] = srcData[srcPos + i];
93
+ }
94
+ }
95
+ framesRead += framesToRead;
96
+ srcPos += framesToRead;
97
+ // Handle loop wrap
98
+ if (hasLoop && srcPos >= this._loopEnd) {
99
+ // Apply crossfade at the loop boundary if declicker is available
100
+ if (this._declicker && framesRead > 0) {
101
+ const fadeLen = this._declicker.getLength();
102
+ const fadeStart = framesRead - Math.min(fadeLen, framesToRead);
103
+ if (fadeStart >= 0) {
104
+ for (let ch = 0; ch < channels; ch++) {
105
+ this._declicker.applyFadeOut(this._buffer[ch], fadeStart);
106
+ }
107
+ }
108
+ }
109
+ srcPos = this._loopStart;
110
+ }
111
+ }
112
+ this._writeOffset = framesRead;
113
+ this._readPosition = 0;
114
+ return framesRead;
115
+ }
116
+ /**
117
+ * Read samples from the internal buffer into output arrays.
118
+ * @param output - Per-channel output arrays to write into
119
+ * @param offset - Offset into the output arrays
120
+ * @param count - Number of frames to read
121
+ * @returns Number of frames actually read
122
+ */
123
+ read(output, offset, count) {
124
+ const available = this._writeOffset - this._readPosition;
125
+ const framesToRead = Math.min(count, available);
126
+ if (framesToRead <= 0)
127
+ return 0;
128
+ const channels = Math.min(this._channelCount, output.length);
129
+ for (let ch = 0; ch < channels; ch++) {
130
+ const src = this._buffer[ch];
131
+ const dest = output[ch];
132
+ for (let i = 0; i < framesToRead; i++) {
133
+ dest[offset + i] = src[this._readPosition + i];
134
+ }
135
+ }
136
+ this._readPosition += framesToRead;
137
+ return framesToRead;
138
+ }
139
+ /**
140
+ * Seek to a specific frame position within the buffer.
141
+ * Note: This only adjusts the internal read pointer; you may need to refill().
142
+ */
143
+ seek(frame) {
144
+ this._readPosition = 0;
145
+ this._writeOffset = 0;
146
+ // The caller should refill after seeking
147
+ }
148
+ /**
149
+ * Get current read position within the internal buffer.
150
+ */
151
+ getPosition() {
152
+ return this._readPosition;
153
+ }
154
+ /**
155
+ * Check if the internal buffer needs a refill (more than half consumed).
156
+ */
157
+ needsRefill() {
158
+ return this._readPosition >= this._writeOffset / 2;
159
+ }
160
+ /**
161
+ * Get the percentage of the buffer that still contains unread data.
162
+ * Useful for monitoring playback buffer health.
163
+ */
164
+ getBufferLoadPercent() {
165
+ if (this._writeOffset === 0)
166
+ return 0;
167
+ const remaining = this._writeOffset - this._readPosition;
168
+ return (remaining / this._chunkSize) * 100;
169
+ }
170
+ }
171
+ /**
172
+ * DiskWriter - Manages buffered recording I/O.
173
+ * Captures audio with alignment and xrun tracking.
174
+ * Inspired by Ardour's DiskWriter.
175
+ */
176
+ export class DiskWriter {
177
+ /**
178
+ * @param channelCount - Number of audio channels
179
+ * @param sampleRate - Audio sample rate (for DeclickAmp ramp calculation)
180
+ * @param xrunTracker - Shared xrun tracker instance
181
+ */
182
+ constructor(channelCount, sampleRate, xrunTracker) {
183
+ this._writePosition = 0;
184
+ this._captureStart = -1;
185
+ this._captureEnd = -1;
186
+ this._isRecording = false;
187
+ this._peakWritePos = 0;
188
+ this._alignmentStyle = 'capture_time';
189
+ this._channelCount = channelCount;
190
+ this._xrunTracker = xrunTracker;
191
+ this._declickAmp = new DeclickAmp(sampleRate);
192
+ this._bufferSize = DiskWriter.INITIAL_BUFFER_FRAMES;
193
+ // Allocate per-channel capture buffers
194
+ this._buffer = [];
195
+ for (let ch = 0; ch < channelCount; ch++) {
196
+ this._buffer.push(new Float32Array(this._bufferSize));
197
+ }
198
+ // Peak buffer for GUI visualization
199
+ this._peakBuffer = [];
200
+ for (let ch = 0; ch < channelCount; ch++) {
201
+ this._peakBuffer.push(new Float32Array(DEFAULT_PEAK_BUFFER_SIZE));
202
+ }
203
+ }
204
+ /**
205
+ * Prepare for recording. Resets buffers and sets the capture start frame.
206
+ * @param startFrame - The session frame at which recording will begin
207
+ */
208
+ prepareRecord(startFrame) {
209
+ this._captureStart = startFrame;
210
+ this._captureEnd = -1;
211
+ this._writePosition = 0;
212
+ this._peakWritePos = 0;
213
+ // Clear buffers
214
+ for (let ch = 0; ch < this._channelCount; ch++) {
215
+ this._buffer[ch].fill(0);
216
+ this._peakBuffer[ch].fill(0);
217
+ }
218
+ // Reset declick: start at gain 0, will ramp up when recording starts
219
+ this._declickAmp.reset(0.0);
220
+ this._declickAmp.setTarget(1.0);
221
+ }
222
+ /**
223
+ * Start recording. Activates capture and begins the fade-in ramp.
224
+ */
225
+ startRecord() {
226
+ this._isRecording = true;
227
+ this._declickAmp.setTarget(1.0);
228
+ }
229
+ /**
230
+ * Stop recording. Begins fade-out ramp and marks the capture end.
231
+ * @returns The capture end frame in session coordinates
232
+ */
233
+ stopRecord() {
234
+ this._isRecording = false;
235
+ this._declickAmp.setTarget(0.0);
236
+ this._captureEnd = this._captureStart + this._writePosition;
237
+ return this._captureEnd;
238
+ }
239
+ /**
240
+ * Write incoming audio samples to the capture buffer.
241
+ * Applies declick ramp and tracks peak data for GUI.
242
+ * Reports an xrun if the buffer overflows.
243
+ * @param input - Per-channel input arrays
244
+ * @param offset - Offset into the input arrays
245
+ * @param count - Number of frames to write
246
+ */
247
+ write(input, offset, count) {
248
+ if (!this._isRecording && !this._declickAmp.isRamping())
249
+ return;
250
+ // Check for buffer overflow
251
+ if (this._writePosition + count > this._bufferSize) {
252
+ // Grow the buffer (double it)
253
+ this._growBuffer();
254
+ // If still not enough (shouldn't happen), report xrun
255
+ if (this._writePosition + count > this._bufferSize) {
256
+ this._xrunTracker.reportXrun(this._captureStart + this._writePosition, 'overrun', count);
257
+ return;
258
+ }
259
+ }
260
+ const channels = Math.min(this._channelCount, input.length);
261
+ // Copy input data into capture buffer
262
+ for (let ch = 0; ch < channels; ch++) {
263
+ const src = input[ch];
264
+ const dest = this._buffer[ch];
265
+ for (let i = 0; i < count; i++) {
266
+ dest[this._writePosition + i] = src[offset + i];
267
+ }
268
+ }
269
+ // Apply declick ramp to the just-written segment
270
+ const segmentBuffers = this._buffer;
271
+ this._declickAmp.applyToBuffers(segmentBuffers, this._writePosition, count);
272
+ // Update peak data for GUI visualization
273
+ this._updatePeaks(channels, count);
274
+ this._writePosition += count;
275
+ }
276
+ /**
277
+ * Get the captured audio as trimmed Float32Arrays (one per channel).
278
+ */
279
+ getCapturedAudio() {
280
+ const result = [];
281
+ for (let ch = 0; ch < this._channelCount; ch++) {
282
+ result.push(this._buffer[ch].slice(0, this._writePosition));
283
+ }
284
+ return result;
285
+ }
286
+ /**
287
+ * Get the capture range in session frame coordinates.
288
+ */
289
+ getCaptureRange() {
290
+ return {
291
+ start: this._captureStart,
292
+ end: this._captureEnd >= 0
293
+ ? this._captureEnd
294
+ : this._captureStart + this._writePosition,
295
+ };
296
+ }
297
+ /**
298
+ * Get peak data for GUI real-time visualization during recording.
299
+ * Returns per-channel arrays of peak values.
300
+ */
301
+ getPeakData() {
302
+ const result = [];
303
+ for (let ch = 0; ch < this._channelCount; ch++) {
304
+ result.push(this._peakBuffer[ch].slice(0, this._peakWritePos));
305
+ }
306
+ return result;
307
+ }
308
+ /**
309
+ * Reset peak data (e.g. when the GUI display scrolls).
310
+ */
311
+ resetPeakData() {
312
+ this._peakWritePos = 0;
313
+ for (let ch = 0; ch < this._channelCount; ch++) {
314
+ this._peakBuffer[ch].fill(0);
315
+ }
316
+ }
317
+ /**
318
+ * Set the alignment style for the captured recording.
319
+ * - 'existing_material': Align to existing material on the track (snap to beat/region boundaries)
320
+ * - 'capture_time': Align to the exact time the audio was captured (default)
321
+ */
322
+ setAlignment(style) {
323
+ this._alignmentStyle = style;
324
+ }
325
+ /**
326
+ * Check if currently recording.
327
+ */
328
+ isRecording() {
329
+ return this._isRecording;
330
+ }
331
+ /**
332
+ * Get the number of frames captured so far.
333
+ */
334
+ getCapturedFrames() {
335
+ return this._writePosition;
336
+ }
337
+ // ─── Private helpers ────────────────────────────────────────────────────
338
+ /**
339
+ * Grow the capture buffer by doubling its size.
340
+ */
341
+ _growBuffer() {
342
+ const newSize = this._bufferSize * 2;
343
+ for (let ch = 0; ch < this._channelCount; ch++) {
344
+ const newBuf = new Float32Array(newSize);
345
+ newBuf.set(this._buffer[ch]);
346
+ this._buffer[ch] = newBuf;
347
+ }
348
+ this._bufferSize = newSize;
349
+ }
350
+ /**
351
+ * Update the peak buffer with the maximum absolute sample values
352
+ * from the most recently written segment. Each peak entry represents
353
+ * a chunk of recorded samples, downsampled for efficient GUI rendering.
354
+ */
355
+ _updatePeaks(channels, count) {
356
+ // Each peak entry covers a fixed number of source samples
357
+ const samplesPerPeak = 512;
358
+ const startSample = this._writePosition;
359
+ const endSample = startSample + count;
360
+ for (let pos = startSample; pos < endSample; pos += samplesPerPeak) {
361
+ const blockEnd = Math.min(pos + samplesPerPeak, endSample);
362
+ for (let ch = 0; ch < channels; ch++) {
363
+ let peak = 0;
364
+ const buf = this._buffer[ch];
365
+ for (let i = pos; i < blockEnd; i++) {
366
+ const abs = Math.abs(buf[i]);
367
+ if (abs > peak)
368
+ peak = abs;
369
+ }
370
+ // Grow peak buffer if needed
371
+ if (this._peakWritePos >= this._peakBuffer[ch].length) {
372
+ const newPeakBuf = new Float32Array(this._peakBuffer[ch].length * 2);
373
+ newPeakBuf.set(this._peakBuffer[ch]);
374
+ this._peakBuffer[ch] = newPeakBuf;
375
+ }
376
+ this._peakBuffer[ch][this._peakWritePos] = peak;
377
+ }
378
+ this._peakWritePos++;
379
+ }
380
+ }
381
+ }
382
+ /** Initial capture buffer size: 10 minutes at 48kHz stereo */
383
+ DiskWriter.INITIAL_BUFFER_FRAMES = 48000 * 60 * 10;
384
+ //# sourceMappingURL=DiskIO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiskIO.js","sourceRoot":"","sources":["../../../src/audio/engine/DiskIO.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * LatencyCompensator
3
+ *
4
+ * A per-channel ring-buffer delay line used to time-align audio routes.
5
+ * When one route has higher processing latency than another, the lower-
6
+ * latency route gets a LatencyCompensator inserted with the appropriate
7
+ * delay so that both routes arrive at the summing point in phase.
8
+ */
9
+ export declare class LatencyCompensator {
10
+ private _delaySamples;
11
+ private _buffer;
12
+ private _writePos;
13
+ private _channels;
14
+ private _maxDelay;
15
+ constructor(channels?: number, maxDelay?: number);
16
+ /** Current delay in samples. */
17
+ get delaySamples(): number;
18
+ /**
19
+ * Set the compensation delay.
20
+ * @param samples Delay in samples (clamped to 0 .. maxDelay - 1).
21
+ */
22
+ setDelay(samples: number): void;
23
+ /**
24
+ * Process a block of audio through the delay buffer.
25
+ *
26
+ * For each sample in the block the method writes the input into the ring
27
+ * buffer at `_writePos` and reads the output from `_writePos - delay`
28
+ * (wrapped). This introduces an exact `_delaySamples` latency.
29
+ *
30
+ * If `_delaySamples` is 0 the input is copied directly to the output
31
+ * with no ring-buffer overhead.
32
+ *
33
+ * @param input Per-channel input arrays (length >= blockSize each).
34
+ * @param output Per-channel output arrays (length >= blockSize each).
35
+ * May alias the same arrays as `input`.
36
+ * @param blockSize Number of samples to process.
37
+ */
38
+ process(input: Float32Array[], output: Float32Array[], blockSize: number): void;
39
+ /**
40
+ * Reset all ring buffers to silence and rewind the write pointer.
41
+ * Call after a transport locate or when the delay amount changes to
42
+ * avoid stale audio leaking through.
43
+ */
44
+ reset(): void;
45
+ }
46
+ //# sourceMappingURL=LatencyCompensator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LatencyCompensator.d.ts","sourceRoot":"","sources":["../../../src/audio/engine/LatencyCompensator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;gBAEd,QAAQ,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAa;IAWzD,gCAAgC;IAChC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI/B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IA8B/E;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * LatencyCompensator
3
+ *
4
+ * A per-channel ring-buffer delay line used to time-align audio routes.
5
+ * When one route has higher processing latency than another, the lower-
6
+ * latency route gets a LatencyCompensator inserted with the appropriate
7
+ * delay so that both routes arrive at the summing point in phase.
8
+ */
9
+ export class LatencyCompensator {
10
+ constructor(channels = 2, maxDelay = 8192) {
11
+ this._delaySamples = 0;
12
+ this._writePos = 0;
13
+ this._channels = channels;
14
+ this._maxDelay = maxDelay;
15
+ // Allocate one ring buffer per channel.
16
+ this._buffer = [];
17
+ for (let ch = 0; ch < channels; ch++) {
18
+ this._buffer.push(new Float32Array(maxDelay));
19
+ }
20
+ }
21
+ /** Current delay in samples. */
22
+ get delaySamples() {
23
+ return this._delaySamples;
24
+ }
25
+ /**
26
+ * Set the compensation delay.
27
+ * @param samples Delay in samples (clamped to 0 .. maxDelay - 1).
28
+ */
29
+ setDelay(samples) {
30
+ this._delaySamples = Math.max(0, Math.min(samples, this._maxDelay - 1));
31
+ }
32
+ /**
33
+ * Process a block of audio through the delay buffer.
34
+ *
35
+ * For each sample in the block the method writes the input into the ring
36
+ * buffer at `_writePos` and reads the output from `_writePos - delay`
37
+ * (wrapped). This introduces an exact `_delaySamples` latency.
38
+ *
39
+ * If `_delaySamples` is 0 the input is copied directly to the output
40
+ * with no ring-buffer overhead.
41
+ *
42
+ * @param input Per-channel input arrays (length >= blockSize each).
43
+ * @param output Per-channel output arrays (length >= blockSize each).
44
+ * May alias the same arrays as `input`.
45
+ * @param blockSize Number of samples to process.
46
+ */
47
+ process(input, output, blockSize) {
48
+ const delay = this._delaySamples;
49
+ // Fast path: no delay — straight copy.
50
+ if (delay === 0) {
51
+ for (let ch = 0; ch < this._channels; ch++) {
52
+ if (input[ch] !== output[ch]) {
53
+ output[ch].set(input[ch].subarray(0, blockSize));
54
+ }
55
+ }
56
+ return;
57
+ }
58
+ const maxDelay = this._maxDelay;
59
+ for (let i = 0; i < blockSize; i++) {
60
+ const wp = this._writePos;
61
+ // Read position: wrap around if negative.
62
+ let rp = wp - delay;
63
+ if (rp < 0)
64
+ rp += maxDelay;
65
+ for (let ch = 0; ch < this._channels; ch++) {
66
+ this._buffer[ch][wp] = input[ch][i];
67
+ output[ch][i] = this._buffer[ch][rp];
68
+ }
69
+ this._writePos = (wp + 1) % maxDelay;
70
+ }
71
+ }
72
+ /**
73
+ * Reset all ring buffers to silence and rewind the write pointer.
74
+ * Call after a transport locate or when the delay amount changes to
75
+ * avoid stale audio leaking through.
76
+ */
77
+ reset() {
78
+ this._writePos = 0;
79
+ for (let ch = 0; ch < this._channels; ch++) {
80
+ this._buffer[ch].fill(0);
81
+ }
82
+ }
83
+ }
84
+ //# sourceMappingURL=LatencyCompensator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LatencyCompensator.js","sourceRoot":"","sources":["../../../src/audio/engine/LatencyCompensator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IAO3B,YAAY,WAAmB,CAAC,EAAE,WAAmB,IAAI;QANjD,kBAAa,GAAW,CAAC,CAAC;QAE1B,cAAS,GAAW,CAAC,CAAC;QAK1B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAE1B,wCAAwC;QACxC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClD,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,IAAI,YAAY;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,OAAe;QACpB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,KAAqB,EAAE,MAAsB,EAAE,SAAiB;QACpE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;QAEjC,uCAAuC;QACvC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACd,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC;gBACzC,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC3B,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;gBACrD,CAAC;YACL,CAAC;YACD,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,0CAA0C;YAC1C,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;YACpB,IAAI,EAAE,GAAG,CAAC;gBAAE,EAAE,IAAI,QAAQ,CAAC;YAE3B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC;YAED,IAAI,CAAC,SAAS,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;QACzC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK;QACD,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;CACJ"}