playlist-data-engine 1.1.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 (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +352 -0
  3. package/dist/__vite-browser-external-DYxpcVy9.js +4 -0
  4. package/dist/constants/DefaultClasses.d.ts +46 -0
  5. package/dist/constants/DefaultClasses.d.ts.map +1 -0
  6. package/dist/constants/DefaultEnchantments.d.ts +337 -0
  7. package/dist/constants/DefaultEnchantments.d.ts.map +1 -0
  8. package/dist/constants/DefaultEnemies.d.ts +83 -0
  9. package/dist/constants/DefaultEnemies.d.ts.map +1 -0
  10. package/dist/constants/DefaultEquipment.d.ts +23 -0
  11. package/dist/constants/DefaultEquipment.d.ts.map +1 -0
  12. package/dist/constants/DefaultFeatures.d.ts +22 -0
  13. package/dist/constants/DefaultFeatures.d.ts.map +1 -0
  14. package/dist/constants/DefaultRaces.d.ts +102 -0
  15. package/dist/constants/DefaultRaces.d.ts.map +1 -0
  16. package/dist/constants/DefaultSkills.d.ts +26 -0
  17. package/dist/constants/DefaultSkills.d.ts.map +1 -0
  18. package/dist/constants/DefaultSpells.d.ts +41 -0
  19. package/dist/constants/DefaultSpells.d.ts.map +1 -0
  20. package/dist/constants/EncounterBalance.d.ts +208 -0
  21. package/dist/constants/EncounterBalance.d.ts.map +1 -0
  22. package/dist/constants/EnemyEquipment.d.ts +71 -0
  23. package/dist/constants/EnemyEquipment.d.ts.map +1 -0
  24. package/dist/constants/EnemyRarity.d.ts +79 -0
  25. package/dist/constants/EnemyRarity.d.ts.map +1 -0
  26. package/dist/constants/EnemyTemplates/Construct.d.ts +63 -0
  27. package/dist/constants/EnemyTemplates/Construct.d.ts.map +1 -0
  28. package/dist/constants/EnemyTemplates/Dragon.d.ts +68 -0
  29. package/dist/constants/EnemyTemplates/Dragon.d.ts.map +1 -0
  30. package/dist/constants/EnemyTemplates/Elemental.d.ts +64 -0
  31. package/dist/constants/EnemyTemplates/Elemental.d.ts.map +1 -0
  32. package/dist/constants/EnemyTemplates/Fiend.d.ts +62 -0
  33. package/dist/constants/EnemyTemplates/Fiend.d.ts.map +1 -0
  34. package/dist/constants/EnemyTemplates/Monstrosity.d.ts +63 -0
  35. package/dist/constants/EnemyTemplates/Monstrosity.d.ts.map +1 -0
  36. package/dist/constants/EnemyTemplates/Undead.d.ts +61 -0
  37. package/dist/constants/EnemyTemplates/Undead.d.ts.map +1 -0
  38. package/dist/constants/ItemTemplates.d.ts +40 -0
  39. package/dist/constants/ItemTemplates.d.ts.map +1 -0
  40. package/dist/constants/MagicItems.d.ts +30 -0
  41. package/dist/constants/MagicItems.d.ts.map +1 -0
  42. package/dist/constants/SpellSlots.d.ts +30 -0
  43. package/dist/constants/SpellSlots.d.ts.map +1 -0
  44. package/dist/constants/StatScaling.d.ts +113 -0
  45. package/dist/constants/StatScaling.d.ts.map +1 -0
  46. package/dist/core/analysis/AudioAnalyzer.d.ts +599 -0
  47. package/dist/core/analysis/AudioAnalyzer.d.ts.map +1 -0
  48. package/dist/core/analysis/ColorExtractor.d.ts +64 -0
  49. package/dist/core/analysis/ColorExtractor.d.ts.map +1 -0
  50. package/dist/core/analysis/EssentiaPitchDetector.d.ts +282 -0
  51. package/dist/core/analysis/EssentiaPitchDetector.d.ts.map +1 -0
  52. package/dist/core/analysis/LevelSerializer.d.ts +265 -0
  53. package/dist/core/analysis/LevelSerializer.d.ts.map +1 -0
  54. package/dist/core/analysis/MelodyContourAnalyzer.d.ts +283 -0
  55. package/dist/core/analysis/MelodyContourAnalyzer.d.ts.map +1 -0
  56. package/dist/core/analysis/MultiBandAnalyzer.d.ts +214 -0
  57. package/dist/core/analysis/MultiBandAnalyzer.d.ts.map +1 -0
  58. package/dist/core/analysis/MusicClassifier.d.ts +524 -0
  59. package/dist/core/analysis/MusicClassifier.d.ts.map +1 -0
  60. package/dist/core/analysis/PitchAnalyzer.d.ts +266 -0
  61. package/dist/core/analysis/PitchAnalyzer.d.ts.map +1 -0
  62. package/dist/core/analysis/PitchDetector.d.ts +251 -0
  63. package/dist/core/analysis/PitchDetector.d.ts.map +1 -0
  64. package/dist/core/analysis/SpectrumScanner.d.ts +52 -0
  65. package/dist/core/analysis/SpectrumScanner.d.ts.map +1 -0
  66. package/dist/core/analysis/beat/BeatInterpolator.d.ts +477 -0
  67. package/dist/core/analysis/beat/BeatInterpolator.d.ts.map +1 -0
  68. package/dist/core/analysis/beat/BeatMapGenerator.d.ts +170 -0
  69. package/dist/core/analysis/beat/BeatMapGenerator.d.ts.map +1 -0
  70. package/dist/core/analysis/beat/BeatStream.d.ts +316 -0
  71. package/dist/core/analysis/beat/BeatStream.d.ts.map +1 -0
  72. package/dist/core/analysis/beat/BeatSubdivider.d.ts +205 -0
  73. package/dist/core/analysis/beat/BeatSubdivider.d.ts.map +1 -0
  74. package/dist/core/analysis/beat/BeatTracker.d.ts +137 -0
  75. package/dist/core/analysis/beat/BeatTracker.d.ts.map +1 -0
  76. package/dist/core/analysis/beat/CompositeStreamGenerator.d.ts +180 -0
  77. package/dist/core/analysis/beat/CompositeStreamGenerator.d.ts.map +1 -0
  78. package/dist/core/analysis/beat/DensityAnalyzer.d.ts +246 -0
  79. package/dist/core/analysis/beat/DensityAnalyzer.d.ts.map +1 -0
  80. package/dist/core/analysis/beat/DifficultyVariantGenerator.d.ts +1082 -0
  81. package/dist/core/analysis/beat/DifficultyVariantGenerator.d.ts.map +1 -0
  82. package/dist/core/analysis/beat/GrooveAnalyzer.d.ts +192 -0
  83. package/dist/core/analysis/beat/GrooveAnalyzer.d.ts.map +1 -0
  84. package/dist/core/analysis/beat/OnsetStrengthEnvelope.d.ts +133 -0
  85. package/dist/core/analysis/beat/OnsetStrengthEnvelope.d.ts.map +1 -0
  86. package/dist/core/analysis/beat/PhraseAnalyzer.d.ts +230 -0
  87. package/dist/core/analysis/beat/PhraseAnalyzer.d.ts.map +1 -0
  88. package/dist/core/analysis/beat/RhythmQuantizer.d.ts +399 -0
  89. package/dist/core/analysis/beat/RhythmQuantizer.d.ts.map +1 -0
  90. package/dist/core/analysis/beat/RhythmicBalancer.d.ts +262 -0
  91. package/dist/core/analysis/beat/RhythmicBalancer.d.ts.map +1 -0
  92. package/dist/core/analysis/beat/StreamScorer.d.ts +275 -0
  93. package/dist/core/analysis/beat/StreamScorer.d.ts.map +1 -0
  94. package/dist/core/analysis/beat/TempoAwareQuantizer.d.ts +256 -0
  95. package/dist/core/analysis/beat/TempoAwareQuantizer.d.ts.map +1 -0
  96. package/dist/core/analysis/beat/TempoDetector.d.ts +220 -0
  97. package/dist/core/analysis/beat/TempoDetector.d.ts.map +1 -0
  98. package/dist/core/analysis/beat/TransientDetector.d.ts +303 -0
  99. package/dist/core/analysis/beat/TransientDetector.d.ts.map +1 -0
  100. package/dist/core/analysis/beat/beatKeyHelpers.d.ts +180 -0
  101. package/dist/core/analysis/beat/beatKeyHelpers.d.ts.map +1 -0
  102. package/dist/core/analysis/beat/index.d.ts +41 -0
  103. package/dist/core/analysis/beat/index.d.ts.map +1 -0
  104. package/dist/core/analysis/beat/utils/audioUtils.d.ts +204 -0
  105. package/dist/core/analysis/beat/utils/audioUtils.d.ts.map +1 -0
  106. package/dist/core/analysis/beat/utils/beatInterpolationDebug.d.ts +404 -0
  107. package/dist/core/analysis/beat/utils/beatInterpolationDebug.d.ts.map +1 -0
  108. package/dist/core/analysis/beat/utils/subdivideBeatMap.d.ts +61 -0
  109. package/dist/core/analysis/beat/utils/subdivideBeatMap.d.ts.map +1 -0
  110. package/dist/core/analysis/beat/utils/unifyBeatMap.d.ts +33 -0
  111. package/dist/core/analysis/beat/utils/unifyBeatMap.d.ts.map +1 -0
  112. package/dist/core/analysis/index.d.ts +18 -0
  113. package/dist/core/analysis/index.d.ts.map +1 -0
  114. package/dist/core/combat/AI/AICombatRunner.d.ts +108 -0
  115. package/dist/core/combat/AI/AICombatRunner.d.ts.map +1 -0
  116. package/dist/core/combat/AI/CombatAI.d.ts +179 -0
  117. package/dist/core/combat/AI/CombatAI.d.ts.map +1 -0
  118. package/dist/core/combat/AI/CombatMetricsTracker.d.ts +30 -0
  119. package/dist/core/combat/AI/CombatMetricsTracker.d.ts.map +1 -0
  120. package/dist/core/combat/Analysis/BalanceValidator.d.ts +170 -0
  121. package/dist/core/combat/Analysis/BalanceValidator.d.ts.map +1 -0
  122. package/dist/core/combat/Analysis/ComparativeAnalyzer.d.ts +231 -0
  123. package/dist/core/combat/Analysis/ComparativeAnalyzer.d.ts.map +1 -0
  124. package/dist/core/combat/Analysis/DifficultyCalculator.d.ts +203 -0
  125. package/dist/core/combat/Analysis/DifficultyCalculator.d.ts.map +1 -0
  126. package/dist/core/combat/Analysis/ParameterSweep.d.ts +201 -0
  127. package/dist/core/combat/Analysis/ParameterSweep.d.ts.map +1 -0
  128. package/dist/core/combat/AttackResolver.d.ts +220 -0
  129. package/dist/core/combat/AttackResolver.d.ts.map +1 -0
  130. package/dist/core/combat/CombatEngine.d.ts +388 -0
  131. package/dist/core/combat/CombatEngine.d.ts.map +1 -0
  132. package/dist/core/combat/DiceRoller.d.ts +115 -0
  133. package/dist/core/combat/DiceRoller.d.ts.map +1 -0
  134. package/dist/core/combat/InitiativeRoller.d.ts +62 -0
  135. package/dist/core/combat/InitiativeRoller.d.ts.map +1 -0
  136. package/dist/core/combat/PartyAnalyzer.d.ts +215 -0
  137. package/dist/core/combat/PartyAnalyzer.d.ts.map +1 -0
  138. package/dist/core/combat/SeededDiceRoller.d.ts +120 -0
  139. package/dist/core/combat/SeededDiceRoller.d.ts.map +1 -0
  140. package/dist/core/combat/Simulation/CombatSimulator.d.ts +366 -0
  141. package/dist/core/combat/Simulation/CombatSimulator.d.ts.map +1 -0
  142. package/dist/core/combat/SpellCaster.d.ts +113 -0
  143. package/dist/core/combat/SpellCaster.d.ts.map +1 -0
  144. package/dist/core/config/index.d.ts +24 -0
  145. package/dist/core/config/index.d.ts.map +1 -0
  146. package/dist/core/config/progressionConfig.d.ts +73 -0
  147. package/dist/core/config/progressionConfig.d.ts.map +1 -0
  148. package/dist/core/config/sensorConfig.d.ts +134 -0
  149. package/dist/core/config/sensorConfig.d.ts.map +1 -0
  150. package/dist/core/equipment/BoxOpener.d.ts +175 -0
  151. package/dist/core/equipment/BoxOpener.d.ts.map +1 -0
  152. package/dist/core/equipment/EquipmentEffectApplier.d.ts +189 -0
  153. package/dist/core/equipment/EquipmentEffectApplier.d.ts.map +1 -0
  154. package/dist/core/equipment/EquipmentModifier.d.ts +327 -0
  155. package/dist/core/equipment/EquipmentModifier.d.ts.map +1 -0
  156. package/dist/core/equipment/EquipmentSpawnHelper.d.ts +246 -0
  157. package/dist/core/equipment/EquipmentSpawnHelper.d.ts.map +1 -0
  158. package/dist/core/equipment/EquipmentValidator.d.ts +173 -0
  159. package/dist/core/equipment/EquipmentValidator.d.ts.map +1 -0
  160. package/dist/core/extensions/ExtensionManager.d.ts +517 -0
  161. package/dist/core/extensions/ExtensionManager.d.ts.map +1 -0
  162. package/dist/core/extensions/WeightedSelector.d.ts +156 -0
  163. package/dist/core/extensions/WeightedSelector.d.ts.map +1 -0
  164. package/dist/core/extensions/index.d.ts +11 -0
  165. package/dist/core/extensions/index.d.ts.map +1 -0
  166. package/dist/core/extensions/initializeDefaults.d.ts +170 -0
  167. package/dist/core/extensions/initializeDefaults.d.ts.map +1 -0
  168. package/dist/core/features/FeatureEffectApplier.d.ts +102 -0
  169. package/dist/core/features/FeatureEffectApplier.d.ts.map +1 -0
  170. package/dist/core/features/FeatureQuery.d.ts +368 -0
  171. package/dist/core/features/FeatureQuery.d.ts.map +1 -0
  172. package/dist/core/features/FeatureTypes.d.ts +199 -0
  173. package/dist/core/features/FeatureTypes.d.ts.map +1 -0
  174. package/dist/core/features/FeatureValidator.d.ts +149 -0
  175. package/dist/core/features/FeatureValidator.d.ts.map +1 -0
  176. package/dist/core/features/index.d.ts +12 -0
  177. package/dist/core/features/index.d.ts.map +1 -0
  178. package/dist/core/generation/AbilityScoreCalculator.d.ts +83 -0
  179. package/dist/core/generation/AbilityScoreCalculator.d.ts.map +1 -0
  180. package/dist/core/generation/AppearanceGenerator.d.ts +32 -0
  181. package/dist/core/generation/AppearanceGenerator.d.ts.map +1 -0
  182. package/dist/core/generation/BeatConverter.d.ts +127 -0
  183. package/dist/core/generation/BeatConverter.d.ts.map +1 -0
  184. package/dist/core/generation/ButtonMapper.d.ts +346 -0
  185. package/dist/core/generation/ButtonMapper.d.ts.map +1 -0
  186. package/dist/core/generation/ButtonPatternLibrary.d.ts +92 -0
  187. package/dist/core/generation/ButtonPatternLibrary.d.ts.map +1 -0
  188. package/dist/core/generation/CRLevelConverter.d.ts +242 -0
  189. package/dist/core/generation/CRLevelConverter.d.ts.map +1 -0
  190. package/dist/core/generation/CharacterGenerator.d.ts +194 -0
  191. package/dist/core/generation/CharacterGenerator.d.ts.map +1 -0
  192. package/dist/core/generation/ClassSuggester.d.ts +184 -0
  193. package/dist/core/generation/ClassSuggester.d.ts.map +1 -0
  194. package/dist/core/generation/EnemyEquipmentGenerator.d.ts +151 -0
  195. package/dist/core/generation/EnemyEquipmentGenerator.d.ts.map +1 -0
  196. package/dist/core/generation/EnemyGenerator.d.ts +595 -0
  197. package/dist/core/generation/EnemyGenerator.d.ts.map +1 -0
  198. package/dist/core/generation/EquipmentGenerator.d.ts +204 -0
  199. package/dist/core/generation/EquipmentGenerator.d.ts.map +1 -0
  200. package/dist/core/generation/LegendaryGenerator.d.ts +213 -0
  201. package/dist/core/generation/LegendaryGenerator.d.ts.map +1 -0
  202. package/dist/core/generation/LevelGenerator.d.ts +390 -0
  203. package/dist/core/generation/LevelGenerator.d.ts.map +1 -0
  204. package/dist/core/generation/NamingEngine.d.ts +136 -0
  205. package/dist/core/generation/NamingEngine.d.ts.map +1 -0
  206. package/dist/core/generation/PitchBeatLinker.d.ts +150 -0
  207. package/dist/core/generation/PitchBeatLinker.d.ts.map +1 -0
  208. package/dist/core/generation/RaceSelector.d.ts +58 -0
  209. package/dist/core/generation/RaceSelector.d.ts.map +1 -0
  210. package/dist/core/generation/RhythmGenerator.d.ts +597 -0
  211. package/dist/core/generation/RhythmGenerator.d.ts.map +1 -0
  212. package/dist/core/generation/SkillAssigner.d.ts +78 -0
  213. package/dist/core/generation/SkillAssigner.d.ts.map +1 -0
  214. package/dist/core/generation/SpellManager.d.ts +132 -0
  215. package/dist/core/generation/SpellManager.d.ts.map +1 -0
  216. package/dist/core/generation/SpellcastingGenerator.d.ts +255 -0
  217. package/dist/core/generation/SpellcastingGenerator.d.ts.map +1 -0
  218. package/dist/core/generation/index.d.ts +41 -0
  219. package/dist/core/generation/index.d.ts.map +1 -0
  220. package/dist/core/parser/MetadataExtractor.d.ts +66 -0
  221. package/dist/core/parser/MetadataExtractor.d.ts.map +1 -0
  222. package/dist/core/parser/PlaylistParser.d.ts +45 -0
  223. package/dist/core/parser/PlaylistParser.d.ts.map +1 -0
  224. package/dist/core/playback/SubdivisionPlaybackController.d.ts +333 -0
  225. package/dist/core/playback/SubdivisionPlaybackController.d.ts.map +1 -0
  226. package/dist/core/playback/index.d.ts +5 -0
  227. package/dist/core/playback/index.d.ts.map +1 -0
  228. package/dist/core/progression/CharacterUpdater.d.ts +203 -0
  229. package/dist/core/progression/CharacterUpdater.d.ts.map +1 -0
  230. package/dist/core/progression/LevelUpProcessor.d.ts +234 -0
  231. package/dist/core/progression/LevelUpProcessor.d.ts.map +1 -0
  232. package/dist/core/progression/PrestigeSystem.d.ts +217 -0
  233. package/dist/core/progression/PrestigeSystem.d.ts.map +1 -0
  234. package/dist/core/progression/RhythmXPCalculator.d.ts +182 -0
  235. package/dist/core/progression/RhythmXPCalculator.d.ts.map +1 -0
  236. package/dist/core/progression/SessionTracker.d.ts +169 -0
  237. package/dist/core/progression/SessionTracker.d.ts.map +1 -0
  238. package/dist/core/progression/XPCalculator.d.ts +128 -0
  239. package/dist/core/progression/XPCalculator.d.ts.map +1 -0
  240. package/dist/core/progression/stat/StatIncreaseStrategy.d.ts +97 -0
  241. package/dist/core/progression/stat/StatIncreaseStrategy.d.ts.map +1 -0
  242. package/dist/core/progression/stat/StatManager.d.ts +179 -0
  243. package/dist/core/progression/stat/StatManager.d.ts.map +1 -0
  244. package/dist/core/sensors/EnvironmentalSensors.d.ts +301 -0
  245. package/dist/core/sensors/EnvironmentalSensors.d.ts.map +1 -0
  246. package/dist/core/sensors/GamingPlatformSensors.d.ts +162 -0
  247. package/dist/core/sensors/GamingPlatformSensors.d.ts.map +1 -0
  248. package/dist/core/sensors/GeolocationProvider.d.ts +156 -0
  249. package/dist/core/sensors/GeolocationProvider.d.ts.map +1 -0
  250. package/dist/core/sensors/MotionDetector.d.ts +58 -0
  251. package/dist/core/sensors/MotionDetector.d.ts.map +1 -0
  252. package/dist/core/sensors/SteamAPIClient.d.ts +108 -0
  253. package/dist/core/sensors/SteamAPIClient.d.ts.map +1 -0
  254. package/dist/core/sensors/WeatherAPIClient.d.ts +360 -0
  255. package/dist/core/sensors/WeatherAPIClient.d.ts.map +1 -0
  256. package/dist/core/sensors/schemas/weather.schema.d.ts +144 -0
  257. package/dist/core/sensors/schemas/weather.schema.d.ts.map +1 -0
  258. package/dist/core/skills/SkillQuery.d.ts +159 -0
  259. package/dist/core/skills/SkillQuery.d.ts.map +1 -0
  260. package/dist/core/skills/SkillTypes.d.ts +233 -0
  261. package/dist/core/skills/SkillTypes.d.ts.map +1 -0
  262. package/dist/core/skills/SkillValidator.d.ts +146 -0
  263. package/dist/core/skills/SkillValidator.d.ts.map +1 -0
  264. package/dist/core/skills/index.d.ts +11 -0
  265. package/dist/core/skills/index.d.ts.map +1 -0
  266. package/dist/core/spells/SpellQuery.d.ts +194 -0
  267. package/dist/core/spells/SpellQuery.d.ts.map +1 -0
  268. package/dist/core/spells/SpellTypes.d.ts +71 -0
  269. package/dist/core/spells/SpellTypes.d.ts.map +1 -0
  270. package/dist/core/spells/SpellValidator.d.ts +129 -0
  271. package/dist/core/spells/SpellValidator.d.ts.map +1 -0
  272. package/dist/core/spells/index.d.ts +11 -0
  273. package/dist/core/spells/index.d.ts.map +1 -0
  274. package/dist/core/types/AudioProfile.d.ts +143 -0
  275. package/dist/core/types/AudioProfile.d.ts.map +1 -0
  276. package/dist/core/types/BeatMap.d.ts +1825 -0
  277. package/dist/core/types/BeatMap.d.ts.map +1 -0
  278. package/dist/core/types/ButtonMapping.d.ts +345 -0
  279. package/dist/core/types/ButtonMapping.d.ts.map +1 -0
  280. package/dist/core/types/Character.d.ts +397 -0
  281. package/dist/core/types/Character.d.ts.map +1 -0
  282. package/dist/core/types/ChartedBeatMap.d.ts +169 -0
  283. package/dist/core/types/ChartedBeatMap.d.ts.map +1 -0
  284. package/dist/core/types/Combat.d.ts +268 -0
  285. package/dist/core/types/Combat.d.ts.map +1 -0
  286. package/dist/core/types/CombatAI.d.ts +143 -0
  287. package/dist/core/types/CombatAI.d.ts.map +1 -0
  288. package/dist/core/types/Enemy.d.ts +447 -0
  289. package/dist/core/types/Enemy.d.ts.map +1 -0
  290. package/dist/core/types/Environmental.d.ts +213 -0
  291. package/dist/core/types/Environmental.d.ts.map +1 -0
  292. package/dist/core/types/Equipment.d.ts +309 -0
  293. package/dist/core/types/Equipment.d.ts.map +1 -0
  294. package/dist/core/types/ISessionTracker.d.ts +48 -0
  295. package/dist/core/types/ISessionTracker.d.ts.map +1 -0
  296. package/dist/core/types/LevelExport.d.ts +366 -0
  297. package/dist/core/types/LevelExport.d.ts.map +1 -0
  298. package/dist/core/types/Playlist.d.ts +70 -0
  299. package/dist/core/types/Playlist.d.ts.map +1 -0
  300. package/dist/core/types/Prestige.d.ts +94 -0
  301. package/dist/core/types/Prestige.d.ts.map +1 -0
  302. package/dist/core/types/Progression.d.ts +214 -0
  303. package/dist/core/types/Progression.d.ts.map +1 -0
  304. package/dist/core/types/RhythmXP.d.ts +398 -0
  305. package/dist/core/types/RhythmXP.d.ts.map +1 -0
  306. package/dist/core/utils/AbilityConstants.d.ts +31 -0
  307. package/dist/core/utils/AbilityConstants.d.ts.map +1 -0
  308. package/dist/core/utils/EffectApplierUtils.d.ts +56 -0
  309. package/dist/core/utils/EffectApplierUtils.d.ts.map +1 -0
  310. package/dist/core/utils/ImageValidator.d.ts +66 -0
  311. package/dist/core/utils/ImageValidator.d.ts.map +1 -0
  312. package/dist/core/utils/PrerequisiteValidator.d.ts +88 -0
  313. package/dist/core/utils/PrerequisiteValidator.d.ts.map +1 -0
  314. package/dist/essentia-wasm.es-BUEnKUts.js +2990 -0
  315. package/dist/essentia.js-model.es-CGA0xotH.js +306 -0
  316. package/dist/index.d.ts +176 -0
  317. package/dist/index.d.ts.map +1 -0
  318. package/dist/playlist-data-engine.js +124 -0
  319. package/dist/playlist-data-engine.mjs +49251 -0
  320. package/dist/utils/EnchantmentLibrary.d.ts +378 -0
  321. package/dist/utils/EnchantmentLibrary.d.ts.map +1 -0
  322. package/dist/utils/arweaveGatewayManager.d.ts +485 -0
  323. package/dist/utils/arweaveGatewayManager.d.ts.map +1 -0
  324. package/dist/utils/arweaveUtils.d.ts +118 -0
  325. package/dist/utils/arweaveUtils.d.ts.map +1 -0
  326. package/dist/utils/constants.d.ts +439 -0
  327. package/dist/utils/constants.d.ts.map +1 -0
  328. package/dist/utils/equipmentConstants.d.ts +60 -0
  329. package/dist/utils/equipmentConstants.d.ts.map +1 -0
  330. package/dist/utils/hash.d.ts +33 -0
  331. package/dist/utils/hash.d.ts.map +1 -0
  332. package/dist/utils/logger.d.ts +192 -0
  333. package/dist/utils/logger.d.ts.map +1 -0
  334. package/dist/utils/magicItemExamples.d.ts +46 -0
  335. package/dist/utils/magicItemExamples.d.ts.map +1 -0
  336. package/dist/utils/playlistUtils.d.ts +149 -0
  337. package/dist/utils/playlistUtils.d.ts.map +1 -0
  338. package/dist/utils/random.d.ts +34 -0
  339. package/dist/utils/random.d.ts.map +1 -0
  340. package/dist/utils/sensorDashboard.d.ts +60 -0
  341. package/dist/utils/sensorDashboard.d.ts.map +1 -0
  342. package/dist/utils/validators.d.ts +189 -0
  343. package/dist/utils/validators.d.ts.map +1 -0
  344. package/dist/vite.svg +1 -0
  345. package/package.json +82 -0
@@ -0,0 +1,1825 @@
1
+ /**
2
+ * Beat Detection type definitions
3
+ *
4
+ * Based on the Ellis Dynamic Programming beat tracking algorithm
5
+ * Reference: "Beat Tracking by Dynamic Programming" (Ellis, 2007)
6
+ */
7
+ /**
8
+ * Represents a single detected beat in the audio
9
+ */
10
+ export interface Beat {
11
+ /** Timestamp in seconds from the start of the audio */
12
+ timestamp: number;
13
+ /** Position within the measure (0 = downbeat, 1, 2, 3, etc. for subsequent beats) */
14
+ beatInMeasure: number;
15
+ /** Whether this beat is a downbeat (first beat of a measure) */
16
+ isDownbeat: boolean;
17
+ /** Measure number (0-indexed from first detected downbeat) */
18
+ measureNumber: number;
19
+ /** Onset strength at this beat (0.0 - 1.0, normalized) */
20
+ intensity: number;
21
+ /** Confidence score for this beat detection (0.0 - 1.0) */
22
+ confidence: number;
23
+ /**
24
+ * Optional required key for rhythm game chart creation.
25
+ * When specified, this key must be pressed for the beat to count as a hit.
26
+ * Frontend maps physical inputs to these strings before calling the engine.
27
+ * @example 'up', 'down', 'left', 'right', 'a', 'b', 'x', 'y'
28
+ */
29
+ requiredKey?: string;
30
+ }
31
+ /**
32
+ * Time signature configuration for beat grid
33
+ * Defaults to 4/4 time if not specified
34
+ */
35
+ export interface TimeSignatureConfig {
36
+ /** Number of beats per measure (default: 4 for 4/4 time) */
37
+ beatsPerMeasure: number;
38
+ }
39
+ /** Default time signature (4/4) */
40
+ export declare const DEFAULT_TIME_SIGNATURE: TimeSignatureConfig;
41
+ /**
42
+ * A segment of downbeat configuration
43
+ * Used to support time signature changes within a track
44
+ *
45
+ * Segments are CONTIGUOUS - each segment covers all beats from its startBeat
46
+ * until the next segment's startBeat (or end of track). There are no gaps.
47
+ *
48
+ * Example: If segment 1 has startBeat: 0 and segment 2 has startBeat: 32,
49
+ * then segment 1 covers beats 0-31 and segment 2 covers beats 32+.
50
+ */
51
+ export interface DownbeatSegment {
52
+ /**
53
+ * Beat index where this segment starts
54
+ * The first segment should typically have startBeat: 0
55
+ */
56
+ startBeat: number;
57
+ /**
58
+ * Beat index that represents the "one" (downbeat) in this segment
59
+ * This is an absolute beat index, not relative to startBeat
60
+ *
61
+ * Example: If set to 9 with beatsPerMeasure: 4, then beats 1, 5, 9, 13, 17... are downbeats
62
+ * (calculated bidirectionally from beat 9)
63
+ */
64
+ downbeatBeatIndex: number;
65
+ /** Time signature for this segment */
66
+ timeSignature: TimeSignatureConfig;
67
+ }
68
+ /**
69
+ * Downbeat configuration for manual placement
70
+ * Supports multiple segments for time signature changes within a track
71
+ */
72
+ export interface DownbeatConfig {
73
+ /**
74
+ * Array of downbeat segments
75
+ * - For simple tracks: single segment with startBeat: 0
76
+ * - For time signature changes: multiple segments ordered by startBeat
77
+ *
78
+ * Each segment defines its own downbeat anchor and time signature.
79
+ * The downbeatBeatIndex is absolute (not relative to segment start).
80
+ */
81
+ segments: DownbeatSegment[];
82
+ }
83
+ /** Default downbeat config (first beat is the one, 4/4 time) */
84
+ export declare const DEFAULT_DOWNBEAT_CONFIG: DownbeatConfig;
85
+ /** Minimum beats per measure */
86
+ export declare const MIN_BEATS_PER_MEASURE = 2;
87
+ /** Maximum beats per measure */
88
+ export declare const MAX_BEATS_PER_MEASURE = 12;
89
+ /**
90
+ * Validate downbeat configuration (structural validation only)
91
+ *
92
+ * Note: Beat count validation (e.g., downbeatBeatIndex < totalBeats) happens
93
+ * inside generateBeatMap() AFTER beat detection, since we don't know the
94
+ * total beat count until then.
95
+ *
96
+ * @param config - The downbeat configuration to validate
97
+ * @throws Error if configuration is invalid
98
+ */
99
+ export declare function validateDownbeatConfig(config: DownbeatConfig): void;
100
+ /**
101
+ * Validate downbeat config against actual beat count
102
+ * Called inside generateBeatMap() after beat detection
103
+ *
104
+ * @param config - The downbeat configuration to validate
105
+ * @param totalBeats - The total number of beats in the beat map
106
+ * @throws Error if downbeatBeatIndex exceeds total beats
107
+ */
108
+ export declare function validateDownbeatConfigAgainstBeats(config: DownbeatConfig, totalBeats: number): void;
109
+ /**
110
+ * Reapply downbeat configuration to recalculate measure labels
111
+ *
112
+ * This is the PRIMARY way to set downbeat configuration. The typical workflow is:
113
+ * 1. Generate beat map with default config
114
+ * 2. Examine the beat map to identify the correct downbeat position
115
+ * 3. Call this function to apply the correct configuration
116
+ *
117
+ * This does NOT re-analyze audio - it only recalculates measure labels.
118
+ *
119
+ * @param beatMap - The original beat map
120
+ * @param newConfig - New downbeat configuration to apply
121
+ * @returns New BeatMap with updated measure labels (original is not modified)
122
+ * @throws Error if configuration is invalid or downbeatBeatIndex exceeds total beats
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * // Generate first, then configure
127
+ * const beatMap = await generator.generateBeatMap('song.mp3', 'track-1');
128
+ *
129
+ * // After examining, you identify beat 9 as the downbeat
130
+ * const correctedMap = reapplyDownbeatConfig(beatMap, {
131
+ * segments: [{
132
+ * startBeat: 0,
133
+ * downbeatBeatIndex: 9, // Beat 9 is the "one"
134
+ * timeSignature: { beatsPerMeasure: 4 },
135
+ * }],
136
+ * });
137
+ * // Beats 1, 5, 9, 13, 17... are now downbeats
138
+ * ```
139
+ */
140
+ export declare function reapplyDownbeatConfig(beatMap: BeatMap, newConfig: DownbeatConfig): BeatMap;
141
+ /**
142
+ * Metadata about the beat detection algorithm and settings used
143
+ */
144
+ export interface BeatMapMetadata {
145
+ /** Version of the beat detection algorithm */
146
+ version: string;
147
+ /** Algorithm name (e.g., 'ellis-dp-v1') */
148
+ algorithm: string;
149
+ /** Minimum BPM threshold used during detection */
150
+ minBpm: number;
151
+ /** Maximum BPM threshold used during detection */
152
+ maxBpm: number;
153
+ /** Pre-processing sensitivity used (0.1 - 10.0) */
154
+ sensitivity: number;
155
+ /** Post-processing grid-alignment filter used (0.0 - 1.0) */
156
+ filter: number;
157
+ /** Noise floor threshold for filtering low-energy detections */
158
+ noiseFloorThreshold: number;
159
+ /** Milliseconds between FFT frames */
160
+ hopSizeMs: number;
161
+ /** FFT window size in samples */
162
+ fftSize: number;
163
+ /** Ellis balance factor (alpha) for tempo consistency vs onset strength */
164
+ dpAlpha: number;
165
+ /** Number of Mel frequency bands for onset strength envelope */
166
+ melBands: number;
167
+ /** High-pass filter cutoff in Hz for onset strength envelope */
168
+ highPassCutoff: number;
169
+ /** Gaussian smoothing window in ms for onset strength envelope */
170
+ gaussianSmoothMs: number;
171
+ /** Tempo center in seconds (default 0.5s = 120 BPM) */
172
+ tempoCenter: number;
173
+ /** Tempo width in octaves for perception weighting */
174
+ tempoWidth: number;
175
+ /** Whether TPS2 octave resolution was enabled for duple meter detection */
176
+ useOctaveResolution: boolean;
177
+ /** Whether TPS3 triple meter resolution was enabled for 3/4, 6/8 detection */
178
+ useTripleMeter: boolean;
179
+ /** Timestamp when the beat map was generated */
180
+ generatedAt: string;
181
+ }
182
+ /**
183
+ * Complete beat map for a single audio track
184
+ *
185
+ * Contains all detected beats and metadata. BPM is calculated dynamically
186
+ * during playback from actual beat intervals, not stored as a static value.
187
+ */
188
+ export interface BeatMap {
189
+ /** Unique identifier for the audio source */
190
+ audioId: string;
191
+ /** Duration of the audio in seconds */
192
+ duration: number;
193
+ /** Array of all detected beats */
194
+ beats: Beat[];
195
+ /** Initial BPM estimate from tempo detection */
196
+ bpm: number;
197
+ /** Algorithm metadata and settings */
198
+ metadata: BeatMapMetadata;
199
+ /**
200
+ * The downbeat configuration used to generate this beat map
201
+ * Only stored if explicitly provided; undefined means default (beat 0 = downbeat, 4/4 time)
202
+ * Stored for reproducibility and reprocessing
203
+ */
204
+ downbeatConfig?: DownbeatConfig;
205
+ }
206
+ /**
207
+ * Event types emitted by the BeatStream during playback
208
+ */
209
+ export type BeatEventType = 'upcoming' | 'exact' | 'passed';
210
+ /**
211
+ * Event emitted by the BeatStream during playback
212
+ */
213
+ export interface BeatEvent {
214
+ /** The beat this event relates to */
215
+ beat: Beat;
216
+ /** Current BPM calculated from recent beat intervals */
217
+ currentBpm: number;
218
+ /** Current audio context time in seconds */
219
+ audioTime: number;
220
+ /** Time until the beat occurs (negative if passed) */
221
+ timeUntilBeat: number;
222
+ /** Type of event: 'upcoming', 'exact', or 'passed' */
223
+ type: BeatEventType;
224
+ }
225
+ /**
226
+ * Callback function type for BeatStream subscriptions
227
+ */
228
+ export type BeatStreamCallback = (event: BeatEvent) => void;
229
+ /**
230
+ * Audio synchronization state for debugging and monitoring
231
+ */
232
+ export interface AudioSyncState {
233
+ /** Current audio context time in seconds */
234
+ audioContextTime: number;
235
+ /** Audio element current time in seconds */
236
+ audioElementTime: number;
237
+ /** Calculated drift between audio and beat stream */
238
+ drift: number;
239
+ /** Whether the sync is within acceptable tolerance */
240
+ isSynchronized: boolean;
241
+ /** Output latency from AudioContext (0 if unsupported) */
242
+ outputLatency: number;
243
+ /** Base latency from AudioContext (0 if unsupported) */
244
+ baseLatency: number;
245
+ /** User-calibrated offset in milliseconds */
246
+ userOffsetMs: number;
247
+ /** Total effective latency compensation in seconds */
248
+ totalCompensation: number;
249
+ }
250
+ /**
251
+ * Options for BeatMapGenerator
252
+ *
253
+ * ## OSE Parameter Modes
254
+ *
255
+ * OSE parameters support two configuration styles:
256
+ * - **Mode-based**: Use `hopSizeMode`, `melBandsMode`, `gaussianSmoothMode` for preset values
257
+ * - **Direct numeric**: Use `hopSizeMs`, `melBands`, `gaussianSmoothMs` for exact control
258
+ *
259
+ * **Precedence**: When both mode and direct value are provided, mode takes precedence.
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * // Mode-based configuration (recommended)
264
+ * const options: BeatMapGeneratorOptions = {
265
+ * hopSizeMode: { mode: 'standard' }, // 4ms (Ellis 2007 paper spec)
266
+ * melBandsMode: { mode: 'detailed' }, // 64 bands
267
+ * gaussianSmoothMode: { mode: 'smooth' } // 40ms
268
+ * };
269
+ *
270
+ * // Direct numeric configuration (backward compatible)
271
+ * const options: BeatMapGeneratorOptions = {
272
+ * hopSizeMs: 4,
273
+ * melBands: 40,
274
+ * gaussianSmoothMs: 20
275
+ * };
276
+ * ```
277
+ */
278
+ export interface BeatMapGeneratorOptions {
279
+ /** Minimum BPM to detect (default: 90) */
280
+ minBpm?: number;
281
+ /** Maximum BPM to detect (default: 180) */
282
+ maxBpm?: number;
283
+ /** Pre-processing sensitivity (0.1-10.0, default: 1.0) */
284
+ sensitivity?: number;
285
+ /** Post-processing grid-alignment filter (0.0-1.0, default: 0.0) */
286
+ filter?: number;
287
+ /** Minimum threshold to prevent noise detection (default: 0) */
288
+ noiseFloorThreshold?: number;
289
+ /**
290
+ * Milliseconds between FFT frames (default: 4).
291
+ * Ignored if hopSizeMode is provided.
292
+ * @see hopSizeMode for mode-based configuration
293
+ */
294
+ hopSizeMs?: number;
295
+ /** FFT window size in samples (default: 2048) */
296
+ fftSize?: number;
297
+ /** Number of beats for rolling BPM calculation (default: 8) */
298
+ rollingBpmWindowSize?: number;
299
+ /**
300
+ * Ellis balance factor for tempo consistency vs onset strength (default: 680)
301
+ * Higher values = stricter tempo adherence (good for songs with clear beats)
302
+ * Lower values = more flexibility for songs with weak/irregular beats
303
+ */
304
+ dpAlpha?: number;
305
+ /**
306
+ * Number of Mel frequency bands for OSE (default: 40).
307
+ * Ignored if melBandsMode is provided.
308
+ * @see melBandsMode for mode-based configuration
309
+ */
310
+ melBands?: number;
311
+ /** High-pass filter cutoff in Hz, removes DC offset from OSE (default: 0.4) */
312
+ highPassCutoff?: number;
313
+ /**
314
+ * Gaussian smoothing window in ms for OSE (default: 20).
315
+ * Ignored if gaussianSmoothMode is provided.
316
+ * @see gaussianSmoothMode for mode-based configuration
317
+ */
318
+ gaussianSmoothMs?: number;
319
+ /** Tempo center in seconds for perception bias (default: 0.5 = 120 BPM) */
320
+ tempoCenter?: number;
321
+ /** Tempo width in octaves for perception weighting (default: 1.4) */
322
+ tempoWidth?: number;
323
+ /**
324
+ * Whether to use TPS2 octave resolution to prevent half-tempo/double-tempo ambiguity.
325
+ *
326
+ * When enabled, uses the Ellis TPS2 calculation (Equation 7) to prefer tempos
327
+ * with strong half-period evidence, improving accuracy from 77% to 84%.
328
+ *
329
+ * This helps prevent the algorithm from locking onto 73 BPM when the true tempo
330
+ * is 146 BPM (octave error).
331
+ *
332
+ * Default: false (opt-in for now)
333
+ */
334
+ useOctaveResolution?: boolean;
335
+ /**
336
+ * Whether to use TPS3 triple meter resolution for 3/4, 6/8 time signatures.
337
+ *
338
+ * When enabled, uses the Ellis TPS3 calculation (Equation 7 variant) to prefer tempos
339
+ * with strong third-period evidence, improving detection for waltzes and triple meter music.
340
+ *
341
+ * The TPS3 formula combines the main tempo with its third-harmonic:
342
+ * `TPS3(τ) = TPS(τ) + 0.33×TPS(3τ) + 0.33×TPS(3τ-1) + 0.33×TPS(3τ+1)`
343
+ *
344
+ * Tempos with strong third-period evidence (indicating triple meter) will have
345
+ * higher TPS3 scores, allowing proper beat detection for waltzes and 6/8 shuffles.
346
+ *
347
+ * Default: false (opt-in for triple meter music)
348
+ */
349
+ useTripleMeter?: boolean;
350
+ /**
351
+ * Hop size mode configuration.
352
+ * Takes precedence over hopSizeMs when both are provided.
353
+ * @default { mode: 'standard' } (4ms)
354
+ */
355
+ hopSizeMode?: HopSizeConfig;
356
+ /**
357
+ * Mel bands mode configuration.
358
+ * Takes precedence over melBands when both are provided.
359
+ * @default { mode: 'standard' } (40 bands)
360
+ */
361
+ melBandsMode?: MelBandsConfig;
362
+ /**
363
+ * Gaussian smooth mode configuration.
364
+ * Takes precedence over gaussianSmoothMs when both are provided.
365
+ * @default { mode: 'standard' } (20ms)
366
+ */
367
+ gaussianSmoothMode?: GaussianSmoothConfig;
368
+ }
369
+ /**
370
+ * Options for BeatStream configuration
371
+ */
372
+ export interface BeatStreamOptions {
373
+ /** Time before beat to emit 'upcoming' event in seconds (default: 2.0) */
374
+ anticipationTime?: number;
375
+ /** Player-calibrated audio/visual offset in milliseconds (default: 0) */
376
+ userOffsetMs?: number;
377
+ /**
378
+ * Auto-adjust using AudioContext.outputLatency (default: true)
379
+ * Gracefully falls back to 0 if unsupported (e.g., Safari/older browsers)
380
+ */
381
+ compensateOutputLatency?: boolean;
382
+ /** Timing tolerance for synchronization in seconds (default: 0.01 = 10ms) */
383
+ timingTolerance?: number;
384
+ /**
385
+ * Difficulty preset for accuracy thresholds (default: 'medium')
386
+ * Ignored if customThresholds is provided.
387
+ */
388
+ difficultyPreset?: DifficultyPreset;
389
+ /**
390
+ * Custom accuracy thresholds (in seconds)
391
+ * If provided, overrides difficultyPreset.
392
+ */
393
+ customThresholds?: Partial<AccuracyThresholds>;
394
+ /**
395
+ * Use interpolated beats from InterpolatedBeatMap (default: false)
396
+ * If true and an InterpolatedBeatMap is provided to the BeatStream constructor,
397
+ * the stream will use mergedBeats (interpolated + detected) instead of
398
+ * the original detectedBeats.
399
+ *
400
+ * This allows seamless use of beat interpolation without modifying the BeatMap.
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // With interpolation
405
+ * const interpolatedMap = interpolator.interpolate(beatMap);
406
+ * const beatStream = new BeatStream(interpolatedMap, audioContext, {
407
+ * useInterpolatedBeats: true // Use mergedBeats
408
+ * });
409
+ *
410
+ * // Without interpolation (original behavior)
411
+ * const beatStream = new BeatStream(beatMap, audioContext, {
412
+ * useInterpolatedBeats: false // Use beats array
413
+ * });
414
+ * ```
415
+ */
416
+ useInterpolatedBeats?: boolean;
417
+ /**
418
+ * Ignore required key assignments on beats (default: false)
419
+ * When true, beats with requiredKey will use timing-only evaluation,
420
+ * ignoring key matching. Useful for "easy mode" gameplay.
421
+ *
422
+ * When false (default), if a beat has a requiredKey:
423
+ * - Correct key: timing-based accuracy (perfect/great/good/ok/miss)
424
+ * - Wrong key: accuracy becomes 'wrongKey' regardless of timing
425
+ * - No key provided: treated as 'miss'
426
+ */
427
+ ignoreKeyRequirements?: boolean;
428
+ }
429
+ /**
430
+ * Accuracy levels for button press detection
431
+ */
432
+ export type BeatAccuracy = 'perfect' | 'great' | 'good' | 'ok' | 'miss' | 'wrongKey';
433
+ /**
434
+ * Accuracy thresholds for button press detection (in seconds)
435
+ * Used to configure difficulty levels for rhythm games.
436
+ */
437
+ export interface AccuracyThresholds {
438
+ /** Perfect: within this threshold (seconds) */
439
+ perfect: number;
440
+ /** Great: within this threshold (seconds) */
441
+ great: number;
442
+ /** Good: within this threshold (seconds) */
443
+ good: number;
444
+ /** Ok: within this threshold (seconds) */
445
+ ok: number;
446
+ }
447
+ /**
448
+ * Preset difficulty levels for accuracy thresholds
449
+ *
450
+ * - 'easy': Forgiving timing, simplified rhythm
451
+ * - 'medium': Balanced timing and rhythm
452
+ * - 'hard': Tight timing, full rhythm density
453
+ * - 'natural': Unedited composite stream (what was actually detected in the audio)
454
+ * - 'custom': User-defined settings
455
+ */
456
+ export type DifficultyPreset = 'easy' | 'medium' | 'hard' | 'natural' | 'custom';
457
+ /**
458
+ * Easy difficulty thresholds (forgiving)
459
+ */
460
+ export declare const EASY_ACCURACY_THRESHOLDS: AccuracyThresholds;
461
+ /**
462
+ * Medium difficulty thresholds (balanced)
463
+ */
464
+ export declare const MEDIUM_ACCURACY_THRESHOLDS: AccuracyThresholds;
465
+ /**
466
+ * Hard difficulty thresholds (strict - for veterans)
467
+ */
468
+ export declare const HARD_ACCURACY_THRESHOLDS: AccuracyThresholds;
469
+ /**
470
+ * Natural difficulty thresholds (same as hard - unedited composite)
471
+ */
472
+ export declare const NATURAL_ACCURACY_THRESHOLDS: AccuracyThresholds;
473
+ /**
474
+ * Result of a button press accuracy check
475
+ */
476
+ export interface ButtonPressResult {
477
+ /** Accuracy level of the press */
478
+ accuracy: BeatAccuracy;
479
+ /** Time difference from nearest beat in seconds (negative = early, positive = late) */
480
+ offset: number;
481
+ /** The beat that was matched (nearest beat to the press) */
482
+ matchedBeat: Beat;
483
+ /** Absolute time difference in seconds */
484
+ absoluteOffset: number;
485
+ /**
486
+ * Whether the pressed key matched the required key (if any).
487
+ * True if: no key required, or pressedKey matches requiredKey.
488
+ * False if: key required but wrong key pressed (accuracy will be 'wrongKey').
489
+ */
490
+ keyMatch: boolean;
491
+ /**
492
+ * The key that was pressed (passed to checkButtonPress).
493
+ * Undefined if no key was provided.
494
+ */
495
+ pressedKey?: string;
496
+ /**
497
+ * The required key from the matched beat (convenience copy).
498
+ * Undefined if the beat has no required key.
499
+ */
500
+ requiredKey?: string;
501
+ }
502
+ /**
503
+ * JSON-serializable version of BeatMap
504
+ *
505
+ * Identical to BeatMap but ensures all values are JSON-safe
506
+ * for serialization/deserialization operations
507
+ */
508
+ export interface BeatMapJSON {
509
+ audioId: string;
510
+ duration: number;
511
+ beats: Array<{
512
+ timestamp: number;
513
+ beatInMeasure: number;
514
+ isDownbeat: boolean;
515
+ measureNumber: number;
516
+ intensity: number;
517
+ confidence: number;
518
+ requiredKey?: string;
519
+ }>;
520
+ bpm: number;
521
+ metadata: BeatMapMetadata;
522
+ /**
523
+ * The downbeat configuration used to generate this beat map
524
+ * Only stored if explicitly provided; undefined means default (beat 0 = downbeat, 4/4 time)
525
+ * Stored for reproducibility and reprocessing
526
+ */
527
+ downbeatConfig?: DownbeatConfig;
528
+ }
529
+ /**
530
+ * JSON-serializable version of BeatWithSource
531
+ */
532
+ export interface BeatWithSourceJSON {
533
+ timestamp: number;
534
+ beatInMeasure: number;
535
+ isDownbeat: boolean;
536
+ measureNumber: number;
537
+ intensity: number;
538
+ confidence: number;
539
+ requiredKey?: string;
540
+ source: BeatSource;
541
+ distanceToAnchor?: number;
542
+ nearestAnchorTimestamp?: number;
543
+ }
544
+ /**
545
+ * JSON-serializable version of QuarterNoteDetection
546
+ */
547
+ export interface QuarterNoteDetectionJSON {
548
+ intervalSeconds: number;
549
+ bpm: number;
550
+ confidence: number;
551
+ histogramPeak: number;
552
+ secondaryPeaks: number[];
553
+ method: 'histogram' | 'kde' | 'tempo-detector-fallback';
554
+ denseSectionCount: number;
555
+ denseSectionBeats: number;
556
+ }
557
+ /**
558
+ * JSON-serializable version of GapAnalysis
559
+ */
560
+ export interface GapAnalysisJSON {
561
+ totalGaps: number;
562
+ halfNoteGaps: number;
563
+ anomalies: number[];
564
+ avgGapSize: number;
565
+ gridAlignmentScore: number;
566
+ }
567
+ /**
568
+ * JSON-serializable version of TempoSection
569
+ */
570
+ export interface TempoSectionJSON {
571
+ start: number;
572
+ end: number;
573
+ bpm: number;
574
+ intervalSeconds: number;
575
+ beatCount: number;
576
+ startBeatIndex: number;
577
+ endBeatIndex: number;
578
+ }
579
+ /**
580
+ * JSON-serializable version of InterpolationMetadata
581
+ */
582
+ export interface InterpolationMetadataJSON {
583
+ quarterNoteDetection: QuarterNoteDetectionJSON;
584
+ gapAnalysis: GapAnalysisJSON;
585
+ detectedBeatCount: number;
586
+ interpolatedBeatCount: number;
587
+ totalBeatCount: number;
588
+ interpolationRatio: number;
589
+ avgInterpolatedConfidence: number;
590
+ tempoDriftRatio: number;
591
+ /** Tempos found during normal analysis (e.g., [128, 140]) */
592
+ detectedClusterTempos?: number[];
593
+ /** Quick flag for checking if multi-tempo re-analysis is available */
594
+ hasMultipleTempos: boolean;
595
+ /** Full section data (only after multi-tempo re-analysis) */
596
+ tempoSections?: TempoSectionJSON[];
597
+ /** True only after multi-tempo re-analysis completes */
598
+ hasMultiTempoApplied?: boolean;
599
+ }
600
+ /**
601
+ * JSON-serializable version of InterpolatedBeatMap
602
+ *
603
+ * Ensures all values are JSON-safe for serialization/deserialization operations.
604
+ * Use with BeatInterpolator.toJSON() and BeatInterpolator.fromJSON() methods.
605
+ */
606
+ export interface InterpolatedBeatMapJSON {
607
+ audioId: string;
608
+ duration: number;
609
+ detectedBeats: Array<{
610
+ timestamp: number;
611
+ beatInMeasure: number;
612
+ isDownbeat: boolean;
613
+ measureNumber: number;
614
+ intensity: number;
615
+ confidence: number;
616
+ requiredKey?: string;
617
+ }>;
618
+ mergedBeats: BeatWithSourceJSON[];
619
+ quarterNoteInterval: number;
620
+ quarterNoteBpm: number;
621
+ quarterNoteConfidence: number;
622
+ originalMetadata: BeatMapMetadata;
623
+ interpolationMetadata: InterpolationMetadataJSON;
624
+ /** The downbeat configuration inherited from the original BeatMap */
625
+ downbeatConfig?: DownbeatConfig;
626
+ }
627
+ /**
628
+ * JSON-serializable version of SubdividedBeat
629
+ *
630
+ * Extends Beat with subdivision-specific fields.
631
+ * Use with BeatSubdivider.toJSON() and BeatSubdivider.fromJSON() methods.
632
+ */
633
+ export interface SubdividedBeatJSON {
634
+ timestamp: number;
635
+ beatInMeasure: number;
636
+ isDownbeat: boolean;
637
+ measureNumber: number;
638
+ intensity: number;
639
+ confidence: number;
640
+ requiredKey?: string;
641
+ isDetected: boolean;
642
+ originalBeatIndex?: number;
643
+ subdivisionType: SubdivisionType;
644
+ }
645
+ /**
646
+ * JSON-serializable version of SubdivisionMetadata
647
+ */
648
+ export interface SubdivisionMetadataJSON {
649
+ originalBeatCount: number;
650
+ subdividedBeatCount: number;
651
+ averageDensityMultiplier: number;
652
+ explicitBeatCount: number;
653
+ subdivisionsUsed: SubdivisionType[];
654
+ hasMultipleTempos: boolean;
655
+ maxDensity: number;
656
+ }
657
+ /**
658
+ * JSON-serializable version of SubdividedBeatMap
659
+ *
660
+ * Ensures all values are JSON-safe for serialization/deserialization operations.
661
+ * Use with BeatSubdivider.toJSON() and BeatSubdivider.fromJSON() methods.
662
+ */
663
+ export interface SubdividedBeatMapJSON {
664
+ audioId: string;
665
+ duration: number;
666
+ beats: SubdividedBeatJSON[];
667
+ detectedBeatIndices: number[];
668
+ subdivisionConfig: SubdivisionConfigJSON;
669
+ downbeatConfig: DownbeatConfig;
670
+ tempoSections?: TempoSectionJSON[];
671
+ subdivisionMetadata: SubdivisionMetadataJSON;
672
+ }
673
+ /**
674
+ * Tempo estimation result from the TempoDetector
675
+ */
676
+ export interface TempoEstimate {
677
+ /** Main tempo estimate in BPM */
678
+ primaryBpm: number;
679
+ /** Adjacent metrical level in BPM (e.g., half-time or double-time) */
680
+ secondaryBpm: number;
681
+ /** Relative strength of the primary tempo (0.0 - 1.0) */
682
+ primaryWeight: number;
683
+ /** Relative strength of the secondary tempo (0.0 - 1.0) */
684
+ secondaryWeight: number;
685
+ /** Target inter-beat interval in seconds for DP tracker */
686
+ targetIntervalSeconds: number;
687
+ }
688
+ /**
689
+ * Tier 1: Hop size mode for controlling beat detection precision
690
+ *
691
+ * Hop size determines the time resolution of onset detection.
692
+ * Smaller values = more precise but slower analysis.
693
+ */
694
+ export type HopSizeMode = 'efficient' | 'standard' | 'hq' | 'custom';
695
+ /**
696
+ * Preset hop size values in milliseconds
697
+ *
698
+ * - efficient: 10ms - Fast analysis, reduced precision (legacy default)
699
+ * - standard: 4ms - Paper specification (Ellis 2007) - RECOMMENDED
700
+ * - hq: 2ms - High quality, maximum precision
701
+ */
702
+ export declare const HOP_SIZE_PRESETS: {
703
+ readonly efficient: 10;
704
+ readonly standard: 4;
705
+ readonly hq: 2;
706
+ };
707
+ /**
708
+ * Configuration for hop size mode selection
709
+ */
710
+ export interface HopSizeConfig {
711
+ /** The hop size mode to use */
712
+ mode: HopSizeMode;
713
+ /** Custom hop size in milliseconds (only used when mode === 'custom') */
714
+ customValue?: number;
715
+ }
716
+ /**
717
+ * Tier 2: Mel bands mode for controlling frequency resolution
718
+ *
719
+ * Mel bands determine the frequency resolution of the onset detection.
720
+ * More bands = better frequency resolution but slightly slower analysis.
721
+ */
722
+ export type MelBandsMode = 'standard' | 'detailed' | 'maximum';
723
+ /**
724
+ * Preset mel bands values
725
+ *
726
+ * - standard: 40 bands - Paper default, librosa default - RECOMMENDED
727
+ * - detailed: 64 bands - Better frequency resolution
728
+ * - maximum: 80 bands - Maximum detail
729
+ */
730
+ export declare const MEL_BANDS_PRESETS: {
731
+ readonly standard: 40;
732
+ readonly detailed: 64;
733
+ readonly maximum: 80;
734
+ };
735
+ /**
736
+ * Configuration for mel bands mode selection
737
+ */
738
+ export interface MelBandsConfig {
739
+ /** The mel bands mode to use */
740
+ mode: MelBandsMode;
741
+ }
742
+ /**
743
+ * Tier 2: Gaussian smooth mode for controlling onset envelope smoothing
744
+ *
745
+ * Gaussian smoothing determines how much the onset envelope is smoothed.
746
+ * More smoothing = cleaner peaks but may miss fast transients.
747
+ */
748
+ export type GaussianSmoothMode = 'minimal' | 'standard' | 'smooth';
749
+ /**
750
+ * Preset gaussian smoothing values in milliseconds
751
+ *
752
+ * - minimal: 10ms - Preserves fast transients
753
+ * - standard: 20ms - Paper default - RECOMMENDED
754
+ * - smooth: 40ms - Cleaner peaks, less noise
755
+ */
756
+ export declare const GAUSSIAN_SMOOTH_PRESETS: {
757
+ readonly minimal: 10;
758
+ readonly standard: 20;
759
+ readonly smooth: 40;
760
+ };
761
+ /**
762
+ * Configuration for gaussian smooth mode selection
763
+ */
764
+ export interface GaussianSmoothConfig {
765
+ /** The gaussian smooth mode to use */
766
+ mode: GaussianSmoothMode;
767
+ }
768
+ /**
769
+ * Convert hop size mode to actual milliseconds value
770
+ *
771
+ * @param config - Hop size configuration (default: { mode: 'standard' })
772
+ * @returns Hop size in milliseconds
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * // Using preset modes
777
+ * getHopSizeMs({ mode: 'standard' }); // 4ms (Ellis 2007 paper spec)
778
+ * getHopSizeMs({ mode: 'efficient' }); // 10ms (fast analysis)
779
+ * getHopSizeMs({ mode: 'hq' }); // 2ms (maximum precision)
780
+ *
781
+ * // Using custom value (clamped to 1-50ms)
782
+ * getHopSizeMs({ mode: 'custom', customValue: 5 }); // 5ms
783
+ * getHopSizeMs({ mode: 'custom', customValue: 100 }); // 50ms (clamped)
784
+ * ```
785
+ */
786
+ export declare function getHopSizeMs(config?: HopSizeConfig): number;
787
+ /**
788
+ * Convert mel bands mode to actual count
789
+ *
790
+ * @param config - Mel bands configuration (default: { mode: 'standard' })
791
+ * @returns Number of mel bands
792
+ *
793
+ * @example
794
+ * ```typescript
795
+ * getMelBands({ mode: 'standard' }); // 40 bands (librosa default)
796
+ * getMelBands({ mode: 'detailed' }); // 64 bands (better resolution)
797
+ * getMelBands({ mode: 'maximum' }); // 80 bands (maximum detail)
798
+ * ```
799
+ */
800
+ export declare function getMelBands(config?: MelBandsConfig): number;
801
+ /**
802
+ * Convert gaussian smooth mode to actual milliseconds value
803
+ *
804
+ * @param config - Gaussian smooth configuration (default: { mode: 'standard' })
805
+ * @returns Smoothing window in milliseconds
806
+ *
807
+ * @example
808
+ * ```typescript
809
+ * getGaussianSmoothMs({ mode: 'minimal' }); // 10ms (preserves transients)
810
+ * getGaussianSmoothMs({ mode: 'standard' }); // 20ms (paper default)
811
+ * getGaussianSmoothMs({ mode: 'smooth' }); // 40ms (cleaner peaks)
812
+ * ```
813
+ */
814
+ export declare function getGaussianSmoothMs(config?: GaussianSmoothConfig): number;
815
+ /**
816
+ * Configuration for Onset Strength Envelope calculation
817
+ *
818
+ * ## Parameter Modes vs Direct Values
819
+ *
820
+ * OSE parameters support two configuration styles:
821
+ * - **Mode-based**: Use `hopSizeMode`, `melBandsMode`, `gaussianSmoothMode` for preset values
822
+ * - **Direct numeric**: Use `hopSizeMs`, `melBands`, `gaussianSmoothMs` for exact control
823
+ *
824
+ * **Precedence**: When both mode and direct value are provided, mode takes precedence.
825
+ *
826
+ * @example
827
+ * ```typescript
828
+ * // Mode-based configuration (recommended)
829
+ * const config: OSEConfig = {
830
+ * hopSizeMode: { mode: 'standard' }, // 4ms (Ellis 2007 paper spec)
831
+ * melBandsMode: { mode: 'detailed' }, // 64 bands
832
+ * gaussianSmoothMode: { mode: 'smooth' } // 40ms
833
+ * };
834
+ *
835
+ * // Direct numeric configuration (backward compatible)
836
+ * const config: OSEConfig = {
837
+ * hopSizeMs: 4,
838
+ * melBands: 40,
839
+ * gaussianSmoothMs: 20
840
+ * };
841
+ *
842
+ * // Mixed - mode takes precedence (hopSizeMs is ignored)
843
+ * const config: OSEConfig = {
844
+ * hopSizeMode: { mode: 'hq' }, // Uses 2ms
845
+ * hopSizeMs: 10 // Ignored because hopSizeMode is set
846
+ * };
847
+ * ```
848
+ */
849
+ export interface OSEConfig {
850
+ /** Target sample rate for resampling (default: 8000 Hz) */
851
+ targetSampleRate?: number;
852
+ /** FFT window size in milliseconds (default: 32) */
853
+ fftWindowSize?: number;
854
+ /**
855
+ * Hop size in milliseconds (default: 4).
856
+ * Ignored if hopSizeMode is provided.
857
+ * @see hopSizeMode for mode-based configuration
858
+ */
859
+ hopSizeMs?: number;
860
+ /**
861
+ * Hop size mode configuration.
862
+ * Takes precedence over hopSizeMs when both are provided.
863
+ * @default { mode: 'standard' }
864
+ */
865
+ hopSizeMode?: HopSizeConfig;
866
+ /**
867
+ * Number of Mel frequency bands (default: 40).
868
+ * Ignored if melBandsMode is provided.
869
+ * @see melBandsMode for mode-based configuration
870
+ */
871
+ melBands?: number;
872
+ /**
873
+ * Mel bands mode configuration.
874
+ * Takes precedence over melBands when both are provided.
875
+ * @default { mode: 'standard' }
876
+ */
877
+ melBandsMode?: MelBandsConfig;
878
+ /** High-pass filter cutoff in Hz (default: 0.4) */
879
+ highPassCutoff?: number;
880
+ /**
881
+ * Gaussian smoothing window in ms (default: 20).
882
+ * Ignored if gaussianSmoothMode is provided.
883
+ * @see gaussianSmoothMode for mode-based configuration
884
+ */
885
+ gaussianSmoothMs?: number;
886
+ /**
887
+ * Gaussian smooth mode configuration.
888
+ * Takes precedence over gaussianSmoothMs when both are provided.
889
+ * @default { mode: 'standard' }
890
+ */
891
+ gaussianSmoothMode?: GaussianSmoothConfig;
892
+ }
893
+ /**
894
+ * Configuration for the BeatTracker (DP algorithm)
895
+ */
896
+ export interface BeatTrackerConfig {
897
+ /** Ellis balance factor (default: 680) */
898
+ dpAlpha?: number;
899
+ /** Sensitivity multiplier (0.1-10, default: 1.0) */
900
+ sensitivity?: number;
901
+ /** Minimum predecessor ratio (default: 0.5 = τp/2) */
902
+ minPredecessorRatio?: number;
903
+ /** Maximum predecessor ratio (default: 2.0 = 2τp) */
904
+ maxPredecessorRatio?: number;
905
+ }
906
+ /**
907
+ * Configuration for the TempoDetector.
908
+ *
909
+ * Controls tempo estimation behavior including BPM range, perceptual weighting,
910
+ * and optional meter resolution algorithms.
911
+ *
912
+ * Key options:
913
+ * - `useOctaveResolution`: Enable TPS2 calculation to resolve duple meter ambiguity
914
+ * (half-tempo/double-tempo errors). Use for most 4/4, 2/4 music.
915
+ * - `useTripleMeter`: Enable TPS3 calculation to resolve triple meter ambiguity
916
+ * (3/4, 6/8 time signatures). Use for waltzes and shuffle feels.
917
+ *
918
+ * Both options can be enabled simultaneously - they run independently and each
919
+ * resolves its respective meter ambiguity.
920
+ *
921
+ * @see {@link https://eeewing.com/pubs/ismir2007.pdf} - Ellis 2007, "Beat Tracking by Dynamic Programming"
922
+ */
923
+ export interface TempoDetectorConfig {
924
+ /** Tempo center in seconds (default: 0.5 = 120 BPM) */
925
+ tempoCenter?: number;
926
+ /** Tempo width in octaves (default: 1.4, or 0.9 for stricter) */
927
+ tempoWidth?: number;
928
+ /** Minimum BPM (default: 90) */
929
+ minBpm?: number;
930
+ /** Maximum BPM (default: 180) */
931
+ maxBpm?: number;
932
+ /**
933
+ * Whether to use TPS2 octave resolution to prevent half-tempo/double-tempo ambiguity.
934
+ *
935
+ * When enabled, uses the Ellis TPS2 calculation (Equation 7) to prefer tempos
936
+ * with strong half-period evidence, improving accuracy from 77% to 84%.
937
+ *
938
+ * This helps prevent the algorithm from locking onto 73 BPM when the true tempo
939
+ * is 146 BPM (octave error).
940
+ *
941
+ * Default: false (opt-in for now)
942
+ */
943
+ useOctaveResolution?: boolean;
944
+ /**
945
+ * Whether to use TPS3 triple meter resolution for 3/4, 6/8 time signatures.
946
+ *
947
+ * When enabled, uses the Ellis TPS3 calculation (Equation 7 variant) to prefer tempos
948
+ * with strong third-period evidence, improving detection for waltzes and triple meter music.
949
+ *
950
+ * The TPS3 formula combines the main tempo with its third-harmonic:
951
+ * `TPS3(τ) = TPS(τ) + 0.33×TPS(3τ) + 0.33×TPS(3τ-1) + 0.33×TPS(3τ+1)`
952
+ *
953
+ * Tempos with strong third-period evidence (indicating triple meter) will have
954
+ * higher TPS3 scores, allowing proper beat detection for waltzes and 6/8 shuffles.
955
+ *
956
+ * Default: false (opt-in for triple meter music)
957
+ */
958
+ useTripleMeter?: boolean;
959
+ }
960
+ /**
961
+ * Progress information during beat map generation
962
+ */
963
+ export interface BeatMapGenerationProgress {
964
+ /** Current phase of generation */
965
+ phase: 'loading' | 'preprocessing' | 'ose_calculation' | 'tempo_estimation' | 'beat_tracking' | 'measure_labeling' | 'finalizing' | 'complete' | 'error';
966
+ /** Progress percentage (0-100) */
967
+ progress: number;
968
+ /** Human-readable status message */
969
+ message: string;
970
+ /** Error message if phase is 'error' */
971
+ error?: string;
972
+ }
973
+ /**
974
+ * Default values for BeatMapGeneratorOptions
975
+ */
976
+ export declare const DEFAULT_BEATMAP_GENERATOR_OPTIONS: Required<BeatMapGeneratorOptions>;
977
+ /**
978
+ * Default values for BeatStreamOptions
979
+ */
980
+ export declare const DEFAULT_BEATSTREAM_OPTIONS: Required<BeatStreamOptions>;
981
+ /**
982
+ * Default accuracy thresholds (Hard difficulty preset)
983
+ * Equivalent to HARD_ACCURACY_THRESHOLDS - use either constant
984
+ */
985
+ export declare const BEAT_ACCURACY_THRESHOLDS: AccuracyThresholds;
986
+ /**
987
+ * Get accuracy thresholds for a difficulty preset
988
+ * @param preset - The difficulty preset ('easy', 'medium', 'hard', or 'custom')
989
+ * @returns The accuracy thresholds for the specified preset
990
+ * @note 'custom' preset returns hard thresholds as a base for customization
991
+ */
992
+ export declare function getAccuracyThresholdsForPreset(preset: DifficultyPreset): AccuracyThresholds;
993
+ /**
994
+ * Result of validating accuracy thresholds
995
+ */
996
+ export interface ThresholdValidationResult {
997
+ /** Whether the thresholds are valid */
998
+ valid: boolean;
999
+ /** List of validation error messages (empty if valid) */
1000
+ errors: string[];
1001
+ }
1002
+ /**
1003
+ * Source of a beat - whether it was detected by the algorithm or interpolated
1004
+ */
1005
+ export type BeatSource = 'detected' | 'interpolated';
1006
+ /**
1007
+ * A beat with source information for interpolation
1008
+ *
1009
+ * Extends the base Beat interface with fields tracking the beat's origin
1010
+ * and relationship to detected beats.
1011
+ */
1012
+ export interface BeatWithSource extends Beat {
1013
+ /** Whether this beat was detected or interpolated */
1014
+ source: BeatSource;
1015
+ /** Distance in seconds to the nearest detected beat (for interpolated beats) */
1016
+ distanceToAnchor?: number;
1017
+ /** Timestamp of the nearest detected beat (for interpolated beats) */
1018
+ nearestAnchorTimestamp?: number;
1019
+ }
1020
+ /**
1021
+ * Result of quarter note detection with dense section priority
1022
+ *
1023
+ * The quarter note interval is determined by analyzing beat intervals,
1024
+ * with higher weight given to intervals from dense sections (consecutive
1025
+ * beats at regular spacing).
1026
+ */
1027
+ export interface QuarterNoteDetection {
1028
+ /** Detected quarter note duration in seconds */
1029
+ intervalSeconds: number;
1030
+ /** Equivalent BPM (60 / intervalSeconds) */
1031
+ bpm: number;
1032
+ /** Confidence in the detection (0-1) */
1033
+ confidence: number;
1034
+ /** Raw histogram peak value for the detected interval */
1035
+ histogramPeak: number;
1036
+ /** Other significant peaks (e.g., half-note = 2× quarter note) */
1037
+ secondaryPeaks: number[];
1038
+ /** Method used for detection */
1039
+ method: 'histogram' | 'kde' | 'tempo-detector-fallback';
1040
+ /** Number of dense sections that contributed to the detection */
1041
+ denseSectionCount: number;
1042
+ /** Total beats from dense sections used in the detection */
1043
+ denseSectionBeats: number;
1044
+ }
1045
+ /**
1046
+ * Analysis of gaps between detected beats
1047
+ *
1048
+ * Identifies missing beats and anomalies in the detected beat pattern.
1049
+ */
1050
+ export interface GapAnalysis {
1051
+ /** Total number of gaps found between detected beats */
1052
+ totalGaps: number;
1053
+ /** Number of gaps that are exactly 2× quarter note (half-note gaps) */
1054
+ halfNoteGaps: number;
1055
+ /** Indices of beats that appear to be anomalies (false positives) */
1056
+ anomalies: number[];
1057
+ /** Average gap size in beats (1.0 = one quarter note) */
1058
+ avgGapSize: number;
1059
+ /** How well the detected beats align to the grid (0-1, higher is better) */
1060
+ gridAlignmentScore: number;
1061
+ }
1062
+ /**
1063
+ * Represents a distinct tempo section within a track
1064
+ *
1065
+ * When a track has multiple distinct tempo sections (e.g., a slow intro at 90 BPM
1066
+ * followed by a fast section at 140 BPM), each section is represented by this interface.
1067
+ *
1068
+ * Sections have hard boundaries - no morphing/blending between tempos.
1069
+ * This is only populated when multi-tempo analysis is enabled and detects multiple tempos.
1070
+ */
1071
+ export interface TempoSection {
1072
+ /** Section start time in seconds */
1073
+ start: number;
1074
+ /** Section end time in seconds */
1075
+ end: number;
1076
+ /** Tempo for this section in BPM */
1077
+ bpm: number;
1078
+ /** Quarter note interval in seconds (60 / bpm) */
1079
+ intervalSeconds: number;
1080
+ /** Number of detected beats in this section's cluster */
1081
+ beatCount: number;
1082
+ /** Index of the first beat in this section */
1083
+ startBeatIndex: number;
1084
+ /** Index of the last beat in this section */
1085
+ endBeatIndex: number;
1086
+ }
1087
+ /**
1088
+ * Metadata about the interpolation process
1089
+ */
1090
+ export interface InterpolationMetadata {
1091
+ /** Quarter note detection details */
1092
+ quarterNoteDetection: QuarterNoteDetection;
1093
+ /** Gap analysis results */
1094
+ gapAnalysis: GapAnalysis;
1095
+ /** Number of originally detected beats */
1096
+ detectedBeatCount: number;
1097
+ /** Number of beats added by interpolation */
1098
+ interpolatedBeatCount: number;
1099
+ /** Total beats in the merged output */
1100
+ totalBeatCount: number;
1101
+ /** Ratio of interpolated beats to total beats */
1102
+ interpolationRatio: number;
1103
+ /** Average confidence of interpolated beats */
1104
+ avgInterpolatedConfidence: number;
1105
+ /** Ratio of maximum local tempo to minimum local tempo (drift indicator) */
1106
+ tempoDriftRatio: number;
1107
+ /**
1108
+ * Tempos found during normal analysis (e.g., [128, 140])
1109
+ * Populated by normal analysis - cheap to compute
1110
+ */
1111
+ detectedClusterTempos?: number[];
1112
+ /**
1113
+ * Quick flag for checking if multi-tempo re-analysis is available
1114
+ * True if detectedClusterTempos has more than one tempo
1115
+ */
1116
+ hasMultipleTempos: boolean;
1117
+ /**
1118
+ * Full section data with boundaries
1119
+ * Only populated after multi-tempo re-analysis (enableMultiTempo: true)
1120
+ */
1121
+ tempoSections?: TempoSection[];
1122
+ /**
1123
+ * True only after multi-tempo re-analysis completes
1124
+ * Used to distinguish between "detected multi-tempo" and "applied multi-tempo"
1125
+ */
1126
+ hasMultiTempoApplied?: boolean;
1127
+ }
1128
+ /**
1129
+ * Complete interpolated beat map with two output streams
1130
+ *
1131
+ * Contains both the original detected beats and a merged stream that
1132
+ * includes interpolated beats to fill gaps.
1133
+ */
1134
+ export interface InterpolatedBeatMap {
1135
+ /** Unique identifier for the audio source */
1136
+ audioId: string;
1137
+ /** Duration of the audio in seconds */
1138
+ duration: number;
1139
+ /** Original detected beats only (unchanged from BeatMap) */
1140
+ detectedBeats: Beat[];
1141
+ /** Interpolated beats with detected beats overriding at same positions */
1142
+ mergedBeats: BeatWithSource[];
1143
+ /** Detected quarter note interval in seconds */
1144
+ quarterNoteInterval: number;
1145
+ /** Equivalent BPM for the quarter note */
1146
+ quarterNoteBpm: number;
1147
+ /** Confidence in the quarter note detection */
1148
+ quarterNoteConfidence: number;
1149
+ /** Metadata from the original BeatMap */
1150
+ originalMetadata: BeatMapMetadata;
1151
+ /** Metadata about the interpolation process */
1152
+ interpolationMetadata: InterpolationMetadata;
1153
+ /**
1154
+ * The downbeat configuration inherited from the original BeatMap
1155
+ * Used for subdivision to determine measure boundaries
1156
+ */
1157
+ downbeatConfig?: DownbeatConfig;
1158
+ }
1159
+ /**
1160
+ * Options for beat interpolation
1161
+ *
1162
+ * Controls how the interpolation algorithm generates the beat grid.
1163
+ * Uses the Adaptive Phase-Locked Grid algorithm for beat interpolation.
1164
+ */
1165
+ export interface BeatInterpolationOptions {
1166
+ /** Minimum confidence for a beat to be used as an anchor (default: 0.3) */
1167
+ minAnchorConfidence?: number;
1168
+ /** Tolerance in seconds for snapping detected beats to grid (default: 0.05) */
1169
+ gridSnapTolerance?: number;
1170
+ /**
1171
+ * Rate of tempo adaptation at anchor points (0-1, default: 0.3)
1172
+ * 0 = fixed tempo, 1 = full adaptation to each anchor
1173
+ */
1174
+ tempoAdaptationRate?: number;
1175
+ /** Whether to extrapolate grid before first detected beat (default: true) */
1176
+ extrapolateStart?: boolean;
1177
+ /** Whether to extrapolate grid after last detected beat (default: true) */
1178
+ extrapolateEnd?: boolean;
1179
+ /**
1180
+ * Multiplier for anomaly detection (default: 0.4)
1181
+ * Intervals < (1 - threshold) × QN or > (1 + threshold) × QN are flagged
1182
+ */
1183
+ anomalyThreshold?: number;
1184
+ /** Minimum beats to count as a dense section (default: 3) */
1185
+ denseSectionMinBeats?: number;
1186
+ /** Weight for grid alignment in confidence calculation (default: 0.5) */
1187
+ gridAlignmentWeight?: number;
1188
+ /** Weight for anchor confidence in confidence calculation (default: 0.3) */
1189
+ anchorConfidenceWeight?: number;
1190
+ /** Weight for pace confidence in confidence calculation (default: 0.2) */
1191
+ paceConfidenceWeight?: number;
1192
+ /**
1193
+ * Tempo difference threshold for section detection (default: 0.1 = 10%)
1194
+ * Two tempos must differ by more than this ratio to be considered separate sections
1195
+ */
1196
+ tempoSectionThreshold?: number;
1197
+ /**
1198
+ * Minimum beats for a valid tempo cluster (default: 4)
1199
+ * Clusters with fewer beats are not considered for multi-tempo detection
1200
+ */
1201
+ minClusterBeats?: number;
1202
+ /**
1203
+ * Enable multi-tempo analysis and interpolation (default: false)
1204
+ * If true and hasMultipleTempos is detected, runs crossing paths analysis
1205
+ * and applies per-section interpolation
1206
+ */
1207
+ enableMultiTempo?: boolean;
1208
+ }
1209
+ /**
1210
+ * Default values for BeatInterpolationOptions
1211
+ */
1212
+ export declare const DEFAULT_BEAT_INTERPOLATION_OPTIONS: Required<BeatInterpolationOptions>;
1213
+ /**
1214
+ * Validate accuracy thresholds for correctness
1215
+ *
1216
+ * Checks that:
1217
+ * - All provided threshold values are positive numbers
1218
+ * - Thresholds are in ascending order (perfect < great < good < ok)
1219
+ *
1220
+ * @param thresholds - The thresholds to validate (can be partial)
1221
+ * @returns Validation result with detailed error messages
1222
+ *
1223
+ * @example
1224
+ * ```typescript
1225
+ * // Valid thresholds
1226
+ * const result = validateThresholds({ perfect: 0.05, great: 0.1, good: 0.15, ok: 0.2 });
1227
+ * console.log(result.valid); // true
1228
+ *
1229
+ * // Invalid thresholds (not ascending)
1230
+ * const invalid = validateThresholds({ perfect: 0.1, great: 0.05 });
1231
+ * console.log(invalid.valid); // false
1232
+ * console.log(invalid.errors); // ['great (0.05) must be greater than perfect (0.1)']
1233
+ * ```
1234
+ */
1235
+ export declare function validateThresholds(thresholds: Partial<AccuracyThresholds>): ThresholdValidationResult;
1236
+ /**
1237
+ * Types of beat subdivision
1238
+ *
1239
+ * - quarter: Default, 1x density (unchanged)
1240
+ * - half: 0.5x density (beats on 1 and 3 only)
1241
+ * - eighth: 2x density (beat between each quarter)
1242
+ * - sixteenth: 4x density (3 beats between each quarter) - MAXIMUM DENSITY
1243
+ * - triplet8: Eighth triplets (3 beats per quarter note)
1244
+ * - triplet4: Quarter triplets (3 beats per half note)
1245
+ * - dotted4: Dotted quarter (keeps every 3rd beat: positions 0, 3, 6...)
1246
+ * - dotted8: Dotted eighth (beat at 3/4 between quarters - 3:1 long-short ratio)
1247
+ * - swing: Swing feel (beat at 2/3 between quarters - 2:1 long-short ratio)
1248
+ * - offbeat8: 8th rest + 8th note (skips original beat, adds beat at 0.5)
1249
+ * - rest: 0x density (no beats generated - used for gaps in rhythm patterns)
1250
+ *
1251
+ * Note: Sixteenth notes (4x) are the maximum supported density.
1252
+ * Higher densities are not supported and will throw an error.
1253
+ */
1254
+ export type SubdivisionType = 'quarter' | 'half' | 'eighth' | 'sixteenth' | 'triplet8' | 'triplet4' | 'dotted4' | 'dotted8' | 'swing' | 'offbeat8' | 'rest';
1255
+ /**
1256
+ * Subdivision configuration for rhythm pattern generation
1257
+ *
1258
+ * This configuration allows each beat to have its own subdivision type,
1259
+ * enabling fine-grained control for creating complex rhythmic phrases.
1260
+ * Uses a sparse Map for efficient storage - beats not in the map use
1261
+ * the default subdivision.
1262
+ *
1263
+ * @example
1264
+ * ```typescript
1265
+ * // Create a rhythm phrase with varying subdivisions
1266
+ * const config: SubdivisionConfig = {
1267
+ * beatSubdivisions: new Map([
1268
+ * [0, 'quarter'], // Beat 0: quarter note
1269
+ * [1, 'eighth'], // Beat 1: eighth notes
1270
+ * [2, 'eighth'], // Beat 2: eighth notes
1271
+ * [3, 'quarter'], // Beat 3: quarter note
1272
+ * ]),
1273
+ * defaultSubdivision: 'quarter',
1274
+ * };
1275
+ *
1276
+ * // Sparse representation - only specify beats that differ from default
1277
+ * const sparseConfig: SubdivisionConfig = {
1278
+ * beatSubdivisions: new Map([
1279
+ * [4, 'triplet8'], // Only beat 4 uses triplets
1280
+ * [8, 'triplet8'], // Only beat 8 uses triplets
1281
+ * ]),
1282
+ * defaultSubdivision: 'quarter', // All other beats are quarter notes
1283
+ * };
1284
+ *
1285
+ * // Create gaps in rhythm using 'rest'
1286
+ * const configWithRests: SubdivisionConfig = {
1287
+ * beatSubdivisions: new Map([
1288
+ * [0, 'quarter'], // Beat 0: quarter note
1289
+ * [1, 'rest'], // Beat 1: no beat (rest)
1290
+ * [2, 'eighth'], // Beat 2: eighth notes
1291
+ * [3, 'rest'], // Beat 3: no beat (rest)
1292
+ * ]),
1293
+ * defaultSubdivision: 'quarter',
1294
+ * };
1295
+ * ```
1296
+ */
1297
+ export interface SubdivisionConfig {
1298
+ /**
1299
+ * Subdivision type for each beat index (sparse).
1300
+ * Beats not in this map use the defaultSubdivision.
1301
+ * Key: beat index (0-based), Value: subdivision type
1302
+ */
1303
+ beatSubdivisions: Map<number, SubdivisionType>;
1304
+ /** Default subdivision for beats not in the beatSubdivisions map */
1305
+ defaultSubdivision: SubdivisionType;
1306
+ }
1307
+ /** JSON-serializable version of SubdivisionConfig */
1308
+ export interface SubdivisionConfigJSON {
1309
+ /** Subdivision assignments as array of [beatIndex, subdivisionType] tuples */
1310
+ beatSubdivisions: [number, SubdivisionType][];
1311
+ /** Default subdivision for beats not in the beatSubdivisions array */
1312
+ defaultSubdivision: SubdivisionType;
1313
+ }
1314
+ /** Default subdivision config (quarter notes throughout) */
1315
+ export declare const DEFAULT_SUBDIVISION_CONFIG: SubdivisionConfig;
1316
+ /**
1317
+ * A unified beat map with detected + interpolated beats merged
1318
+ *
1319
+ * This is the foundation for subdivision. All beats are treated equally
1320
+ * regardless of whether they were originally detected or interpolated.
1321
+ * Detected beats are flagged for accent/rhythm pattern use.
1322
+ *
1323
+ * Created from an InterpolatedBeatMap by the unifyBeatMap() utility.
1324
+ *
1325
+ * @example
1326
+ * ```typescript
1327
+ * import { BeatMapGenerator, BeatInterpolator, unifyBeatMap } from 'playlist-data-engine';
1328
+ *
1329
+ * // Generate and interpolate beat map
1330
+ * const beatMap = await generator.generateBeatMap('song.mp3', 'track-1');
1331
+ * const interpolatedMap = interpolator.interpolate(beatMap);
1332
+ *
1333
+ * // Create unified beat map (foundation for subdivision)
1334
+ * const unifiedMap = unifyBeatMap(interpolatedMap);
1335
+ *
1336
+ * // Access detected beats for accent patterns
1337
+ * const detectedBeats = unifiedMap.beats.filter((_, i) =>
1338
+ * unifiedMap.detectedBeatIndices.includes(i)
1339
+ * );
1340
+ * ```
1341
+ */
1342
+ export interface UnifiedBeatMap {
1343
+ /** Unique identifier for the audio source */
1344
+ audioId: string;
1345
+ /** Duration of the audio in seconds */
1346
+ duration: number;
1347
+ /** All beats (detected + interpolated) as a single unified list */
1348
+ beats: Beat[];
1349
+ /** Indices of beats that were originally detected (for accent lookup) */
1350
+ detectedBeatIndices: number[];
1351
+ /** Quarter note interval in seconds (primary tempo) */
1352
+ quarterNoteInterval: number;
1353
+ /** Equivalent BPM for the quarter note (primary tempo) */
1354
+ quarterNoteBpm: number;
1355
+ /** The downbeat configuration inherited from interpolation */
1356
+ downbeatConfig: DownbeatConfig;
1357
+ /** Tempo sections for multi-tempo support (from InterpolationMetadata) */
1358
+ tempoSections?: TempoSection[];
1359
+ /** Metadata from the original beat map */
1360
+ originalMetadata: BeatMapMetadata;
1361
+ }
1362
+ /**
1363
+ * A beat in a subdivided beat map
1364
+ *
1365
+ * Note: beatInMeasure is a DECIMAL in SubdividedBeat (e.g., 0.5, 1.25, 2.75)
1366
+ * while the base Beat interface uses integers. This allows for positions
1367
+ * like "the 'and' of beat 1" (1.5) or swing patterns.
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * // Eighth note positions in 4/4 time
1372
+ * // beatInMeasure values: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5
1373
+ *
1374
+ * // Triplet positions in 4/4 time
1375
+ * // beatInMeasure values: 0, 0.33, 0.66, 1, 1.33, 1.66...
1376
+ *
1377
+ * // Check if a beat was originally detected
1378
+ * if (beat.isDetected) {
1379
+ * // Use for accent patterns
1380
+ * playAccentSound(beat);
1381
+ * }
1382
+ *
1383
+ * // Get original position before subdivision
1384
+ * const originalIndex = beat.originalBeatIndex; // undefined for generated beats
1385
+ * ```
1386
+ */
1387
+ export interface SubdividedBeat extends Beat {
1388
+ /** Position within the measure as a decimal (e.g., 0, 0.5, 1, 1.5 for eighth notes) */
1389
+ beatInMeasure: number;
1390
+ /** Whether this beat was originally detected (vs interpolated or subdivision-generated) */
1391
+ isDetected: boolean;
1392
+ /** Index of the original beat in the UnifiedBeatMap (input to subdivider) */
1393
+ originalBeatIndex?: number;
1394
+ /** The subdivision type that created this beat */
1395
+ subdivisionType: SubdivisionType;
1396
+ }
1397
+ /**
1398
+ * Metadata about the subdivision process
1399
+ *
1400
+ * @example
1401
+ * ```typescript
1402
+ * const metadata = subdividedMap.subdivisionMetadata;
1403
+ *
1404
+ * console.log(`Original beats: ${metadata.originalBeatCount}`);
1405
+ * console.log(`Subdivided beats: ${metadata.subdividedBeatCount}`);
1406
+ * console.log(`Density multiplier: ${metadata.averageDensityMultiplier}x`);
1407
+ * console.log(`Subdivisions used: ${metadata.subdivisionsUsed.join(', ')}`);
1408
+ * console.log(`Has tempo changes: ${metadata.hasMultipleTempos}`);
1409
+ * console.log(`Max density: ${metadata.maxDensity}x`);
1410
+ * ```
1411
+ */
1412
+ export interface SubdivisionMetadata {
1413
+ /** Number of beats in the original unified map */
1414
+ originalBeatCount: number;
1415
+ /** Number of beats after subdivision */
1416
+ subdividedBeatCount: number;
1417
+ /** Overall density multiplier (2.0 = twice as many beats) */
1418
+ averageDensityMultiplier: number;
1419
+ /** Number of beats with explicit non-default subdivision */
1420
+ explicitBeatCount: number;
1421
+ /** Subdivision types used */
1422
+ subdivisionsUsed: SubdivisionType[];
1423
+ /** Whether the track has multiple tempo sections */
1424
+ hasMultipleTempos: boolean;
1425
+ /** Maximum density encountered (for validation against limit) */
1426
+ maxDensity: number;
1427
+ }
1428
+ /**
1429
+ * A beat map with subdivision applied
1430
+ *
1431
+ * The beat grid has been transformed according to the subdivision config,
1432
+ * which may add beats (eighth, sixteenth, triplets), remove beats (half),
1433
+ * or reposition beats (dotted patterns).
1434
+ *
1435
+ * @example
1436
+ * ```typescript
1437
+ * import { BeatSubdivider, unifyBeatMap } from 'playlist-data-engine';
1438
+ *
1439
+ * const subdivider = new BeatSubdivider();
1440
+ * const unifiedMap = unifyBeatMap(interpolatedMap);
1441
+ *
1442
+ * // Apply subdivision
1443
+ * const subdividedMap = subdivider.subdivide(unifiedMap, {
1444
+ * beatSubdivisions: new Map(),
1445
+ * defaultSubdivision: 'eighth',
1446
+ * });
1447
+ *
1448
+ * // Access subdivision results
1449
+ * console.log(`Original beats: ${subdividedMap.subdivisionMetadata.originalBeatCount}`);
1450
+ * console.log(`Subdivided beats: ${subdividedMap.subdivisionMetadata.subdividedBeatCount}`);
1451
+ * console.log(`Density multiplier: ${subdividedMap.subdivisionMetadata.averageDensityMultiplier}`);
1452
+ *
1453
+ * // Filter beats by type
1454
+ * const detectedBeats = subdividedMap.beats.filter(b => b.isDetected);
1455
+ * ```
1456
+ */
1457
+ export interface SubdividedBeatMap {
1458
+ /** Unique identifier for the audio source */
1459
+ audioId: string;
1460
+ /** Duration of the audio in seconds */
1461
+ duration: number;
1462
+ /** Beats after subdivision applied */
1463
+ beats: SubdividedBeat[];
1464
+ /** Indices of beats that were originally detected (for accent lookup) */
1465
+ detectedBeatIndices: number[];
1466
+ /** The subdivision configuration used */
1467
+ subdivisionConfig: SubdivisionConfig;
1468
+ /** The downbeat configuration inherited from UnifiedBeatMap (preserved unchanged) */
1469
+ downbeatConfig: DownbeatConfig;
1470
+ /** Tempo sections inherited from UnifiedBeatMap (for reference) */
1471
+ tempoSections?: TempoSection[];
1472
+ /** Metadata about the subdivision process */
1473
+ subdivisionMetadata: SubdivisionMetadata;
1474
+ }
1475
+ /** Maximum density multiplier (sixteenth notes = 4x) */
1476
+ export declare const MAX_SUBDIVISION_DENSITY = 4;
1477
+ /** All valid subdivision type values */
1478
+ export declare const VALID_SUBDIVISION_TYPES: SubdivisionType[];
1479
+ /**
1480
+ * Check if a value is a valid SubdivisionType
1481
+ *
1482
+ * @param value - The value to check
1483
+ * @returns true if the value is a valid SubdivisionType
1484
+ */
1485
+ export declare function isValidSubdivisionType(value: unknown): value is SubdivisionType;
1486
+ /**
1487
+ * Get the density multiplier for a subdivision type
1488
+ *
1489
+ * @param subdivision - The subdivision type
1490
+ * @returns The density multiplier (e.g., 2 for eighth notes, 4 for sixteenth notes)
1491
+ */
1492
+ export declare function getSubdivisionDensity(subdivision: SubdivisionType): number;
1493
+ /**
1494
+ * Validate subdivision configuration (structural validation only)
1495
+ *
1496
+ * This validates:
1497
+ * - beatSubdivisions is a Map
1498
+ * - All subdivision types in the map are valid
1499
+ * - defaultSubdivision is a valid subdivision type
1500
+ *
1501
+ * @param config - The subdivision configuration to validate
1502
+ * @throws Error if configuration is invalid
1503
+ */
1504
+ export declare function validateSubdivisionConfig(config: SubdivisionConfig): void;
1505
+ /**
1506
+ * Validate subdivision config against actual beat count
1507
+ *
1508
+ * This validates:
1509
+ * - Beat indices in beatSubdivisions don't exceed total beat count
1510
+ *
1511
+ * Note: Beat indices beyond the beat count are no-ops (they just won't apply).
1512
+ *
1513
+ * @param config - The subdivision configuration to validate
1514
+ * @param totalBeats - The total number of beats in the unified beat map
1515
+ * @throws Error if beat index configuration is invalid
1516
+ */
1517
+ export declare function validateSubdivisionConfigAgainstBeats(config: SubdivisionConfig, totalBeats: number): void;
1518
+ /**
1519
+ * Validate that subdivision density does not exceed maximum
1520
+ *
1521
+ * This validates that the requested subdivision doesn't exceed the
1522
+ * maximum supported density (sixteenth notes = 4x).
1523
+ *
1524
+ * @param subdivision - The subdivision type to validate
1525
+ * @throws Error if subdivision exceeds maximum density
1526
+ */
1527
+ export declare function validateSubdivisionDensity(subdivision: SubdivisionType): void;
1528
+ /**
1529
+ * Transition mode for subdivision changes during playback
1530
+ *
1531
+ * - 'immediate': Switch subdivision instantly at the current position
1532
+ * - 'next-downbeat': Wait for the next downbeat before switching
1533
+ * - 'next-measure': Wait for the next measure before switching
1534
+ */
1535
+ export type SubdivisionTransitionMode = 'immediate' | 'next-downbeat' | 'next-measure';
1536
+ /**
1537
+ * Options for the SubdivisionPlaybackController
1538
+ *
1539
+ * @example
1540
+ * ```typescript
1541
+ * const controller = new SubdivisionPlaybackController(unifiedMap, audioContext, {
1542
+ * initialSubdivision: 'quarter',
1543
+ * transitionMode: 'next-downbeat',
1544
+ * anticipationTime: 2.0,
1545
+ * onSubdivisionChange: (oldType, newType) => {
1546
+ * console.log(`Switched from ${oldType} to ${newType}`);
1547
+ * },
1548
+ * });
1549
+ * ```
1550
+ */
1551
+ export interface SubdivisionPlaybackOptions {
1552
+ /** Starting subdivision type (default: 'quarter') */
1553
+ initialSubdivision?: SubdivisionType;
1554
+ /** How to handle subdivision changes (default: 'immediate') */
1555
+ transitionMode?: SubdivisionTransitionMode;
1556
+ /** Callback when subdivision changes */
1557
+ onSubdivisionChange?: (oldType: SubdivisionType, newType: SubdivisionType) => void;
1558
+ /** Anticipation time for beat events in seconds (default: 2.0) */
1559
+ anticipationTime?: number;
1560
+ /** Timing tolerance for beat event detection in seconds (default: 0.01) */
1561
+ timingTolerance?: number;
1562
+ /** User-calibrated offset in milliseconds (default: 0) */
1563
+ userOffsetMs?: number;
1564
+ /** Whether to compensate for output latency (default: true) */
1565
+ compensateOutputLatency?: boolean;
1566
+ }
1567
+ /**
1568
+ * Default options for SubdivisionPlaybackController
1569
+ */
1570
+ export declare const DEFAULT_SUBDIVISION_PLAYBACK_OPTIONS: Required<SubdivisionPlaybackOptions>;
1571
+ /**
1572
+ * Event emitted by the SubdivisionPlaybackController during playback
1573
+ *
1574
+ * @example
1575
+ * ```typescript
1576
+ * controller.subscribe((event) => {
1577
+ * console.log(`Beat at ${event.beat.timestamp}s, subdivision: ${event.currentSubdivision}`);
1578
+ * console.log(`Time until beat: ${event.timeUntilBeat}s`);
1579
+ * });
1580
+ * ```
1581
+ */
1582
+ export interface SubdivisionBeatEvent {
1583
+ /** The beat this event relates to */
1584
+ beat: SubdividedBeat;
1585
+ /** Current subdivision type being used */
1586
+ currentSubdivision: SubdivisionType;
1587
+ /** Time until the beat occurs (negative if passed) */
1588
+ timeUntilBeat: number;
1589
+ /** Current audio context time in seconds */
1590
+ audioTime: number;
1591
+ /** Type of event: 'upcoming', 'exact', or 'passed' */
1592
+ type: BeatEventType;
1593
+ }
1594
+ /**
1595
+ * Callback function type for SubdivisionPlaybackController subscriptions
1596
+ */
1597
+ export type SubdivisionCallback = (event: SubdivisionBeatEvent) => void;
1598
+ /**
1599
+ * Current version of the beat detection algorithm
1600
+ */
1601
+ export declare const BEAT_DETECTION_VERSION = "1.0.0";
1602
+ /**
1603
+ * Algorithm identifier for the Ellis DP beat tracker
1604
+ */
1605
+ export declare const BEAT_DETECTION_ALGORITHM = "ellis-dp-v1";
1606
+ /**
1607
+ * Groove tier representing the player's current groove intensity level.
1608
+ *
1609
+ * Tiers are determined by hotness value:
1610
+ * - D: 0-33 (starting groove)
1611
+ * - C: 33-66 (building momentum)
1612
+ * - B: 66-100 (solid groove)
1613
+ * - A: 100-150 (locked in)
1614
+ * - S: 150-200 (exceptional)
1615
+ * - SS: 200+ (legendary)
1616
+ */
1617
+ export type GrooveTier = 'D' | 'C' | 'B' | 'A' | 'S' | 'SS' | 'Platinum';
1618
+ /**
1619
+ * Configuration for a single groove tier.
1620
+ */
1621
+ export interface GrooveTierConfig {
1622
+ /** Tier name/label */
1623
+ tier: GrooveTier;
1624
+ /** Minimum hotness for this tier (inclusive) */
1625
+ minHotness: number;
1626
+ /** Maximum hotness for this tier (exclusive, except for SS which has no max) */
1627
+ maxHotness: number;
1628
+ /** Pocket window size in milliseconds at this tier */
1629
+ windowMs: number;
1630
+ }
1631
+ /**
1632
+ * Groove tier configurations with thresholds and window sizes.
1633
+ *
1634
+ * Window sizes represent the pocket tolerance at each tier:
1635
+ * - Lower tier = more forgiving (larger window)
1636
+ * - Higher tier = more demanding (smaller window)
1637
+ *
1638
+ * The window continues to shrink as you climb tiers, making it progressively
1639
+ * harder to maintain your groove.
1640
+ */
1641
+ export declare const GROOVE_TIERS: GrooveTierConfig[];
1642
+ /**
1643
+ * Get the groove tier for a given hotness value.
1644
+ *
1645
+ * @param hotness - Current hotness value (can exceed 100)
1646
+ * @returns The groove tier (D, C, B, A, S, SS, or Platinum)
1647
+ */
1648
+ export declare function getGrooveTier(hotness: number): GrooveTier;
1649
+ /**
1650
+ * Get the pocket window size in milliseconds for a given hotness value.
1651
+ *
1652
+ * Uses linear interpolation within each tier for smooth transitions.
1653
+ *
1654
+ * @param hotness - Current hotness value
1655
+ * @returns Pocket window size in milliseconds
1656
+ */
1657
+ export declare function getGrooveWindowMs(hotness: number): number;
1658
+ /**
1659
+ * Get the minimum hotness required for a specific tier.
1660
+ *
1661
+ * @param tier - The groove tier
1662
+ * @returns Minimum hotness required for that tier
1663
+ */
1664
+ export declare function getMinHotnessForTier(tier: GrooveTier): number;
1665
+ /**
1666
+ * Direction of the established pocket relative to the beat
1667
+ *
1668
+ * - 'push': Playing ahead of the beat (rushing, negative offset)
1669
+ * - 'pull': Playing behind the beat (dragging, positive offset)
1670
+ * - 'neutral': Playing on the beat (within ±10ms dead zone)
1671
+ */
1672
+ export type GrooveDirection = 'push' | 'pull' | 'neutral';
1673
+ /**
1674
+ * Result returned after each hit recorded by the GrooveAnalyzer
1675
+ *
1676
+ * Provides all information needed for UI display and game feedback.
1677
+ */
1678
+ export interface GrooveResult {
1679
+ /** Direction of current pocket */
1680
+ pocketDirection: GrooveDirection;
1681
+ /** Running average offset in seconds (established pocket center) */
1682
+ establishedOffset: number;
1683
+ /** How close this hit was to the pocket (0-1, 1 = perfect consistency) */
1684
+ consistency: number;
1685
+ /** Current hotness/meter value (0+, can exceed 100 for higher tiers) */
1686
+ hotness: number;
1687
+ /** Current groove tier based on hotness (D, C, B, A, S, or SS) */
1688
+ tier: GrooveTier;
1689
+ /** Current streak length within pocket */
1690
+ streakLength: number;
1691
+ /** Whether this hit was in the pocket window */
1692
+ inPocket: boolean;
1693
+ /** Current pocket window size in seconds (changes with tier) */
1694
+ pocketWindow: number;
1695
+ /**
1696
+ * Stats from the groove that just ended (if any).
1697
+ * Present when hotness drops to 0 or direction changes (push↔pull).
1698
+ * Use this to calculate groove end bonus XP immediately.
1699
+ */
1700
+ endedGrooveStats?: {
1701
+ maxStreak: number;
1702
+ maxHotness: number;
1703
+ avgHotness: number;
1704
+ duration: number;
1705
+ totalHits: number;
1706
+ startTime: number;
1707
+ endTime: number;
1708
+ };
1709
+ }
1710
+ /**
1711
+ * Snapshot of current groove analyzer state
1712
+ *
1713
+ * Used for UI display and state inspection.
1714
+ */
1715
+ export interface GrooveState {
1716
+ /** Direction of established pocket */
1717
+ pocketDirection: GrooveDirection;
1718
+ /** Running average offset in seconds */
1719
+ establishedOffset: number;
1720
+ /** Current hotness/meter value (0+, can exceed 100 for higher tiers) */
1721
+ hotness: number;
1722
+ /** Current groove tier based on hotness (D, C, B, A, S, or SS) */
1723
+ tier: GrooveTier;
1724
+ /** Current streak length within pocket */
1725
+ streakLength: number;
1726
+ /** Total number of hits recorded */
1727
+ hitCount: number;
1728
+ /** Current pocket window size in seconds */
1729
+ pocketWindow: number;
1730
+ /** When the current groove started (audio time in seconds), null if no active groove */
1731
+ grooveStartTime: number | null;
1732
+ /** Duration of the current groove in seconds (0 if no active groove) */
1733
+ grooveDuration: number;
1734
+ /** Peak hotness reached during the current groove (0+) */
1735
+ maxHotness: number;
1736
+ /** Average hotness over the groove lifetime (0+) */
1737
+ avgHotness: number;
1738
+ /** Total hits in the current groove */
1739
+ grooveHitCount: number;
1740
+ }
1741
+ /**
1742
+ * Statistics for groove end bonus calculation.
1743
+ * Returned by GrooveAnalyzer.getGrooveStats() when a groove ends.
1744
+ */
1745
+ export interface GrooveStats {
1746
+ /** Peak streak during the groove */
1747
+ maxStreak: number;
1748
+ /** Peak hotness reached during the groove (0-100) */
1749
+ maxHotness: number;
1750
+ /** Average hotness over the groove lifetime (0-100) */
1751
+ avgHotness: number;
1752
+ /** How long the groove lasted in seconds */
1753
+ duration: number;
1754
+ /** Total hits in the groove */
1755
+ totalHits: number;
1756
+ /** When the groove started (audio time in seconds) */
1757
+ startTime: number;
1758
+ /** When the groove ended (audio time in seconds) */
1759
+ endTime: number;
1760
+ }
1761
+ /**
1762
+ * Configuration options for the GrooveAnalyzer
1763
+ */
1764
+ export interface GrooveAnalyzerOptions {
1765
+ /** Minimum hits to establish a pocket (default: 3) */
1766
+ minHitsForPocket: number;
1767
+ /** Base pocket window as fraction of beat (default: 0.03125 = 1/32 note) */
1768
+ basePocketWindowFraction: number;
1769
+ /** Minimum pocket window in seconds (floor for progressive tightening) */
1770
+ minPocketWindowSeconds: number;
1771
+ /** Hotness gain per consistent hit (default: 8) */
1772
+ hotnessGainPerHit: number;
1773
+ /** Hotness loss on pocket break (default: 80) */
1774
+ hotnessLossOnBreak: number;
1775
+ /** Hotness loss on missed beat (default: 80) */
1776
+ hotnessLossOnMiss: number;
1777
+ /** Number of recent hits to average for pocket establishment (default: 4) */
1778
+ averagingWindowSize: number;
1779
+ /** Dead zone around zero for neutral classification in seconds (default: 0.010 = ±10ms) */
1780
+ neutralDeadZone: number;
1781
+ }
1782
+ /**
1783
+ * Default configuration options for the GrooveAnalyzer
1784
+ */
1785
+ export declare const DEFAULT_GROOVE_OPTIONS: GrooveAnalyzerOptions;
1786
+ /**
1787
+ * Groove penalty configuration for difficulty presets.
1788
+ *
1789
+ * These values control how harshly the groove meter punishes mistakes.
1790
+ * Higher values = more severe penalties for misses and wrong keys.
1791
+ */
1792
+ export interface GroovePenaltyConfig {
1793
+ /** Hotness loss when missing a beat or pressing wrong key */
1794
+ hotnessLossOnMiss: number;
1795
+ /** Hotness loss when breaking the pocket (hitting outside established timing) */
1796
+ hotnessLossOnBreak: number;
1797
+ }
1798
+ /**
1799
+ * Easy groove penalties - forgiving for casual players.
1800
+ * Miss penalty: 35 (moderate)
1801
+ */
1802
+ export declare const EASY_GROOVE_PENALTIES: GroovePenaltyConfig;
1803
+ /**
1804
+ * Medium groove penalties - balanced difficulty.
1805
+ * Miss penalty: 50 (noticeable)
1806
+ */
1807
+ export declare const MEDIUM_GROOVE_PENALTIES: GroovePenaltyConfig;
1808
+ /**
1809
+ * Hard groove penalties - strict for veterans.
1810
+ * Miss penalty: 65 (severe)
1811
+ */
1812
+ export declare const HARD_GROOVE_PENALTIES: GroovePenaltyConfig;
1813
+ /**
1814
+ * Map of preset names to their groove penalty configurations.
1815
+ */
1816
+ export declare const GROOVE_PENALTY_PRESETS: Record<Exclude<DifficultyPreset, 'custom'>, GroovePenaltyConfig>;
1817
+ /**
1818
+ * Get groove penalty configuration for a difficulty preset.
1819
+ *
1820
+ * @param preset - The difficulty preset ('easy', 'medium', 'hard', or 'custom')
1821
+ * @param customPenalties - Custom penalties to use when preset is 'custom'
1822
+ * @returns The groove penalty configuration for the given preset
1823
+ */
1824
+ export declare function getGroovePenaltiesForPreset(preset: DifficultyPreset, customPenalties?: Partial<GroovePenaltyConfig>): GroovePenaltyConfig;
1825
+ //# sourceMappingURL=BeatMap.d.ts.map