@joshtol/emotive-engine 3.3.5 → 3.3.6

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.6",
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,21 +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
+ // Apply BPM multiplier to scale animation speed:
543
+ // - multiplier 0.5 = animations run at half speed (for high BPM songs)
544
+ // - multiplier 2.0 = animations run at double speed (for slow songs)
545
+ const effectiveBeatProgress = (this.beatProgress * this.bpmMultiplier) % 1;
546
+ const effectiveBarProgress = (this.barProgress * this.bpmMultiplier) % 1;
535
547
 
536
548
  // Vertical bounce: synced to beat with configurable frequency
537
- const bouncePhase = (this.beatProgress * bounceFreq * Math.PI * 2) + phaseOffset;
549
+ const bouncePhase = (effectiveBeatProgress * bounceFreq * 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 = (effectiveBarProgress * swayFreq * 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
549
- const beatProximity = (Math.cos(this.beatProgress * Math.PI * 2) + 1) * 0.5; // 0-1, peaks at beat
561
+ const beatProximity = (Math.cos(effectiveBeatProgress * Math.PI * 2) + 1) * 0.5; // 0-1, peaks at beat
550
562
  const accentStrength = Math.max(0, this.accent - 0.4) / 0.6; // 0-1, normalized above 0.4 threshold
551
563
  const accentBoost = beatProximity * accentStrength * 0.25; // Smooth accent curve
552
564
 
@@ -774,6 +786,35 @@ export class Rhythm3DAdapter {
774
786
  this.grooveConfidence = Math.max(0, Math.min(1, confidence));
775
787
  }
776
788
 
789
+ /**
790
+ * Set BPM multiplier for animation speed control
791
+ *
792
+ * This scales the effective BPM used for groove animations without affecting
793
+ * the actual BPM detection or rhythm engine. Useful for:
794
+ * - Halving animation speed for high BPM songs (set to 0.5)
795
+ * - Doubling animation speed for slow songs (set to 2.0)
796
+ *
797
+ * @example
798
+ * // Halve animation speed for songs > 90 BPM
799
+ * const status = mascot.getBPMStatus();
800
+ * if (status.bpm > 90) {
801
+ * mascot.setBPMMultiplier(0.5);
802
+ * }
803
+ *
804
+ * @param {number} multiplier - BPM multiplier (0.25 to 4.0, default 1.0)
805
+ */
806
+ setBPMMultiplier(multiplier) {
807
+ this.bpmMultiplier = Math.max(0.25, Math.min(4.0, multiplier));
808
+ }
809
+
810
+ /**
811
+ * Get current BPM multiplier
812
+ * @returns {number} Current BPM multiplier (default 1.0)
813
+ */
814
+ getBPMMultiplier() {
815
+ return this.bpmMultiplier;
816
+ }
817
+
777
818
  /**
778
819
  * Set groove configuration (for custom tuning)
779
820
  * @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