@dawcore/transport 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -66,7 +66,8 @@ editor.adapterFactory = () => new NativePlayoutAdapter(audioContext);
66
66
  ```typescript
67
67
  const transport = new Transport(audioContext, {
68
68
  tempo: 120,
69
- beatsPerBar: 4,
69
+ numerator: 4,
70
+ denominator: 4,
70
71
  });
71
72
 
72
73
  transport.setMetronomeEnabled(true);
@@ -74,6 +75,22 @@ transport.setMetronomeClickSounds(accentBuffer, normalBuffer);
74
75
  transport.play();
75
76
  ```
76
77
 
78
+ ### Mixed Meter
79
+
80
+ ```typescript
81
+ const transport = new Transport(audioContext, { tempo: 120, numerator: 4, denominator: 4 });
82
+
83
+ // Switch to 7/8 at bar 5
84
+ transport.setMeter(7, 8, transport.barToTick(5));
85
+
86
+ // Query active meter at any tick
87
+ const { numerator, denominator } = transport.getMeter(transport.barToTick(5));
88
+ // → { numerator: 7, denominator: 8 }
89
+
90
+ transport.setMetronomeEnabled(true);
91
+ transport.play();
92
+ ```
93
+
77
94
  ### Effects
78
95
 
79
96
  ```typescript
@@ -102,7 +119,8 @@ new Transport(audioContext: AudioContext, options?: TransportOptions)
102
119
  | `sampleRate` | `audioContext.sampleRate` | Sample rate for timeline conversions |
103
120
  | `ppqn` | `960` | Ticks per quarter note |
104
121
  | `tempo` | `120` | Initial tempo in BPM |
105
- | `beatsPerBar` | `4` | Beats per bar |
122
+ | `numerator` | `4` | Beats per bar (time signature numerator) |
123
+ | `denominator` | `4` | Beat unit (time signature denominator) |
106
124
  | `schedulerLookahead` | `0.2` | How far ahead to schedule (seconds) |
107
125
 
108
126
  **Playback:**
@@ -129,9 +147,14 @@ new Transport(audioContext: AudioContext, options?: TransportOptions)
129
147
  **Loop:**
130
148
  - `setLoop(enabled, start, end)` — Set loop region in seconds
131
149
 
132
- **Tempo & Metronome:**
133
- - `setTempo(bpm)` / `getTempo()`
134
- - `setBeatsPerBar(beats)`
150
+ **Tempo & Meter:**
151
+ - `setTempo(bpm, atTick?)` / `getTempo(atTick?)`
152
+ - `clearTempos()` — remove all tempo entries
153
+ - `setMeter(numerator, denominator, atTick?)` / `getMeter(atTick?)`
154
+ - `removeMeter(atTick)` / `clearMeters()`
155
+ - `barToTick(bar)` / `tickToBar(tick)`
156
+
157
+ **Metronome:**
135
158
  - `setMetronomeEnabled(enabled)`
136
159
  - `setMetronomeClickSounds(accent, normal)`
137
160
 
package/dist/index.d.mts CHANGED
@@ -22,11 +22,29 @@ interface TransportOptions {
22
22
  ppqn?: number;
23
23
  /** Initial tempo in BPM. Default: 120 */
24
24
  tempo?: number;
25
- /** Beats per bar. Default: 4 */
26
- beatsPerBar?: number;
25
+ /** Time signature numerator. Default: 4 */
26
+ numerator?: number;
27
+ /** Time signature denominator. Default: 4 */
28
+ denominator?: number;
27
29
  /** How far ahead to schedule audio, in seconds. Default: 0.2 */
28
30
  schedulerLookahead?: number;
29
31
  }
32
+ /** Public return type for getMeter() */
33
+ interface MeterSignature {
34
+ numerator: number;
35
+ denominator: number;
36
+ }
37
+ /** Storage entry for MeterMap */
38
+ interface MeterEntry {
39
+ /** Tick position where this meter starts */
40
+ tick: number;
41
+ /** Time signature numerator (e.g., 6 in 6/8) */
42
+ numerator: number;
43
+ /** Time signature denominator (e.g., 8 in 6/8) */
44
+ denominator: number;
45
+ /** Cached cumulative bar count from tick 0 to this entry. Derived — do not set manually. */
46
+ readonly barAtTick: number;
47
+ }
30
48
  interface TempoEntry {
31
49
  /** Tick position where this tempo starts */
32
50
  tick: number;
@@ -103,16 +121,6 @@ declare class SampleTimeline {
103
121
  secondsToSamples(seconds: number): number;
104
122
  }
105
123
 
106
- declare class TickTimeline {
107
- private _ppqn;
108
- constructor(ppqn?: number);
109
- get ppqn(): number;
110
- ticksPerBeat(): number;
111
- ticksPerBar(beatsPerBar: number): number;
112
- toPosition(ticks: number, beatsPerBar: number): TransportPosition;
113
- fromPosition(bar: number, beat: number, tick: number, beatsPerBar: number): number;
114
- }
115
-
116
124
  declare class TempoMap {
117
125
  private _ppqn;
118
126
  private _entries;
@@ -123,11 +131,41 @@ declare class TempoMap {
123
131
  secondsToTicks(seconds: number): number;
124
132
  beatsToSeconds(beats: number): number;
125
133
  secondsToBeats(seconds: number): number;
134
+ clearTempos(): void;
126
135
  private _ticksToSecondsInternal;
127
136
  private _entryAt;
128
137
  private _recomputeCache;
129
138
  }
130
139
 
140
+ declare class MeterMap {
141
+ private _ppqn;
142
+ private _entries;
143
+ constructor(ppqn: number, numerator?: number, denominator?: number);
144
+ get ppqn(): number;
145
+ getMeter(atTick?: number): MeterSignature;
146
+ setMeter(numerator: number, denominator: number, atTick?: number): void;
147
+ removeMeter(atTick: number): void;
148
+ clearMeters(): void;
149
+ ticksPerBeat(atTick?: number): number;
150
+ ticksPerBar(atTick?: number): number;
151
+ barToTick(bar: number): number;
152
+ tickToBar(tick: number): number;
153
+ isBarBoundary(tick: number): boolean;
154
+ /** Internal: get the full entry at a tick (for MetronomePlayer beat grid anchoring) */
155
+ getEntryAt(tick: number): MeterEntry;
156
+ private _entryAt;
157
+ private _ticksPerBarForEntry;
158
+ private _snapToBarBoundary;
159
+ private _computeBarAtTick;
160
+ private _recomputeCache;
161
+ /**
162
+ * After changing a meter entry, re-snap downstream entries to bar boundaries
163
+ * of their preceding meter so barAtTick stays integer.
164
+ */
165
+ private _resnapDownstreamEntries;
166
+ private _validateMeter;
167
+ }
168
+
131
169
  declare class MasterNode {
132
170
  private _gainNode;
133
171
  constructor(audioContext: AudioContext);
@@ -199,17 +237,15 @@ interface MetronomeEvent extends SchedulerEvent {
199
237
  declare class MetronomePlayer implements SchedulerListener<MetronomeEvent> {
200
238
  private _audioContext;
201
239
  private _tempoMap;
202
- private _tickTimeline;
240
+ private _meterMap;
203
241
  private _destination;
204
242
  private _toAudioTime;
205
243
  private _enabled;
206
- private _beatsPerBar;
207
244
  private _accentBuffer;
208
245
  private _normalBuffer;
209
246
  private _activeSources;
210
- constructor(audioContext: AudioContext, tempoMap: TempoMap, tickTimeline: TickTimeline, destination: AudioNode, toAudioTime: (transportTime: number) => number);
247
+ constructor(audioContext: AudioContext, tempoMap: TempoMap, meterMap: MeterMap, destination: AudioNode, toAudioTime: (transportTime: number) => number);
211
248
  setEnabled(enabled: boolean): void;
212
- setBeatsPerBar(beats: number): void;
213
249
  setClickSounds(accent: AudioBuffer, normal: AudioBuffer): void;
214
250
  generate(fromTime: number, toTime: number): MetronomeEvent[];
215
251
  consume(event: MetronomeEvent): void;
@@ -223,6 +259,7 @@ interface TransportEvents {
223
259
  stop: () => void;
224
260
  loop: () => void;
225
261
  tempochange: () => void;
262
+ meterchange: () => void;
226
263
  }
227
264
  type TransportEventType = keyof TransportEvents;
228
265
  declare class Transport {
@@ -231,7 +268,7 @@ declare class Transport {
231
268
  private _scheduler;
232
269
  private _timer;
233
270
  private _sampleTimeline;
234
- private _tickTimeline;
271
+ private _meterMap;
235
272
  private _tempoMap;
236
273
  private _clipPlayer;
237
274
  private _metronomePlayer;
@@ -261,9 +298,19 @@ declare class Transport {
261
298
  setTrackSolo(trackId: string, soloed: boolean): void;
262
299
  setMasterVolume(volume: number): void;
263
300
  setLoop(enabled: boolean, start: number, end: number): void;
264
- setTempo(bpm: number): void;
265
- getTempo(): number;
266
- setBeatsPerBar(beats: number): void;
301
+ setTempo(bpm: number, atTick?: number): void;
302
+ getTempo(atTick?: number): number;
303
+ setMeter(numerator: number, denominator: number, atTick?: number): void;
304
+ getMeter(atTick?: number): MeterSignature;
305
+ removeMeter(atTick: number): void;
306
+ clearMeters(): void;
307
+ clearTempos(): void;
308
+ barToTick(bar: number): number;
309
+ tickToBar(tick: number): number;
310
+ /** Convert transport time (seconds) to tick position, using the tempo map. */
311
+ timeToTick(seconds: number): number;
312
+ /** Convert tick position to transport time (seconds), using the tempo map. */
313
+ tickToTime(tick: number): number;
267
314
  setMetronomeEnabled(enabled: boolean): void;
268
315
  setMetronomeClickSounds(accent: AudioBuffer, normal: AudioBuffer): void;
269
316
  connectTrackOutput(trackId: string, node: AudioNode): void;
@@ -303,4 +350,4 @@ declare class NativePlayoutAdapter implements PlayoutAdapter {
303
350
  dispose(): void;
304
351
  }
305
352
 
306
- export { type ClipEvent, ClipPlayer, Clock, MasterNode, type MetronomeEvent, MetronomePlayer, NativePlayoutAdapter, SampleTimeline, Scheduler, type SchedulerEvent, type SchedulerListener, type SchedulerOptions, type TempoEntry, TempoMap, TickTimeline, Timer, TrackNode, Transport, type TransportEvents, type TransportOptions, type TransportPosition };
353
+ export { type ClipEvent, ClipPlayer, Clock, MasterNode, type MeterEntry, MeterMap, type MeterSignature, type MetronomeEvent, MetronomePlayer, NativePlayoutAdapter, SampleTimeline, Scheduler, type SchedulerEvent, type SchedulerListener, type SchedulerOptions, type TempoEntry, TempoMap, Timer, TrackNode, Transport, type TransportEvents, type TransportOptions, type TransportPosition };
package/dist/index.d.ts CHANGED
@@ -22,11 +22,29 @@ interface TransportOptions {
22
22
  ppqn?: number;
23
23
  /** Initial tempo in BPM. Default: 120 */
24
24
  tempo?: number;
25
- /** Beats per bar. Default: 4 */
26
- beatsPerBar?: number;
25
+ /** Time signature numerator. Default: 4 */
26
+ numerator?: number;
27
+ /** Time signature denominator. Default: 4 */
28
+ denominator?: number;
27
29
  /** How far ahead to schedule audio, in seconds. Default: 0.2 */
28
30
  schedulerLookahead?: number;
29
31
  }
32
+ /** Public return type for getMeter() */
33
+ interface MeterSignature {
34
+ numerator: number;
35
+ denominator: number;
36
+ }
37
+ /** Storage entry for MeterMap */
38
+ interface MeterEntry {
39
+ /** Tick position where this meter starts */
40
+ tick: number;
41
+ /** Time signature numerator (e.g., 6 in 6/8) */
42
+ numerator: number;
43
+ /** Time signature denominator (e.g., 8 in 6/8) */
44
+ denominator: number;
45
+ /** Cached cumulative bar count from tick 0 to this entry. Derived — do not set manually. */
46
+ readonly barAtTick: number;
47
+ }
30
48
  interface TempoEntry {
31
49
  /** Tick position where this tempo starts */
32
50
  tick: number;
@@ -103,16 +121,6 @@ declare class SampleTimeline {
103
121
  secondsToSamples(seconds: number): number;
104
122
  }
105
123
 
106
- declare class TickTimeline {
107
- private _ppqn;
108
- constructor(ppqn?: number);
109
- get ppqn(): number;
110
- ticksPerBeat(): number;
111
- ticksPerBar(beatsPerBar: number): number;
112
- toPosition(ticks: number, beatsPerBar: number): TransportPosition;
113
- fromPosition(bar: number, beat: number, tick: number, beatsPerBar: number): number;
114
- }
115
-
116
124
  declare class TempoMap {
117
125
  private _ppqn;
118
126
  private _entries;
@@ -123,11 +131,41 @@ declare class TempoMap {
123
131
  secondsToTicks(seconds: number): number;
124
132
  beatsToSeconds(beats: number): number;
125
133
  secondsToBeats(seconds: number): number;
134
+ clearTempos(): void;
126
135
  private _ticksToSecondsInternal;
127
136
  private _entryAt;
128
137
  private _recomputeCache;
129
138
  }
130
139
 
140
+ declare class MeterMap {
141
+ private _ppqn;
142
+ private _entries;
143
+ constructor(ppqn: number, numerator?: number, denominator?: number);
144
+ get ppqn(): number;
145
+ getMeter(atTick?: number): MeterSignature;
146
+ setMeter(numerator: number, denominator: number, atTick?: number): void;
147
+ removeMeter(atTick: number): void;
148
+ clearMeters(): void;
149
+ ticksPerBeat(atTick?: number): number;
150
+ ticksPerBar(atTick?: number): number;
151
+ barToTick(bar: number): number;
152
+ tickToBar(tick: number): number;
153
+ isBarBoundary(tick: number): boolean;
154
+ /** Internal: get the full entry at a tick (for MetronomePlayer beat grid anchoring) */
155
+ getEntryAt(tick: number): MeterEntry;
156
+ private _entryAt;
157
+ private _ticksPerBarForEntry;
158
+ private _snapToBarBoundary;
159
+ private _computeBarAtTick;
160
+ private _recomputeCache;
161
+ /**
162
+ * After changing a meter entry, re-snap downstream entries to bar boundaries
163
+ * of their preceding meter so barAtTick stays integer.
164
+ */
165
+ private _resnapDownstreamEntries;
166
+ private _validateMeter;
167
+ }
168
+
131
169
  declare class MasterNode {
132
170
  private _gainNode;
133
171
  constructor(audioContext: AudioContext);
@@ -199,17 +237,15 @@ interface MetronomeEvent extends SchedulerEvent {
199
237
  declare class MetronomePlayer implements SchedulerListener<MetronomeEvent> {
200
238
  private _audioContext;
201
239
  private _tempoMap;
202
- private _tickTimeline;
240
+ private _meterMap;
203
241
  private _destination;
204
242
  private _toAudioTime;
205
243
  private _enabled;
206
- private _beatsPerBar;
207
244
  private _accentBuffer;
208
245
  private _normalBuffer;
209
246
  private _activeSources;
210
- constructor(audioContext: AudioContext, tempoMap: TempoMap, tickTimeline: TickTimeline, destination: AudioNode, toAudioTime: (transportTime: number) => number);
247
+ constructor(audioContext: AudioContext, tempoMap: TempoMap, meterMap: MeterMap, destination: AudioNode, toAudioTime: (transportTime: number) => number);
211
248
  setEnabled(enabled: boolean): void;
212
- setBeatsPerBar(beats: number): void;
213
249
  setClickSounds(accent: AudioBuffer, normal: AudioBuffer): void;
214
250
  generate(fromTime: number, toTime: number): MetronomeEvent[];
215
251
  consume(event: MetronomeEvent): void;
@@ -223,6 +259,7 @@ interface TransportEvents {
223
259
  stop: () => void;
224
260
  loop: () => void;
225
261
  tempochange: () => void;
262
+ meterchange: () => void;
226
263
  }
227
264
  type TransportEventType = keyof TransportEvents;
228
265
  declare class Transport {
@@ -231,7 +268,7 @@ declare class Transport {
231
268
  private _scheduler;
232
269
  private _timer;
233
270
  private _sampleTimeline;
234
- private _tickTimeline;
271
+ private _meterMap;
235
272
  private _tempoMap;
236
273
  private _clipPlayer;
237
274
  private _metronomePlayer;
@@ -261,9 +298,19 @@ declare class Transport {
261
298
  setTrackSolo(trackId: string, soloed: boolean): void;
262
299
  setMasterVolume(volume: number): void;
263
300
  setLoop(enabled: boolean, start: number, end: number): void;
264
- setTempo(bpm: number): void;
265
- getTempo(): number;
266
- setBeatsPerBar(beats: number): void;
301
+ setTempo(bpm: number, atTick?: number): void;
302
+ getTempo(atTick?: number): number;
303
+ setMeter(numerator: number, denominator: number, atTick?: number): void;
304
+ getMeter(atTick?: number): MeterSignature;
305
+ removeMeter(atTick: number): void;
306
+ clearMeters(): void;
307
+ clearTempos(): void;
308
+ barToTick(bar: number): number;
309
+ tickToBar(tick: number): number;
310
+ /** Convert transport time (seconds) to tick position, using the tempo map. */
311
+ timeToTick(seconds: number): number;
312
+ /** Convert tick position to transport time (seconds), using the tempo map. */
313
+ tickToTime(tick: number): number;
267
314
  setMetronomeEnabled(enabled: boolean): void;
268
315
  setMetronomeClickSounds(accent: AudioBuffer, normal: AudioBuffer): void;
269
316
  connectTrackOutput(trackId: string, node: AudioNode): void;
@@ -303,4 +350,4 @@ declare class NativePlayoutAdapter implements PlayoutAdapter {
303
350
  dispose(): void;
304
351
  }
305
352
 
306
- export { type ClipEvent, ClipPlayer, Clock, MasterNode, type MetronomeEvent, MetronomePlayer, NativePlayoutAdapter, SampleTimeline, Scheduler, type SchedulerEvent, type SchedulerListener, type SchedulerOptions, type TempoEntry, TempoMap, TickTimeline, Timer, TrackNode, Transport, type TransportEvents, type TransportOptions, type TransportPosition };
353
+ export { type ClipEvent, ClipPlayer, Clock, MasterNode, type MeterEntry, MeterMap, type MeterSignature, type MetronomeEvent, MetronomePlayer, NativePlayoutAdapter, SampleTimeline, Scheduler, type SchedulerEvent, type SchedulerListener, type SchedulerOptions, type TempoEntry, TempoMap, Timer, TrackNode, Transport, type TransportEvents, type TransportOptions, type TransportPosition };