-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chord-synth.ts
57 lines (48 loc) · 1.6 KB
/
chord-synth.ts
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
import { defined } from "@glideapps/ts-necessities";
import _ from "lodash";
import * as Tone from "tone";
import { StatSnapshot } from "../stats";
import { randomItem } from "../utils";
import { chords, getRootForOffset, getScaledMelody } from "./melody";
import { Module, PlaySettings } from "./types";
export class ChordSynthBackgroundModule implements Module {
public readonly name = "Chord synth (random)";
public readonly meter: Tone.Meter;
private readonly volume: Tone.Volume;
private readonly chordSynths: readonly Tone.MonoSynth[];
constructor(volume: number) {
this.meter = new Tone.Meter();
this.volume = new Tone.Volume(volume).connect(this.meter);
this.chordSynths = [1, 2, 3].map(() =>
new Tone.MonoSynth({
oscillator: { type: "sine" },
envelope: {
attack: 0.1,
decay: 1,
},
}).chain(this.volume, Tone.Destination)
);
}
public play(
_snapshot: StatSnapshot,
time: number,
{ loopLength, semitoneOffset }: PlaySettings
): void {
const chord = getScaledMelody(
getRootForOffset(semitoneOffset),
randomItem(chords)
);
for (const [n, s] of _.zip(chord, this.chordSynths)) {
defined(s).triggerAttackRelease(defined(n), loopLength, time);
}
}
public isMuted(): boolean {
return this.volume.mute;
}
public mute(): void {
this.volume.mute = true;
}
public unMute(): void {
this.volume.mute = false;
}
}