-
Notifications
You must be signed in to change notification settings - Fork 977
/
Time.js
156 lines (142 loc) · 4.48 KB
/
Time.js
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import Tone from "../core/Tone";
import "../type/TimeBase";
import "../type/Frequency";
/**
* @class Tone.Time is a primitive type for encoding Time values.
* Tone.Time can be constructed with or without the `new` keyword. Tone.Time can be passed
* into the parameter of any method which takes time as an argument.
* @constructor
* @extends {Tone.TimeBase}
* @param {String|Number|Object} val The time value.
* @param {String=} units The units of the value.
* @example
* var t = Tone.Time("4n");//a quarter note
*/
Tone.Time = function(val, units){
if (this instanceof Tone.Time){
Tone.TimeBase.call(this, val, units);
} else {
return new Tone.Time(val, units);
}
};
Tone.extend(Tone.Time, Tone.TimeBase);
/**
* Extend the base expressions
*/
Tone.Time.prototype._expressions = Object.assign({}, Tone.TimeBase.prototype._expressions, {
"quantize" : {
regexp : /^@(.+)/,
method : function(capture){
if (Tone.Transport){
var quantTo = new this.constructor(capture);
return this._secondsToUnits(Tone.Transport.nextSubdivision(quantTo));
} else {
return 0;
}
}
},
"now" : {
regexp : /^\+(.+)/,
method : function(capture){
return this._now() + (new this.constructor(capture));
}
}
});
/**
* Quantize the time by the given subdivision. Optionally add a
* percentage which will move the time value towards the ideal
* quantized value by that percentage.
* @param {Number|Time} val The subdivision to quantize to
* @param {NormalRange} [percent=1] Move the time value
* towards the quantized value by
* a percentage.
* @return {Number} this
* @example
* Tone.Time(21).quantize(2) //returns 22
* Tone.Time(0.6).quantize("4n", 0.5) //returns 0.55
*/
Tone.Time.prototype.quantize = function(subdiv, percent){
percent = Tone.defaultArg(percent, 1);
var subdivision = new this.constructor(subdiv);
var value = this.valueOf();
var multiple = Math.round(value / subdivision);
var ideal = multiple * subdivision;
var diff = ideal - value;
return value + diff * percent;
};
///////////////////////////////////////////////////////////////////////////
// CONVERSIONS
///////////////////////////////////////////////////////////////////////////
/**
* Convert a Time to Notation. The notation values are will be the
* closest representation between 1m to 128th note.
* @return {Notation}
* @example
* //if the Transport is at 120bpm:
* Tone.Time(2).toNotation();//returns "1m"
*/
Tone.Time.prototype.toNotation = function(){
var time = this.toSeconds();
var testNotations = ["1m"];
for (var power = 1; power < 8; power++){
var subdiv = Math.pow(2, power);
testNotations.push(subdiv + "n.");
testNotations.push(subdiv + "n");
testNotations.push(subdiv + "t");
}
testNotations.push("0");
//find the closets notation representation
var closest = testNotations[0];
var closestSeconds = Tone.Time(testNotations[0]).toSeconds();
testNotations.forEach(function(notation){
var notationSeconds = Tone.Time(notation).toSeconds();
if (Math.abs(notationSeconds - time) < Math.abs(closestSeconds - time)){
closest = notation;
closestSeconds = notationSeconds;
}
});
return closest;
};
/**
* Return the time encoded as Bars:Beats:Sixteenths.
* @return {BarsBeatsSixteenths}
*/
Tone.Time.prototype.toBarsBeatsSixteenths = function(){
var quarterTime = this._beatsToUnits(1);
var quarters = this.valueOf() / quarterTime;
quarters = parseFloat(quarters.toFixed(4));
var measures = Math.floor(quarters / this._getTimeSignature());
var sixteenths = (quarters % 1) * 4;
quarters = Math.floor(quarters) % this._getTimeSignature();
sixteenths = sixteenths.toString();
if (sixteenths.length > 3){
// the additional parseFloat removes insignificant trailing zeroes
sixteenths = parseFloat(parseFloat(sixteenths).toFixed(3));
}
var progress = [measures, quarters, sixteenths];
return progress.join(":");
};
/**
* Return the time in ticks.
* @return {Ticks}
*/
Tone.Time.prototype.toTicks = function(){
var quarterTime = this._beatsToUnits(1);
var quarters = this.valueOf() / quarterTime;
return Math.round(quarters * this._getPPQ());
};
/**
* Return the time in seconds.
* @return {Seconds}
*/
Tone.Time.prototype.toSeconds = function(){
return this.valueOf();
};
/**
* Return the value as a midi note.
* @return {Midi}
*/
Tone.Time.prototype.toMidi = function(){
return Tone.Frequency.ftom(this.toFrequency());
};
export default Tone.Time;