-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsynth.js
116 lines (104 loc) · 3.23 KB
/
synth.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
function Synth() {
this.output = new Tone.Gain().connect(FX_BUS);
const noiseSynth = new Tone.NoiseSynth({ volume: -Infinity });
this.noiseSynthController = {
noiseSynth,
isLooping: false,
loop: new Tone.Loop((time) => {
noiseSynth.triggerAttack(time);
}),
};
this.synths = [...new Array(NUM_OSCS)].map((_, i) => {
const omniOsc = new Tone.OmniOscillator({
type: "triangle",
phase: (i / NUM_OSCS) * 360,
volume: 0 - i * 2,
});
const env = new Tone.AmplitudeEnvelope({
attack: 0.2,
decay: 2,
sustain: 1,
release: 0.3,
});
omniOsc.chain(env);
const loop = new Tone.Loop((time) => {
env.triggerAttack(time);
});
const isLooping = true;
return { harmonic: i + 1, omniOsc, env, loop, isLooping };
});
// connect first to output
this.synths[0].env.connect(this.output);
// connect rest to previous one
for (let i = 1; i < this.synths.length; i++) {
this.synths[i].env.connect(this.synths[0].env);
}
this.noiseSynthController.noiseSynth.connect(this.synths[0].env);
const getOscs = () => this.synths;
return {
getOscs,
getNoiseSynthController: () => this.noiseSynthController,
setOscType: (oscIndex, type) => {
this.synths[oscIndex].omniOsc.set({ type });
},
setLoop: (oscIndex, interval) => {
console.log(interval);
if (interval === "off") {
this.synths[oscIndex].isLooping = false;
this.synths[oscIndex].loop.cancel();
} else {
this.synths[oscIndex].loop.set({ interval });
this.synths[oscIndex].isLooping = true;
}
},
setHarmonic: (oscIndex, harmonic) => {
this.synths[oscIndex].harmonic = harmonic;
},
setVolume: (oscIndex, volume) => {
this.synths[oscIndex].omniOsc.volume.value =
volume === -24 ? -Infinity : volume;
},
setDetune: (oscIndex, detune) => {
this.synths[oscIndex].omniOsc.set({ detune });
},
setEnvValue: (oscIndex, param, val) => {
this.synths[oscIndex].env[param] = val;
},
setNoiseVolume: (volume) => {
this.noiseSynthController.noiseSynth.volume.value =
volume === -24 ? -Infinity : volume;
},
setNoiseEnvValue: (param, val) => {
this.noiseSynthController.noiseSynth.envelope[param] = val;
},
triggerAttack: (note, time) => {
if (this.noiseSynthController.isLooping) {
this.noiseSynthController.loop.cancel();
this.noiseSynthController.loop.start();
} else {
this.noiseSynthController.loop.cancel();
this.noiseSynthController.noiseSynth.triggerAttack(time);
}
getOscs().forEach(({ omniOsc, env, harmonic, loop, isLooping }, i) => {
const fq = note * (harmonic === 0 ? 0.5 : harmonic);
omniOsc.frequency.value = fq;
if (omniOsc.state === "stopped") {
omniOsc.start(time);
}
if (isLooping) {
loop.cancel();
loop.start();
} else {
loop.cancel();
env.triggerAttack(time);
}
});
},
triggerRelease: (time) => {
this.noiseSynthController.noiseSynth.triggerRelease();
getOscs().forEach(({ omniOsc, env }, i) => {
env.triggerRelease();
});
},
};
}