@@ -4,15 +4,18 @@ define(function (require) {
4
4
var p5sound = require ( 'master' ) ;
5
5
var Clock = require ( 'Tone/core/Clock' ) ;
6
6
7
+ /**
8
+ * SoundLoop
9
+ *
10
+ * @class p5.SoundLoop
11
+ * @constructor
12
+ */
7
13
p5 . SoundLoop = function ( callback , interval , BPM ) {
8
14
9
15
this . callback = callback ;
10
16
11
- //set private variables
12
- this . _interval = interval ;
13
-
14
- //musicalTimeMode is true if time is specified as "4n", "8n" ...etc
15
17
this . musicalTimeMode = typeof this . _interval === 'number' ? false : true ;
18
+ this . _interval = interval ;
16
19
17
20
//These variables should only be modified if using musicalTimeMode
18
21
//If these variables are modified when interval is measured in seconds,
@@ -22,47 +25,126 @@ define(function (require) {
22
25
this . _timeSignature = 4 ;
23
26
this . _bpm = BPM || 60 ;
24
27
28
+ this . isPlaying = false ;
25
29
var self = this ;
26
30
this . clock = new Clock ( {
27
31
'callback' : function ( time ) {
28
32
var timeFromNow = time - p5sound . audiocontext . currentTime ;
29
- self . callback ( timeFromNow ) ;
33
+ if ( timeFromNow > 0 ) { self . callback ( timeFromNow ) ; }
30
34
} ,
31
- 'frequency' : this . calcFreq ( )
35
+ 'frequency' : this . _calcFreq ( )
32
36
} ) ;
33
37
} ;
34
38
35
-
39
+ /**
40
+ * Start the loop
41
+ * @method start
42
+ * @param {Number } [timeFromNow] schedule a starting time
43
+ */
36
44
p5 . SoundLoop . prototype . start = function ( timeFromNow ) {
37
45
var t = timeFromNow || 0 ;
38
46
var now = p5sound . audiocontext . currentTime ;
39
- this . clock . start ( now + t ) ;
47
+ if ( ! this . isPlaying ) {
48
+ this . clock . start ( now + t ) ;
49
+ this . isPlaying = true ;
50
+ }
40
51
} ;
41
52
53
+ /**
54
+ * Stop the loop
55
+ * @method stop
56
+ * @param {Number } [timeFromNow] schedule a stopping time
57
+ */
42
58
p5 . SoundLoop . prototype . stop = function ( timeFromNow ) {
43
59
var t = timeFromNow || 0 ;
44
60
var now = p5sound . audiocontext . currentTime ;
45
- this . clock . stop ( now + t ) ;
61
+ if ( this . isPlaying ) {
62
+ this . clock . stop ( now + t ) ;
63
+ this . isPlaying = false ;
64
+ }
46
65
} ;
66
+ /**
67
+ * Start the loop
68
+ * @method pause
69
+ * @param {Number } [timeFromNow] schedule a pausing time
70
+ */
71
+ p5 . SoundLoop . prototype . pause = function ( timeFromNow ) {
72
+ var t = timeFromNow || 0 ;
73
+ if ( this . isPlaying ) {
74
+ this . clock . pause ( t ) ;
75
+ this . isPlaying = false ;
76
+ }
77
+ } ;
78
+
79
+ //use synced start to start 2 loops at the same time
80
+ //OR
81
+ //sync the start of one loop with one that is already playing
82
+ //loop.syncedStart(someother loop)
83
+ //
84
+ //
85
+ //loopToStart.syncedStart( loopToSyncWtih );
86
+ //
87
+ /**
88
+ * Synchronize loops. Use this method to start two more more loops in synchronization
89
+ * or to start a loop in synchronization with a loop that is already playing
90
+ * This method will schedule the implicit loop in sync with the explicit master loop
91
+ * i.e. loopToStart.syncedStart(loopToSyncWith)
92
+ *
93
+ * @method syncedStart
94
+ * @param {Object } otherLoop a p5.SoundLoop to sync with
95
+ * @param {Number } [timeFromNow] Start the loops in sync after timeFromNow seconds
96
+ */
97
+ p5 . SoundLoop . prototype . syncedStart = function ( otherLoop , timeFromNow ) {
98
+ var t = timeFromNow || 0 ;
99
+ var now = p5sound . audiocontext . currentTime ;
47
100
48
- p5 . SoundLoop . prototype . pause = function ( time ) {
49
- this . clock . pause ( time ) ;
101
+ if ( ! otherLoop . isPlaying ) {
102
+ otherLoop . clock . start ( now + t ) ;
103
+ otherLoop . isPlaying = true ;
104
+ this . clock . start ( now + t ) ;
105
+ this . isPlaying = true ;
106
+ } else if ( otherLoop . isPlaying ) {
107
+ var time = otherLoop . clock . _nextTick - p5sound . audiocontext . currentTime ;
108
+ this . clock . start ( now + time ) ;
109
+ this . isPlaying = true ;
110
+ }
50
111
} ;
51
112
113
+
114
+
115
+ /**
116
+ * Updates frequency value, reflected in next callback
117
+ * @private
118
+ * @method _update
119
+ */
52
120
p5 . SoundLoop . prototype . _update = function ( ) {
53
- this . clock . frequency . value = this . calcFreq ( ) ;
121
+ this . clock . frequency . value = this . _calcFreq ( ) ;
54
122
} ;
55
123
56
- p5 . SoundLoop . prototype . calcFreq = function ( ) {
124
+ /**
125
+ * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature
126
+ * @private
127
+ * @method _calcFreq
128
+ * @return {Number } new clock frequency value
129
+ */
130
+ p5 . SoundLoop . prototype . _calcFreq = function ( ) {
57
131
if ( typeof this . _interval === 'number' ) {
58
- console . log ( this . _interval ) ;
132
+ this . musicalTimeMode = false ;
59
133
return this . _bpm / 60 / this . _interval * ( this . _timeSignature / 4 ) ;
60
134
} else if ( typeof this . _interval === 'string' ) {
135
+ this . musicalTimeMode = true ;
61
136
return this . _bpm / 60 / this . _convertNotation ( this . _interval ) * ( this . _timeSignature / 4 ) ;
62
137
}
63
138
} ;
64
139
65
- //TIME NOTATION FUNCS
140
+ /**
141
+ * Convert notation from musical time format to seconds
142
+ * Uses <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> convention
143
+ * @private
144
+ * @method _convertNotation
145
+ * @param {String } value value to be converted
146
+ * @return {Number } converted value in seconds
147
+ */
66
148
p5 . SoundLoop . prototype . _convertNotation = function ( value ) {
67
149
var type = value . slice ( - 1 ) ;
68
150
value = Number ( value . slice ( 0 , - 1 ) ) ;
@@ -72,33 +154,44 @@ define(function (require) {
72
154
case 'n' :
73
155
return this . _note ( value ) ;
74
156
default :
75
- //console.warn(something);
157
+ console . warn ( 'Specified interval is not formatted correctly. See Tone.js ' +
158
+ 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time' ) ;
76
159
}
77
-
78
160
} ;
79
161
80
-
162
+ /**
163
+ * Helper conversion methods of measure and note
164
+ * @private
165
+ * @method _measure
166
+ * @method _note
167
+ */
81
168
p5 . SoundLoop . prototype . _measure = function ( value ) {
82
169
return value * this . _timeSignature ;
83
170
} ;
84
-
85
171
p5 . SoundLoop . prototype . _note = function ( value ) {
86
172
return this . _timeSignature / value ;
87
173
} ;
88
174
89
- // PUBLIC VARIABLES
175
+
176
+ /**
177
+ * Getters and Setters, setting any paramter will result in a change in the clock's
178
+ * frequency, that will be reflected after the next callback
179
+ * @param {Number } bpm
180
+ * @param {Number } timeSignature
181
+ * @param {Number/String } interval [description]
182
+ */
90
183
Object . defineProperty ( p5 . SoundLoop . prototype , 'bpm' , {
91
184
get : function ( ) {
92
185
return this . _bpm ;
93
186
} ,
94
187
set : function ( bpm ) {
95
- if ( ! this . musicalTimeMode ) {
96
- console . warn ( 'Changing the BPM in "seconds" mode is not advised. ' +
188
+ if ( ! this . musicalTimeMode ) {
189
+ console . warn ( 'Changing the BPM in "seconds" mode is not advised. ' +
97
190
'This will make the specified time interval inaccurate. ' +
98
191
'8 second interval at 60BPM in 4/4 time will be 8 seconds long ' +
99
192
'8 second interval at 120BPM in 5/4 time will be 3.2 seconds long. ' +
100
193
'Use musical timing notation ("2n", "4n", "1m"...etc' ) ;
101
- }
194
+ }
102
195
this . _bpm = bpm ;
103
196
this . _update ( ) ;
104
197
}
@@ -131,7 +224,5 @@ define(function (require) {
131
224
}
132
225
} ) ;
133
226
134
-
135
227
return p5 . SoundLoop ;
136
-
137
228
} ) ;
0 commit comments