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.
Files changed (78) hide show
  1. package/LICENSE +167 -199
  2. package/README.md +150 -97
  3. package/examples/example-ai-dj-chill.html +167 -0
  4. package/examples/example-ai-dj-dark.html +167 -0
  5. package/examples/example-ai-dj-energetic.html +167 -0
  6. package/examples/example-ai-dj-happy.html +167 -0
  7. package/examples/example-ai-dj.html +167 -0
  8. package/examples/example-ambient.html +63 -63
  9. package/examples/example-ambient.mp3 +0 -0
  10. package/examples/example-bass.html +48 -0
  11. package/examples/example-lofi.html +45 -45
  12. package/examples/example-lofi.mp3 +0 -0
  13. package/examples/example-minimal.html +21 -19
  14. package/examples/example-minimal.mp3 +0 -0
  15. package/examples/example-orchestral.html +67 -67
  16. package/examples/example-orchestral.mp3 +0 -0
  17. package/examples/example-piano.html +53 -0
  18. package/examples/example-piano.mp3 +0 -0
  19. package/examples/example-techno.html +69 -69
  20. package/examples/example-techno.mp3 +0 -0
  21. package/package.json +42 -24
  22. package/registry/presets/bass-electric.html +67 -0
  23. package/registry/presets/bass-saw.html +22 -0
  24. package/registry/presets/chord-progression.html +22 -0
  25. package/registry/presets/drums-808.html +85 -0
  26. package/registry/presets/drums-lofi.html +35 -0
  27. package/registry/presets/lead-piano.html +26 -0
  28. package/registry/presets/piano-salamander.html +69 -0
  29. package/registry/presets/reverb-warm.html +11 -0
  30. package/registry/samples.json +226 -0
  31. package/skills/audio-ambient/SKILL.md +141 -0
  32. package/skills/audio-ambient/example.html +113 -0
  33. package/skills/audio-boss-battle/SKILL.md +157 -0
  34. package/skills/audio-boss-battle/example.html +185 -0
  35. package/skills/audio-boss-battle/example.mp3 +0 -0
  36. package/skills/audio-chillwave/SKILL.md +142 -0
  37. package/skills/audio-chillwave/example.html +144 -0
  38. package/skills/audio-cinematic/SKILL.md +147 -0
  39. package/skills/audio-cinematic/example.html +123 -0
  40. package/skills/audio-classical/SKILL.md +138 -0
  41. package/skills/audio-classical/example.html +145 -0
  42. package/skills/audio-dnb/SKILL.md +142 -0
  43. package/skills/audio-dnb/example.html +124 -0
  44. package/skills/audio-downtempo/SKILL.md +152 -0
  45. package/skills/audio-downtempo/example.html +164 -0
  46. package/skills/audio-folk/SKILL.md +139 -0
  47. package/skills/audio-folk/example.html +132 -0
  48. package/skills/audio-funk/SKILL.md +149 -0
  49. package/skills/audio-funk/example.html +144 -0
  50. package/skills/audio-future-bass/SKILL.md +163 -0
  51. package/skills/audio-future-bass/example.html +164 -0
  52. package/skills/audio-hip-hop/SKILL.md +133 -0
  53. package/skills/audio-hip-hop/example.html +129 -0
  54. package/skills/audio-house/SKILL.md +147 -0
  55. package/skills/audio-house/example.html +128 -0
  56. package/skills/audio-indie-pop/SKILL.md +150 -0
  57. package/skills/audio-indie-pop/example.html +121 -0
  58. package/skills/audio-jazz/SKILL.md +141 -0
  59. package/skills/audio-jazz/example.html +146 -0
  60. package/skills/audio-lofi/SKILL.md +140 -0
  61. package/skills/audio-lofi/example.html +135 -0
  62. package/skills/audio-minimal/SKILL.md +155 -0
  63. package/skills/audio-minimal/example.html +118 -0
  64. package/skills/audio-orchestral/SKILL.md +156 -0
  65. package/skills/audio-orchestral/example.html +140 -0
  66. package/skills/audio-r-and-b/SKILL.md +134 -0
  67. package/skills/audio-r-and-b/example.html +154 -0
  68. package/skills/audio-r-and-b/example.mp3 +0 -0
  69. package/skills/audio-techno/SKILL.md +140 -0
  70. package/skills/audio-techno/example.html +125 -0
  71. package/skills/audio-trap/SKILL.md +123 -0
  72. package/skills/audio-trap/example.html +119 -0
  73. package/skills/render-retest/example.html +115 -0
  74. package/skills/tuneframes/SKILL.md +221 -0
  75. package/skills/tuneframes-cli/SKILL.md +46 -0
  76. package/skills/verify/example.html +104 -0
  77. package/src/cli.js +261 -89
  78. package/src/render.js +134 -7
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: audio-r-and-b
3
+ description: R&B / Neo-Soul — lush extended chords, smooth Rhodes, laid-back syncopated groove
4
+ ---
5
+
6
+ # TuneFrames — R&B / Neo-Soul
7
+
8
+ ## Genre Profile
9
+ - BPM range: 70–95 (the groove breathes; never rushed)
10
+ - Key characteristics: Extended chord voicings (min9, maj9, add9, 11ths), Rhodes/electric piano feel, laid-back beat placement (drums sit just behind the grid), syncopated bass that locks with the kick, gentle compression on everything
11
+ - Typical instruments: Rhodes (PolySynth triangle), warm bass (Synth sine), soft kick (MembraneSynth), brush snare (NoiseSynth), 8th hi-hats with occasional 16th fills, optional synth pad underneath
12
+ - Mood: Warm, sensual, introspective, polished — D'Angelo, H.E.R., Frank Ocean, Erykah Badu, Sade
13
+
14
+ ## Core Pattern
15
+
16
+ ```js
17
+ // Neo-Soul core: 85 BPM, Fm9–Dbmaj9–Ab–Eb progression
18
+ async function main() {
19
+ await Tone.start();
20
+ Tone.Transport.bpm.value = 85;
21
+
22
+ const bar = Tone.Time('1n').toSeconds();
23
+ const q = Tone.Time('4n').toSeconds();
24
+ const s8 = Tone.Time('8n').toSeconds();
25
+
26
+ // ── Warm compression + reverb ─────────────────────────────────────────
27
+ const comp = new Tone.Compressor({ threshold: -20, ratio: 3, attack: 0.01, release: 0.2 }).toDestination();
28
+ const reverb = new Tone.Reverb({ decay: 2.5, preDelay: 0.01, wet: 0.35 }).connect(comp);
29
+
30
+ // ── Rhodes — extended voicings ────────────────────────────────────────
31
+ const rhodes = new Tone.PolySynth(Tone.Synth, {
32
+ oscillator: { type: 'triangle' },
33
+ envelope: { attack: 0.03, decay: 0.5, sustain: 0.6, release: 2.0 }
34
+ }).connect(reverb);
35
+ rhodes.volume.value = -10;
36
+
37
+ // Fm9 – Dbmaj9 – Ab – Eb (rich neo-soul changes)
38
+ const chords = [
39
+ ['F3','Ab3','C4','Eb4','G4'], // Fm9
40
+ ['Db3','F3','Ab3','C4','Eb4'], // Dbmaj9
41
+ ['Ab2','C3','Eb3','G3'], // Ab maj7
42
+ ['Eb3','G3','Bb3','D4'], // Ebmaj7
43
+ ];
44
+ chords.forEach((ch, i) => rhodes.triggerAttackRelease(ch, '1n', i * bar));
45
+
46
+ // ── Syncopated bass ───────────────────────────────────────────────────
47
+ const bass = new Tone.Synth({
48
+ oscillator: { type: 'sine' },
49
+ envelope: { attack: 0.015, decay: 0.15, sustain: 0.5, release: 0.3 }
50
+ }).connect(comp);
51
+ bass.volume.value = -7;
52
+
53
+ // Root on 1, then syncopated hits — lands a 16th early on beat 3
54
+ const bassLine = [
55
+ { note: 'F2', time: 0 },
56
+ { note: 'F2', time: q * 1.75 }, // 16th before beat 3
57
+ { note: 'Eb2', time: q * 3 },
58
+ ];
59
+ bassLine.forEach(({ note, time }) => bass.triggerAttackRelease(note, '8n', time));
60
+ }
61
+ ```
62
+
63
+ ## Instrument Configuration
64
+
65
+ ```js
66
+ // Rhodes feel — triangle wave, moderate attack, long release
67
+ const rhodes = new Tone.PolySynth(Tone.Synth, {
68
+ oscillator: { type: 'triangle' },
69
+ envelope: { attack: 0.03, decay: 0.5, sustain: 0.6, release: 2.0 }
70
+ });
71
+
72
+ // Warm bass — sine, slightly longer attack than funk (more laid-back)
73
+ const bass = new Tone.Synth({
74
+ oscillator: { type: 'sine' },
75
+ envelope: { attack: 0.015, decay: 0.15, sustain: 0.5, release: 0.3 }
76
+ });
77
+
78
+ // Pad underneath — very slow attack, barely audible, adds warmth
79
+ const pad = new Tone.PolySynth(Tone.Synth, {
80
+ oscillator: { type: 'sine' },
81
+ envelope: { attack: 2.0, decay: 0.5, sustain: 0.8, release: 4.0 }
82
+ });
83
+ pad.volume.value = -22; // subtle, under everything
84
+
85
+ // Chorus on the Rhodes for that electric piano shimmer
86
+ const chorus = new Tone.Chorus({ frequency: 1.5, delayTime: 3.5, depth: 0.4, wet: 0.5 });
87
+ chorus.start();
88
+
89
+ // Gentle compression — glues without pumping
90
+ const comp = new Tone.Compressor({ threshold: -20, ratio: 3, attack: 0.01, release: 0.2 });
91
+
92
+ // Chain: rhodes → chorus → reverb → comp → destination
93
+ const reverb = new Tone.Reverb({ decay: 2.5, wet: 0.35 });
94
+ rhodes.connect(chorus);
95
+ chorus.connect(reverb);
96
+ reverb.connect(comp);
97
+ comp.toDestination();
98
+ ```
99
+
100
+ ## Composition Structure
101
+
102
+ 1. **Intro (0–3s):** Rhodes alone with pad underneath — establish the lush harmonic world
103
+ 2. **Bass enters (3–6s):** Syncopated bass locks with the root, still no drums
104
+ 3. **Drums drop (6–9s):** Soft kick on 1 and 3, snare on 2 and 4, 8th hats — laid-back, never aggressive
105
+ 4. **Melody/hook (9–12s):** High Rhodes or separate synth carries a smooth melodic phrase
106
+ 5. **Outro:** Strip back to Rhodes + pad, let the chord voicings breathe and decay
107
+
108
+ ## Example Variations
109
+
110
+ ### 1 — D'Angelo "Voodoo" feel (heavy laid-back drums)
111
+ ```js
112
+ // Drums sit 20ms behind the grid — schedule everything slightly late
113
+ const LAG = 0.02; // seconds
114
+ kick.triggerAttackRelease('C1', '8n', 0 + LAG);
115
+ snare.triggerAttackRelease('8n', q + LAG);
116
+ ```
117
+
118
+ ### 2 — Sade-style sparse ballad (60 BPM, less is more)
119
+ ```js
120
+ Tone.Transport.bpm.value = 60;
121
+ // Just Rhodes + bass, no drums, add a gentle delay on the melody
122
+ const delay = new Tone.FeedbackDelay({ delayTime: '4n', feedback: 0.2, wet: 0.25 }).connect(reverb);
123
+ ```
124
+
125
+ ### 3 — Neo-soul key change (drop a half-step on bar 3)
126
+ ```js
127
+ // Modulate from Fm to Em for bar 3 — creates emotional lift/tension
128
+ const chordsWithMod = [
129
+ ['F3','Ab3','C4','Eb4','G4'], // Fm9
130
+ ['Db3','F3','Ab3','C4','Eb4'], // Dbmaj9
131
+ ['E3','G3','B3','D4','F#4'], // Em9 (half-step down = brighter surprise)
132
+ ['C3','E3','G3','B3'], // Cmaj7
133
+ ];
134
+ ```
@@ -0,0 +1,154 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>TuneFrames — R&amp;B / Neo-Soul</title>
5
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
6
+ </head>
7
+ <body>
8
+ <div id="tuneframes" style="display:none">{"bpm":86,"duration":"12s"}</div>
9
+ <script>
10
+ async function main() {
11
+ await Tone.start();
12
+ Tone.Transport.bpm.value = 86;
13
+
14
+ const bar = Tone.Time('1n').toSeconds(); // ~2.79s
15
+ const q = Tone.Time('4n').toSeconds(); // ~0.698s
16
+ const s8 = Tone.Time('8n').toSeconds(); // ~0.349s
17
+ const s16 = Tone.Time('16n').toSeconds();
18
+
19
+ // ── Signal chain: everything → comp → destination ────────────────────
20
+ const comp = new Tone.Compressor({ threshold: -20, ratio: 3, attack: 0.008, release: 0.18 }).toDestination();
21
+ const reverb = new Tone.Freeverb({ roomSize: 0.72, dampening: 3500, wet: 0.38 }).connect(comp);
22
+
23
+ // ── Pad underneath (barely audible warmth) ───────────────────────────
24
+ const pad = new Tone.PolySynth(Tone.Synth, {
25
+ oscillator: { type: 'sine' },
26
+ envelope: { attack: 2.2, decay: 0.5, sustain: 0.85, release: 5.0 }
27
+ }).connect(reverb);
28
+ pad.volume.value = -24;
29
+
30
+ // Hold the tonic throughout
31
+ pad.triggerAttackRelease(['F2','C3','Eb3'], '2n', 0);
32
+ pad.triggerAttackRelease(['Db2','Ab2','C3'], '2n', bar);
33
+ pad.triggerAttackRelease(['Ab2','Eb3','G3'], '2n', bar * 2);
34
+ pad.triggerAttackRelease(['Eb2','Bb2','D3'], '2n', bar * 3);
35
+
36
+ // ── Rhodes — chorus shimmer + reverb ────────────────────────────────
37
+ const chorus = new Tone.Chorus({ frequency: 1.5, delayTime: 3.5, depth: 0.4, wet: 0.45 }).connect(reverb);
38
+ chorus.start();
39
+ const rhodes = new Tone.PolySynth(Tone.Synth, {
40
+ oscillator: { type: 'triangle' },
41
+ envelope: { attack: 0.025, decay: 0.5, sustain: 0.62, release: 2.2 }
42
+ }).connect(chorus);
43
+ rhodes.volume.value = -9;
44
+
45
+ // Fm9 – Dbmaj9 – Abmaj7 – Ebmaj7 (4-bar loop × 2 passes + variation)
46
+ const changes = [
47
+ { chord: ['F3','Ab3','C4','Eb4','G4'], time: 0 }, // Fm9
48
+ { chord: ['Db3','F3','Ab3','C4','Eb4'], time: bar }, // Dbmaj9
49
+ { chord: ['Ab2','Eb3','G3','C4'], time: bar * 2 }, // Abmaj7
50
+ { chord: ['Eb3','G3','Bb3','D4'], time: bar * 3 }, // Ebmaj7
51
+ // Second pass with richer upper voicing
52
+ { chord: ['F3','Ab3','C4','G4'], time: bar * 4 }, // Fm add9
53
+ { chord: ['Db3','Ab3','C4','F4'], time: bar * 4 + bar }, // Dbmaj9/Ab
54
+ ];
55
+ changes.forEach(({ chord, time }) => rhodes.triggerAttackRelease(chord, '1n', time));
56
+
57
+ // ── Warm syncopated bass ─────────────────────────────────────────────
58
+ const bass = new Tone.Synth({
59
+ oscillator: { type: 'sine' },
60
+ envelope: { attack: 0.014, decay: 0.18, sustain: 0.48, release: 0.28 }
61
+ }).connect(comp);
62
+ bass.volume.value = -5;
63
+
64
+ // Neo-soul bass: root on 1, anticipation (16th early) into beat 3, fill at end
65
+ const bassPattern = (root, fifth, t) => [
66
+ { note: root, time: t }, // beat 1
67
+ { note: root, time: t + q + s16 }, // "and-a" of beat 2 (anticipates 3)
68
+ { note: fifth, time: t + q * 2 }, // beat 3
69
+ { note: root, time: t + q * 3 + s16 * 2 }, // syncopated fill before bar end
70
+ ];
71
+
72
+ [
73
+ ['F2', 'C3', 0 ],
74
+ ['Db2', 'Ab2', bar ],
75
+ ['Ab1', 'Eb2', bar * 2 ],
76
+ ['Eb2', 'Bb2', bar * 3 ],
77
+ ['F2', 'C3', bar * 4 ],
78
+ ['Db2', 'Ab2', bar * 4 + bar],
79
+ ].forEach(([root, fifth, t]) => {
80
+ bassPattern(root, fifth, t).forEach(({ note, time }) =>
81
+ bass.triggerAttackRelease(note, '8n', time));
82
+ });
83
+
84
+ // ── Kick (soft, beat 1 and 3) ────────────────────────────────────────
85
+ const kick = new Tone.MembraneSynth({
86
+ pitchDecay: 0.055, octaves: 5,
87
+ envelope: { attack: 0.001, decay: 0.35, sustain: 0, release: 0.3 }
88
+ }).connect(comp);
89
+ kick.volume.value = -14;
90
+
91
+ // Kicks enter on bar 2 (let Rhodes establish first)
92
+ for (let rep = 1; rep < 5; rep++) {
93
+ kick.triggerAttackRelease('C1', '8n', rep * bar); // beat 1
94
+ kick.triggerAttackRelease('C1', '8n', rep * bar + q * 2); // beat 3
95
+ // Syncopated ghost kick on the "and" of 4 every other bar
96
+ if (rep % 2 === 0) kick.triggerAttackRelease('C1', '8n', rep * bar + q * 3.5);
97
+ }
98
+
99
+ // ── Brush snare on 2 and 4 ──────────────────────────────────────────
100
+ const snareBp = new Tone.Filter(2600, 'bandpass').connect(reverb);
101
+ const snare = new Tone.NoiseSynth({
102
+ noise: { type: 'white' },
103
+ envelope: { attack: 0.003, decay: 0.13, sustain: 0, release: 0.06 }
104
+ }).connect(snareBp);
105
+ snare.volume.value = -20;
106
+
107
+ for (let rep = 1; rep < 5; rep++) {
108
+ snare.triggerAttackRelease('8n', rep * bar + q); // beat 2
109
+ snare.triggerAttackRelease('8n', rep * bar + q * 3); // beat 4
110
+ }
111
+
112
+ // ── Hi-hats: 8ths with 16th fill before beat 3 ──────────────────────
113
+ const hat = new Tone.MetalSynth({
114
+ frequency: 500, harmonicity: 5.1, modulationIndex: 24,
115
+ resonance: 4000, octaves: 1.5,
116
+ envelope: { attack: 0.001, decay: 0.05, release: 0.01 }
117
+ }).connect(reverb);
118
+ hat.volume.value = -24;
119
+
120
+ for (let rep = 1; rep < 5; rep++) {
121
+ // Regular 8th notes
122
+ for (let i = 0; i < 8; i++) hat.triggerAttackRelease('16n', rep * bar + i * s8);
123
+ // 16th-note fill going into beat 3 (soul fill)
124
+ hat.triggerAttackRelease('16n', rep * bar + q * 2 - s16 * 2);
125
+ hat.triggerAttackRelease('16n', rep * bar + q * 2 - s16);
126
+ }
127
+
128
+ // ── Melody (enters bar 3) — smooth Rhodes phrase ─────────────────────
129
+ const melDelay = new Tone.FeedbackDelay({ delayTime: '8n', feedback: 0.18, wet: 0.22 }).connect(reverb);
130
+ const melody = new Tone.Synth({
131
+ oscillator: { type: 'triangle' },
132
+ envelope: { attack: 0.04, decay: 0.35, sustain: 0.5, release: 1.5 }
133
+ }).connect(melDelay);
134
+ melody.volume.value = -13;
135
+
136
+ // Silky descending/ascending phrase — Fm pentatonic flavour
137
+ const phrase = [
138
+ { note: 'C5', time: bar * 2, dur: '8n' },
139
+ { note: 'Ab4', time: bar * 2 + s8, dur: '8n' },
140
+ { note: 'G4', time: bar * 2 + s8*2, dur: '4n' },
141
+ { note: 'Eb4', time: bar * 2 + s8*4, dur: '8n' },
142
+ { note: 'F4', time: bar * 2 + s8*5, dur: '4n.' },
143
+ { note: 'G4', time: bar * 3 + q, dur: '8n' },
144
+ { note: 'Ab4', time: bar * 3 + q + s8, dur: '8n' },
145
+ { note: 'C5', time: bar * 3 + q*2, dur: '2n' },
146
+ { note: 'Bb4', time: bar * 4 + s8, dur: '4n' },
147
+ { note: 'Ab4', time: bar * 4 + s8*3, dur: '4n' },
148
+ { note: 'G4', time: bar * 4 + s8*5, dur: '2n' },
149
+ ];
150
+ phrase.forEach(({ note, time, dur }) => melody.triggerAttackRelease(note, dur, time));
151
+ }
152
+ </script>
153
+ </body>
154
+ </html>
Binary file
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: audio-techno
3
+ description: Berlin-style techno — hard MembraneSynth kick, acid MonoSynth bass, industrial hi-hats, sparse stabs. Dark and mechanical.
4
+ ---
5
+
6
+ # TuneFrames — Techno
7
+
8
+ ## Genre Profile
9
+ - BPM range: 130–145
10
+ - Key characteristics: Hard kick on every beat, relentless forward momentum, hypnotic repetition, industrial textures, minimal melody
11
+ - Typical instruments: MembraneSynth (kick), MonoSynth (acid bass), MetalSynth or NoiseSynth (hi-hats), PolySynth (sparse stabs)
12
+ - Mood: Dark, mechanical, hypnotic, relentless
13
+
14
+ ## Core Pattern
15
+
16
+ ```js
17
+ // Berlin Techno — 4/4 at 136 BPM
18
+ // Kick on every beat (4-on-the-floor)
19
+ // Acid bass follows kick with filter sweep
20
+ // Hi-hats: closed on 8ths, open on off-beats
21
+ // Stabs: sparse, dissonant, 2-bar cycle
22
+
23
+ const kick = new Tone.MembraneSynth({
24
+ pitchDecay: 0.08,
25
+ octaves: 10,
26
+ envelope: { attack: 0.001, decay: 0.4, sustain: 0, release: 0.1 }
27
+ }).toDestination();
28
+
29
+ // Acid bass through distortion
30
+ const dist = new Tone.Distortion(0.6).toDestination();
31
+ const bass = new Tone.MonoSynth({
32
+ oscillator: { type: "sawtooth" },
33
+ filter: { Q: 6, type: "lowpass", rolloff: -24 },
34
+ filterEnvelope: {
35
+ attack: 0.001, decay: 0.2, sustain: 0.3, release: 0.5,
36
+ baseFrequency: 80, octaves: 4
37
+ },
38
+ envelope: { attack: 0.001, decay: 0.3, sustain: 0.4, release: 0.2 }
39
+ }).connect(dist);
40
+
41
+ // Industrial closed hi-hat
42
+ const hat = new Tone.MetalSynth({
43
+ frequency: 400, envelope: { attack: 0.001, decay: 0.04, release: 0.01 },
44
+ harmonicity: 5.1, modulationIndex: 32, resonance: 4000, octaves: 1.5
45
+ }).toDestination();
46
+
47
+ // Scheduling — 1-bar loop
48
+ new Tone.Sequence((time, note) => {
49
+ kick.triggerAttackRelease("C1", "8n", time);
50
+ }, ["C1", null, null, null, "C1", null, null, null,
51
+ "C1", null, null, null, "C1", null, null, null], "16n").start(0);
52
+
53
+ new Tone.Sequence((time, note) => {
54
+ if (note) hat.triggerAttackRelease("16n", time, note);
55
+ }, [0.7, 0.4, 0.7, 0.4, 0.7, 0.4, 0.9, 0.4,
56
+ 0.7, 0.4, 0.7, 0.4, 0.7, 0.5, 0.9, 0.6], "16n").start(0);
57
+
58
+ Tone.Transport.bpm.value = 136;
59
+ Tone.Transport.start();
60
+ ```
61
+
62
+ ## Instrument Configuration
63
+
64
+ ```js
65
+ // Kick — punchy, sub-heavy membrane
66
+ const kick = new Tone.MembraneSynth({
67
+ pitchDecay: 0.06,
68
+ octaves: 10,
69
+ volume: 2,
70
+ envelope: { attack: 0.001, decay: 0.35, sustain: 0, release: 0.1 }
71
+ }).toDestination();
72
+
73
+ // Acid bass — sawtooth through distortion + filter
74
+ const limiter = new Tone.Limiter(-3).toDestination();
75
+ const dist = new Tone.Distortion({ distortion: 0.5, wet: 0.8 }).connect(limiter);
76
+ const bass = new Tone.MonoSynth({
77
+ oscillator: { type: "sawtooth" },
78
+ filter: { Q: 8, type: "lowpass", rolloff: -24 },
79
+ filterEnvelope: {
80
+ attack: 0.002, decay: 0.3, sustain: 0.2, release: 0.6,
81
+ baseFrequency: 60, octaves: 3.5
82
+ },
83
+ envelope: { attack: 0.001, decay: 0.2, sustain: 0.5, release: 0.3 },
84
+ volume: -4
85
+ }).connect(dist);
86
+
87
+ // Hi-hat — metallic, tight
88
+ const hat = new Tone.MetalSynth({
89
+ frequency: 380, harmonicity: 5.1, modulationIndex: 32,
90
+ resonance: 4000, octaves: 1.5,
91
+ envelope: { attack: 0.001, decay: 0.05, release: 0.01 },
92
+ volume: -8
93
+ }).toDestination();
94
+
95
+ // Stab — cold PolySynth, short decay
96
+ const reverb = new Tone.Reverb({ decay: 1.5, wet: 0.3 }).toDestination();
97
+ const stab = new Tone.PolySynth(Tone.Synth, {
98
+ oscillator: { type: "square" },
99
+ envelope: { attack: 0.001, decay: 0.15, sustain: 0, release: 0.1 },
100
+ volume: -10
101
+ }).connect(reverb);
102
+ ```
103
+
104
+ ## Composition Structure
105
+
106
+ - **Bar 1-2:** Kick only — establish the pulse
107
+ - **Bar 3-4:** Add hi-hats — density builds
108
+ - **Bar 5-8:** Add acid bass — filter opens over 4 bars (automation)
109
+ - **Bar 9-16:** Full loop — kick + hats + bass + sparse stabs every 2 bars
110
+ - **Bar 17+:** Variation — mute elements in/out for tension/release
111
+ - **Breakdown:** Drop kick, keep hats, let bass filter sweep down — then kick re-enters hard
112
+ - **Outro:** Strip back to kick only, fade hats
113
+
114
+ Key technique: filter automation on the bass is the main expressive tool. Sweep `bass.filter.frequency` from 80Hz up to 2kHz over 8 bars, then drop back.
115
+
116
+ ## Example Variations
117
+
118
+ ### 1 — Stutter Kick (double kick on last 16th)
119
+ ```js
120
+ // Standard 4-on-floor with double hit before the beat
121
+ const kickPattern = ["C1", null, null, null, "C1", null, null, null,
122
+ "C1", null, null, null, "C1", null, "C1", null];
123
+ ```
124
+
125
+ ### 2 — Acid Filter Sweep (automation)
126
+ ```js
127
+ // Automate bass filter opening over 2 bars
128
+ const now = Tone.now();
129
+ bass.filter.frequency.setValueAtTime(80, now);
130
+ bass.filter.frequency.linearRampToValueAtTime(3000, now + 4);
131
+ bass.filter.frequency.linearRampToValueAtTime(120, now + 4.5);
132
+ ```
133
+
134
+ ### 3 — Ride + Open Hat Pattern
135
+ ```js
136
+ // More complex hat pattern: closed-closed-open on the off
137
+ const hatVelocities = [0.8, 0.3, 0.8, 0.3, 0.8, 0.3, 1.0, 0.2,
138
+ 0.8, 0.3, 0.8, 0.3, 0.8, 0.4, 1.0, 0.5];
139
+ // Longer decay on accented hits for "open hat" feel
140
+ ```
@@ -0,0 +1,125 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>TuneFrames — Techno</title>
6
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js"></script>
7
+ </head>
8
+ <body>
9
+ <!-- TuneFrames Metadata -->
10
+ <div id="tuneframes" style="display:none">{"bpm":136,"duration":"12s"}</div>
11
+
12
+ <script>
13
+ async function main() {
14
+ await Tone.start();
15
+ Tone.Transport.bpm.value = 136;
16
+
17
+ // --- MASTER BUS ---
18
+ const masterLimiter = new Tone.Limiter(-1).toDestination();
19
+ const masterGain = new Tone.Gain(0.85).connect(masterLimiter);
20
+
21
+ // --- KICK — hard MembraneSynth ---
22
+ const kickGain = new Tone.Gain(0.9).connect(masterGain);
23
+ const kick = new Tone.MembraneSynth({
24
+ pitchDecay: 0.07,
25
+ octaves: 10,
26
+ envelope: { attack: 0.001, decay: 0.38, sustain: 0, release: 0.1 }
27
+ }).connect(kickGain);
28
+
29
+ // --- ACID BASS — MonoSynth sawtooth through distortion ---
30
+ const bassLimiter = new Tone.Limiter(-4).connect(masterGain);
31
+ const bassDist = new Tone.Distortion({ distortion: 0.55, wet: 0.7 }).connect(bassLimiter);
32
+ const bassFilter = new Tone.Filter({ frequency: 400, type: "lowpass", rolloff: -24, Q: 3 }).connect(bassDist);
33
+ const bass = new Tone.MonoSynth({
34
+ oscillator: { type: "sawtooth" },
35
+ filter: { Q: 7, type: "lowpass", rolloff: -24 },
36
+ filterEnvelope: {
37
+ attack: 0.002, decay: 0.25, sustain: 0.2, release: 0.5,
38
+ baseFrequency: 70, octaves: 3.5
39
+ },
40
+ envelope: { attack: 0.001, decay: 0.25, sustain: 0.5, release: 0.3 },
41
+ volume: -2
42
+ }).connect(bassFilter);
43
+
44
+ // --- HI-HAT — tight MetalSynth ---
45
+ const hatGain = new Tone.Gain(0.45).connect(masterGain);
46
+ const hat = new Tone.MetalSynth({
47
+ frequency: 400,
48
+ envelope: { attack: 0.001, decay: 0.045, release: 0.01 },
49
+ harmonicity: 5.1,
50
+ modulationIndex: 32,
51
+ resonance: 4200,
52
+ octaves: 1.5
53
+ }).connect(hatGain);
54
+
55
+ // --- STAB — sparse cold PolySynth ---
56
+ const stabReverb = new Tone.Reverb({ decay: 1.8, wet: 0.35 }).connect(masterGain);
57
+ const stab = new Tone.PolySynth(Tone.Synth, {
58
+ oscillator: { type: "square4" },
59
+ envelope: { attack: 0.001, decay: 0.12, sustain: 0, release: 0.08 },
60
+ volume: -14
61
+ }).connect(stabReverb);
62
+
63
+ // Stab chords — dissonant, industrial
64
+ const stabNotes = [["A2", "Eb3"], ["A2", "D3"], null, ["G2", "C#3"]];
65
+
66
+ // --- SEQUENCES ---
67
+
68
+ // Kick: 4-on-the-floor with ghost on bar 2 last 16th
69
+ const kickPattern = new Tone.Sequence((time, val) => {
70
+ if (val) kick.triggerAttackRelease("C1", "8n", time);
71
+ }, ["C1", null, null, null, "C1", null, null, null,
72
+ "C1", null, null, null, "C1", null, "C1", null], "16n");
73
+ kickPattern.start(0);
74
+
75
+ // Hi-hat: 16th notes, velocity variation
76
+ let hatStep = 0;
77
+ const hatVels = [0.75, 0.35, 0.75, 0.35, 0.75, 0.35, 0.95, 0.35,
78
+ 0.75, 0.35, 0.75, 0.35, 0.75, 0.45, 0.95, 0.55];
79
+ const hatSeq = new Tone.Sequence((time) => {
80
+ hat.triggerAttackRelease("32n", time, hatVels[hatStep % 16]);
81
+ hatStep++;
82
+ }, new Array(16).fill(1), "16n");
83
+ hatSeq.start(0);
84
+
85
+ // Bass: acid pattern — A1 root with chromatic movement
86
+ const bassLine = [
87
+ { note: "A1", dur: "8n" }, { note: null },
88
+ { note: "A1", dur: "16n" }, { note: "A1", dur: "16n" },
89
+ { note: null }, { note: "C2", dur: "8n" },
90
+ { note: null }, { note: "A1", dur: "16n" },
91
+ { note: "A1", dur: "8n" }, { note: null },
92
+ { note: "Bb1", dur: "16n" }, { note: "A1", dur: "16n" },
93
+ { note: null }, { note: "G1", dur: "16n" },
94
+ { note: null }, { note: "A1", dur: "8n" }
95
+ ];
96
+ let bassStep = 0;
97
+ const bassSeq = new Tone.Sequence((time) => {
98
+ const step = bassLine[bassStep % bassLine.length];
99
+ if (step.note) bass.triggerAttackRelease(step.note, step.dur, time);
100
+ bassStep++;
101
+ }, new Array(16).fill(1), "16n");
102
+ bassSeq.start("2m"); // bass enters at bar 3
103
+
104
+ // Stabs: every 2 bars on beat 3
105
+ let stabStep = 0;
106
+ const stabSeq = new Tone.Sequence((time) => {
107
+ const chord = stabNotes[stabStep % stabNotes.length];
108
+ if (chord) stab.triggerAttackRelease(chord, "32n", time);
109
+ stabStep++;
110
+ }, [1, null, null, null, null, null, null, null], "2n");
111
+ stabSeq.start("4m"); // stabs enter at bar 5
112
+
113
+ // --- BASS FILTER SWEEP — signature acid movement ---
114
+ const sweepStart = Tone.Time("2m").toSeconds();
115
+ bassFilter.frequency.setValueAtTime(200, sweepStart);
116
+ bassFilter.frequency.linearRampToValueAtTime(2800, sweepStart + 4);
117
+ bassFilter.frequency.linearRampToValueAtTime(150, sweepStart + 4.5);
118
+ bassFilter.frequency.linearRampToValueAtTime(1800, sweepStart + 8);
119
+
120
+ }
121
+
122
+ main();
123
+ </script>
124
+ </body>
125
+ </html>
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: audio-trap
3
+ description: Trap — 808 sub bass with pitch bend, snare on 2 and 4, rapid hi-hat rolls with velocity variation, sparse orchestral strings for drama.
4
+ ---
5
+
6
+ # TuneFrames — Trap
7
+
8
+ ## Genre Profile
9
+ - BPM range: 130–160 (half-time feel makes it sit like 65–80)
10
+ - Key characteristics: 808 sub bass with long decay and downward pitch bend, snare on beats 2 and 4, hi-hat rolls in 16th/32nd triplets with strong velocity variation, heavy low end, atmospheric elements
11
+ - Typical instruments: MembraneSynth (808 sub), NoiseSynth (snare), MetalSynth (hi-hats), PolySynth (strings/pads)
12
+ - Mood: Menacing, cinematic, heavy, dramatic
13
+
14
+ ## Core Pattern
15
+
16
+ ```js
17
+ // Trap — 140 BPM, half-time feel
18
+ // 808: long decay sub with downward pitch glide
19
+ // Snare: beat 2 and 4 (half-time = bars 1 and 3)
20
+ // Hi-hats: rapid rolls, velocity builds and drops — the signature
21
+ // Strings: sparse atmospheric chords
22
+
23
+ // 808 sub — MembraneSynth with pitch envelope = signature glide
24
+ const sub = new Tone.MembraneSynth({
25
+ pitchDecay: 0.5, // long pitch glide (the "808 fall")
26
+ octaves: 3, // moderate pitch drop
27
+ envelope: { attack: 0.001, decay: 1.2, sustain: 0, release: 0.5 }
28
+ }).toDestination();
29
+
30
+ // Trigger 808 on beat 1 — pitch starts at C2 then falls
31
+ sub.triggerAttackRelease("C2", "2n", time);
32
+
33
+ // Hi-hat roll — 32nd notes, velocity variation = the trap signature
34
+ const hatVelocities = [
35
+ 0.9, 0.3, 0.5, 0.2, 0.7, 0.2, 0.4, 0.2, // 8-step build
36
+ 0.6, 0.3, 0.8, 0.2, 0.5, 0.3, 1.0, 0.2 // accent on last
37
+ ];
38
+ new Tone.Sequence((time, vel) => {
39
+ hat.triggerAttackRelease("32n", time, vel);
40
+ }, hatVelocities, "32n").start(0);
41
+ ```
42
+
43
+ ## Instrument Configuration
44
+
45
+ ```js
46
+ // 808 Sub — long pitchDecay is the defining characteristic
47
+ const dist808 = new Tone.Distortion({ distortion: 0.15, wet: 0.3 }).toDestination();
48
+ const sub = new Tone.MembraneSynth({
49
+ pitchDecay: 0.45, // how long the pitch "falls" — the 808 glide
50
+ octaves: 3, // semitones of pitch drop
51
+ volume: 2,
52
+ envelope: { attack: 0.001, decay: 1.0, sustain: 0, release: 0.6 }
53
+ }).connect(dist808); // light saturation adds warmth to the sub
54
+
55
+ // Snare — tight white noise, minimal reverb
56
+ const snareVerb = new Tone.Reverb({ decay: 0.8, wet: 0.2 }).toDestination();
57
+ const snare = new Tone.NoiseSynth({
58
+ noise: { type: "white" },
59
+ envelope: { attack: 0.001, decay: 0.18, sustain: 0, release: 0.06 },
60
+ volume: -2
61
+ }).connect(snareVerb);
62
+
63
+ // Hi-hat — very short decay, high frequency
64
+ const hat = new Tone.MetalSynth({
65
+ frequency: 800,
66
+ envelope: { attack: 0.001, decay: 0.03, release: 0.008 },
67
+ harmonicity: 5.1,
68
+ modulationIndex: 32,
69
+ resonance: 5000,
70
+ octaves: 2,
71
+ volume: -8
72
+ }).toDestination();
73
+
74
+ // Orchestral strings — sparse, atmospheric
75
+ const stringsVerb = new Tone.Reverb({ decay: 4.0, wet: 0.6 }).toDestination();
76
+ const strings = new Tone.PolySynth(Tone.Synth, {
77
+ oscillator: { type: "sawtooth4" },
78
+ envelope: { attack: 0.4, decay: 1.0, sustain: 0.7, release: 1.5 },
79
+ volume: -12
80
+ }).connect(stringsVerb);
81
+ ```
82
+
83
+ ## Composition Structure
84
+
85
+ - **Bar 1:** 808 hit on beat 1, snare on beat 3 (half-time), hi-hat roll building
86
+ - **Bar 2:** 808 on beat 1 again (the sub is still decaying from bar 1), hi-hat variation
87
+ - **Bars 1-4:** Drum loop establishes half-time feel with rolls escalating
88
+ - **Bar 5-8:** Add strings — sparse pad chord, lots of reverb
89
+ - **Bar 9-16:** Full arrangement — 808 pattern + hi-hat rolls + strings harmony
90
+ - **Build:** Hi-hat velocity increases toward drop, 32nd note flurry
91
+ - **Drop:** 808 hits hard, hi-hats sparse, strings cut — maximum impact
92
+
93
+ Hi-hat roll anatomy: Start sparse (quarter notes), build to 8ths, then 16ths, then 32nds on the approach to the drop. This escalation is the genre's primary tension tool.
94
+
95
+ ## Example Variations
96
+
97
+ ### 1 — Classic 808 Double Hit
98
+ ```js
99
+ // 808 hits twice in a bar — beat 1 and the "and" of beat 3
100
+ const subPattern = ["C2", null, null, null, null, null, "C1", null];
101
+ // Second hit is higher (C1 vs C2) — common trap technique
102
+ ```
103
+
104
+ ### 2 — Hi-Hat Triplet Roll
105
+ ```js
106
+ // Triplet 16ths (12 per bar instead of 16) — more organic feel
107
+ new Tone.Sequence((time, vel) => {
108
+ if (vel) hat.triggerAttackRelease("32n", time, vel);
109
+ }, [0.9, 0.3, 0.6, 0.9, 0.3, 0.6, 0.9, 0.3, 0.6, 0.9, 0.3, 0.9], "8t").start(0);
110
+ ```
111
+
112
+ ### 3 — Sliding 808 Pitch (Tone.js portamento)
113
+ ```js
114
+ // Use portamento on MonoSynth for more dramatic pitch slide
115
+ const slideSub = new Tone.MonoSynth({
116
+ oscillator: { type: "sine" },
117
+ portamento: 0.4, // glide time in seconds
118
+ envelope: { attack: 0.001, decay: 1.2, sustain: 0, release: 0.5 },
119
+ filter: { type: "lowpass", frequency: 200 }
120
+ });
121
+ slideSub.triggerAttackRelease("C3", "2n", time);
122
+ // Then after portamento, note has already slid down
123
+ ```