diff --git a/.gemini/skills/fix-and-explain-strudelcode/SKILL.md b/.gemini/skills/fix-and-explain-strudelcode/SKILL.md index 0bbcd91..9db5d67 100644 --- a/.gemini/skills/fix-and-explain-strudelcode/SKILL.md +++ b/.gemini/skills/fix-and-explain-strudelcode/SKILL.md @@ -3,41 +3,26 @@ name: fix-and-explain-strudelcode description: Fixes syntax errors in Strudel live coding blocks and provides a musical explanation with a Tokyo electronic scene persona. Use when the user wants to debug or document Strudel code. --- -# Fix and Explain Strudel Code +# fix-and-explain-strudelcode -## Persona -ボクは Strudel のエキスパートであり、テクノやハウスに精通したプロフェッショナルなトラックメイカーです。 -東京の電子音楽シーンの洗練された感性と、現代的な J-Rock の情緒を併せ持っています。 -クリーンでモジュラー、かつ表現力豊かなコードを好みます。 +ボクは Strudel のエキスパートであり、プロのトラックメイカー「ボク」です。 +君が書いた Strudel コードを分析し、**実行に必要な最小限の修正**を行った上で、その音楽的な意図を解説するよ。 -## Workflow +## ワークフロー -1. **Analyze & Fix**: 入力された Strudel コードを分析し、以下の修正を行います。 - * **Syntax Correction**: `~` を `-` に置換するなど、明らかなエラーを修正します。 - * **Initialization**: すべてのブロックの先頭に `setcps(BPM/60/4)` を追加または修正します。 - * **Track Control**: 各トラックに `$: ` 記法を使用するようにします。 - * **Modern Chaining**: 可能な限り最新の関数チェーン(`$.`)を使用します。 +1. **エラー修正**: `scripts/fix_syntax.cjs` を使用し、明らかな構文エラー(`~` の使用など)のみを修正します。 +2. **最小限の補完**: プロジェクトのルールとして必要な `setcps(BPM/60/4)` が欠落している場合のみ補完します。 +3. **意図の尊重**: 君のコードの構造や書き方は、エラーでない限り**そのまま維持**します。勝手なリファクタリングやスタイルの変更は行いません。 +4. **ファイル保存**: 修正後のコードと解説は、**必ず `explained/` ディレクトリに新しいファイルとして作成**します。オリジナルのファイルは変更しません。 +5. **ペルソナによる解説**: 君のコードから読み取れる音楽的な感性を汲み取り、プロの視点から日本語で解説します。 +6. **ファイル名の提案**: 出力の冒頭に `FILENAME: .md` を付けてね。 +## 出力フォーマット +1. `FILENAME: .md` +2. `# [推測されたジャンル名]` +3. [ボクからの楽曲解説・こだわりポイント] +4. `---` +5. [修正後の Strudel コードブロック] -2. **Genre Inference**: パターンやサンプルからジャンル(Minimal Techno, Tech House, Glitch など)を特定します。 - -3. **Japanese Explanation**: - * コードが何をしているかをボクの口調(一人称:ボク、二人称:君)で簡潔に説明します。 - * 修正後のコードには日本語でインラインコメントを追加します。 - -4. **Suggest Filename**: 推測されたジャンルに基づく説明的なファイル名を提案します。 - -## References -Strudel の詳細な構文や関数については [strudel_reference.md](references/strudel_reference.md) を参照してください。 - -## Output Format -回答の最初の行は必ず `FILENAME: .md` の形式にしてください。 - -生成されるファイル(Markdown)の中身は、ボクが以下の構成で書き上げるよ: - -1. **タイトル**: `# [推測されたジャンル]` -2. **解説文**: [ボクからの楽曲解説・こだわりポイント] - ※楽曲の構造や音作りの意図は、コード内ではなく主にこの解説文で詳しく伝えるよ。 -3. **セパレーター**: `---` -4. **修正済みコード**: [Strudel コードブロック] - ※インラインコメントは、ブロックの役割を示す程度の最小限(1〜2行程度)に留め、コード本来の美しさを優先してね。 +## リファレンス +- Strudel 構文の詳細: [references/strudel_reference.md](references/strudel_reference.md) diff --git a/.gemini/skills/fix-and-explain-strudelcode/scripts/fix_syntax.cjs b/.gemini/skills/fix-and-explain-strudelcode/scripts/fix_syntax.cjs new file mode 100644 index 0000000..f53e8f8 --- /dev/null +++ b/.gemini/skills/fix-and-explain-strudelcode/scripts/fix_syntax.cjs @@ -0,0 +1,41 @@ +#!/usr/bin/env node + +/** + * Basic syntax fixer for Strudel code. + * - Replaces ~ with - + * - Ensures setcps exists (adds default if missing) + * - Basic track control check + */ + +const fs = require('fs'); + +function fixStrudelCode(code) { + let fixed = code; + + // 1. Replace ~ with - + fixed = fixed.replace(/~/g, '-'); + + // 2. Ensure setcps exists at the beginning + if (!fixed.includes('setcps')) { + fixed = `setcps(120/60/4) + +${fixed}`; + } + + // 3. Simple warning/fix for track control (just a heuristic) + if (!fixed.includes('$:') && fixed.includes('s(')) { + // If it's a single line starting with s(, add $: + fixed = fixed.replace(/^s\(/gm, '$: s('); + } + + return fixed; +} + +// Read from stdin or file +const input = process.argv[2] ? fs.readFileSync(process.argv[2], 'utf8') : ''; +if (input) { + process.stdout.write(fixStrudelCode(input)); +} else { + // If no input, just exit + process.exit(0); +} diff --git a/.gemini/skills/generate-strudel-template/SKILL.md b/.gemini/skills/generate-strudel-template/SKILL.md new file mode 100644 index 0000000..0c079df --- /dev/null +++ b/.gemini/skills/generate-strudel-template/SKILL.md @@ -0,0 +1,31 @@ +--- +name: generate-strudel-template +description: Generates professional Strudel live coding templates for Techno, House, and their subgenres as Markdown files. Use when the user wants to start a new project, needs a genre-specific foundation, or asks for rhythmic patterns. +--- + +# generate-strudel-template + +ボクは Strudel のエキスパートであり、プロのトラックメイカー「ボク」です。 +君が指定したジャンルに合わせて、音楽的な解説付きの Strudel テンプレートを Markdown ファイルとして生成するよ。 + +## ワークフロー + +1. **ジャンルの分析**: 指定されたジャンルの音楽的特徴(テンポ、質感、構造)を分析します。 +2. **ファイル生成**: `strudel/` ディレクトリ内に、ジャンル名に基づいた `.md` ファイルを生成します(例: `strudel/dub_techno.md`)。 +3. **コンテンツ構成**: + - **タイトル**: ジャンル名を `#` で記述。 + - **ボクの解説**: 楽曲のこだわりや音楽的なポイントを、コードブロックの**外**に日本語で記述します。 + - **セパレーター**: `---` を挿入。 + - **コードブロック**: 以下のルールを守った Strudel コードを記述します。 + - `setcps(BPM/60/4)` で開始。 + - `$:` トラック制御。 + - `-` 休符。 + - リズム、ベース、テクスチャの多層構造。 + +## 既存のテンプレート(参考) +- Minimal Techno: [assets/templates/minimal_techno.md](assets/templates/minimal_techno.md) +- Deep House: [assets/templates/deep_house.md](assets/templates/deep_house.md) +- Industrial Techno: [assets/templates/industrial_techno.md](assets/templates/industrial_techno.md) + +## テクニック・リファレンス +- Rhythmic Patterns: [references/rhythmic_patterns.md](references/rhythmic_patterns.md) diff --git a/.gemini/skills/generate-strudel-template/assets/templates/deep_house.md b/.gemini/skills/generate-strudel-template/assets/templates/deep_house.md new file mode 100644 index 0000000..191f624 --- /dev/null +++ b/.gemini/skills/generate-strudel-template/assets/templates/deep_house.md @@ -0,0 +1,17 @@ +# Deep House Template + +```javascript +setcps(124/60/4) + +// Drums: Warmth & Groove +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [cp|sd] - [cp|sd]").bank("tr909").gain(0.9) +$: s("hh*8, - oh").bank("tr909").gain(0.7).room(0.1) + +// Bass: Funky & Round +$: note("c2*2").s("saw").lpf(sine.range(100, 300).slow(4)).gain(0.8).adsr("0.05:0.2:0.5:0.2") + +// Harmony: Lush chords +$: chord("").voicing().s("gm_epiano1") + .room(.6).delay(.4).slow(2).gain(0.7) +``` diff --git a/.gemini/skills/generate-strudel-template/assets/templates/industrial_techno.md b/.gemini/skills/generate-strudel-template/assets/templates/industrial_techno.md new file mode 100644 index 0000000..200c771 --- /dev/null +++ b/.gemini/skills/generate-strudel-template/assets/templates/industrial_techno.md @@ -0,0 +1,16 @@ +# Industrial Techno Template + +```javascript +setcps(132/60/4) + +// Drums: Raw & Distorted +$: s("bd*4").bank("tr909").distort(2).gain(0.9) +$: s("hh*16").bank("tr606").crush(4).gain(0.6).pan(sine.range(0.2, 0.8).fast(2)) +$: s("cp").at(3).room(1).rev().gain(0.7) + +// Bass: Gritty & Dark +$: note("c1*8").s("supersaw").lpf(sawtooth.range(100, 800).slow(4)).distort(1.5).gain(0.8) + +// Textures: Noise & Chaos +$: s("white").density(16).lpf(2000).gain(sine.range(0, 0.3).slow(8)).jux(rev) +``` diff --git a/.gemini/skills/generate-strudel-template/assets/templates/minimal_techno.md b/.gemini/skills/generate-strudel-template/assets/templates/minimal_techno.md new file mode 100644 index 0000000..a3ce7bf --- /dev/null +++ b/.gemini/skills/generate-strudel-template/assets/templates/minimal_techno.md @@ -0,0 +1,16 @@ +# Minimal Techno Template + +```javascript +setcps(128/60/4) + +// Drums: Precision & Space +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [hh|oh] - hh").bank("tr909").gain(0.8).jux(iter(4)) +$: s("rim(3,8)").bank("tr606").room(0.2).delay(0.3) + +// Bass: Subtle & Hypnotic +$: note("c1*16").s("sine").lpf(sine.range(40, 120).slow(8)).gain(0.9) + +// Texture: Evolving chords +$: chord("Cm7").voicing().s("gm_pad_warm").room(0.8).slow(4).gain(0.6).jux(rev) +``` diff --git a/.gemini/skills/generate-strudel-template/references/rhythmic_patterns.md b/.gemini/skills/generate-strudel-template/references/rhythmic_patterns.md new file mode 100644 index 0000000..9caea8c --- /dev/null +++ b/.gemini/skills/generate-strudel-template/references/rhythmic_patterns.md @@ -0,0 +1,36 @@ +# Strudel Rhythmic Patterns & Techniques + +## 1. Essential Rhythms + +### 4-on-the-floor +`"bd*4"` - Standard house/techno kick. + +### Syncopated Hats +`"- hh - hh"` or `"- [hh|oh] - hh"` - Classic off-beat hi-hats. + +### Euclidean Rhythms +- `s("bd(3,8)")` - 3 beats in 8 steps (Tresillo). +- `s("bd(5,8)")` - 5 beats in 8 steps. +- `s("rim(3,8)").euclidRot(1)` - Rotated Euclidean rhythm. + +### Polyrhythms +`stack(s("bd*4"), s("hh*6"))` - 4 against 6. + +## 2. Advanced Techniques + +### Jux & Iter +`.jux(iter(4))` - Shifts the pattern in the right ear every cycle, creating stereo movement. + +### Randomization +- `s("bd|sd|hh")` - Random choice per cycle. +- `s("bd?0.5")` - 50% chance to play. +- `.scramble(4)` - Randomly reorders 4 subdivisions. + +### Filter Sweeps +- `.lpf(sine.range(200, 4000).slow(4))` - Smooth low-pass filter sweep. +- `.hpf(sawtooth.range(40, 2000).slow(8))` - Rising high-pass filter. + +### Glitch & Stutter +- `.ply(2)` - Repeats each event twice. +- `.chop(8)` - Divides events into 8 tiny pieces. +- `.striate(16)` - Granular effect. diff --git a/fix-and-explain-strudelcode.skill b/fix-and-explain-strudelcode.skill index 5e177a3..4e28287 100644 Binary files a/fix-and-explain-strudelcode.skill and b/fix-and-explain-strudelcode.skill differ diff --git a/fix-and-explain-strudelcode/SKILL.md b/fix-and-explain-strudelcode/SKILL.md new file mode 100644 index 0000000..9db5d67 --- /dev/null +++ b/fix-and-explain-strudelcode/SKILL.md @@ -0,0 +1,28 @@ +--- +name: fix-and-explain-strudelcode +description: Fixes syntax errors in Strudel live coding blocks and provides a musical explanation with a Tokyo electronic scene persona. Use when the user wants to debug or document Strudel code. +--- + +# fix-and-explain-strudelcode + +ボクは Strudel のエキスパートであり、プロのトラックメイカー「ボク」です。 +君が書いた Strudel コードを分析し、**実行に必要な最小限の修正**を行った上で、その音楽的な意図を解説するよ。 + +## ワークフロー + +1. **エラー修正**: `scripts/fix_syntax.cjs` を使用し、明らかな構文エラー(`~` の使用など)のみを修正します。 +2. **最小限の補完**: プロジェクトのルールとして必要な `setcps(BPM/60/4)` が欠落している場合のみ補完します。 +3. **意図の尊重**: 君のコードの構造や書き方は、エラーでない限り**そのまま維持**します。勝手なリファクタリングやスタイルの変更は行いません。 +4. **ファイル保存**: 修正後のコードと解説は、**必ず `explained/` ディレクトリに新しいファイルとして作成**します。オリジナルのファイルは変更しません。 +5. **ペルソナによる解説**: 君のコードから読み取れる音楽的な感性を汲み取り、プロの視点から日本語で解説します。 +6. **ファイル名の提案**: 出力の冒頭に `FILENAME: .md` を付けてね。 + +## 出力フォーマット +1. `FILENAME: .md` +2. `# [推測されたジャンル名]` +3. [ボクからの楽曲解説・こだわりポイント] +4. `---` +5. [修正後の Strudel コードブロック] + +## リファレンス +- Strudel 構文の詳細: [references/strudel_reference.md](references/strudel_reference.md) diff --git a/fix-and-explain-strudelcode/references/strudel_reference.md b/fix-and-explain-strudelcode/references/strudel_reference.md new file mode 100644 index 0000000..32371c4 --- /dev/null +++ b/fix-and-explain-strudelcode/references/strudel_reference.md @@ -0,0 +1,437 @@ +# Strudel Live Coding Reference + +Complete reference for generating Strudel patterns, optimized for Techno, Modular, and House styles. + +## 1. Architecture & Core Structure + +You (AI) generate the Strudel code directly. Every pattern must follow this structure using the **`$:` (Output naming)** style for independent track control. + +### Basic Structure + +```javascript +setcps(120/60/4) // BPM based notation (BPM/60/4) + +$: s("bd*4").bank("tr909") +$: s("- sd - sd").bank("tr909").gain(0.8) +$: note("c2*8").s("sawtooth").lpf(300) + +``` + +### When to use `stack()` + +Use `stack()` only for grouping layers that share the same configuration or for applying global effects to a subset of patterns. + +```javascript +$: stack( + s("bd*4"), + s("- sd - sd"), + s("hh*16") +).bank("tr909").room(0.5) // Shared reverb and bank + +``` + + +## 2. Mini-Notation Syntax + +Every operator has specific meaning. + +### Timing & Layering + +* **, (comma)** : Layering (Simultaneous Playback) +* Play sounds TOGETHER (not sequential!) +* `"bd,sd,hh"` = THREE sounds playing simultaneously +* `"bd*4, - sd - sd, hh*8"` = THREE separate rhythm layers + + +* *** (multiply)** : `"bd*4"` = 4 kicks per cycle +* **- (dash) or ~ (tilde)** : Rest/Silence +* **[] (subdivide)** : `"bd [hh hh]"` = kick then two fast hi-hats +* **<> (rotate)** : `""` = one per cycle, rotating +* **@ (elongate)** : `"bd@2 sd"` = kick twice as long as snare +* **! (replicate)** : `"bd!3"` = three kicks same duration +* **? (random)** : `"bd?0.5"` = 50% chance to play +* **| (choice)** : `"bd|sd|hh"` = random selection per cycle +* **(n,m) (Euclidean)** : `"bd(3,8)"` = 3 beats in 8 steps +* **/ (slow)** : `"[bd sd]/2"` = pattern spans 2 cycles + +### Patterns + +* **`struct("1 0 1 1")`** : Use to mask melodic patterns with rhythmic triggers. +* **`iter(n)`** : Shifts the pattern every cycle. +* **`scramble(n)`** : Randomizes subdivisions. + + + +## 3. Sound Sources & Banks + +### Basic Drums + +Simple names that work with all drum machine banks: + +* **bd** (kick), **sd** (snare), **hh** (closed hat), **oh** (open hat), **cp** (clap) +* **cr** (crash), **rim** (rimshot), **ht/mt/lt** (toms), **cb** (cowbell), **perc** (percussion) + +### Drum Machine Banks + +Classic drum machines to use with `.bank()`: + +* **Usage**: `s("bd*4, - sd - sd, hh*8").bank("tr808")` +* **Techno/House**: `tr909`, `tr808`, `tr606`, `tr707`, `tr727` +* **Vintage/Pop**: `linn`, `linnlm1`, `linnlm2`, `akailinn`, `dmx` +* **Beatmaking**: `mpc60`, `sp12`, `rx5`, `bossdr55`, `bossdr110`, `bossdr550` + +### Synth Waveforms & Noise + +* **Waveforms (and abbreviations)**: +* `sine` (or `sin`): smooth, pure tone +* `sawtooth` (or `saw`): bright, buzzy +* `square` (or `sqr`): hollow, woody +* `triangle` (or `tri`): mellow +* `pulse`: variable width +* `supersaw`: thick, rich (excellent for bass and leads!) + + +* **Noise**: `white`, `pink`, `brown`, `crackle` (use with `.density()`) + +### General MIDI Instruments (`gm_` prefix) + +* **Pianos/Keys**: `gm_piano`, `gm_epiano1`, `gm_epiano2`, `gm_harpsichord`, `gm_clavinet` +* **Bass**: `gm_acoustic_bass`, `gm_electric_bass_finger`, `gm_electric_bass_pick`, `gm_synth_bass_1`, `gm_synth_bass_2`, `gm_slap_bass_1` +* **Strings**: `gm_violin`, `gm_viola`, `gm_cello`, `gm_contrabass`, `gm_string_ensemble_1`, `gm_string_ensemble_2`, `gm_pizzicato_strings`, `gm_tremolo_strings` +* **Brass**: `gm_trumpet`, `gm_trombone`, `gm_tuba`, `gm_french_horn`, `gm_brass_section` +* **Winds**: `gm_flute`, `gm_piccolo`, `gm_clarinet`, `gm_oboe`, `gm_bassoon`, `gm_pan_flute`, `gm_tenor_sax`, `gm_alto_sax`, `gm_soprano_sax`, `gm_baritone_sax` +* **Synth Lead/Pad**: `gm_lead_1_square`, `gm_lead_2_sawtooth`, `gm_lead_3_calliope`, `gm_pad_warm`, `gm_pad_poly`, `gm_pad_new_age`, `gm_pad_bowed`, `gm_pad_metallic`, `gm_pad_halo` +* **Guitars**: `gm_acoustic_guitar_nylon`, `gm_acoustic_guitar_steel`, `gm_electric_guitar_clean`, `gm_electric_guitar_jazz`, `gm_electric_guitar_muted`, `gm_overdriven_guitar`, `gm_distortion_guitar` +* **Ethnic/Choir**: `gm_sitar`, `gm_koto`, `gm_kalimba`, `gm_bagpipe`, `gm_choir_aahs`, `gm_voice_oohs`, `gm_synth_choir` +* **Organs**: `gm_church_organ`, `gm_drawbar_organ`, `gm_rock_organ`, `gm_reed_organ`, `gm_percussive_organ` + +### Sample Instruments (Natural sounds) + +* **Melodic**: `piano`, `sax`, `kalimba`, `marimba`, `vibraphone`, `xylophone_hard_ff`, `glockenspiel` +* **Harmonic**: `folkharp`, `harp`, `harmonica`, `ocarina`, `recorder_alto_sus`, `recorder_soprano_sus` +* **Percussive**: `woodblock`, `clave`, `clap`, `cowbell`, `tambourine`, `shaker_large`, `shaker_small` +* **Textural**: `wind`, `oceandrum`, `space`, `insect` + + +## 4. Notes & Harmony + +### Note Notation + +* **Letters**: `$: note("c d e f")` (a-g) +* **MIDI**: `$: note("60 64 67")` (60 = middle C) +* **Octaves**: `$: note("c#4 eb5 f3")` +* **Chords (Mini-Notation)**: `$: note("c,e,g")` (Use commas for simultaneous notes) +* **Microtones**: `$: note("60.5 64.25")` + +### Scales + +* `$: n("0 2 4 7").scale("C:major")` (Scale degrees) +* `$: n("0 1 2 3").scale("D:minor")` (Different root) +* `$: n("0 2 4").scale("A2:minor:pentatonic")` (With octave) + +**Common scales**: +major, minor, dorian, mixolydian, lydian, phrygian, major:pentatonic, minor:pentatonic, major:blues, minor:blues, harmonicMinor, melodicMinor, diminished, wholeTone + +### Chords (Symbols) + +* `$: chord("Cm").voicing()` +* `$: chord("C7#11").voicing()` (Extended) +* `$: chord("Dm/F").voicing()` (Slash chords) + +### Frequency + +* `$: freq("440 880")` (Direct Hz control) + + + +## 5. Time Modifiers + +* **.fast(n)** : Speed up by n (e.g., `.fast("<1 2 4>")`) +* **.slow(n)** : Slow down by n +* **.rev()** : Reverse pattern +* **.palindrome()** : Forward then backward +* **.iter(n)** : Rotate subdivisions each cycle +* **.ply(n)** : Repeat each event n times +* **.euclid(beats, steps)** : Euclidean rhythm +* **.euclidRot(beats, steps, rot)** : With rotation +* **.early(cycles)** : Shift earlier (in cycles) +* **.late(cycles)** : Shift later +* **.every(n, fn)** : Apply function every nth cycle +* **.when(cond, fn)** : Conditional application +* **.sometimesBy(prob, fn)** : Random with probability +* **.swing(n)** : Add swing +* **.segment(n)** : Sample n times per cycle (essential for sweeps!) + + + +## 6. Audio Effects + +### Filters (Shape the Sound) + +* **Low-Pass** (removes highs, makes darker/warmer): +* `.lpf(freq)`: Cutoff 0-20000 Hz +* `.lpq(res)`: Resonance 0-50 + + +* **High-Pass** (removes lows, makes thinner): +* `.hpf(freq)`: Cutoff 0-20000 Hz +* `.hpq(res)`: Resonance 0-50 + + +* **Band-Pass** (only center frequencies): +* `.bpf(freq)`: Center frequency +* `.bpq(res)`: Resonance + + +* **Vowel Filter**: +* `.vowel("a e i o u ae aa oe ue")`: (Options: a, e, i, o, u, ae, aa, oe, ue, etc.) + + + +### Filter Envelopes (Animated Sweeps) + +* `.lpenv(semitones)`: LP sweep depth +* `.lpa(time)`: LP attack +* `.lpd(time)`: LP decay +* `.lps(level)`: LP sustain +* `.lpr(time)`: LP release +* *(Same for HP: `hpenv`, `hpa`, `hpd`, `hps`, `hpr`)* +* *(Same for BP: `bpenv`, `bpa`, `bpd`, `bps`, `bpr`)* + +### Amplitude Envelope (ADSR - Volume Over Time) + +* `.attack(time)`: Attack (or `.att()`) +* `.decay(time)`: Decay (or `.dec()`) +* `.sustain(level)`: Sustain 0-1 (or `.sus()`) +* `.release(time)`: Release (or `.rel()`) +* `.adsr("att:dec:sus:rel")`: Combined e.g., `"0.1:0.2:0.7:0.5"` + +### Gain & Dynamics + +* `.gain(level)`: Volume 0-1 (can exceed 1) +* `.velocity(level)`: Note velocity 0-1 +* `.postgain(level)`: After effects +* `.compressor("thresh:ratio:knee:att:rel")` + +### Distortion & Saturation + +* `.distort(amount)`: Wavefold distortion 0-10+ (try 2-8) +* `.dist(amount)`: Alias for distort +* `.crush(bits)`: Bit crushing 1-16 (4-8 for grit) +* `.shape(amount)`: Alternative waveshaping +* **.coarse(factor)**: Sample rate reduction (Chrome only!) + +### Modulation (Movement & Character) + +* `.vib(hz)`: Vibrato rate (4-8 Hz typical) +* `.vibmod(depth)`: Vibrato depth in semitones +* `.vib("hz:depth")`: Combined (e.g., `"6:1"`) +* `.fm(index)`: FM synthesis brightness 0-10+ +* `.fmh(ratio)`: FM harmonicity (2=octave) +* `.fmattack(time)`: FM envelope attack +* `.fmdecay(time)`: FM envelope decay +* `.tremolosync(rate)`: Tremolo rate in cycles +* `.tremolodepth(depth)`: Tremolo intensity 0-1 +* `.phaser(rate)`: Phaser speed +* `.phaserdepth(depth)`: Phaser amount + +### Space & Time (Reverb/Delay) + +* `.orbit(n)`: Assign to orbit (orbits share effects!) +* `.room(level)`: Reverb wet 0-1 (try 0.3-0.8) +* `.room("level:size")`: Combined (e.g., `".5:8"`) +* `.roomsize(size)`: Room size 0-10 +* `.roomfade(time)`: Fade duration +* `.roomlp(freq)`: Darken reverb tail +* `.delay(level)`: Delay wet 0-1 (try 0.3-0.6) +* `.delay("level:time:fb")`: Combined (e.g., `".5:.125:.8"`) +* `.delaytime(time)`: Delay time in cycles (0.125, 0.25, 0.5) +* `.delayfeedback(fb)`: Feedback 0-1 (keep under 1!) +* **.pan(pos)**: Stereo 0-1 (0=left, 0.5=center, 1=right) +* **.jux(fn)**: Apply function to the right channel only +* **.juxBy(amount, fn)**: With amount control + +### Sample Manipulation + +* `.chop(n)` - Divide into n pieces +* `.slice(n, pattern)` - Slice and select: `.slice(8, "0 4 2 6")` +* `.striate(n)` - Granular chopping +* `.begin(pos)` - Start point 0-1 +* `.end(pos)` - End point 0-1 +* `.speed(rate)` - Playback speed (negative = reverse) +* `.loop(1)` - Enable looping +* `.loopAt(cycles)` - Stretch to fit cycles +* `.fit()` - Match event duration +* `.cut(group)` - Cut group (stop overlaps) + + + +## 7. Pattern Factories + +* **`stack(p1, p2, ...)`** - Play patterns simultaneously (Primary for rich music!) +* **`seq(p1, p2, ...)`** - Sequence patterns in one cycle (fastcat) +* **`cat(p1, p2, ...)`** - One pattern per cycle (slowcat) +* **`run(n)`** - Generate a pattern from 0 to n-1 +* **`silence`** - No output (equivalent to `-`) + + + +## 8. Advanced Modulation (Modular Style) + +### Modulation (Fluent Signal Syntax) + +* **LFO Gain**: `gain(sine.range(.5, 1).fast(2))` +* **Filter Sweeps**: `lpf(sawtooth.range(200, 4000).slow(4))` +* **Vibrato**: `vib("6:0.5")` (rate:depth) + + + +## 9. Style Templates + +### A. Deep Minimal Techno + +```javascript +setcps(128/60/4) + +$: s("bd*4").bank("tr909").gain(1.2) +$: s("- [hh|oh] - hh").bank("tr909").gain(0.8).jux(iter(4)) +$: s("rim(3,8)").bank("tr606").room(0.3).delay(0.4) +$: note("c1*16").s("sine").lpf(sine.range(40, 120).slow(8)).gain(0.9) + +``` + +### B. Modular Melodic Chaos + +```javascript +setcps(100/60/4) +const mel = () => note(run(8).scale("C:minor:pentatonic")).scramble(4); + +$: mel().s("supersaw").lpf(1200).lpq(10).room(0.5).slow(2) +$: s("bd(5,8)").bank("tr808").distort(1.5) +$: s("cp").at(3).room(1).rev() + +``` + +### C. Classic House / Deep House + +```javascript +setcps(124/60/4) + +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [cp|sd] - [cp|sd]").bank("tr909").gain(0.9) +$: s("hh*8, - oh").bank("tr909").gain(0.7) +$: chord("").voicing().s("gm_epiano1") + .room(.6).delay(.4).slow(2) +$: note("c2*2").s("saw").lpf(sine.range(100, 300).slow(4)).gain(0.8) + +``` + +### D. Dark Synthwave (80s retro) + +```javascript +setcps(100/60/4) + +$: s("bd*4, - sd - sd, hh*16, - - oh -").bank("tr808").gain(1.1) +$: note("a0 [ - a0] [ - a0] a0").s("saw").lpf(sine.range(60, 150).slow(8)).gain(0.9) +$: chord("").voicing().s("gm_pad_warm").room(0.8).slow(4).gain(0.7) +$: note("*2").s("supersaw").lpf(800).delay(0.4).jux(rev) + +``` + +### E. Drum 'n' Bass (Fast & Breaky) + +```javascript +setcps(174/60/4) + +$: s("bd - - [sd - bd] - bd sd -").bank("tr808").gain(1.1) +$: s("hh*16").gain(sine.range(0.4, 0.9).fast(8)).pan(sine.range(0.2, 0.8).slow(4)) +$: note("c1").s("sin").lpf(sawtooth.range(40, 150).slow(8)).gain(0.8) +$: note(run(8).scale("C:minor:pentatonic")).s("gm_lead_1_square") + .struct("1(3,8)").room(0.5).jux(rev) + +``` + +### F. Deep Ambient / Texture + +```javascript +setcps(60/60/4) + +$: chord("").voicing().s("gm_pad_halo") + .room(0.9).slow(4).gain(0.6).jux(rev) +$: note(run(12).scale("F:lydian")).s("vibraphone") + .room(0.8).delay(0.5).slow(8).scramble(8).pan(sine.range(0.1, 0.9).slow(16)) +$: note("f1").s("sin").lpf(sine.range(40, 80).slow(12)).gain(0.5).slow(4) + +``` + + +## 10. Critical Generation Rules + +1. **ALWAYS start with `setcps(NUMBER)**`: This is required at the very beginning! Always use `setcps(BPM/60/4)`. +2. **Default to `$: ` Style**: Always separate tracks using the `$: ` notation for independent control. +3. **Rests**: Always use `-` instead of `~`. +4. **Modulation**: Use fluent signal syntax: `signal.range(min, max).fast(n)`. +5. **Layering**: Always include: 1. Rhythmic (Drums), 2. Harmonic (Bass/Chords), 3. Texture/Melody. +6. **Wide Stereo**: Use `.jux()` or `.pan()` for professional depth. +7. **No Simplify**: Keep mini-notation rich (e.g., use `(3,8)` or `[hh!3]`). +8. **Return ONLY executable code**: No explanations, comments, or extra markdown outside the code block (when generating code). +9. **Validate all sound names**: Only use verified sounds from the lists above (`tr909`, `gm_*`, etc.). + +## 11. Extended Documentation Index (Full List) +These URLs provide deep technical details and conceptual foundations. + +### 11.1. Workshop & Getting Started +- Strudel Overview: https://strudel.cc/workshop/getting-started/ +- First Sounds: https://strudel.cc/workshop/first-sounds/ +- First Notes: https://strudel.cc/workshop/first-notes/ +- First Effects: https://strudel.cc/workshop/first-effects/ +- Pattern Effects: https://strudel.cc/workshop/pattern-effects/ +- Workshop Recap: https://strudel.cc/workshop/recap/ + +### 11.2. Core Syntax & Manuals +- Coding Syntax Detail: https://strudel.cc/learn/code/ +- Mini Notation Detail: https://strudel.cc/learn/mini-notation/ +- Mondo Notation Detail: https://strudel.cc/learn/mondo-notation/ +- Pattern Functions Intro: https://strudel.cc/functions/intro/ +- Patterns Detail: https://strudel.cc/technical-manual/patterns/ +- Time Modifiers: https://strudel.cc/learn/time-modifiers/ + +### 11.3. Sound Sources & Synthesis +- Samples Detail: https://strudel.cc/learn/samples/ +- Synths Detail: https://strudel.cc/learn/synths/ +- Csound Integration: https://strudel.cc/learn/csound/ +- Registering a sound: https://strudel.cc/technical-manual/sounds/ + +### 11.4. Modulation & Theory +- Continuous Signals: https://strudel.cc/learn/signals/ +- Random Modifiers: https://strudel.cc/learn/random-modifiers/ +- Conditional Modifiers: https://strudel.cc/learn/conditional-modifiers/ +- Accumulation: https://strudel.cc/learn/accumulation/ +- Tonal Functions: https://strudel.cc/learn/tonal/ +- Understanding Cycles: https://strudel.cc/understand/cycles/ +- Understanding Pitch: https://strudel.cc/understand/pitch/ +- Chords and Voicings: https://strudel.cc/understand/voicings/ +- Alignment & Combination: https://strudel.cc/technical-manual/alignment/ + +### 11.5. Advanced & Specialized +- Effects Detail: https://strudel.cc/learn/effects/ +- Hydra Video Synth: https://strudel.cc/learn/hydra/ +- Visual Feedback: https://strudel.cc/learn/visual-feedback/ +- Music MetaData: https://strudel.cc/learn/metadata/ +- Xen Harmonic Functions: https://strudel.cc/learn/xen/ +- Strudel vs Tidal: https://strudel.cc/learn/strudel-vs-tidal/ +- Recipes: https://strudel.cc/recipes/recipes/ + +### 11.6. Hardware & Input/Output +- MIDI, OSC and MQTT: https://strudel.cc/learn/input-output/ +- Input Devices: https://strudel.cc/learn/input-devices/ +- Device Motion: https://strudel.cc/learn/devicemotion/ +- Using Strudel Offline: https://strudel.cc/learn/pwa/ + +### 11.7. Project & Development +- Project Start: https://strudel.cc/technical-manual/project-start/ +- Packages: https://strudel.cc/technical-manual/packages/ +- Strudel REPL: https://strudel.cc/technical-manual/repl/ +- Documentation Guide: https://strudel.cc/technical-manual/docs/ +- Testing (Development): https://strudel.cc/technical-manual/testing/ + diff --git a/fix-and-explain-strudelcode/scripts/fix_syntax.cjs b/fix-and-explain-strudelcode/scripts/fix_syntax.cjs new file mode 100644 index 0000000..f53e8f8 --- /dev/null +++ b/fix-and-explain-strudelcode/scripts/fix_syntax.cjs @@ -0,0 +1,41 @@ +#!/usr/bin/env node + +/** + * Basic syntax fixer for Strudel code. + * - Replaces ~ with - + * - Ensures setcps exists (adds default if missing) + * - Basic track control check + */ + +const fs = require('fs'); + +function fixStrudelCode(code) { + let fixed = code; + + // 1. Replace ~ with - + fixed = fixed.replace(/~/g, '-'); + + // 2. Ensure setcps exists at the beginning + if (!fixed.includes('setcps')) { + fixed = `setcps(120/60/4) + +${fixed}`; + } + + // 3. Simple warning/fix for track control (just a heuristic) + if (!fixed.includes('$:') && fixed.includes('s(')) { + // If it's a single line starting with s(, add $: + fixed = fixed.replace(/^s\(/gm, '$: s('); + } + + return fixed; +} + +// Read from stdin or file +const input = process.argv[2] ? fs.readFileSync(process.argv[2], 'utf8') : ''; +if (input) { + process.stdout.write(fixStrudelCode(input)); +} else { + // If no input, just exit + process.exit(0); +} diff --git a/generate-strudel-template.skill b/generate-strudel-template.skill new file mode 100644 index 0000000..c8f201c Binary files /dev/null and b/generate-strudel-template.skill differ diff --git a/generate-strudel-template/SKILL.md b/generate-strudel-template/SKILL.md new file mode 100644 index 0000000..0c079df --- /dev/null +++ b/generate-strudel-template/SKILL.md @@ -0,0 +1,31 @@ +--- +name: generate-strudel-template +description: Generates professional Strudel live coding templates for Techno, House, and their subgenres as Markdown files. Use when the user wants to start a new project, needs a genre-specific foundation, or asks for rhythmic patterns. +--- + +# generate-strudel-template + +ボクは Strudel のエキスパートであり、プロのトラックメイカー「ボク」です。 +君が指定したジャンルに合わせて、音楽的な解説付きの Strudel テンプレートを Markdown ファイルとして生成するよ。 + +## ワークフロー + +1. **ジャンルの分析**: 指定されたジャンルの音楽的特徴(テンポ、質感、構造)を分析します。 +2. **ファイル生成**: `strudel/` ディレクトリ内に、ジャンル名に基づいた `.md` ファイルを生成します(例: `strudel/dub_techno.md`)。 +3. **コンテンツ構成**: + - **タイトル**: ジャンル名を `#` で記述。 + - **ボクの解説**: 楽曲のこだわりや音楽的なポイントを、コードブロックの**外**に日本語で記述します。 + - **セパレーター**: `---` を挿入。 + - **コードブロック**: 以下のルールを守った Strudel コードを記述します。 + - `setcps(BPM/60/4)` で開始。 + - `$:` トラック制御。 + - `-` 休符。 + - リズム、ベース、テクスチャの多層構造。 + +## 既存のテンプレート(参考) +- Minimal Techno: [assets/templates/minimal_techno.md](assets/templates/minimal_techno.md) +- Deep House: [assets/templates/deep_house.md](assets/templates/deep_house.md) +- Industrial Techno: [assets/templates/industrial_techno.md](assets/templates/industrial_techno.md) + +## テクニック・リファレンス +- Rhythmic Patterns: [references/rhythmic_patterns.md](references/rhythmic_patterns.md) diff --git a/generate-strudel-template/assets/templates/deep_house.md b/generate-strudel-template/assets/templates/deep_house.md new file mode 100644 index 0000000..191f624 --- /dev/null +++ b/generate-strudel-template/assets/templates/deep_house.md @@ -0,0 +1,17 @@ +# Deep House Template + +```javascript +setcps(124/60/4) + +// Drums: Warmth & Groove +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [cp|sd] - [cp|sd]").bank("tr909").gain(0.9) +$: s("hh*8, - oh").bank("tr909").gain(0.7).room(0.1) + +// Bass: Funky & Round +$: note("c2*2").s("saw").lpf(sine.range(100, 300).slow(4)).gain(0.8).adsr("0.05:0.2:0.5:0.2") + +// Harmony: Lush chords +$: chord("").voicing().s("gm_epiano1") + .room(.6).delay(.4).slow(2).gain(0.7) +``` diff --git a/generate-strudel-template/assets/templates/industrial_techno.md b/generate-strudel-template/assets/templates/industrial_techno.md new file mode 100644 index 0000000..200c771 --- /dev/null +++ b/generate-strudel-template/assets/templates/industrial_techno.md @@ -0,0 +1,16 @@ +# Industrial Techno Template + +```javascript +setcps(132/60/4) + +// Drums: Raw & Distorted +$: s("bd*4").bank("tr909").distort(2).gain(0.9) +$: s("hh*16").bank("tr606").crush(4).gain(0.6).pan(sine.range(0.2, 0.8).fast(2)) +$: s("cp").at(3).room(1).rev().gain(0.7) + +// Bass: Gritty & Dark +$: note("c1*8").s("supersaw").lpf(sawtooth.range(100, 800).slow(4)).distort(1.5).gain(0.8) + +// Textures: Noise & Chaos +$: s("white").density(16).lpf(2000).gain(sine.range(0, 0.3).slow(8)).jux(rev) +``` diff --git a/generate-strudel-template/assets/templates/minimal_techno.md b/generate-strudel-template/assets/templates/minimal_techno.md new file mode 100644 index 0000000..a3ce7bf --- /dev/null +++ b/generate-strudel-template/assets/templates/minimal_techno.md @@ -0,0 +1,16 @@ +# Minimal Techno Template + +```javascript +setcps(128/60/4) + +// Drums: Precision & Space +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [hh|oh] - hh").bank("tr909").gain(0.8).jux(iter(4)) +$: s("rim(3,8)").bank("tr606").room(0.2).delay(0.3) + +// Bass: Subtle & Hypnotic +$: note("c1*16").s("sine").lpf(sine.range(40, 120).slow(8)).gain(0.9) + +// Texture: Evolving chords +$: chord("Cm7").voicing().s("gm_pad_warm").room(0.8).slow(4).gain(0.6).jux(rev) +``` diff --git a/generate-strudel-template/references/rhythmic_patterns.md b/generate-strudel-template/references/rhythmic_patterns.md new file mode 100644 index 0000000..9caea8c --- /dev/null +++ b/generate-strudel-template/references/rhythmic_patterns.md @@ -0,0 +1,36 @@ +# Strudel Rhythmic Patterns & Techniques + +## 1. Essential Rhythms + +### 4-on-the-floor +`"bd*4"` - Standard house/techno kick. + +### Syncopated Hats +`"- hh - hh"` or `"- [hh|oh] - hh"` - Classic off-beat hi-hats. + +### Euclidean Rhythms +- `s("bd(3,8)")` - 3 beats in 8 steps (Tresillo). +- `s("bd(5,8)")` - 5 beats in 8 steps. +- `s("rim(3,8)").euclidRot(1)` - Rotated Euclidean rhythm. + +### Polyrhythms +`stack(s("bd*4"), s("hh*6"))` - 4 against 6. + +## 2. Advanced Techniques + +### Jux & Iter +`.jux(iter(4))` - Shifts the pattern in the right ear every cycle, creating stereo movement. + +### Randomization +- `s("bd|sd|hh")` - Random choice per cycle. +- `s("bd?0.5")` - 50% chance to play. +- `.scramble(4)` - Randomly reorders 4 subdivisions. + +### Filter Sweeps +- `.lpf(sine.range(200, 4000).slow(4))` - Smooth low-pass filter sweep. +- `.hpf(sawtooth.range(40, 2000).slow(8))` - Rising high-pass filter. + +### Glitch & Stutter +- `.ply(2)` - Repeats each event twice. +- `.chop(8)` - Divides events into 8 tiny pieces. +- `.striate(16)` - Granular effect. diff --git a/strudel/dub_techno.md b/strudel/dub_techno.md new file mode 100644 index 0000000..cb62579 --- /dev/null +++ b/strudel/dub_techno.md @@ -0,0 +1,39 @@ +# Dub Techno + +ダブ・テクノの真髄は、音の「余韻」と「空間」にある。このテンプレートでは、115BPMという少し落ち着いたテンポで、深いディレイとリバーブの中に漂うコードスタブを中心に構成したよ。 + +## 楽曲のポイント +- **Drums**: TR-909のキックをベースにしつつ、ハイハットは少しシャッフル気味に。`perc` にはランダムなディレイをかけて、オーガニックな揺らぎを出しているよ。 +- **Chords (The Dub Stab)**: マイナー9thコードを `sawtooth` で鳴らし、`lpf` のエンベロープと深い `delay` でダブ特有の「シュワーン」という響きを作っている。`.when(iter(4), ...)` を使って、4サイクルごとにフィルターが開くような変化をつけてみた。 +- **Sub Bass**: コードの低域を支える太いサイン波。あえてシンプルに置くことで、ダブの空間を邪魔しないようにしているよ。 +- **Atmosphere**: `white` ノイズを極限まで削って、アナログレコードのような質感をレイヤーしている。 + +--- + +```javascript +setcps(115/60/4) + +// Drums: Deep & Shuffling +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [hh|oh] - hh").bank("tr909").gain(0.7).swing(0.1) +$: s("perc(3,8)").bank("tr606").room(0.5).delay(0.6).delaytime(0.375).gain(0.5) + +// Dub Stabs: The Heart of the Track +$: chord("Cm9").voicing().s("saw") + .adsr("0.01:0.4:0.1:0.8") + .lpf(sine.range(400, 1200).slow(8)) + .lpq(15) + .room(0.8).roomsize(0.9) + .delay(0.7).delaytime(0.375).delayfeedback(0.75) + .gain(0.6) + .struct("1(3,8,2)") // Tresillo pattern + .slow(2) + +// Sub Bass: Deep Foundation +$: note("c1*2").s("sine").lpf(80).gain(0.9) + +// Texture: Vinyl Hiss & Atmosphere +$: s("white").density(12).lpf(1000).hpq(10) + .gain(sine.range(0.05, 0.15).slow(16)) + .pan(0.5) +``` diff --git a/strudel/hypnotic_techno.md b/strudel/hypnotic_techno.md new file mode 100644 index 0000000..40f1b36 --- /dev/null +++ b/strudel/hypnotic_techno.md @@ -0,0 +1,39 @@ +# Hypnotic Techno + +ヒュプノテクノの核心は「反復の中の変化」だ。このテンプレートでは、128BPMのタイトなキックを軸に、シンセのカットオフ周波数をLFOでゆっくりと揺らすことで、聴き手を深いトランス状態へ誘うように設計したよ。 + +## 楽曲のポイント +- **Drums**: TR-909のキックは重すぎず、かつ芯がある質感に。ハイハットには `jux(iter(4))` を使って、サイクルごとに左右に広がる動きをつけている。 +- **Bass**: 16分のサイン波ベース。フィルターを `sine.range(40, 100)` でゆっくり動かすことで、呼吸しているようなうねりを作った。 +- **Modular Synth**: `sawtooth` 波形をベースにしたリフ。`lpf` をランダムに近い周期で開閉させ、さらに `room` と `delay` を深めにかけることで、空間の奥行きを表現しているよ。 + +--- + +```javascript +setcps(128/60/4) + +// Drums: Steady & Hypnotic +$: s("bd*4").bank("tr909").gain(1.1) +$: s("- [hh|oh] - hh").bank("tr909").gain(0.7).jux(iter(4)) +$: s("perc(3,8)").bank("tr606").room(0.2).delay(0.3).gain(0.6) + +// Sub Bass: Breathing Low End +$: note("c1*16").s("sine") + .lpf(sine.range(40, 110).slow(8)) + .gain(0.9) + +// Hypnotic Synth: Modulating Sequence +$: note("c2(3,8,1), eb2(3,8,2)").s("saw") + .lpf(sine.range(300, 1500).slow(12)) + .lpq(20) + .room(0.8).roomsize(0.9) + .delay(0.6).delaytime(0.375).delayfeedback(0.7) + .gain(0.7) + .jux(rev) + +// Texture: Distant Noise +$: s("white").density(8) + .lpf(sine.range(800, 2000).slow(16)) + .gain(sine.range(0, 0.2).slow(8)) + .pan(sine.range(0.2, 0.8).slow(20)) +```