tuneframes 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +167 -199
- package/README.md +150 -97
- package/examples/example-ai-dj-chill.html +167 -0
- package/examples/example-ai-dj-dark.html +167 -0
- package/examples/example-ai-dj-energetic.html +167 -0
- package/examples/example-ai-dj-happy.html +167 -0
- package/examples/example-ai-dj.html +167 -0
- package/examples/example-ambient.html +63 -63
- package/examples/example-ambient.mp3 +0 -0
- package/examples/example-bass.html +48 -0
- package/examples/example-lofi.html +45 -45
- package/examples/example-lofi.mp3 +0 -0
- package/examples/example-minimal.html +21 -19
- package/examples/example-minimal.mp3 +0 -0
- package/examples/example-orchestral.html +67 -67
- package/examples/example-orchestral.mp3 +0 -0
- package/examples/example-piano.html +53 -0
- package/examples/example-piano.mp3 +0 -0
- package/examples/example-techno.html +69 -69
- package/examples/example-techno.mp3 +0 -0
- package/package.json +42 -24
- package/registry/presets/bass-electric.html +67 -0
- package/registry/presets/bass-saw.html +22 -0
- package/registry/presets/chord-progression.html +22 -0
- package/registry/presets/drums-808.html +85 -0
- package/registry/presets/drums-lofi.html +35 -0
- package/registry/presets/lead-piano.html +26 -0
- package/registry/presets/piano-salamander.html +69 -0
- package/registry/presets/reverb-warm.html +11 -0
- package/registry/samples.json +226 -0
- package/skills/audio-ambient/SKILL.md +141 -0
- package/skills/audio-ambient/example.html +113 -0
- package/skills/audio-boss-battle/SKILL.md +157 -0
- package/skills/audio-boss-battle/example.html +185 -0
- package/skills/audio-boss-battle/example.mp3 +0 -0
- package/skills/audio-chillwave/SKILL.md +142 -0
- package/skills/audio-chillwave/example.html +144 -0
- package/skills/audio-cinematic/SKILL.md +147 -0
- package/skills/audio-cinematic/example.html +123 -0
- package/skills/audio-classical/SKILL.md +138 -0
- package/skills/audio-classical/example.html +145 -0
- package/skills/audio-dnb/SKILL.md +142 -0
- package/skills/audio-dnb/example.html +124 -0
- package/skills/audio-downtempo/SKILL.md +152 -0
- package/skills/audio-downtempo/example.html +164 -0
- package/skills/audio-folk/SKILL.md +139 -0
- package/skills/audio-folk/example.html +132 -0
- package/skills/audio-funk/SKILL.md +149 -0
- package/skills/audio-funk/example.html +144 -0
- package/skills/audio-future-bass/SKILL.md +163 -0
- package/skills/audio-future-bass/example.html +164 -0
- package/skills/audio-hip-hop/SKILL.md +133 -0
- package/skills/audio-hip-hop/example.html +129 -0
- package/skills/audio-house/SKILL.md +147 -0
- package/skills/audio-house/example.html +128 -0
- package/skills/audio-indie-pop/SKILL.md +150 -0
- package/skills/audio-indie-pop/example.html +121 -0
- package/skills/audio-jazz/SKILL.md +141 -0
- package/skills/audio-jazz/example.html +146 -0
- package/skills/audio-lofi/SKILL.md +140 -0
- package/skills/audio-lofi/example.html +135 -0
- package/skills/audio-minimal/SKILL.md +155 -0
- package/skills/audio-minimal/example.html +118 -0
- package/skills/audio-orchestral/SKILL.md +156 -0
- package/skills/audio-orchestral/example.html +140 -0
- package/skills/audio-r-and-b/SKILL.md +134 -0
- package/skills/audio-r-and-b/example.html +154 -0
- package/skills/audio-r-and-b/example.mp3 +0 -0
- package/skills/audio-techno/SKILL.md +140 -0
- package/skills/audio-techno/example.html +125 -0
- package/skills/audio-trap/SKILL.md +123 -0
- package/skills/audio-trap/example.html +119 -0
- package/skills/render-retest/example.html +115 -0
- package/skills/tuneframes/SKILL.md +221 -0
- package/skills/tuneframes-cli/SKILL.md +46 -0
- package/skills/verify/example.html +104 -0
- package/src/cli.js +261 -89
- package/src/render.js +134 -7
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<!-- Classic trap 808 pattern — synthesis only, no CDN required -->
|
|
8
|
+
<!-- 2 bars at 140 BPM: 1 bar = 4 beats × (60/140)s ≈ 1.714s → 2 bars ≈ 3.43s -->
|
|
9
|
+
<div id="tuneframes" style="display:none">{"bpm":140,"duration":"7s"}</div>
|
|
10
|
+
<script>
|
|
11
|
+
async function main() {
|
|
12
|
+
await Tone.start();
|
|
13
|
+
|
|
14
|
+
// --- 808 Kick: pitched MembraneSynth with long pitch fall ---
|
|
15
|
+
const kick808 = new Tone.MembraneSynth({
|
|
16
|
+
pitchDecay: 0.5,
|
|
17
|
+
octaves: 8,
|
|
18
|
+
envelope: { attack: 0.001, decay: 0.8, sustain: 0, release: 0.4 }
|
|
19
|
+
}).toDestination();
|
|
20
|
+
kick808.volume.value = 2;
|
|
21
|
+
|
|
22
|
+
// --- Snare: layered noise (body) + click (transient) ---
|
|
23
|
+
const snareNoise = new Tone.NoiseSynth({
|
|
24
|
+
noise: { type: 'white' },
|
|
25
|
+
envelope: { attack: 0.001, decay: 0.18, sustain: 0, release: 0.05 }
|
|
26
|
+
});
|
|
27
|
+
const snareFilter = new Tone.Filter({ frequency: 3500, type: 'highpass' }).toDestination();
|
|
28
|
+
snareNoise.connect(snareFilter);
|
|
29
|
+
snareNoise.volume.value = -4;
|
|
30
|
+
|
|
31
|
+
// --- Hi-hat: MetalSynth for crisp metallic transient ---
|
|
32
|
+
const hihat = new Tone.MetalSynth({
|
|
33
|
+
frequency: 400,
|
|
34
|
+
envelope: { attack: 0.001, decay: 0.04, release: 0.01 },
|
|
35
|
+
harmonicity: 5.1,
|
|
36
|
+
modulationIndex: 32,
|
|
37
|
+
resonance: 4000,
|
|
38
|
+
octaves: 1.5
|
|
39
|
+
}).toDestination();
|
|
40
|
+
hihat.volume.value = -10;
|
|
41
|
+
|
|
42
|
+
// Open hi-hat: longer decay
|
|
43
|
+
const openHat = new Tone.MetalSynth({
|
|
44
|
+
frequency: 500,
|
|
45
|
+
envelope: { attack: 0.001, decay: 0.3, release: 0.1 },
|
|
46
|
+
harmonicity: 5.1,
|
|
47
|
+
modulationIndex: 32,
|
|
48
|
+
resonance: 4000,
|
|
49
|
+
octaves: 1.5
|
|
50
|
+
}).toDestination();
|
|
51
|
+
openHat.volume.value = -14;
|
|
52
|
+
|
|
53
|
+
const beat = Tone.Time('4n').toSeconds(); // one beat in seconds at 140 BPM
|
|
54
|
+
const bar = beat * 4;
|
|
55
|
+
|
|
56
|
+
// Render 2 bars of trap pattern
|
|
57
|
+
for (let b = 0; b < 2; b++) {
|
|
58
|
+
const o = b * bar;
|
|
59
|
+
|
|
60
|
+
// --- 808 kick: beats 1, 2.5, 3 (classic trap syncopation) ---
|
|
61
|
+
kick808.triggerAttackRelease('C1', '8n', o);
|
|
62
|
+
kick808.triggerAttackRelease('C1', '8n', o + beat * 1.5);
|
|
63
|
+
kick808.triggerAttackRelease('C1', '8n', o + beat * 2);
|
|
64
|
+
|
|
65
|
+
// --- Snare: beat 3 (half-time feel) ---
|
|
66
|
+
snareNoise.triggerAttackRelease('8n', o + beat * 2);
|
|
67
|
+
|
|
68
|
+
// --- Hi-hats: 16th notes throughout, open hat on beat 3-and ---
|
|
69
|
+
const sixteenth = beat / 4;
|
|
70
|
+
for (let s = 0; s < 16; s++) {
|
|
71
|
+
// Skip the snare slot (beat 3) on closed hats so open hat rings
|
|
72
|
+
if (s === 8) {
|
|
73
|
+
openHat.triggerAttackRelease('C5', '8n', o + s * sixteenth);
|
|
74
|
+
} else {
|
|
75
|
+
// Accent downbeats slightly
|
|
76
|
+
const vel = (s % 4 === 0) ? 1.0 : (s % 2 === 0 ? 0.6 : 0.35);
|
|
77
|
+
hihat.volume.value = -10 + (vel - 1) * 4;
|
|
78
|
+
hihat.triggerAttackRelease('C5', '32n', o + s * sixteenth);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
</body>
|
|
85
|
+
</html>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!-- TuneFrames preset: drums-lofi
|
|
2
|
+
Kick + snare + hi-hat loop. Paste inside <script> in your composition. -->
|
|
3
|
+
<script>
|
|
4
|
+
const beat = Tone.Time('4n').toSeconds();
|
|
5
|
+
|
|
6
|
+
const kick = new Tone.MembraneSynth({
|
|
7
|
+
pitchDecay: 0.05, octaves: 6,
|
|
8
|
+
oscillator: { type: 'sine' },
|
|
9
|
+
envelope: { attack: 0.001, decay: 0.4, sustain: 0, release: 0.1 }
|
|
10
|
+
}).toDestination();
|
|
11
|
+
|
|
12
|
+
const snare = new Tone.NoiseSynth({
|
|
13
|
+
noise: { type: 'white' },
|
|
14
|
+
envelope: { attack: 0.001, decay: 0.2, sustain: 0, release: 0.1 }
|
|
15
|
+
}).toDestination();
|
|
16
|
+
|
|
17
|
+
const hihat = new Tone.NoiseSynth({
|
|
18
|
+
noise: { type: 'white' },
|
|
19
|
+
envelope: { attack: 0.001, decay: 0.04, sustain: 0, release: 0.01 }
|
|
20
|
+
}).toDestination();
|
|
21
|
+
hihat.volume.value = -14;
|
|
22
|
+
|
|
23
|
+
// Kick on 1, 2, 3, 4
|
|
24
|
+
for (let i = 0; i < 4; i++) {
|
|
25
|
+
kick.triggerAttackRelease('C1', '4n', i * beat);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Snare on 2 and 4
|
|
29
|
+
[1, 3].forEach(i => snare.triggerAttackRelease('C3', '4n', i * beat));
|
|
30
|
+
|
|
31
|
+
// Hi-hat on every 8th note
|
|
32
|
+
for (let i = 0; i < 8; i++) {
|
|
33
|
+
hihat.triggerAttackRelease('16n', i * beat * 0.5);
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!-- TuneFrames preset: lead-piano
|
|
2
|
+
Simple 8-bar piano melody. Paste inside <script>. -->
|
|
3
|
+
<script>
|
|
4
|
+
const beat = Tone.Time('4n').toSeconds();
|
|
5
|
+
|
|
6
|
+
const piano = new Tone.PolySynth(Tone.Synth, {
|
|
7
|
+
oscillator: { type: 'triangle' },
|
|
8
|
+
envelope: { attack: 0.005, decay: 0.3, sustain: 0.4, release: 0.8 }
|
|
9
|
+
}).toDestination();
|
|
10
|
+
piano.volume.value = -8;
|
|
11
|
+
|
|
12
|
+
const melody = [
|
|
13
|
+
{ note: 'C5', time: 0 },
|
|
14
|
+
{ note: 'E5', time: 1 },
|
|
15
|
+
{ note: 'G5', time: 2 },
|
|
16
|
+
{ note: 'E5', time: 3 },
|
|
17
|
+
{ note: 'D5', time: 4 },
|
|
18
|
+
{ note: 'F5', time: 5 },
|
|
19
|
+
{ note: 'A5', time: 6 },
|
|
20
|
+
{ note: 'F5', time: 7 },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
melody.forEach(({ note, time }) => {
|
|
24
|
+
piano.triggerAttackRelease(note, '4n', time * beat);
|
|
25
|
+
});
|
|
26
|
+
</script>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<!-- Am - F - C - G chord progression, 4 chords × 2s = 8s -->
|
|
8
|
+
<div id="tuneframes" style="display:none">{"bpm":120,"duration":"9s"}</div>
|
|
9
|
+
<script>
|
|
10
|
+
async function main() {
|
|
11
|
+
await Tone.start();
|
|
12
|
+
|
|
13
|
+
// Load acoustic grand piano samples from gleitz FluidR3_GM CDN
|
|
14
|
+
const piano = new Tone.Sampler({
|
|
15
|
+
urls: {
|
|
16
|
+
A0: 'A0.mp3',
|
|
17
|
+
C2: 'C2.mp3',
|
|
18
|
+
Ds2: 'Ds2.mp3',
|
|
19
|
+
Fs2: 'Fs2.mp3',
|
|
20
|
+
A2: 'A2.mp3',
|
|
21
|
+
C3: 'C3.mp3',
|
|
22
|
+
Ds3: 'Ds3.mp3',
|
|
23
|
+
Fs3: 'Fs3.mp3',
|
|
24
|
+
A3: 'A3.mp3',
|
|
25
|
+
C4: 'C4.mp3',
|
|
26
|
+
Ds4: 'Ds4.mp3',
|
|
27
|
+
Fs4: 'Fs4.mp3',
|
|
28
|
+
A4: 'A4.mp3',
|
|
29
|
+
C5: 'C5.mp3',
|
|
30
|
+
Ds5: 'Ds5.mp3',
|
|
31
|
+
Fs5: 'Fs5.mp3',
|
|
32
|
+
A5: 'A5.mp3',
|
|
33
|
+
C6: 'C6.mp3',
|
|
34
|
+
A6: 'A6.mp3',
|
|
35
|
+
C7: 'C7.mp3',
|
|
36
|
+
C8: 'C8.mp3'
|
|
37
|
+
},
|
|
38
|
+
baseUrl: 'https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/acoustic_grand_piano-mp3/'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Light reverb for hall ambience
|
|
42
|
+
const reverb = new Tone.Reverb({ decay: 2.5, wet: 0.25 }).toDestination();
|
|
43
|
+
piano.connect(reverb);
|
|
44
|
+
|
|
45
|
+
// CRITICAL: wait for all samples to load before scheduling any notes
|
|
46
|
+
await Tone.loaded();
|
|
47
|
+
|
|
48
|
+
// Am - F - C - G, 2 seconds each, 8 seconds total
|
|
49
|
+
// Voicings are close-position triads with a bass note for warmth
|
|
50
|
+
const chords = [
|
|
51
|
+
{ notes: ['A2', 'E3', 'A3', 'C4', 'E4'], label: 'Am' },
|
|
52
|
+
{ notes: ['F2', 'C3', 'F3', 'A3', 'C4'], label: 'F' },
|
|
53
|
+
{ notes: ['C3', 'G3', 'C4', 'E4', 'G4'], label: 'C' },
|
|
54
|
+
{ notes: ['G2', 'D3', 'G3', 'B3', 'D4'], label: 'G' }
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const chordDuration = 2; // seconds per chord
|
|
58
|
+
const noteDuration = '1n'; // sustain each chord for a whole note
|
|
59
|
+
|
|
60
|
+
chords.forEach((chord, i) => {
|
|
61
|
+
const t = i * chordDuration;
|
|
62
|
+
// Arpeggiate the bass note very slightly ahead of the chord for a natural feel
|
|
63
|
+
piano.triggerAttackRelease(chord.notes[0], noteDuration, t);
|
|
64
|
+
piano.triggerAttackRelease(chord.notes.slice(1), noteDuration, t + 0.04);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
</body>
|
|
69
|
+
</html>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!-- TuneFrames preset: reverb-warm
|
|
2
|
+
Long reverb chain. Paste before your instruments. -->
|
|
3
|
+
<script>
|
|
4
|
+
// Reverb: long decay, high wet — lush, ambient
|
|
5
|
+
const verb = new Tone.Reverb({
|
|
6
|
+
decay: 4,
|
|
7
|
+
wet: 0.75
|
|
8
|
+
}).toDestination();
|
|
9
|
+
// Call .generate() to build the impulse response (runs at composition start)
|
|
10
|
+
verb.generate();
|
|
11
|
+
</script>
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"cdn": {
|
|
4
|
+
"gleitz_fluidr3_gm": {
|
|
5
|
+
"name": "gleitz FluidR3_GM",
|
|
6
|
+
"baseUrlTemplate": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/{instrument}-mp3/",
|
|
7
|
+
"format": "mp3",
|
|
8
|
+
"noteNameFormat": "Sharps written with 's' suffix (e.g. F#4 = Fs4, C#3 = Cs3)",
|
|
9
|
+
"license": "Public domain (FluidR3_GM SoundFont)",
|
|
10
|
+
"repo": "https://github.com/gleitz/midi-js-soundfonts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"instruments": {
|
|
14
|
+
"acoustic_grand_piano": {
|
|
15
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
16
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/acoustic_grand_piano-mp3/",
|
|
17
|
+
"category": "piano",
|
|
18
|
+
"range": { "low": "A0", "high": "C8" },
|
|
19
|
+
"urls": {
|
|
20
|
+
"A0": "A0.mp3",
|
|
21
|
+
"C1": "C1.mp3",
|
|
22
|
+
"Ds1": "Ds1.mp3",
|
|
23
|
+
"Fs1": "Fs1.mp3",
|
|
24
|
+
"A1": "A1.mp3",
|
|
25
|
+
"C2": "C2.mp3",
|
|
26
|
+
"Ds2": "Ds2.mp3",
|
|
27
|
+
"Fs2": "Fs2.mp3",
|
|
28
|
+
"A2": "A2.mp3",
|
|
29
|
+
"C3": "C3.mp3",
|
|
30
|
+
"Ds3": "Ds3.mp3",
|
|
31
|
+
"Fs3": "Fs3.mp3",
|
|
32
|
+
"A3": "A3.mp3",
|
|
33
|
+
"C4": "C4.mp3",
|
|
34
|
+
"Ds4": "Ds4.mp3",
|
|
35
|
+
"Fs4": "Fs4.mp3",
|
|
36
|
+
"A4": "A4.mp3",
|
|
37
|
+
"C5": "C5.mp3",
|
|
38
|
+
"Ds5": "Ds5.mp3",
|
|
39
|
+
"Fs5": "Fs5.mp3",
|
|
40
|
+
"A5": "A5.mp3",
|
|
41
|
+
"C6": "C6.mp3",
|
|
42
|
+
"Ds6": "Ds6.mp3",
|
|
43
|
+
"Fs6": "Fs6.mp3",
|
|
44
|
+
"A6": "A6.mp3",
|
|
45
|
+
"C7": "C7.mp3",
|
|
46
|
+
"Ds7": "Ds7.mp3",
|
|
47
|
+
"Fs7": "Fs7.mp3",
|
|
48
|
+
"A7": "A7.mp3",
|
|
49
|
+
"C8": "C8.mp3"
|
|
50
|
+
},
|
|
51
|
+
"notes": "Full 88-key range. Tone.Sampler pitch-shifts from nearest sample automatically."
|
|
52
|
+
},
|
|
53
|
+
"acoustic_bass": {
|
|
54
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
55
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/acoustic_bass-mp3/",
|
|
56
|
+
"category": "bass",
|
|
57
|
+
"range": { "low": "C1", "high": "G4" },
|
|
58
|
+
"urls": {
|
|
59
|
+
"C1": "C1.mp3",
|
|
60
|
+
"Ds1": "Ds1.mp3",
|
|
61
|
+
"Fs1": "Fs1.mp3",
|
|
62
|
+
"A1": "A1.mp3",
|
|
63
|
+
"C2": "C2.mp3",
|
|
64
|
+
"Ds2": "Ds2.mp3",
|
|
65
|
+
"Fs2": "Fs2.mp3",
|
|
66
|
+
"A2": "A2.mp3",
|
|
67
|
+
"C3": "C3.mp3",
|
|
68
|
+
"Ds3": "Ds3.mp3",
|
|
69
|
+
"Fs3": "Fs3.mp3",
|
|
70
|
+
"A3": "A3.mp3",
|
|
71
|
+
"C4": "C4.mp3",
|
|
72
|
+
"Fs4": "Fs4.mp3"
|
|
73
|
+
},
|
|
74
|
+
"notes": "Upright/double bass. Best in C1–C3 range for natural timbre."
|
|
75
|
+
},
|
|
76
|
+
"string_ensemble_1": {
|
|
77
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
78
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/string_ensemble_1-mp3/",
|
|
79
|
+
"category": "strings",
|
|
80
|
+
"range": { "low": "C2", "high": "C7" },
|
|
81
|
+
"urls": {
|
|
82
|
+
"C2": "C2.mp3",
|
|
83
|
+
"Ds2": "Ds2.mp3",
|
|
84
|
+
"Fs2": "Fs2.mp3",
|
|
85
|
+
"A2": "A2.mp3",
|
|
86
|
+
"C3": "C3.mp3",
|
|
87
|
+
"Ds3": "Ds3.mp3",
|
|
88
|
+
"Fs3": "Fs3.mp3",
|
|
89
|
+
"A3": "A3.mp3",
|
|
90
|
+
"C4": "C4.mp3",
|
|
91
|
+
"Ds4": "Ds4.mp3",
|
|
92
|
+
"Fs4": "Fs4.mp3",
|
|
93
|
+
"A4": "A4.mp3",
|
|
94
|
+
"C5": "C5.mp3",
|
|
95
|
+
"Ds5": "Ds5.mp3",
|
|
96
|
+
"Fs5": "Fs5.mp3",
|
|
97
|
+
"A5": "A5.mp3",
|
|
98
|
+
"C6": "C6.mp3",
|
|
99
|
+
"Ds6": "Ds6.mp3",
|
|
100
|
+
"Fs6": "Fs6.mp3",
|
|
101
|
+
"A6": "A6.mp3",
|
|
102
|
+
"C7": "C7.mp3"
|
|
103
|
+
},
|
|
104
|
+
"notes": "Lush string section. Long note durations ('1n', '2n') sound most natural."
|
|
105
|
+
},
|
|
106
|
+
"brass_section": {
|
|
107
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
108
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/brass_section-mp3/",
|
|
109
|
+
"category": "brass",
|
|
110
|
+
"range": { "low": "C2", "high": "C6" },
|
|
111
|
+
"urls": {
|
|
112
|
+
"C2": "C2.mp3",
|
|
113
|
+
"Ds2": "Ds2.mp3",
|
|
114
|
+
"Fs2": "Fs2.mp3",
|
|
115
|
+
"A2": "A2.mp3",
|
|
116
|
+
"C3": "C3.mp3",
|
|
117
|
+
"Ds3": "Ds3.mp3",
|
|
118
|
+
"Fs3": "Fs3.mp3",
|
|
119
|
+
"A3": "A3.mp3",
|
|
120
|
+
"C4": "C4.mp3",
|
|
121
|
+
"Ds4": "Ds4.mp3",
|
|
122
|
+
"Fs4": "Fs4.mp3",
|
|
123
|
+
"A4": "A4.mp3",
|
|
124
|
+
"C5": "C5.mp3",
|
|
125
|
+
"Ds5": "Ds5.mp3",
|
|
126
|
+
"Fs5": "Fs5.mp3",
|
|
127
|
+
"A5": "A5.mp3",
|
|
128
|
+
"C6": "C6.mp3"
|
|
129
|
+
},
|
|
130
|
+
"notes": "Big brass stabs and fanfares. Works best for short, punchy note durations ('8n', '4n')."
|
|
131
|
+
},
|
|
132
|
+
"acoustic_guitar_nylon": {
|
|
133
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
134
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/acoustic_guitar_nylon-mp3/",
|
|
135
|
+
"category": "guitar",
|
|
136
|
+
"range": { "low": "E2", "high": "D6" },
|
|
137
|
+
"urls": {
|
|
138
|
+
"Fs2": "Fs2.mp3",
|
|
139
|
+
"A2": "A2.mp3",
|
|
140
|
+
"C3": "C3.mp3",
|
|
141
|
+
"Ds3": "Ds3.mp3",
|
|
142
|
+
"Fs3": "Fs3.mp3",
|
|
143
|
+
"A3": "A3.mp3",
|
|
144
|
+
"C4": "C4.mp3",
|
|
145
|
+
"Ds4": "Ds4.mp3",
|
|
146
|
+
"Fs4": "Fs4.mp3",
|
|
147
|
+
"A4": "A4.mp3",
|
|
148
|
+
"C5": "C5.mp3",
|
|
149
|
+
"Ds5": "Ds5.mp3",
|
|
150
|
+
"Fs5": "Fs5.mp3",
|
|
151
|
+
"A5": "A5.mp3",
|
|
152
|
+
"C6": "C6.mp3"
|
|
153
|
+
},
|
|
154
|
+
"notes": "Classical nylon-string guitar. Natural decay — use release or short durations."
|
|
155
|
+
},
|
|
156
|
+
"vibraphone": {
|
|
157
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
158
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/vibraphone-mp3/",
|
|
159
|
+
"category": "mallet",
|
|
160
|
+
"range": { "low": "C3", "high": "C7" },
|
|
161
|
+
"urls": {
|
|
162
|
+
"C3": "C3.mp3",
|
|
163
|
+
"Ds3": "Ds3.mp3",
|
|
164
|
+
"Fs3": "Fs3.mp3",
|
|
165
|
+
"A3": "A3.mp3",
|
|
166
|
+
"C4": "C4.mp3",
|
|
167
|
+
"Ds4": "Ds4.mp3",
|
|
168
|
+
"Fs4": "Fs4.mp3",
|
|
169
|
+
"A4": "A4.mp3",
|
|
170
|
+
"C5": "C5.mp3",
|
|
171
|
+
"Ds5": "Ds5.mp3",
|
|
172
|
+
"Fs5": "Fs5.mp3",
|
|
173
|
+
"A5": "A5.mp3",
|
|
174
|
+
"C6": "C6.mp3",
|
|
175
|
+
"Ds6": "Ds6.mp3",
|
|
176
|
+
"Fs6": "Fs6.mp3",
|
|
177
|
+
"A6": "A6.mp3",
|
|
178
|
+
"C7": "C7.mp3"
|
|
179
|
+
},
|
|
180
|
+
"notes": "Warm bell-like timbre. Pairs well with reverb for jazz/ambient contexts."
|
|
181
|
+
},
|
|
182
|
+
"flute": {
|
|
183
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
184
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/flute-mp3/",
|
|
185
|
+
"category": "woodwind",
|
|
186
|
+
"range": { "low": "C4", "high": "A7" },
|
|
187
|
+
"urls": {
|
|
188
|
+
"C4": "C4.mp3",
|
|
189
|
+
"Ds4": "Ds4.mp3",
|
|
190
|
+
"Fs4": "Fs4.mp3",
|
|
191
|
+
"A4": "A4.mp3",
|
|
192
|
+
"C5": "C5.mp3",
|
|
193
|
+
"Ds5": "Ds5.mp3",
|
|
194
|
+
"Fs5": "Fs5.mp3",
|
|
195
|
+
"A5": "A5.mp3",
|
|
196
|
+
"C6": "C6.mp3",
|
|
197
|
+
"Ds6": "Ds6.mp3",
|
|
198
|
+
"Fs6": "Fs6.mp3",
|
|
199
|
+
"A6": "A6.mp3",
|
|
200
|
+
"C7": "C7.mp3"
|
|
201
|
+
},
|
|
202
|
+
"notes": "Breathy and lyrical. Best for melodic lines, not chords."
|
|
203
|
+
},
|
|
204
|
+
"choir_aahs": {
|
|
205
|
+
"cdn": "gleitz_fluidr3_gm",
|
|
206
|
+
"baseUrl": "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/choir_aahs-mp3/",
|
|
207
|
+
"category": "choir",
|
|
208
|
+
"range": { "low": "C3", "high": "G5" },
|
|
209
|
+
"urls": {
|
|
210
|
+
"C3": "C3.mp3",
|
|
211
|
+
"Ds3": "Ds3.mp3",
|
|
212
|
+
"Fs3": "Fs3.mp3",
|
|
213
|
+
"A3": "A3.mp3",
|
|
214
|
+
"C4": "C4.mp3",
|
|
215
|
+
"Ds4": "Ds4.mp3",
|
|
216
|
+
"Fs4": "Fs4.mp3",
|
|
217
|
+
"A4": "A4.mp3",
|
|
218
|
+
"C5": "C5.mp3",
|
|
219
|
+
"Ds5": "Ds5.mp3",
|
|
220
|
+
"Fs5": "Fs5.mp3",
|
|
221
|
+
"A5": "A5.mp3"
|
|
222
|
+
},
|
|
223
|
+
"notes": "Sustained 'aah' choir vowel. Long durations ('1n', '2n') and reverb are essential for realism."
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: audio-ambient
|
|
3
|
+
description: Brian Eno-style ambient — long evolving drone pads, massive reverb (8-12s decay), no percussion, slow pitch movement
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TuneFrames — Ambient
|
|
7
|
+
|
|
8
|
+
## Genre Profile
|
|
9
|
+
- BPM range: 50-70 (or unmeasured — BPM matters only for note scheduling)
|
|
10
|
+
- Key characteristics: slow fade-ins/outs (attack 3-6s, release 5-8s), pitch movement by semitones over 4-8 seconds, overlapping sustain layers, no rhythm
|
|
11
|
+
- Typical instruments: PolySynth (sine/triangle), soft AM pads, FMSynth with gentle modulation
|
|
12
|
+
- Mood: deep, meditative, timeless, oceanic
|
|
13
|
+
|
|
14
|
+
## Core Pattern
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
// Ambient: overlapping long pads that evolve slowly
|
|
18
|
+
// Key = D minor — dark and peaceful
|
|
19
|
+
// Chord tones: D2, F2, A2, C3, E3, G3
|
|
20
|
+
|
|
21
|
+
const reverb = new Tone.Reverb({ decay: 10, wet: 0.9 });
|
|
22
|
+
await reverb.generate(); // must await before using
|
|
23
|
+
reverb.toDestination();
|
|
24
|
+
|
|
25
|
+
const delay = new Tone.FeedbackDelay({ delayTime: '4n', feedback: 0.4, wet: 0.3 });
|
|
26
|
+
delay.connect(reverb);
|
|
27
|
+
|
|
28
|
+
// Primary drone pad — slow attack, very long sustain
|
|
29
|
+
const drone = new Tone.PolySynth(Tone.Synth, {
|
|
30
|
+
oscillator: { type: 'sine' },
|
|
31
|
+
envelope: { attack: 4.0, decay: 2.0, sustain: 0.9, release: 6.0 },
|
|
32
|
+
volume: -10,
|
|
33
|
+
});
|
|
34
|
+
drone.connect(delay);
|
|
35
|
+
|
|
36
|
+
// Shimmer layer — high harmonics, triangle wave
|
|
37
|
+
const shimmer = new Tone.PolySynth(Tone.Synth, {
|
|
38
|
+
oscillator: { type: 'triangle' },
|
|
39
|
+
envelope: { attack: 5.0, decay: 1.5, sustain: 0.7, release: 7.0 },
|
|
40
|
+
volume: -18,
|
|
41
|
+
});
|
|
42
|
+
shimmer.connect(reverb);
|
|
43
|
+
|
|
44
|
+
// Schedule evolving chord tones — no rhythm, just slow fades in/out
|
|
45
|
+
const notes = ['D2', 'A2', 'F3', 'C3', 'E3', 'D3', 'G2'];
|
|
46
|
+
notes.forEach((note, i) => {
|
|
47
|
+
const offset = i * 2.5; // stagger each note by 2.5 seconds
|
|
48
|
+
Tone.Transport.scheduleOnce((time) => {
|
|
49
|
+
drone.triggerAttackRelease(note, '8n', time); // long hold
|
|
50
|
+
}, offset);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Shimmer tones — offset so they breathe between drone attacks
|
|
54
|
+
['F4', 'A4', 'C5', 'E5'].forEach((note, i) => {
|
|
55
|
+
Tone.Transport.scheduleOnce((time) => {
|
|
56
|
+
shimmer.triggerAttackRelease(note, '8n', time);
|
|
57
|
+
}, i * 3.2 + 1.5);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
Tone.Transport.bpm.value = 60;
|
|
61
|
+
Tone.Transport.start();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Instrument Configuration
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
// Massive reverb — the defining character of ambient
|
|
68
|
+
const reverb = new Tone.Reverb({ decay: 10, preDelay: 0.05, wet: 0.88 });
|
|
69
|
+
await reverb.generate(); // always await!
|
|
70
|
+
|
|
71
|
+
// Sidechain delay for shimmer depth
|
|
72
|
+
const delay = new Tone.FeedbackDelay({ delayTime: 0.375, feedback: 0.45, wet: 0.35 });
|
|
73
|
+
|
|
74
|
+
// Primary drone — sine waves, extremely slow envelope
|
|
75
|
+
const drone = new Tone.PolySynth(Tone.Synth, {
|
|
76
|
+
oscillator: { type: 'sine' },
|
|
77
|
+
envelope: { attack: 4.5, decay: 2.0, sustain: 0.85, release: 7.0 },
|
|
78
|
+
volume: -8,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Overtone layer — triangle adds warmth without brightness
|
|
82
|
+
const overtone = new Tone.PolySynth(Tone.Synth, {
|
|
83
|
+
oscillator: { type: 'triangle' },
|
|
84
|
+
envelope: { attack: 3.0, decay: 1.5, sustain: 0.7, release: 5.0 },
|
|
85
|
+
volume: -16,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Sub drone — sine one octave below, anchors the space
|
|
89
|
+
const sub = new Tone.Synth({
|
|
90
|
+
oscillator: { type: 'sine' },
|
|
91
|
+
envelope: { attack: 6.0, decay: 3.0, sustain: 0.9, release: 8.0 },
|
|
92
|
+
volume: -14,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Signal chain: instruments → delay → reverb → destination
|
|
96
|
+
drone.connect(delay);
|
|
97
|
+
overtone.connect(reverb);
|
|
98
|
+
sub.connect(reverb);
|
|
99
|
+
delay.connect(reverb);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Composition Structure
|
|
103
|
+
|
|
104
|
+
**Ambient has no traditional structure — it breathes.**
|
|
105
|
+
|
|
106
|
+
1. **Entry (0-4s):** First note fades in almost imperceptibly — attack is 4+ seconds
|
|
107
|
+
2. **Accumulation (4-10s):** Second and third pitches enter, staggered 2-4s apart, building a slow chord cloud
|
|
108
|
+
3. **Shimmer (8-14s):** Upper register tones enter — overtones of the root
|
|
109
|
+
4. **Sustained body (10-20s+):** All layers overlap. Nothing resolves — everything just exists together
|
|
110
|
+
5. **No outro needed** — ambient fades naturally because of long release envelopes
|
|
111
|
+
|
|
112
|
+
**Pitch movement rules:**
|
|
113
|
+
- Move by semitones or whole steps only — no jumps larger than a 4th
|
|
114
|
+
- Let dissonance exist — it resolves by itself over time
|
|
115
|
+
- Never use more than 4-5 notes simultaneously
|
|
116
|
+
|
|
117
|
+
## Example Variations
|
|
118
|
+
|
|
119
|
+
### Variation 1: Major / peaceful
|
|
120
|
+
```js
|
|
121
|
+
// C major drone — open and spacious
|
|
122
|
+
const chordNotes = ['C3', 'G3', 'E4', 'B3', 'D4'];
|
|
123
|
+
// Brighter attack on shimmer: attack: 2.5
|
|
124
|
+
// Higher reverb wet: 0.92
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Variation 2: Cluster / tension
|
|
128
|
+
```js
|
|
129
|
+
// Half-step cluster — creates gentle tension that never resolves
|
|
130
|
+
const tones = ['E3', 'F3', 'G3', 'Ab3']; // chromatic compression
|
|
131
|
+
// Slower attack: 6.0 — the dissonance appears gradually so it never feels harsh
|
|
132
|
+
// Delay feedback higher: 0.55 — creates wash of overtones
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Variation 3: Single-note breath
|
|
136
|
+
```js
|
|
137
|
+
// Pure minimalism — one pitch at a time, long silences between
|
|
138
|
+
const seq = ['D3', null, null, null, 'F3', null, null, null, 'A3'];
|
|
139
|
+
// This is the most meditative form — inspired by Feldman/Satie
|
|
140
|
+
// Set reverb decay to 12s so notes bleed into silence
|
|
141
|
+
```
|