@joshtol/emotive-engine 3.3.5 → 3.3.7

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@joshtol/emotive-engine",
4
- "version": "3.3.5",
4
+ "version": "3.3.7",
5
5
  "description": "Open-source animation engine for AI-controlled emotional visualizations with musical time synchronization",
6
6
  "main": "dist/emotive-mascot.umd.js",
7
7
  "module": "dist/mascot.js",
@@ -142,6 +142,12 @@ export class Rhythm3DAdapter {
142
142
  // Ranges from 0.15 (tentative) to 1.0 (fully locked), provided by BPM detector
143
143
  this.grooveConfidence = 1.0; // Default to full when not using BPM detection
144
144
 
145
+ // BPM multiplier: scales the effective BPM used for animations
146
+ // Default 1.0 = use detected BPM as-is
147
+ // Set to 0.5 to halve animation speed (e.g., for high BPM songs)
148
+ // Set to 2.0 to double animation speed (e.g., for slow songs)
149
+ this.bpmMultiplier = 1.0;
150
+
145
151
  // Modulation output (computed each frame) - these are the SMOOTHED values
146
152
  this.modulation = {
147
153
  scaleMultiplier: 1.0, // Applied to gesture scale output
@@ -532,20 +538,27 @@ export class Rhythm3DAdapter {
532
538
  // Compute groove motions from ABSOLUTE beat/bar progress
533
539
  // This is frame-rate independent because beatProgress/barProgress come from
534
540
  // RhythmEngine which uses performance.now(), not accumulated frame deltas
541
+ //
542
+ // BPM multiplier scales animation FREQUENCY (not progress value):
543
+ // - multiplier 0.5 = animations take 2 beats to complete one cycle (half speed)
544
+ // - multiplier 2.0 = animations complete 2 cycles per beat (double speed)
545
+ // Applied directly to the phase calculation, not the progress value
535
546
 
536
547
  // Vertical bounce: synced to beat with configurable frequency
537
- const bouncePhase = (this.beatProgress * bounceFreq * Math.PI * 2) + phaseOffset;
548
+ // bpmMultiplier scales the frequency so 0.5 = half as many bounces per beat
549
+ const bouncePhase = (this.beatProgress * bounceFreq * this.bpmMultiplier * Math.PI * 2) + phaseOffset;
538
550
  const rawBounce = Math.sin(bouncePhase);
539
551
  const easedBounce = this._applyEasing(rawBounce, easing);
540
552
 
541
553
  // Horizontal sway: synced to bar with configurable frequency
542
- const swayPhase = (this.barProgress * swayFreq * Math.PI * 2) + phaseOffset;
554
+ const swayPhase = (this.barProgress * swayFreq * this.bpmMultiplier * Math.PI * 2) + phaseOffset;
543
555
  const rawSway = Math.sin(swayPhase);
544
556
  const easedSway = this._applyEasing(rawSway, easing);
545
557
 
546
558
  // Accent response: smooth curve that peaks at beat start, scaled by accent level
547
559
  // Uses cosine curve centered on beat boundaries (0 and 1) for smooth falloff
548
560
  // beatProgress 0.0 → peak, 0.5 → minimum, 1.0 → peak again
561
+ // Note: accent response uses raw beatProgress (not multiplied) to still sync with actual beats
549
562
  const beatProximity = (Math.cos(this.beatProgress * Math.PI * 2) + 1) * 0.5; // 0-1, peaks at beat
550
563
  const accentStrength = Math.max(0, this.accent - 0.4) / 0.6; // 0-1, normalized above 0.4 threshold
551
564
  const accentBoost = beatProximity * accentStrength * 0.25; // Smooth accent curve
@@ -774,6 +787,35 @@ export class Rhythm3DAdapter {
774
787
  this.grooveConfidence = Math.max(0, Math.min(1, confidence));
775
788
  }
776
789
 
790
+ /**
791
+ * Set BPM multiplier for animation speed control
792
+ *
793
+ * This scales the effective BPM used for groove animations without affecting
794
+ * the actual BPM detection or rhythm engine. Useful for:
795
+ * - Halving animation speed for high BPM songs (set to 0.5)
796
+ * - Doubling animation speed for slow songs (set to 2.0)
797
+ *
798
+ * @example
799
+ * // Halve animation speed for songs > 90 BPM
800
+ * const status = mascot.getBPMStatus();
801
+ * if (status.bpm > 90) {
802
+ * mascot.setBPMMultiplier(0.5);
803
+ * }
804
+ *
805
+ * @param {number} multiplier - BPM multiplier (0.25 to 4.0, default 1.0)
806
+ */
807
+ setBPMMultiplier(multiplier) {
808
+ this.bpmMultiplier = Math.max(0.25, Math.min(4.0, multiplier));
809
+ }
810
+
811
+ /**
812
+ * Get current BPM multiplier
813
+ * @returns {number} Current BPM multiplier (default 1.0)
814
+ */
815
+ getBPMMultiplier() {
816
+ return this.bpmMultiplier;
817
+ }
818
+
777
819
  /**
778
820
  * Set groove configuration (for custom tuning)
779
821
  * @param {Object} config - Groove settings
package/src/3d/index.js CHANGED
@@ -1245,6 +1245,43 @@ export class EmotiveMascot3D {
1245
1245
  return this.core3D?.rhythm3DAdapter?.grooveConfidence ?? 1.0;
1246
1246
  }
1247
1247
 
1248
+ /**
1249
+ * Set BPM multiplier for groove animation speed control
1250
+ *
1251
+ * This scales the effective BPM used for groove animations without affecting
1252
+ * the actual BPM detection or rhythm engine. Useful for controlling how fast
1253
+ * the mascot dances regardless of the detected song tempo.
1254
+ *
1255
+ * Common use cases:
1256
+ * - Set to 0.5 to halve animation speed for high BPM songs (>90 BPM)
1257
+ * - Set to 2.0 to double animation speed for very slow songs
1258
+ * - Set to 1.0 (default) to use detected BPM as-is
1259
+ *
1260
+ * @example
1261
+ * // Halve animation speed for fast songs
1262
+ * const status = mascot.getBPMStatus();
1263
+ * if (status.bpm > 90) {
1264
+ * mascot.setBPMMultiplier(0.5);
1265
+ * } else {
1266
+ * mascot.setBPMMultiplier(1.0);
1267
+ * }
1268
+ *
1269
+ * @param {number} multiplier - BPM multiplier (0.25 to 4.0, default 1.0)
1270
+ */
1271
+ setBPMMultiplier(multiplier) {
1272
+ if (this.core3D?.rhythm3DAdapter) {
1273
+ this.core3D.rhythm3DAdapter.setBPMMultiplier(multiplier);
1274
+ }
1275
+ }
1276
+
1277
+ /**
1278
+ * Get current BPM multiplier
1279
+ * @returns {number} Current BPM multiplier (default 1.0)
1280
+ */
1281
+ getBPMMultiplier() {
1282
+ return this.core3D?.rhythm3DAdapter?.getBPMMultiplier() ?? 1.0;
1283
+ }
1284
+
1248
1285
  /**
1249
1286
  * Set groove configuration for idle animations (advanced tuning)
1250
1287
  * @param {Object} config - Groove settings