Skip to content

Commit 383e10a

Browse files
committed
added interation control and inline example
1 parent dd82572 commit 383e10a

File tree

2 files changed

+87
-50
lines changed

2 files changed

+87
-50
lines changed

examples/sound_loop/sketch.js

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,8 @@
66
*/
77

88
var click, beatbox ;
9-
var clickPhrase = [1, 0, 0, 0];
10-
var bboxPhrase = [0, 0, 1, 0, 0, 0, 1, 1];
11-
129

1310
var looper1, looper2;
14-
var num;
15-
16-
var c,d;
17-
var count1, count2;
18-
1911

2012

2113
function preload() {
@@ -26,23 +18,23 @@ function preload() {
2618
}
2719

2820
function setup() {
29-
createCanvas(500,500)
30-
count1 = 0;
31-
count2 = 0;
32-
c = color(50);
33-
d = color(50);
34-
21+
22+
//Hemiola! 2 loops, playing sounds in a 4 over 3 pattern
23+
//gradually increase the tempo of both loops
24+
//
3525
//the looper's callback is passed the timeFromNow
3626
//this value should be used as a reference point from
3727
//which to schedule sounds
3828

3929
looper1 = new p5.SoundLoop(function(timeFromNow){
4030
click.play(timeFromNow);
41-
}, 1);
31+
looper1.bpm looper1.bpm += 0.5;
32+
}, "8n");
4233

4334
looper2 = new p5.SoundLoop(function(timeFromNow){
4435
beatbox.play(timeFromNow);
45-
}, "16n");
36+
looper2.bpm = looper1.bpm;
37+
}, "12n");
4638

4739
//start the loops together
4840
looper1.syncedStart(looper2);

src/soundLoop.js

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,76 @@ define(function (require) {
99
*
1010
* @class p5.SoundLoop
1111
* @constructor
12+
*
13+
* @param {Function} callback this function will be called on each iteration of theloop
14+
* @param {Number or String} [interval] amount of time or beats for each iteration of the loop
15+
* defaults to 1
16+
*
17+
* @example
18+
* <div><code>
19+
* var click;
20+
* var looper1;
21+
*
22+
* function preload() {
23+
* click = loadSound('assets/drum.mp3'
24+
* }
25+
*
26+
* function setup() {
27+
* //the looper's callback is passed the timeFromNow
28+
* //this value should be used as a reference point from
29+
* //which to schedule sounds
30+
* looper1 = new p5.SoundLoop(function(timeFromNow){
31+
* click.play(timeFromNow);
32+
* background(255 * (looper1.iterations % 2));
33+
* }, 2);
34+
*
35+
* //stop after 10 iteratios;
36+
* looper1.maxIterations = 10;
37+
* //start the loop
38+
* looper1.start();
39+
* }
40+
* </code></div>
1241
*/
13-
p5.SoundLoop = function(callback, interval, BPM) {
14-
42+
p5.SoundLoop = function(callback, interval) {
1543
this.callback = callback;
16-
44+
/**
45+
* musicalTimeMode uses <a href = "https://github.com/Tonejs/Tone.js/wiki/Time">Tone.Time</a> convention
46+
* @property {Boolean} musicalTimeMode true if string, false if number
47+
*/
1748
this.musicalTimeMode = typeof this._interval === 'number' ? false : true;
18-
this._interval = interval;
1949

20-
//These variables should only be modified if using musicalTimeMode
21-
//If these variables are modified when interval is measured in seconds,
22-
//the interval will become inaccurate.
23-
//ex. 8 second interval at 60BPM in 4/4 time will be 8 seconds long
24-
//8 second interval at 120BPM in 5/4 time will be 3.2 seconds long
50+
this._interval = interval || 1;
51+
52+
/**
53+
* musicalTimeMode variables
54+
* modify these only when the interval is specified in musicalTime format as a string
55+
* @property {Number} [BPM] beats per minute (defaults to 60)
56+
* @property {Number} [timeSignature] number of quarter notes in a measure (defaults to 4)
57+
*/
2558
this._timeSignature = 4;
26-
this._bpm = BPM || 60;
59+
this._bpm = 60;
2760

2861
this.isPlaying = false;
62+
63+
/**
64+
* Set a limit to the number of loops to play
65+
* @property {Number} [maxIterations] defaults to Infinity
66+
*/
67+
this.maxIterations = Infinity;
2968
var self = this;
69+
3070
this.clock = new Clock({
3171
'callback' : function(time) {
3272
var timeFromNow = time - p5sound.audiocontext.currentTime;
33-
//Do not initiate the callback if timeFromNow is < 0
34-
//This ususually occurs for a few milliseconds when the page
35-
//is not fully loaded
36-
if (timeFromNow > 0) {self.callback(timeFromNow);}
73+
/**
74+
* Do not initiate the callback if timeFromNow is < 0
75+
* This ususually occurs for a few milliseconds when the page
76+
* is not fully loaded
77+
*
78+
* The callback should only be called until maxIterations is reached
79+
*/
80+
if (timeFromNow > 0 && self.iterations <= self.maxIterations) {
81+
self.callback(timeFromNow);}
3782
},
3883
'frequency' : this._calcFreq()
3984
});
@@ -67,7 +112,7 @@ define(function (require) {
67112
}
68113
};
69114
/**
70-
* Start the loop
115+
* Pause the loop
71116
* @method pause
72117
* @param {Number} [timeFromNow] schedule a pausing time
73118
*/
@@ -79,14 +124,7 @@ define(function (require) {
79124
}
80125
};
81126

82-
//use synced start to start 2 loops at the same time
83-
//OR
84-
//sync the start of one loop with one that is already playing
85-
//loop.syncedStart(someother loop)
86-
//
87-
//
88-
//loopToStart.syncedStart( loopToSyncWtih );
89-
//
127+
90128
/**
91129
* Synchronize loops. Use this method to start two more more loops in synchronization
92130
* or to start a loop in synchronization with a loop that is already playing
@@ -183,19 +221,20 @@ define(function (require) {
183221
* frequency, that will be reflected after the next callback
184222
* @param {Number} bpm
185223
* @param {Number} timeSignature
186-
* @param {Number/String} interval [description]
224+
* @param {Number/String} interval length of the loops interval
225+
* @param @readOnly {Number} iteations how many times the callback has been called so far
226+
*
187227
*/
188228
Object.defineProperty(p5.SoundLoop.prototype, 'bpm', {
189229
get : function() {
190230
return this._bpm;
191231
},
192232
set : function(bpm) {
193233
if (!this.musicalTimeMode) {
194-
console.warn('Changing the BPM in "seconds" mode is not advised. '+
195-
'This will make the specified time interval inaccurate. '+
196-
'8 second interval at 60BPM in 4/4 time will be 8 seconds long ' +
197-
'8 second interval at 120BPM in 5/4 time will be 3.2 seconds long. '+
198-
'Use musical timing notation ("2n", "4n", "1m"...etc');
234+
console.warn('Changing the BPM in "seconds" mode has no effect. '+
235+
'BPM is only relevant in musicalTimeMode '+
236+
'when the interval is specified as a string '+
237+
'("2n", "4n", "1m"...etc)');
199238
}
200239
this._bpm = bpm;
201240
this._update();
@@ -208,11 +247,10 @@ define(function (require) {
208247
},
209248
set : function(timeSig) {
210249
if (!this.musicalTimeMode) {
211-
console.warn('Changing the time signature in "seconds" mode is not advised. '+
212-
'This will make the specified time interval inaccurate. '+
213-
'8 second interval at 60BPM in 4/4 time will be 8 seconds long ' +
214-
'8 second interval at 120BPM in 5/4 time will be 3.2 seconds long. '+
215-
'Use musical timing notation ("2n", "4n", "1m"...etc');
250+
console.warn('Changing the timeSignature in "seconds" mode has no effect. '+
251+
'BPM is only relevant in musicalTimeMode '+
252+
'when the interval is specified as a string '+
253+
'("2n", "4n", "1m"...etc)');
216254
}
217255
this._timeSignature = timeSig;
218256
this._update();
@@ -224,10 +262,17 @@ define(function (require) {
224262
return this._interval;
225263
},
226264
set : function(interval) {
265+
this.musicalTimeMode = typeof interval === 'Number'? false : true;
227266
this._interval = interval;
228267
this._update();
229268
}
230269
});
231270

271+
Object.defineProperty(p5.SoundLoop.prototype, 'iterations', {
272+
get : function() {
273+
return this.clock.ticks;
274+
}
275+
});
276+
232277
return p5.SoundLoop;
233278
});

0 commit comments

Comments
 (0)