You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: update musical-time spec to reflect pulse-based implementation [skip release]
- Update algorithm specification to match current pulse-based approach
- Document fromTimePoints static method with timing regularization
- Add [skip release] support to GitHub Actions workflow
- Remove theoretical calculation references that were replaced with pulse-based logic
- Clarify critical design decisions for Issue #40 resolution
This is a documentation update that aligns the specification with the
implemented pulse-based approach without changing functionality.
@@ -12,6 +12,16 @@ This specification defines the interface and behavior for converting real time (
12
12
4. Provide human-readable musical time representations
13
13
5. Maintain identical behavior across Python and TypeScript implementations
14
14
15
+
## Pulse-Based Approach
16
+
17
+
**Critical Design Decision**: This implementation uses a **fully pulse-based approach** rather than theoretical timing calculations. This ensures accurate results when pulse data contains timing variations (rubato):
18
+
19
+
-**Cycle boundaries**: Determined by actual pulse positions, not `cycleDur` calculations
20
+
-**Hierarchical positions**: Derived from actual pulse found, not theoretical subdivision timing
21
+
-**Fractional beat**: Uses actual pulse-to-pulse durations, not theoretical `pulseDur`
22
+
23
+
This approach correctly handles Issue #40 where theoretical calculations returned incorrect cycle numbers at boundaries with rubato timing.
24
+
15
25
## Core Data Structures
16
26
17
27
### MusicalTime
@@ -40,6 +50,34 @@ Readable: "Cycle 1: Beat 3, Subdivision 2 + 0.500 to next pulse"
40
50
41
51
## Core Interface
42
52
53
+
### Meter.fromTimePoints() [Static Method]
54
+
55
+
**Signature:**
56
+
```
57
+
fromTimePoints(timePoints: number[], hierarchy: number[], repetitions?: number, layer?: number): Meter
58
+
```
59
+
60
+
**Purpose:** Create a Meter from actual pulse time points, handling timing variations (rubato).
61
+
62
+
**Parameters:**
63
+
-`timePoints: number[]` - List of actual pulse times in seconds
64
+
-`hierarchy: number[]` - Meter hierarchy (e.g., [4, 4, 2])
65
+
-`repetitions: number` (optional) - Number of cycle repetitions (default: 1)
66
+
-`layer: number` (optional) - Which hierarchical layer the time points represent (default: 0)
67
+
68
+
**Features:**
69
+
-**Timing Regularization**: Automatically handles extreme rubato deviations (>40% of pulse duration) by inserting intermediate time points
70
+
-**Pulse Duration Calculation**: Derives tempo from actual timing data
71
+
-**Extrapolation**: Extends pulse data when fewer time points provided than needed
72
+
73
+
**Algorithm:**
74
+
1. Sort and validate time points
75
+
2. Calculate average pulse duration
76
+
3. Apply timing regularization (insert intermediate points for >40% deviations)
0 commit comments