pycodedj 0.4.0__tar.gz → 0.5.1__tar.gz

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 (38) hide show
  1. {pycodedj-0.4.0 → pycodedj-0.5.1}/CHANGELOG.md +28 -0
  2. {pycodedj-0.4.0 → pycodedj-0.5.1}/PKG-INFO +18 -2
  3. {pycodedj-0.4.0 → pycodedj-0.5.1}/README.ja.md +17 -1
  4. {pycodedj-0.4.0 → pycodedj-0.5.1}/README.md +17 -1
  5. {pycodedj-0.4.0 → pycodedj-0.5.1}/docs/manual.html +85 -15
  6. {pycodedj-0.4.0 → pycodedj-0.5.1}/docs/manual.ja.md +78 -12
  7. {pycodedj-0.4.0 → pycodedj-0.5.1}/docs/manual.md +78 -12
  8. pycodedj-0.5.1/examples/club_set.py +107 -0
  9. {pycodedj-0.4.0 → pycodedj-0.5.1}/pyproject.toml +1 -1
  10. {pycodedj-0.4.0 → pycodedj-0.5.1}/sc/synths.scd +100 -41
  11. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/__init__.py +1 -1
  12. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/__main__.py +2 -0
  13. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/engine.py +2 -1
  14. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/osc_bridge.py +5 -2
  15. pycodedj-0.5.1/src/pycodedj/pattern.py +123 -0
  16. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_engine.py +33 -1
  17. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_osc_bridge.py +45 -5
  18. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_pattern.py +79 -1
  19. pycodedj-0.4.0/examples/club_set.py +0 -150
  20. pycodedj-0.4.0/src/pycodedj/pattern.py +0 -47
  21. {pycodedj-0.4.0 → pycodedj-0.5.1}/.github/workflows/workflow.yml +0 -0
  22. {pycodedj-0.4.0 → pycodedj-0.5.1}/.gitignore +0 -0
  23. {pycodedj-0.4.0 → pycodedj-0.5.1}/LICENSE +0 -0
  24. {pycodedj-0.4.0 → pycodedj-0.5.1}/docs/CNAME +0 -0
  25. {pycodedj-0.4.0 → pycodedj-0.5.1}/docs/index.html +0 -0
  26. {pycodedj-0.4.0 → pycodedj-0.5.1}/examples/demo.py +0 -0
  27. {pycodedj-0.4.0 → pycodedj-0.5.1}/examples/hello_sc.py +0 -0
  28. {pycodedj-0.4.0 → pycodedj-0.5.1}/examples/sound_showcase.py +0 -0
  29. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/_loop.py +0 -0
  30. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/analyzer.py +0 -0
  31. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/block_parser.py +0 -0
  32. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/mapper.py +0 -0
  33. {pycodedj-0.4.0 → pycodedj-0.5.1}/src/pycodedj/watcher.py +0 -0
  34. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/__init__.py +0 -0
  35. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_analyzer.py +0 -0
  36. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_block_parser.py +0 -0
  37. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_mapper.py +0 -0
  38. {pycodedj-0.4.0 → pycodedj-0.5.1}/tests/test_watcher.py +0 -0
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1] - 2026-05-08
4
+
5
+ ### Improvements
6
+
7
+ - `examples/club_set.py` を `pattern()` / `synth=` ベースの重低音クラブセットに刷新。4つ打ちキック、ランブル、サブ、アシッド、ハット、フィル、空間ノイズを含む 11 ループ構成に変更
8
+ - `pycodedj --version` を追加し、公開前チェックでパッケージバージョンを確認できるようにした
9
+
10
+ ### Docs
11
+
12
+ - `docs/manual.ja.md` / `docs/manual.md` / `docs/manual.html` — ループ名と音色名の違いを明確化し、音色は `synth=` で指定することを追記
13
+ - `docs/manual.ja.md` / `docs/manual.md` / `docs/manual.html` — `examples/club_set.py` の重低音クラブセットの使い方と主要レイヤー一覧を追加
14
+ - `README.ja.md` / `README.md` — `examples/club_set.py` の説明を現在の 11 ループ構成に更新
15
+
16
+ ## [0.5.0] - 2026-05-08
17
+
18
+ ### Features
19
+
20
+ - `pattern()` にコード構文 `[0 3]` を追加。1 ステップで複数の度数を同時発音できる
21
+ - `pattern()` にタイ構文 `~` を追加。直前の音(または コード)を次のステップまで延長できる
22
+
23
+ ### Improvements
24
+
25
+ - OSC パターン payload を v2 フォーマット(`"v2"` マーカー付き flat encoding)に統一
26
+ - SC 側 `~setupPattern` を v2 専用 decode に変更。`\sustain` を `Pseq` で制御し、chord/tie の発音長を正確に管理
27
+ - `encode_steps()` を `pattern.py` に追加。Python 内部の `list[PatternStep]` を OSC flat encoding に変換する
28
+
29
+ ---
30
+
3
31
  ## [0.4.0] - 2026-05-08
4
32
 
5
33
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycodedj
3
- Version: 0.4.0
3
+ Version: 0.5.1
4
4
  License: MIT License with Commons Clause
5
5
 
6
6
  "Commons Clause" License Condition v1.0
@@ -213,8 +213,24 @@ def kick():
213
213
  @loop("bass", synth="bass_acid", root="A1", scale="minor", dur=0.25)
214
214
  def bass():
215
215
  pattern("0 . 3 . 5 .")
216
+
217
+ # Chords and ties
218
+ @loop("chord", synth="note", root="A1", scale="minor", dur=0.25)
219
+ def chord():
220
+ pattern("0 . [0 3] ~ 5 . 3 .")
221
+ # [0 3] = two-note chord, ~ = sustain the previous note one more step
216
222
  ```
217
223
 
224
+ Token reference:
225
+
226
+ | Token | Meaning |
227
+ | :--- | :--- |
228
+ | `x` | Trigger (plays root note) |
229
+ | `.` | Rest (silence) |
230
+ | `0`, `1`, `2` … | Scale degree (pitch) |
231
+ | `[0 3]` | Chord (multiple degrees simultaneously) |
232
+ | `~` | Tie (extends the previous note/chord by one step) |
233
+
218
234
  `@loop` arguments for pattern mode:
219
235
 
220
236
  | Argument | Description |
@@ -231,7 +247,7 @@ def bass():
231
247
  | File | Contents |
232
248
  | :--- | :--- |
233
249
  | `examples/demo.py` | Intro demo: bass / melody / pad |
234
- | `examples/club_set.py` | EDM groove: 8 loops (kick, bass, hat, chords, pad) |
250
+ | `examples/club_set.py` | Sub-heavy club set: 11 loops with kick, rumble, sub, acid, hats, and room noise |
235
251
  | `examples/sound_showcase.py` | All 30 synths — evaluate one at a time to audition |
236
252
 
237
253
  ---
@@ -151,8 +151,24 @@ def kick():
151
151
  @loop("bass", synth="bass_acid", root="A1", scale="minor", dur=0.25)
152
152
  def bass():
153
153
  pattern("0 . 3 . 5 .")
154
+
155
+ # コードとタイ
156
+ @loop("chord", synth="note", root="A1", scale="minor", dur=0.25)
157
+ def chord():
158
+ pattern("0 . [0 3] ~ 5 . 3 .")
159
+ # [0 3] = 2音コード、~ = 直前の音を伸ばす
154
160
  ```
155
161
 
162
+ `pattern()` のトークン一覧:
163
+
164
+ | トークン | 意味 |
165
+ | :--- | :--- |
166
+ | `x` | トリガー(ルート音で鳴らす) |
167
+ | `.` | 休符 |
168
+ | `0`, `1`, `2` … | スケール度数 |
169
+ | `[0 3]` | コード(複数の度数を同時発音) |
170
+ | `~` | タイ(直前の音を 1 ステップ延長) |
171
+
156
172
  `@loop` に渡す引数:
157
173
 
158
174
  | 引数 | 説明 |
@@ -169,7 +185,7 @@ def bass():
169
185
  | ファイル | 内容 |
170
186
  | :--- | :--- |
171
187
  | `examples/demo.py` | bass / melody / pad の 3 ループ入門デモ |
172
- | `examples/club_set.py` | EDM クラブグルーヴ(キック・ベース・ハット・コード・パッドを含む 8 ループ) |
188
+ | `examples/club_set.py` | 重低音クラブセット(キック、ランブル、サブ、アシッド、ハット、空間ノイズを含む 11 ループ) |
173
189
  | `examples/sound_showcase.py` | 全 30 音色 — 1 音ずつ eval して確認できる |
174
190
 
175
191
  ---
@@ -151,8 +151,24 @@ def kick():
151
151
  @loop("bass", synth="bass_acid", root="A1", scale="minor", dur=0.25)
152
152
  def bass():
153
153
  pattern("0 . 3 . 5 .")
154
+
155
+ # Chords and ties
156
+ @loop("chord", synth="note", root="A1", scale="minor", dur=0.25)
157
+ def chord():
158
+ pattern("0 . [0 3] ~ 5 . 3 .")
159
+ # [0 3] = two-note chord, ~ = sustain the previous note one more step
154
160
  ```
155
161
 
162
+ Token reference:
163
+
164
+ | Token | Meaning |
165
+ | :--- | :--- |
166
+ | `x` | Trigger (plays root note) |
167
+ | `.` | Rest (silence) |
168
+ | `0`, `1`, `2` … | Scale degree (pitch) |
169
+ | `[0 3]` | Chord (multiple degrees simultaneously) |
170
+ | `~` | Tie (extends the previous note/chord by one step) |
171
+
156
172
  `@loop` arguments for pattern mode:
157
173
 
158
174
  | Argument | Description |
@@ -169,7 +185,7 @@ def bass():
169
185
  | File | Contents |
170
186
  | :--- | :--- |
171
187
  | `examples/demo.py` | Intro demo: bass / melody / pad |
172
- | `examples/club_set.py` | EDM groove: 8 loops (kick, bass, hat, chords, pad) |
188
+ | `examples/club_set.py` | Sub-heavy club set: 11 loops with kick, rumble, sub, acid, hats, and room noise |
173
189
  | `examples/sound_showcase.py` | All 30 synths — evaluate one at a time to audition |
174
190
 
175
191
  ---
@@ -801,11 +801,15 @@ def kick_drum():
801
801
  <tr><td><code>x</code></td><td>ここで音を鳴らす(トリガー)</td></tr>
802
802
  <tr><td><code>.</code></td><td>休符(無音)</td></tr>
803
803
  <tr><td><code>0</code>, <code>1</code>, <code>2</code> …</td><td>音を鳴らす + 音程(スケール度数)</td></tr>
804
+ <tr><td><code>[0 3]</code></td><td>コード(複数の度数を同時発音)</td></tr>
805
+ <tr><td><code>~</code></td><td>タイ(直前の音を 1 ステップ延長)</td></tr>
804
806
  </tbody>
805
807
  </table>
806
808
 
807
809
  <h3>@loop のパラメーター(pattern 用)</h3>
808
810
 
811
+ <p><strong>音色は <code>synth=</code> で指定します。</strong> <code>@loop("bass", synth="floor_kick")</code> と書くと、ループ名は <code>bass</code> のまま、鳴る音色だけが <code>floor_kick</code> になります。</p>
812
+
809
813
  <table>
810
814
  <thead><tr><th>引数</th><th>説明</th><th>例</th></tr></thead>
811
815
  <tbody>
@@ -816,6 +820,10 @@ def kick_drum():
816
820
  </tbody>
817
821
  </table>
818
822
 
823
+ <blockquote>
824
+ <p><code>@loop("kick", synth="floor_kick")</code> の <code>"kick"</code> はループ名、<code>"floor_kick"</code> は音色名です。<code>pycodedj eval demo.py::kick</code> や <code>pycodedj mute kick</code> ではループ名を使います。</p>
825
+ </blockquote>
826
+
819
827
  <h3>トリガーパターン — x と . だけで</h3>
820
828
 
821
829
  <p>音程なしで「リズムだけ」を指定したいときは <code>x</code> と <code>.</code> だけ使います。</p>
@@ -872,6 +880,28 @@ def melody():
872
880
  </tbody>
873
881
  </table>
874
882
 
883
+ <h3>コード — 複数の音を同時に鳴らす</h3>
884
+
885
+ <p>角括弧で複数の度数を囲むと、1 ステップで複数の音を同時に鳴らせます。</p>
886
+
887
+ <pre data-lang="python"><code id="code-s7-chord">@loop("chord", synth="note", root="C3", scale="minor", dur=0.5)
888
+ def chord():
889
+ pattern("[0 2 4] . [0 3] .")
890
+ # [0 2 4]→C3+Eb3+G3(短三和音), 休, [0 3]→C3+Eb3, 休</code></pre>
891
+
892
+ <p>コード内に書けるのは <strong>0 以上の整数のみ</strong>です。<code>.</code>・<code>x</code>・<code>~</code> は書けません。</p>
893
+
894
+ <h3>タイ — 音を伸ばす</h3>
895
+
896
+ <p><code>~</code> を使うと、直前の音(またはコード)を次のステップまで伸ばせます。</p>
897
+
898
+ <pre data-lang="python"><code id="code-s7-tie">@loop("bass", synth="note", root="A1", scale="minor", dur=0.25)
899
+ def bass():
900
+ pattern("0 . [0 3] ~ 5 . 3 .")
901
+ # 0→A1, 休, [0 3]→和音(2ステップ持続), 5→F2, 休, 3→D2, 休</code></pre>
902
+
903
+ <p><code>~</code> は単音・コードの直後にのみ書けます。先頭・<code>.</code> や <code>x</code> の直後は書けません。</p>
904
+
875
905
  <h3>実例: キック・ベース・メロディー</h3>
876
906
 
877
907
  <pre data-lang="python"><code id="code-s7-4">from pycodedj import loop, pattern
@@ -882,7 +912,8 @@ def kick():
882
912
 
883
913
  @loop("bass", synth="bass_acid", root="A1", scale="minor", dur=0.25)
884
914
  def bass():
885
- pattern("0 . 0 . 3 . 5 .")
915
+ pattern("0 . [0 3] ~ 5 . 3 .")
916
+ # 0→A1, 休, [0 3]→和音(2ステップ持続), 5→F2, 休, 3→D2, 休
886
917
 
887
918
  @loop("melody", synth="acid_lead", root="A3", scale="minor", dur=0.5)
888
919
  def melody():
@@ -940,9 +971,29 @@ def atmosphere(volume=0.08):
940
971
 
941
972
  <pre data-lang="bash"><code id="code-s8-2">pycodedj watch myfile.py</code></pre>
942
973
 
974
+ <h3>重低音クラブセットを試す</h3>
975
+
976
+ <p><code>examples/club_set.py</code> は、クラブのフロアで鳴る低域を意識したサンプルです。4つ打ちキック、2・4拍のクラップ、オフビートハット、16分ハット、ランブル、サブベース、アシッドベース、スタブ、フィル、空間ノイズを重ねています。</p>
977
+
978
+ <pre data-lang="bash"><code id="code-s8-3">pycodedj watch examples/club_set.py</code></pre>
979
+
980
+ <p>主なループ名は次の通りです。<code>mute</code> / <code>unmute</code> で足し引きすると、クラブトラックのレイヤー構造がわかりやすくなります。</p>
981
+
982
+ <table>
983
+ <thead><tr><th>ループ名</th><th>役割</th><th>音色名</th></tr></thead>
984
+ <tbody>
985
+ <tr><td><code>kick</code></td><td>4つ打ちの土台</td><td><code>floor_kick</code></td></tr>
986
+ <tr><td><code>rumble</code></td><td>床鳴りする低域</td><td><code>bass_rumble</code></td></tr>
987
+ <tr><td><code>sub</code> / <code>floor</code></td><td>持続する重低音</td><td><code>sub_bass</code></td></tr>
988
+ <tr><td><code>acid</code></td><td>動くベースライン</td><td><code>bass_acid</code></td></tr>
989
+ <tr><td><code>offhat</code> / <code>hats</code></td><td>グルーヴの推進力</td><td><code>hat_ride</code>, <code>hat_engine</code></td></tr>
990
+ <tr><td><code>room</code></td><td>倉庫のような空間感</td><td><code>warehouse_air</code></td></tr>
991
+ </tbody>
992
+ </table>
993
+
943
994
  <h3>演奏中のコントロール</h3>
944
995
 
945
- <pre data-lang="bash"><code id="code-s8-3">pycodedj mute bass # bass を消音(停止はしない)
996
+ <pre data-lang="bash"><code id="code-s8-4">pycodedj mute bass # bass を消音(停止はしない)
946
997
  pycodedj unmute bass # bass の音量を元に戻す
947
998
  pycodedj panic # すべてのループを即時停止
948
999
  pycodedj status # ループの状態を確認</code></pre>
@@ -955,7 +1006,7 @@ pycodedj status # ループの状態を確認</code></pre>
955
1006
  <thead><tr><th>ファイル</th><th>内容</th></tr></thead>
956
1007
  <tbody>
957
1008
  <tr><td><code>examples/demo.py</code></td><td>bass / melody / pad の 3 ループ入門デモ</td></tr>
958
- <tr><td><code>examples/club_set.py</code></td><td>EDM クラブグルーヴ(キック・ベース・ハット・コード・パッドを含む 8 ループ)</td></tr>
1009
+ <tr><td><code>examples/club_set.py</code></td><td>重低音クラブセット(キック、ランブル、サブ、アシッド、ハット、空間ノイズを含む 11 ループ)</td></tr>
959
1010
  <tr><td><code>examples/sound_showcase.py</code></td><td>全 30 音色 — 1 音ずつ eval して確認できる</td></tr>
960
1011
  </tbody>
961
1012
  </table>
@@ -967,16 +1018,35 @@ pycodedj status # ループの状態を確認</code></pre>
967
1018
  <section id="s9">
968
1019
  <h2>9. 音色リファレンス</h2>
969
1020
 
970
- <p><code>@loop</code> の第一引数(ループ名)を変えると、SuperCollider 側で使う音色を選べます。全 30 音色を 1 音ずつ確認したい場合は <code>examples/sound_showcase.py</code> を使います。</p>
1021
+ <p>PyCodeDJ では <strong>ループ名</strong> <strong>音色名</strong> を分けて考えます。</p>
1022
+
1023
+ <ul>
1024
+ <li>ループ名: <code>@loop("kick", ...)</code> の第一引数。<code>pycodedj eval demo.py::kick</code>、<code>mute</code>、<code>solo</code> などで指定する名前</li>
1025
+ <li>音色名: SuperCollider 側のシンセ名。pattern ループでは <code>synth="floor_kick"</code> のように指定する名前</li>
1026
+ </ul>
1027
+
1028
+ <p>音色を選ぶときは、下の表から音色名を選んで <code>synth=</code> に入れます。たとえば <code>@loop("bass", synth="floor_kick")</code> は、<code>bass</code> というループ名で <code>floor_kick</code> の音色を鳴らします。</p>
1029
+
1030
+ <p><code>pattern()</code> を使う場合は、<code>@loop("kick", synth="floor_kick")</code> のように、短いループ名と具体的な音色名を分けて書けます。</p>
1031
+
1032
+ <p><code>pattern()</code> を使わない構造マッピングのループでは、互換性のためにループ名と同じ名前の音色があればそれが使われます。たとえば <code>@loop("bass_acid", interval=0.5)</code> は <code>bass_acid</code> 音色で鳴ります。</p>
1033
+
1034
+ <p>全 30 音色を 1 音ずつ確認したい場合は <code>examples/sound_showcase.py</code> を使います。</p>
971
1035
 
972
- <pre data-lang="bash"><code id="code-s9-1">pycodedj eval examples/sound_showcase.py::bass_acid
973
- pycodedj eval examples/sound_showcase.py::riser_noise
974
- pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1036
+ <pre data-lang="bash"><code id="code-s9-1">pycodedj eval examples/sound_showcase.py::floor_kick
1037
+ pycodedj eval examples/sound_showcase.py::bass_acid
1038
+ pycodedj eval examples/sound_showcase.py::acid_lead</code></pre>
1039
+
1040
+ <p><code>examples/sound_showcase.py</code> では試聴しやすいように、ループ名を音色名と同じにしています。通常の pattern ループでは、次のように <code>synth=</code> にこの表の音色名を指定します。</p>
1041
+
1042
+ <pre data-lang="python"><code id="code-s9-2">@loop("kick", synth="floor_kick", dur=0.25)
1043
+ def kick():
1044
+ pattern("x . x .")</code></pre>
975
1045
 
976
1046
  <h3>キック</h3>
977
1047
  <table>
978
1048
  <thead>
979
- <tr><th>ループ名</th><th>音</th></tr>
1049
+ <tr><th>音色名</th><th>音</th></tr>
980
1050
  </thead>
981
1051
  <tbody>
982
1052
  <tr><td><code>kick_hard</code></td><td>硬めでアタックの強いキック</td></tr>
@@ -988,7 +1058,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
988
1058
  <h3>ベース</h3>
989
1059
  <table>
990
1060
  <thead>
991
- <tr><th>ループ名</th><th>音</th></tr>
1061
+ <tr><th>音色名</th><th>音</th></tr>
992
1062
  </thead>
993
1063
  <tbody>
994
1064
  <tr><td><code>bass_rumble</code></td><td>キック由来の低いランブル</td></tr>
@@ -1001,7 +1071,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1001
1071
  <h3>パーカッション</h3>
1002
1072
  <table>
1003
1073
  <thead>
1004
- <tr><th>ループ名</th><th>音</th></tr>
1074
+ <tr><th>音色名</th><th>音</th></tr>
1005
1075
  </thead>
1006
1076
  <tbody>
1007
1077
  <tr><td><code>hat_engine</code></td><td>クローズ/オープンのハットグリッド</td></tr>
@@ -1017,7 +1087,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1017
1087
  <h3>コード・スタブ</h3>
1018
1088
  <table>
1019
1089
  <thead>
1020
- <tr><th>ループ名</th><th>音</th></tr>
1090
+ <tr><th>音色名</th><th>音</th></tr>
1021
1091
  </thead>
1022
1092
  <tbody>
1023
1093
  <tr><td><code>chord_rave</code></td><td>明るいレイブスタブ</td></tr>
@@ -1032,7 +1102,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1032
1102
  <h3>リード・メロディー</h3>
1033
1103
  <table>
1034
1104
  <thead>
1035
- <tr><th>ループ名</th><th>音</th></tr>
1105
+ <tr><th>音色名</th><th>音</th></tr>
1036
1106
  </thead>
1037
1107
  <tbody>
1038
1108
  <tr><td><code>acid_lead</code></td><td>アシッド系リード</td></tr>
@@ -1046,7 +1116,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1046
1116
  <h3>アトモスフィア</h3>
1047
1117
  <table>
1048
1118
  <thead>
1049
- <tr><th>ループ名</th><th>音</th></tr>
1119
+ <tr><th>音色名</th><th>音</th></tr>
1050
1120
  </thead>
1051
1121
  <tbody>
1052
1122
  <tr><td><code>shimmer_pad</code></td><td>深いシマーパッド</td></tr>
@@ -1058,7 +1128,7 @@ pycodedj eval examples/sound_showcase.py::bell_rave</code></pre>
1058
1128
  <h3>FX</h3>
1059
1129
  <table>
1060
1130
  <thead>
1061
- <tr><th>ループ名</th><th>音</th></tr>
1131
+ <tr><th>音色名</th><th>音</th></tr>
1062
1132
  </thead>
1063
1133
  <tbody>
1064
1134
  <tr><td><code>fx_impact</code></td><td>低いインパクト</td></tr>
@@ -1352,7 +1422,7 @@ pycodedj eval demo.py::pad --sc-port 57200</code></pre>
1352
1422
  <p><strong>使用例:</strong></p>
1353
1423
 
1354
1424
  <pre data-lang="bash"><code id="code-s12-2">pycodedj watch examples/demo.py
1355
- pycodedj watch club_set.py --debounce 0.5
1425
+ pycodedj watch examples/club_set.py --debounce 0.5
1356
1426
  pycodedj watch myfile.py --sc-host 192.168.1.10</code></pre>
1357
1427
 
1358
1428
  <h3><code>pycodedj panic</code></h3>
@@ -496,6 +496,8 @@ def kick_drum():
496
496
  | `x` | ここで音を鳴らす(トリガー) |
497
497
  | `.` | 休符(無音) |
498
498
  | `0`, `1`, `2` … | 音を鳴らす + 音程(スケール度数) |
499
+ | `[0 3]` | コード(複数の度数を同時に鳴らす) |
500
+ | `~` | タイ(直前の音を次のステップまで伸ばす) |
499
501
 
500
502
  スペースで区切ると 1 ステップになります。`"x . x ."` なら 4 ステップのパターンです。
501
503
 
@@ -503,6 +505,8 @@ def kick_drum():
503
505
 
504
506
  `pattern()` を使うループでは、`@loop` デコレータに次の引数を追加します。
505
507
 
508
+ **音色は `synth=` で指定します。** `@loop("bass", synth="floor_kick")` と書くと、ループ名は `bass` のまま、鳴る音色だけが `floor_kick` になります。
509
+
506
510
  | 引数 | 説明 | 例 |
507
511
  | :--- | :--- | :--- |
508
512
  | `synth=` | 使うシンセ名 | `synth="floor_kick"` |
@@ -511,6 +515,7 @@ def kick_drum():
511
515
  | `dur=` | 1 ステップの長さ(秒) | `dur=0.25`(16 分音符相当) |
512
516
 
513
517
  > **ポイント:** `volume=` / `eq=` / `interval=` は pattern ループでも引き続き使えます。
518
+ > `@loop("kick", synth="floor_kick")` の `"kick"` はループ名、`"floor_kick"` は音色名です。`pycodedj eval demo.py::kick` や `pycodedj mute kick` ではループ名を使います。
514
519
 
515
520
  ### トリガーパターン — x と . だけで
516
521
 
@@ -584,6 +589,32 @@ def bass():
584
589
  # 0→C3, 休, x→C3, 休, 3→Eb3, 休, x→C3, 休
585
590
  ```
586
591
 
592
+ ### コード — 複数の音を同時に鳴らす
593
+
594
+ `[0 3]` のように角括弧で複数の度数を囲むと、1 ステップで複数の音を同時に鳴らせます。
595
+
596
+ ```python
597
+ @loop("chord", synth="note", root="C3", scale="minor", dur=0.5)
598
+ def chord():
599
+ pattern("[0 2 4] . [0 3] .")
600
+ # [0 2 4]→C3+Eb3+G3(短三和音), 休, [0 3]→C3+Eb3, 休
601
+ ```
602
+
603
+ コード内に書けるのは **0 以上の整数のみ** です。`.`・`x`・`~` は書けません。
604
+
605
+ ### タイ — 音を伸ばす
606
+
607
+ `~` を使うと、直前の音(または コード)を次のステップまで伸ばせます。
608
+
609
+ ```python
610
+ @loop("bass", synth="note", root="A1", scale="minor", dur=0.25)
611
+ def bass():
612
+ pattern("0 . [0 3] ~ 5 . 3 .")
613
+ # 0→A1, 休, [0 3]→和音(2ステップ分 持続), 5→F2, 休, 3→D2, 休
614
+ ```
615
+
616
+ `~` は単音・コードの直後にのみ書けます。先頭・`.` や `x` の直後は書けません。
617
+
587
618
  ### ルートノートの書き方
588
619
 
589
620
  `root=` にはノート名 + オクターブ番号を渡します。
@@ -596,7 +627,7 @@ def bass():
596
627
  | `"F#3"` | F♯3(`s` を使って `"Fs3"` とも書ける) |
597
628
  | `"C1"` | 低い C |
598
629
 
599
- ### 実例: キックとベースとメロディー
630
+ ### 実例: キックとベースとコード
600
631
 
601
632
  ```python
602
633
  from pycodedj import loop, pattern
@@ -607,7 +638,8 @@ def kick():
607
638
 
608
639
  @loop("bass", synth="bass_acid", root="A1", scale="minor", dur=0.25)
609
640
  def bass():
610
- pattern("0 . 0 . 3 . 5 .")
641
+ pattern("0 . [0 3] ~ 5 . 3 .")
642
+ # 0→A1, 休, [0 3]→2音コード(2ステップ持続), 5→F2, 休, 3→D2, 休
611
643
 
612
644
  @loop("melody", synth="acid_lead", root="A3", scale="minor", dur=0.5)
613
645
  def melody():
@@ -664,6 +696,25 @@ watch で起動すれば、保存するたびに変更したループだけが
664
696
  pycodedj watch myfile.py
665
697
  ```
666
698
 
699
+ ### 重低音クラブセットを試す
700
+
701
+ `examples/club_set.py` は、クラブのフロアで鳴る低域を意識したサンプルです。4つ打ちキック、2・4拍のクラップ、オフビートハット、16分ハット、ランブル、サブベース、アシッドベース、スタブ、フィル、空間ノイズを重ねています。
702
+
703
+ ```bash
704
+ pycodedj watch examples/club_set.py
705
+ ```
706
+
707
+ 主なループ名は次の通りです。`mute` / `unmute` で足し引きすると、クラブトラックのレイヤー構造がわかりやすくなります。
708
+
709
+ | ループ名 | 役割 | 音色名 |
710
+ | :--- | :--- | :--- |
711
+ | `kick` | 4つ打ちの土台 | `floor_kick` |
712
+ | `rumble` | 床鳴りする低域 | `bass_rumble` |
713
+ | `sub` / `floor` | 持続する重低音 | `sub_bass` |
714
+ | `acid` | 動くベースライン | `bass_acid` |
715
+ | `offhat` / `hats` | グルーヴの推進力 | `hat_ride`, `hat_engine` |
716
+ | `room` | 倉庫のような空間感 | `warehouse_air` |
717
+
667
718
  ### 演奏中のコントロール
668
719
 
669
720
  **ミュートとアンミュート**
@@ -700,7 +751,16 @@ pad muted 0.08 200Hz
700
751
 
701
752
  ## 9. 音色リファレンス
702
753
 
703
- `@loop` の第一引数(ループ名)で、SuperCollider 側で使う音色が決まります。
754
+ PyCodeDJ では **ループ名** と **音色名** を分けて考えます。
755
+
756
+ - ループ名: `@loop("kick", ...)` の第一引数。`pycodedj eval demo.py::kick`、`mute`、`solo` などで指定する名前
757
+ - 音色名: SuperCollider 側のシンセ名。pattern ループでは `synth="floor_kick"` のように指定する名前
758
+
759
+ 音色を選ぶときは、下の表から音色名を選んで `synth=` に入れます。たとえば `@loop("bass", synth="floor_kick")` は、`bass` というループ名で `floor_kick` の音色を鳴らします。
760
+
761
+ `pattern()` を使う場合は、`@loop("kick", synth="floor_kick")` のように、短いループ名と具体的な音色名を分けて書けます。
762
+
763
+ `pattern()` を使わない構造マッピングのループでは、互換性のためにループ名と同じ名前の音色があればそれが使われます。たとえば `@loop("bass_acid", interval=0.5)` は `bass_acid` 音色で鳴ります。
704
764
 
705
765
  全 30 音色を 1 音ずつ確認したい場合は `examples/sound_showcase.py` を使います。
706
766
 
@@ -710,11 +770,17 @@ pycodedj eval examples/sound_showcase.py::bass_acid
710
770
  pycodedj eval examples/sound_showcase.py::acid_lead
711
771
  ```
712
772
 
713
- `synth=` パラメーター(pattern 使用時)でも同じ名前を指定できます。
773
+ `examples/sound_showcase.py` では試聴しやすいように、ループ名を音色名と同じにしています。通常の pattern ループでは、次のように `synth=` にこの表の音色名を指定します。
774
+
775
+ ```python
776
+ @loop("kick", synth="floor_kick", dur=0.25)
777
+ def kick():
778
+ pattern("x . x .")
779
+ ```
714
780
 
715
781
  ### キック
716
782
 
717
- | 名前 | 音の特徴 |
783
+ | 音色名 | 音の特徴 |
718
784
  | :--- | :--- |
719
785
  | `kick_hard` | 硬めでアタックの強いキック |
720
786
  | `floor_kick` | 太い四つ打ちキック |
@@ -722,7 +788,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
722
788
 
723
789
  ### ベース
724
790
 
725
- | 名前 | 音の特徴 |
791
+ | 音色名 | 音の特徴 |
726
792
  | :--- | :--- |
727
793
  | `bass_rumble` | 深い低音ランブル |
728
794
  | `bass_reese` | 揺れる Reese 系ベース |
@@ -731,7 +797,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
731
797
 
732
798
  ### パーカッション
733
799
 
734
- | 名前 | 音の特徴 |
800
+ | 音色名 | 音の特徴 |
735
801
  | :--- | :--- |
736
802
  | `hat_engine` | クローズ/オープンのハットグリッド |
737
803
  | `hat_ride` | 長めのライド/オープンハット |
@@ -743,7 +809,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
743
809
 
744
810
  ### コード・スタブ
745
811
 
746
- | 名前 | 音の特徴 |
812
+ | 音色名 | 音の特徴 |
747
813
  | :--- | :--- |
748
814
  | `chord_rave` | 明るいレイブスタブ |
749
815
  | `neon_stab` | ネオン系スタブコード |
@@ -754,7 +820,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
754
820
 
755
821
  ### リード・メロディー
756
822
 
757
- | 名前 | 音の特徴 |
823
+ | 音色名 | 音の特徴 |
758
824
  | :--- | :--- |
759
825
  | `acid_lead` | アシッド系リード |
760
826
  | `lead_hoover` | Hoover 風リード |
@@ -764,7 +830,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
764
830
 
765
831
  ### アトモスフィア
766
832
 
767
- | 名前 | 音の特徴 |
833
+ | 音色名 | 音の特徴 |
768
834
  | :--- | :--- |
769
835
  | `shimmer_pad` | 深いシマーパッド |
770
836
  | `warehouse_air` | 倉庫っぽい空気感 |
@@ -772,7 +838,7 @@ pycodedj eval examples/sound_showcase.py::acid_lead
772
838
 
773
839
  ### FX
774
840
 
775
- | 名前 | 音の特徴 |
841
+ | 音色名 | 音の特徴 |
776
842
  | :--- | :--- |
777
843
  | `fx_impact` | 低いインパクト |
778
844
  | `riser_noise` | ノイズライザー(8 秒でスイープ上昇) |
@@ -1060,7 +1126,7 @@ pycodedj watch FILE [--sc-host HOST] [--sc-port PORT] [--debounce SECS]
1060
1126
 
1061
1127
  ```bash
1062
1128
  pycodedj watch examples/demo.py
1063
- pycodedj watch club_set.py --debounce 0.5
1129
+ pycodedj watch examples/club_set.py --debounce 0.5
1064
1130
  ```
1065
1131
 
1066
1132
  ### `pycodedj panic`