-
Notifications
You must be signed in to change notification settings - Fork 11
/
TimeValueRange.ts
93 lines (74 loc) · 2.67 KB
/
TimeValueRange.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { GUISettings } from '../../types/GUISettings';
export interface TimeRange {
t0: number;
t1: number;
}
export interface ValueRange {
v0: number;
v1: number;
}
export interface TimeValueRange extends TimeRange {}
export interface TimeValueRange extends ValueRange {}
export function x2t( x: number, range: TimeRange, width: number ): number {
return ( x / width ) * ( range.t1 - range.t0 ) + range.t0;
}
export function t2x( t: number, range: TimeRange, width: number ): number {
return ( ( t - range.t0 ) / ( range.t1 - range.t0 ) ) * width;
}
export function y2v( y: number, range: ValueRange, height: number ): number {
return ( 1.0 - y / height ) * ( range.v1 - range.v0 ) + range.v0;
}
export function v2y( v: number, range: ValueRange, height: number ): number {
return ( 1.0 - ( v - range.v0 ) / ( range.v1 - range.v0 ) ) * height;
}
export function dx2dt( x: number, range: TimeRange, width: number ): number {
return ( x / width ) * ( range.t1 - range.t0 );
}
export function dt2dx( t: number, range: TimeRange, width: number ): number {
return t / ( range.t1 - range.t0 ) * width;
}
export function dy2dv( y: number, range: ValueRange, height: number ): number {
return -y / height * ( range.v1 - range.v0 );
}
export function dv2dy( v: number, range: ValueRange, height: number ): number {
return -v / ( range.v1 - range.v0 ) * height;
}
export function snapTime(
time: number,
range: TimeRange,
width: number,
settings: GUISettings
): number {
const { snapTimeActive, snapBeatActive, snapTimeInterval, bpm, beatOffset } = settings;
let result = time;
if ( snapTimeActive ) {
const interval = snapTimeInterval;
const threshold = dx2dt( 5.0, range, width );
const nearest = Math.round( time / interval ) * interval;
result = Math.abs( time - nearest ) < threshold ? nearest : result;
}
if ( snapBeatActive ) {
let interval = 60.0 / bpm;
const order = Math.floor( Math.log( ( range.t1 - range.t0 ) / interval ) / Math.log( 4.0 ) );
interval *= Math.pow( 4.0, order - 2.0 );
const threshold = dx2dt( 5.0, range, width );
const nearest = Math.round( ( time - beatOffset ) / interval ) * interval + beatOffset;
result = Math.abs( time - nearest ) < threshold ? nearest : result;
}
return result;
}
export function snapValue(
value: number,
range: ValueRange,
height: number,
settings: GUISettings | null
): number {
let v = value;
if ( settings?.snapValueActive ) {
const interval = settings.snapValueInterval;
const threshold = dy2dv( -5.0, range, height );
const nearest = Math.round( v / interval ) * interval;
v = Math.abs( v - nearest ) < threshold ? nearest : v;
}
return v;
}