Initial Commit
This commit is contained in:
131
packages/media/audio/audio-controllers/tests/fake-transport.ts
Normal file
131
packages/media/audio/audio-controllers/tests/fake-transport.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Real `TransportLike` implementation backed by an in-memory event log.
|
||||
* Used in tests so step/arpeggio callbacks can be driven deterministically
|
||||
* without spinning a real wall-clock scheduler. This is a real object that
|
||||
* satisfies the `TransportLike` contract — not a runner mock.
|
||||
*/
|
||||
|
||||
import type {
|
||||
BarsBeatsSixteenths,
|
||||
SignalLike,
|
||||
TransportCallback,
|
||||
TransportLike,
|
||||
TransportTime,
|
||||
} from "@suaveplan/audio-transport";
|
||||
|
||||
interface ScheduledRepeat {
|
||||
readonly id: number;
|
||||
readonly callback: TransportCallback;
|
||||
readonly interval: TransportTime;
|
||||
}
|
||||
|
||||
interface ScheduledOnce {
|
||||
readonly id: number;
|
||||
readonly callback: TransportCallback;
|
||||
readonly time: number;
|
||||
}
|
||||
|
||||
const NOOP_BBS: BarsBeatsSixteenths = "0:0:0";
|
||||
|
||||
function makeFakeSignal(): SignalLike {
|
||||
let v = 120;
|
||||
const points: { time: number; value: number; type: "set" }[] = [];
|
||||
const sig: SignalLike = {
|
||||
get points() {
|
||||
return points.slice();
|
||||
},
|
||||
get initialValue() {
|
||||
return 120;
|
||||
},
|
||||
get value() {
|
||||
return v;
|
||||
},
|
||||
setValueAtTime(value: number, time: number) {
|
||||
v = value;
|
||||
points.push({ time, value, type: "set" });
|
||||
},
|
||||
linearRampToValueAtTime(value: number) {
|
||||
v = value;
|
||||
},
|
||||
exponentialRampToValueAtTime(value: number) {
|
||||
v = value;
|
||||
},
|
||||
getValueAtTime() {
|
||||
return v;
|
||||
},
|
||||
cancelScheduledValues() {
|
||||
points.length = 0;
|
||||
},
|
||||
};
|
||||
return sig;
|
||||
}
|
||||
|
||||
export class FakeTransport implements TransportLike {
|
||||
public bpm: SignalLike = makeFakeSignal();
|
||||
public readonly ppq = 192;
|
||||
public readonly timeSignature = 4;
|
||||
public swing = 0;
|
||||
public swingSubdivision: TransportTime = "8n";
|
||||
public loop = false;
|
||||
public loopStart: TransportTime = 0;
|
||||
public loopEnd: TransportTime = 0;
|
||||
public state: "stopped" | "playing" | "paused" = "stopped";
|
||||
public position: BarsBeatsSixteenths = NOOP_BBS;
|
||||
public ticks = 0;
|
||||
public seconds = 0;
|
||||
|
||||
public readonly repeats = new Map<number, ScheduledRepeat>();
|
||||
public readonly onces = new Map<number, ScheduledOnce>();
|
||||
private nextId = 1;
|
||||
|
||||
start(): void {
|
||||
this.state = "playing";
|
||||
}
|
||||
stop(): void {
|
||||
this.state = "stopped";
|
||||
}
|
||||
pause(): void {
|
||||
this.state = "paused";
|
||||
}
|
||||
schedule(callback: TransportCallback, time: TransportTime): number {
|
||||
return this.scheduleOnce(callback, time);
|
||||
}
|
||||
scheduleOnce(callback: TransportCallback, time: TransportTime): number {
|
||||
const id = this.nextId++;
|
||||
const num = typeof time === "number" ? time : 0;
|
||||
this.onces.set(id, { id, callback, time: num });
|
||||
return id;
|
||||
}
|
||||
scheduleRepeat(
|
||||
callback: TransportCallback,
|
||||
interval: TransportTime
|
||||
): number {
|
||||
const id = this.nextId++;
|
||||
this.repeats.set(id, { id, callback, interval });
|
||||
return id;
|
||||
}
|
||||
cancel(eventId: number): void {
|
||||
this.repeats.delete(eventId);
|
||||
this.onces.delete(eventId);
|
||||
}
|
||||
cancelAfter(_time: TransportTime): void {
|
||||
// Not used by audio-controllers tests.
|
||||
}
|
||||
toSeconds(time: TransportTime): number {
|
||||
return typeof time === "number" ? time / this.ppq : 0;
|
||||
}
|
||||
toTicks(time: TransportTime): number {
|
||||
return typeof time === "number" ? time * this.ppq : 0;
|
||||
}
|
||||
|
||||
/** Test helper: drive every active repeat once. */
|
||||
tickAll(time = 0): void {
|
||||
for (const r of this.repeats.values()) r.callback(time);
|
||||
}
|
||||
|
||||
/** Test helper: fire every scheduled `scheduleOnce`. */
|
||||
flushOnces(): void {
|
||||
for (const o of this.onces.values()) o.callback(o.time);
|
||||
this.onces.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user