-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsequencer.js
126 lines (99 loc) · 3.3 KB
/
sequencer.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
class Sequencer {
get audioContext() {
return Sequencer.ac;
}
static get notesPlaying() {
return Sequencer.snotesPlaying;
}
static set notesPlaying(value){
Sequencer.snotesPlaying = value;
}
get synth() {
return Sequencer.synth;
}
get midiOutNamePort() {
return Sequencer.midiOut;
}
static set midiOutNamePort(value) {
Sequencer.midiOut = Function('"use strict";return new MidiOut('+value+')')();
}
get generator() {
return Sequencer.gen;
}
static set generator(scale) {
Sequencer.gen = Function('"use strict"; return new Generator('+JSON.stringify(scale)+','+f+')')();
}
get bpm() {
return Sequencer.bpm;
}
static set bpm(value) {
Sequencer.sbpm = value;
}
get pattern() {
return Sequencer.pattern;
}
static set pattern(value) {
Sequencer.spattern = value;
}
static beatToMilliSeconds(notesObject){
const beat = {128: 31.25, 64: 62.5, 32: 125, 16: 250, 8: 500, 6: 666, 3: 333, 4: 1000, 2: 2000, 1: 4000};
if (Object.keys(notesObject).includes('dur')) {
notesObject.dur = (beat[notesObject.dur < 128 ? notesObject.dur : 128]/1000)/(Sequencer.sbpm/60)*1000;
} else {
Object.assign(notesObject, {dur:(beat[Sequencer.spattern[Sequencer.counter%Sequencer.spattern.length]]/1000)/(Sequencer.sbpm/60)*1000});
}
return notesObject;
}
static synth(value, adsr={a:0,d:0,r:0}) {
if (value != undefined && value != null) {
Sequencer.synth = value + '('+JSON.stringify(adsr)+')';
Sequencer.play = function() {
if (!Sequencer.ac) {
throw 'No audio context set.';
}
const asynth = Function('"use strict"; return new '+Sequencer.synth)();
asynth.audioContext = Sequencer.ac;
const notesObject = Sequencer.beatToMiliSeconds(Sequencer.gen.notes);
asynth.waveType = 'triangle';
asynth.notes = notesObject.notes;
asynth.vel = notesObject.vel;
asynth.adsr = adsr;
asynth.adsr.s = notesObject.dur/1000;
Sequencer.notesPlaying = notesObject;
asynth.connect(scope); // fix
asynth.connect(Sequencer.ac.destination);
asynth.start();
setTimeout(Sequencer.start, notesObject.dur, Sequencer.ac, Sequencer.sbpm, Sequencer.spattern);
}
return this;
}
return null;
}
static midiOut(value) {
if (value != undefined && value != null) {
Sequencer.midiOut = Function('"use strict"; return new MidiOut("'+value+'")')();
Sequencer.play = function() {
const notesObject = Sequencer.gen.notes;
Sequencer.notesPlaying = notesObject;
Sequencer.midiOut.sendNotes(Sequencer.beatToMilliSeconds(notesObject));
setTimeout(Sequencer.start, Sequencer.beatToMilliSeconds(notesObject.dur), null, Sequencer.sbpm, Sequencer.spattern);
}
return this;
}
Sequencer.midiOut = null;
return null;
}
static generator(scale, f) {
Sequencer.counter = 0;
Sequencer.gen = Function('"use strict"; return new Generator('+JSON.stringify(scale)+','+f+')')();
return this;
}
static start(audioContext, bpm=90, pattern=[4]) {
Sequencer.ac = audioContext;
Sequencer.sbpm = bpm;
Sequencer.spattern = pattern;
Sequencer.play();
Sequencer.counter++;
Sequencer.gen.counter = Sequencer.counter;
}
}