Skip to content

Commit c04f28d

Browse files
committed
missing files
1 parent 1be5503 commit c04f28d

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

src/tone.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import * as Tone from 'tone';
2+
3+
class ComplementaryToneGenerator {
4+
constructor() {
5+
this.rootNote = 'C';
6+
this.currentOctave = 4; // Starting octave
7+
this.octaveDirection = 1; // 1 for up, -1 for down
8+
this.octaveMin = 3; // Minimum octave limit
9+
this.octaveMax = 5; // Maximum octave limit
10+
this.scalePatterns = {
11+
major: [2, 2, 1, 2, 2, 2, 1], // W-W-H-W-W-W-H
12+
minor: [2, 1, 2, 2, 1, 2, 2], // W-H-W-W-H-W-W
13+
majorSeventh: [4, 3, 1], // Major 7th Chord (Root-Major 3rd-Perfect 5th-Major 7th)
14+
pentatonic: [2, 2, 3, 2, 3], // Pentatonic Scale
15+
};
16+
this.scaleKeys = Object.keys(this.scalePatterns);
17+
this.currentScalePatternIndex = 0; // Index to keep track of the current scale pattern
18+
this.currentScalePattern = this.scaleKeys[this.currentScalePatternIndex];
19+
this.currentScale = [];
20+
this.scaleIndex = 0;
21+
this.lastFrequency = null;
22+
23+
this.synth = new Tone.Synth({
24+
envelope: {
25+
attack: 0.005,
26+
decay: 0.1,
27+
sustain: 0.1,
28+
release: 0.5,
29+
},
30+
}).toDestination();
31+
32+
this.initializeScale();
33+
}
34+
35+
generateScale(rootNote, pattern) {
36+
let scale = [`${rootNote}${this.currentOctave}`];
37+
let currentFrequency = Tone.Frequency(scale[0]).toFrequency();
38+
39+
pattern.forEach(interval => {
40+
currentFrequency *= Tone.intervalToFrequencyRatio(interval);
41+
scale.push(Tone.Frequency(currentFrequency).toNote());
42+
});
43+
44+
return scale;
45+
}
46+
47+
initializeScale() {
48+
this.currentScale = this.generateScale(this.rootNote, this.scalePatterns[this.currentScalePattern]);
49+
this.scaleIndex = 0; // Reset scale index
50+
}
51+
52+
playNextNote() {
53+
// Check if we've reached the end or start of the scale to change direction
54+
if (this.scaleIndex >= this.currentScale.length - 1 || this.scaleIndex <= 0) {
55+
this.adjustOctaveAndMaybeScale();
56+
}
57+
58+
const nextNote = this.currentScale[this.scaleIndex];
59+
this.synth.triggerAttackRelease(nextNote, '8n', Tone.now());
60+
this.scaleIndex += this.octaveDirection; // Move index in the current direction
61+
this.lastFrequency = Tone.Frequency(nextNote).toFrequency();
62+
}
63+
64+
adjustOctaveAndMaybeScale() {
65+
// When changing direction at octave limits, also change the scale
66+
if (this.currentOctave >= this.octaveMax || this.currentOctave <= this.octaveMin) {
67+
this.octaveDirection *= -1; // Change direction
68+
this.selectNextScaleAndRoot(); // Change scale and root note
69+
} else if (this.scaleIndex === 0 || this.scaleIndex === this.currentScale.length - 1) {
70+
// Regular octave direction change without hitting octave limits
71+
this.octaveDirection *= -1; // Change direction
72+
}
73+
74+
// Adjust the octave within the limits
75+
this.currentOctave += this.octaveDirection;
76+
if (this.currentOctave > this.octaveMax) {
77+
this.currentOctave = this.octaveMax;
78+
} else if (this.currentOctave < this.octaveMin) {
79+
this.currentOctave = this.octaveMin;
80+
}
81+
82+
this.initializeScale(); // Re-initialize the scale with the new settings
83+
}
84+
85+
selectNextScaleAndRoot() {
86+
// Move to the next scale pattern
87+
this.currentScalePatternIndex = (this.currentScalePatternIndex + 1) % this.scaleKeys.length;
88+
this.currentScalePattern = this.scaleKeys[this.currentScalePatternIndex];
89+
90+
const rootNotes = ['C', 'D', 'E', 'B', 'G', 'F', 'A'];
91+
let currentRootIndex = rootNotes.indexOf(this.rootNote);
92+
currentRootIndex = (currentRootIndex + 1) % rootNotes.length;
93+
this.rootNote = rootNotes[currentRootIndex];
94+
}
95+
}
96+
97+
export default ComplementaryToneGenerator;

0 commit comments

Comments
 (0)