baouws commited on
Commit
9d60b19
Β·
verified Β·
1 Parent(s): a0968a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +178 -92
app.py CHANGED
@@ -28,92 +28,165 @@ except Exception as e:
28
  device_map=None
29
  )
30
 
31
- # Curated working Strudel patterns - these are all tested and functional
32
  WORKING_PATTERNS = {
33
  "techno": [
34
  """stack(
35
- s("bd*4").gain(0.8),
36
- s("~ hh ~ hh").gain(0.5),
37
- n("0 ~ 3 ~").s("sawtooth").octave(2).lpf(1200).gain(0.7)
 
38
  ).scale("a:minor")""",
39
 
40
  """stack(
41
- s("bd bd ~ bd").gain(0.8),
42
- s("[hh ch]*4").gain(0.4),
43
- n("[0 3 5 7]*2").s("square").octave(2).cutoff(800).gain(0.6),
44
- n("7 9 7 4").s("triangle").octave(4).delay(0.25).gain(0.5)
45
  ).scale("d:minor")""",
46
 
47
  """stack(
48
- s("bd*4, ~ rim ~ rim").bank("RolandTR909").gain(0.8),
49
- n("0 0 3 3").s("sawtooth").octave(2).lpf(2000).gain(0.7),
50
- n("[7 9]*4").s("square").octave(4).room(0.4).gain(0.4)
51
- ).scale("g:minor")"""
 
 
 
 
 
 
 
 
52
  ],
53
 
54
  "house": [
55
  """stack(
56
- s("bd ~ ~ ~ bd ~ ~ ~").gain(0.7),
57
  s("~ hh ~ hh").gain(0.5),
58
- n("0 2 4 7").s("sine").octave(3).room(0.6).gain(0.6)
 
59
  ).scale("c:major")""",
60
 
61
  """stack(
62
- s("bd ~ [~ bd] ~").gain(0.8),
63
- s("[~ ch ~ hh]*2").gain(0.4),
64
- n("[0 4 7]*2").s("sawtooth").octave(2).lpf(1500).gain(0.7),
65
- n("0 7 4 2").s("triangle").octave(4).delay(0.125).gain(0.4)
66
  ).scale("f:major")""",
67
 
68
  """stack(
69
- s("bd ~ ~ ~ bd ~ ~ ~").sometimes(fast(2)).gain(0.7),
70
- n("[0 2] [4 7] [2 4] [7 0]").s("sine").octave(2).gain(0.6),
71
- s("hh*8").degradeBy(0.3).gain(0.3)
72
- ).scale("g:major")"""
 
 
 
 
 
 
 
 
73
  ],
74
 
75
  "ambient": [
76
  """stack(
77
- s("~ ~ ~ rim").slow(2).gain(0.3).room(0.8),
78
- n("[0 2 4]/3").s("sine").octave(3).slow(4).room(0.9).gain(0.5),
79
- n("[7 9 11]/5").s("triangle").octave(4).slow(8).delay(0.375).gain(0.3)
 
80
  ).scale("d:minor")""",
81
 
82
  """stack(
83
- n("0 2 4 7").s("sine").octave(2).slow(8).room(0.9).gain(0.4),
84
- n("[4 7 9]/7").s("triangle").octave(4).slow(12).delay(0.5).gain(0.3),
85
- s("~ ~ rim ~").slow(4).gain(0.2).room(0.9)
 
86
  ).scale("a:minor")""",
87
 
88
- """n("[0 4 7 11]/4").s("sine").octave(3).slow(8).room(0.9).lpf(800).gain(0.6).scale("e:minor")"""
 
 
 
 
 
 
89
  ],
90
 
91
  "breakbeat": [
92
  """stack(
93
- s("[bd sn]*2").sometimes(rev).gain(0.8),
94
- s("[hh ch]*4").degradeBy(0.2).gain(0.5),
95
- n("0 4 7 0").s("square").octave(2).cutoff(1000).gain(0.7)
 
96
  ).scale("a:minor")""",
97
 
98
  """stack(
99
- s("bd [sn sn] bd sn").speed(0.9).gain(0.8),
100
- n("[0 ~ 7] [3 5]").s("sawtooth").octave(2).lpf(1500).gain(0.6),
101
- s("hh*8").sometimes(fast(2)).gain(0.4)
102
- ).scale("d:minor")"""
 
 
 
 
 
 
 
103
  ],
104
 
105
  "experimental": [
106
  """stack(
107
- s("[bd rim]*3").degradeBy(0.4).gain(0.7),
108
- n("[0 3 7]/5").s("square").octave(2).cutoff(perlin.range(400,2000)).gain(0.6),
109
- s("~ [hh hh] ~").pan(sine.slow(3)).gain(0.4)
 
110
  ).scale("g:minor")""",
111
 
112
  """stack(
113
- s("bd ~ [perc:0 perc:1]").speed(rand.range(0.8,1.2)).gain(0.7),
114
- n("0 [2 5] 7").s("sawtooth").octave(2).sometimes(add(note(12))).gain(0.6),
115
- s("[ch oh]*5").degradeBy(0.5).gain(0.3)
116
- ).scale("f#:minor")"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  ]
118
  }
119
 
@@ -124,11 +197,12 @@ def get_random_working_pattern(genre, complexity="moderate"):
124
  if complexity == "simple":
125
  # Return simpler single-line patterns
126
  simple_patterns = {
127
- "techno": 's("bd*4").gain(0.8)',
128
- "house": 's("bd ~ ~ ~ bd ~ ~ ~").gain(0.7)',
129
- "ambient": 'n("[0 2 4]/3").s("sine").octave(3).slow(4).room(0.9).gain(0.5).scale("d:minor")',
130
- "breakbeat": 's("[bd sn]*2").gain(0.8)',
131
- "experimental": 's("bd ~ [perc:0 perc:1]").degradeBy(0.4).gain(0.7)'
 
132
  }
133
  return simple_patterns.get(genre, simple_patterns["techno"])
134
 
@@ -151,7 +225,7 @@ def create_variations(base_pattern, genre):
151
  variations.append(base_pattern.replace(".gain(0.8)", ".gain(0.8).room(0.4)"))
152
 
153
  # Scale variations
154
- scales = ["a:minor", "d:minor", "g:minor", "c:major", "f:major", "e:minor"]
155
  for scale in scales:
156
  if scale not in base_pattern:
157
  new_pattern = base_pattern
@@ -172,29 +246,33 @@ def generate_working_strudel_code(prompt, genre="techno", complexity="moderate")
172
  base_pattern = get_random_working_pattern(genre, complexity)
173
 
174
  # Create variations based on prompt keywords
175
- if any(word in prompt.lower() for word in ["fast", "speed", "quick", "rapid"]):
176
  if "sometimes(fast(2))" not in base_pattern:
177
  base_pattern = base_pattern.replace(".gain(", ".sometimes(fast(2)).gain(")
178
 
179
- if any(word in prompt.lower() for word in ["slow", "chill", "ambient", "relaxed"]):
180
  if ".slow(" not in base_pattern:
181
  base_pattern = base_pattern.replace(".gain(", ".slow(2).gain(")
182
 
183
- if any(word in prompt.lower() for word in ["reverb", "space", "room", "hall"]):
184
  if ".room(" not in base_pattern:
185
- base_pattern = base_pattern.replace(".gain(", ".room(0.6).gain(")
186
 
187
- if any(word in prompt.lower() for word in ["delay", "echo", "repeat"]):
188
  if ".delay(" not in base_pattern:
189
  base_pattern = base_pattern.replace(".gain(", ".delay(0.25).gain(")
190
 
191
- if any(word in prompt.lower() for word in ["filter", "sweep", "cutoff", "lpf"]):
192
  if ".lpf(" not in base_pattern and ".cutoff(" not in base_pattern:
193
- base_pattern = base_pattern.replace(".gain(", ".lpf(1200).gain(")
194
 
195
- if any(word in prompt.lower() for word in ["glitch", "degraded", "broken", "corrupt"]):
196
  if ".degradeBy(" not in base_pattern:
197
- base_pattern = base_pattern.replace(".gain(", ".degradeBy(0.3).gain(")
 
 
 
 
198
 
199
  # Add comment based on prompt
200
  comment_line = f"// {prompt[:50]}{'...' if len(prompt) > 50 else ''}"
@@ -256,21 +334,22 @@ def generate_interface(prompt, genre, complexity, include_visuals, visual_style,
256
  return "Please enter a description of the music you want to create."
257
 
258
  if use_ai:
259
- # Use AI generation
260
  system_prompt = f"""Generate working Strudel live coding pattern for: {prompt}
261
  Genre: {genre}, Complexity: {complexity}
262
 
263
- Example patterns:
264
- s("bd*4").gain(0.8)
265
- stack(s("bd ~ ~ ~"), n("0 2 4").s("sine").octave(3))
 
266
 
267
- Pattern:"""
268
 
269
  try:
270
  outputs = code_generator(
271
  system_prompt,
272
- max_length=len(system_prompt.split()) + 50,
273
- temperature=0.7,
274
  do_sample=True,
275
  top_p=0.9,
276
  num_return_sequences=1
@@ -279,26 +358,32 @@ Pattern:"""
279
  generated_text = outputs[0]['generated_text']
280
  strudel_code = generated_text[len(system_prompt):].strip()
281
 
282
- # Clean the AI output
283
  lines = strudel_code.split('\n')
284
  clean_lines = []
285
- for line in lines[:5]: # Limit to 5 lines
286
  line = line.strip()
 
287
  if line and (line.startswith('s(') or line.startswith('n(') or line.startswith('stack(') or
288
- '.gain(' in line or '.s(' in line or line.endswith(')')):
 
289
  clean_lines.append(line)
 
 
 
290
 
291
  if clean_lines:
292
  strudel_code = '\n'.join(clean_lines)
293
  strudel_code = f"// AI Generated: {prompt}\n{strudel_code}"
294
  else:
295
- # Fallback to random if AI fails
296
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
297
- except:
298
- # Fallback to random if AI fails
 
299
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
300
  else:
301
- # Use random generation
302
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
303
 
304
  # Create complete working template
@@ -311,12 +396,13 @@ with gr.Blocks(title="Working Strudel Generator", theme=gr.themes.Soft()) as app
311
  gr.Markdown("""
312
  # 🎡 CODEL: Strudel Code Generator
313
 
314
- Generate Strudel live coding patterns!
315
 
316
- βœ… **All patterns tested and functional**
317
  πŸŽ›οΈ **Real Strudel syntax** - copy & paste ready
318
- 🎨 **Working Hydra visuals** included
319
- 🎡 **Genre-specific patterns** that actually sound good
 
320
 
321
  **Usage:** Describe music β†’ Generate β†’ Copy to [strudel.cc](https://strudel.cc) β†’ Play!
322
  """)
@@ -331,7 +417,7 @@ with gr.Blocks(title="Working Strudel Generator", theme=gr.themes.Soft()) as app
331
 
332
  with gr.Row():
333
  genre_dropdown = gr.Dropdown(
334
- choices=["techno", "house", "ambient", "breakbeat", "experimental"],
335
  value="techno",
336
  label="🎡 Genre"
337
  )
@@ -359,11 +445,11 @@ with gr.Blocks(title="Working Strudel Generator", theme=gr.themes.Soft()) as app
359
  label="πŸ‘οΈ Visual Style"
360
  )
361
 
362
- generate_btn = gr.Button("🎡 Generate Working Code", variant="primary", size="lg")
363
 
364
  with gr.Column():
365
  output_code = gr.Code(
366
- label="βœ… Working Strudel Code (Ready to Copy)",
367
  language="javascript",
368
  lines=18
369
  )
@@ -374,26 +460,26 @@ with gr.Blocks(title="Working Strudel Generator", theme=gr.themes.Soft()) as app
374
  2. **Go to** [strudel.cc](https://strudel.cc)
375
  3. **Paste** and **click the play button** ▢️
376
 
377
- **πŸ”§ Customization:**
378
- - Change `.gain()` values (0.1 to 1.0)
379
- - Try different scales: "a:minor", "c:major", etc.
380
- - Adjust `.lpf()` for filter sweeps
381
- - Add `.room()` for reverb
382
  """)
383
 
384
- # Working examples
385
- gr.Markdown("### πŸŽͺ Tested Examples (Guaranteed to Work)")
386
  with gr.Row():
387
  working_examples = [
388
- ["Fast techno with kick and hats", "techno", "moderate"],
389
- ["Chill ambient soundscape", "ambient", "simple"],
390
- ["Driving house beat", "house", "moderate"],
391
- ["Glitchy breakbeat", "breakbeat", "complex"],
392
- ["Experimental textures", "experimental", "complex"],
393
  ]
394
 
395
  for example_text, example_genre, example_complexity in working_examples:
396
- btn = gr.Button(f"βœ… {example_text}", size="sm")
397
  btn.click(
398
  lambda t=example_text, g=example_genre, c=example_complexity: (t, g, c),
399
  outputs=[prompt_input, genre_dropdown, complexity_dropdown]
 
28
  device_map=None
29
  )
30
 
31
+ # Enhanced working Strudel patterns - these are all tested and functional
32
  WORKING_PATTERNS = {
33
  "techno": [
34
  """stack(
35
+ s("bd*4").gain(0.9),
36
+ s("~ hh ~ hh").gain(0.6),
37
+ n("0 ~ 3 ~").s("sawtooth").octave(2).lpf(1200).gain(0.8),
38
+ s("~ ~ rim ~").slow(2).gain(0.5)
39
  ).scale("a:minor")""",
40
 
41
  """stack(
42
+ s("bd bd ~ bd, ~ rim ~ rim").bank("RolandTR909").gain(0.9),
43
+ s("[hh ch]*4").degradeBy(0.1).gain(0.5),
44
+ n("[0 3 5 7]*2").s("square").octave(2).cutoff(sine.range(400,1600).slow(8)).gain(0.7),
45
+ n("7 9 7 4").s("triangle").octave(4).delay(0.25).room(0.4).gain(0.5)
46
  ).scale("d:minor")""",
47
 
48
  """stack(
49
+ s("bd*4, [~ rim]*2, hh*8").bank("RolandTR909").speed(0.95).gain(0.8),
50
+ n("0 0 3 3").s("sawtooth").octave(2).lpf(2000).lpq(8).gain(0.8),
51
+ n("[7 9]*4").s("square").octave(4).room(0.5).cutoff(1800).gain(0.4),
52
+ s("~ ~ ~ clap").slow(2).gain(0.6).room(0.3)
53
+ ).scale("g:minor")""",
54
+
55
+ """stack(
56
+ s("bd*4").sometimes(fast(2)).gain(0.9),
57
+ s("hh*8").degradeBy(0.2).gain(0.4),
58
+ n("[0 3 [5 0] 7]*2").s("sawtooth").octave(2).lpf(sine.range(600,2400).slow(4)).gain(0.8),
59
+ n("0 7 4 2").s("triangle").octave(5).delay(0.125).room(0.6).gain(0.5)
60
+ ).scale("e:minor")"""
61
  ],
62
 
63
  "house": [
64
  """stack(
65
+ s("bd ~ ~ ~ bd ~ ~ ~").gain(0.8),
66
  s("~ hh ~ hh").gain(0.5),
67
+ n("0 2 4 7").s("sine").octave(3).room(0.6).gain(0.7),
68
+ s("~ ~ ~ clap").gain(0.6)
69
  ).scale("c:major")""",
70
 
71
  """stack(
72
+ s("bd ~ [~ bd] ~").sometimes(fast(2)).gain(0.8),
73
+ s("[~ ch ~ hh]*2").pan(sine.slow(4)).gain(0.4),
74
+ n("[0 4 7]*2").s("sawtooth").octave(2).lpf(1500).gain(0.8),
75
+ n("0 7 4 2").s("triangle").octave(4).delay(0.125).room(0.5).gain(0.5)
76
  ).scale("f:major")""",
77
 
78
  """stack(
79
+ s("bd ~ ~ ~ bd ~ ~ ~").gain(0.8),
80
+ n("[0 2] [4 7] [2 4] [7 0]").s("sine").octave(2).lpf(2000).gain(0.7),
81
+ s("hh*8").degradeBy(0.3).pan(cosine.slow(6)).gain(0.4),
82
+ s("~ ~ clap ~").room(0.4).gain(0.6)
83
+ ).scale("g:major")""",
84
+
85
+ """stack(
86
+ s("bd ~ [bd ~] [~ bd] ~").gain(0.8),
87
+ s("~ hh ~ [hh ch]").gain(0.5),
88
+ n("0 4 7 9").s("sawtooth").octave(2).sometimes(add(note(12))).lpf(1800).gain(0.7),
89
+ n("[2 4]*4").s("triangle").octave(4).delay(0.25).gain(0.4)
90
+ ).scale("d:major")"""
91
  ],
92
 
93
  "ambient": [
94
  """stack(
95
+ s("~ ~ ~ rim").slow(4).gain(0.3).room(0.9),
96
+ n("[0 2 4]/3").s("sine").octave(3).slow(8).room(0.9).lpf(800).gain(0.6),
97
+ n("[7 9 11]/5").s("triangle").octave(4).slow(12).delay(0.5).room(0.8).gain(0.4),
98
+ n("[0 4]/7").s("sawtooth").octave(2).slow(16).lpf(400).gain(0.3)
99
  ).scale("d:minor")""",
100
 
101
  """stack(
102
+ n("0 2 4 7").s("sine").octave(2).slow(16).room(0.9).lpf(600).gain(0.5),
103
+ n("[4 7 9]/7").s("triangle").octave(4).slow(12).delay(0.75).room(0.9).gain(0.4),
104
+ s("~ ~ rim ~").slow(8).gain(0.2).room(0.9),
105
+ n("[11 14]/11").s("sine").octave(5).slow(20).gain(0.3)
106
  ).scale("a:minor")""",
107
 
108
+ """n("[0 4 7 11]/4").s("sine").octave(3).slow(12).room(0.9).lpf(perlin.range(400,1200).slow(8)).gain(0.7).scale("e:minor")""",
109
+
110
+ """stack(
111
+ n("[0 2]/5").s("sine").octave(2).slow(16).room(0.9).gain(0.4),
112
+ n("[4 7]/7").s("triangle").octave(4).slow(20).delay(1).room(0.9).gain(0.3),
113
+ s("~ ~ ~ [rim vinyl]").slow(8).gain(0.2).room(0.9)
114
+ ).scale("f:major")"""
115
  ],
116
 
117
  "breakbeat": [
118
  """stack(
119
+ s("[bd sn]*2").sometimes(rev).speed(0.9).gain(0.9),
120
+ s("[hh ch]*4").degradeBy(0.3).gain(0.6),
121
+ n("0 4 7 0").s("square").octave(2).cutoff(1000).gain(0.8),
122
+ s("~ [perc:0 perc:1] ~").gain(0.4)
123
  ).scale("a:minor")""",
124
 
125
  """stack(
126
+ s("bd [sn sn] bd sn").speed(0.85).gain(0.9),
127
+ n("[0 ~ 7] [3 5]").s("sawtooth").octave(2).lpf(1500).gain(0.7),
128
+ s("hh*8").sometimes(fast(2)).degradeBy(0.2).gain(0.5),
129
+ s("~ ~ [perc:2 perc:3] ~").gain(0.5)
130
+ ).scale("d:minor")""",
131
+
132
+ """stack(
133
+ s("[bd ~ sn ~]*2").sometimes(rev).gain(0.9),
134
+ s("[hh ch oh]*3").degradeBy(0.4).pan(perlin.slow(2)).gain(0.5),
135
+ n("[0 7 4 2]*2").s("square").octave(2).cutoff(rand.range(600,1800)).gain(0.7)
136
+ ).scale("g:minor")"""
137
  ],
138
 
139
  "experimental": [
140
  """stack(
141
+ s("[bd rim]*3").degradeBy(0.5).speed(perlin.range(0.8,1.2)).gain(0.8),
142
+ n("[0 3 7]/5").s("square").octave(2).cutoff(perlin.range(400,2000)).gain(0.7),
143
+ s("~ [hh hh] ~").pan(sine.slow(3)).degradeBy(0.6).gain(0.5),
144
+ s("[noise:0]/16").gain(0.2).hpf(2000)
145
  ).scale("g:minor")""",
146
 
147
  """stack(
148
+ s("bd ~ [perc:0 perc:1]").speed(rand.range(0.7,1.3)).gain(0.8),
149
+ n("0 [2 5] 7").s("sawtooth").octave(2).sometimes(add(note(12))).cutoff(sine.range(300,1500)).gain(0.7),
150
+ s("[ch oh]*5").degradeBy(0.7).pan(cosine.slow(2)).gain(0.4),
151
+ n("[9 11]/9").s("triangle").octave(5).delay(0.75).gain(0.3)
152
+ ).scale("f#:minor")""",
153
+
154
+ """stack(
155
+ s("[bd ~ rim]*2").rev().degradeBy(0.4).gain(0.8),
156
+ n("[0 4 7]/7").s("square").octave(2).cutoff(perlin.range(200,2000)).sometimes(fast(4)).gain(0.6),
157
+ s("~ [vinyl:0 vinyl:1]/8").gain(0.3).hpf(1500)
158
+ ).scale("bb:minor")"""
159
+ ],
160
+
161
+ "hiphop": [
162
+ """stack(
163
+ s("bd ~ sn ~").gain(0.9),
164
+ s("hh ~ hh hh ~ hh ~ hh").gain(0.5),
165
+ n("0 0 3 5").s("sawtooth").octave(2).lpf(1000).gain(0.8),
166
+ s("~ ~ ~ [clap clap]").slow(2).gain(0.6)
167
+ ).scale("c:minor")""",
168
+
169
+ """stack(
170
+ s("bd ~ [bd sn] ~").gain(0.9),
171
+ s("[hh ch]*4").degradeBy(0.1).gain(0.5),
172
+ n("[0 3 5]*2").s("square").octave(2).lpf(800).gain(0.8),
173
+ s("~ ~ clap ~").room(0.3).gain(0.7),
174
+ s("~ [perc:0]/4 ~ [perc:1]/4").gain(0.4)
175
+ ).scale("a:minor")""",
176
+
177
+ """stack(
178
+ s("bd ~ sn [~ bd]").sometimes(fast(2)).gain(0.9),
179
+ s("hh*8").degradeBy(0.2).gain(0.4),
180
+ n("0 ~ 3 ~").s("sawtooth").octave(2).lpf(1200).sometimes(add(note(7))).gain(0.8),
181
+ s("~ ~ [clap rim] ~").gain(0.6).room(0.4)
182
+ ).scale("d:minor")""",
183
+
184
+ """stack(
185
+ s("[bd bd] ~ sn ~").gain(0.9),
186
+ s("~ hh ~ [hh ch hh]").gain(0.5),
187
+ n("[0 3] [5 0] [7 3] [5 0]").s("sine").octave(2).lpf(1500).gain(0.7),
188
+ s("~ ~ clap ~").delay(0.125).gain(0.7)
189
+ ).scale("g:minor")"""
190
  ]
191
  }
192
 
 
197
  if complexity == "simple":
198
  # Return simpler single-line patterns
199
  simple_patterns = {
200
+ "techno": 's("bd*4, hh*8").gain(0.8)',
201
+ "house": 's("bd ~ ~ ~ bd ~ ~ ~, ~ hh ~ hh").gain(0.7)',
202
+ "ambient": 'n("[0 2 4]/3").s("sine").octave(3).slow(8).room(0.9).gain(0.6).scale("d:minor")',
203
+ "breakbeat": 's("[bd sn]*2, hh*8").speed(0.9).gain(0.8)',
204
+ "experimental": 's("bd ~ [perc:0 perc:1]").degradeBy(0.4).speed(rand.range(0.8,1.2)).gain(0.7)',
205
+ "hiphop": 's("bd ~ sn ~, hh ~ hh hh ~ hh ~ hh").gain(0.8)'
206
  }
207
  return simple_patterns.get(genre, simple_patterns["techno"])
208
 
 
225
  variations.append(base_pattern.replace(".gain(0.8)", ".gain(0.8).room(0.4)"))
226
 
227
  # Scale variations
228
+ scales = ["a:minor", "d:minor", "g:minor", "c:major", "f:major", "e:minor", "bb:minor", "f#:minor"]
229
  for scale in scales:
230
  if scale not in base_pattern:
231
  new_pattern = base_pattern
 
246
  base_pattern = get_random_working_pattern(genre, complexity)
247
 
248
  # Create variations based on prompt keywords
249
+ if any(word in prompt.lower() for word in ["fast", "speed", "quick", "rapid", "energetic"]):
250
  if "sometimes(fast(2))" not in base_pattern:
251
  base_pattern = base_pattern.replace(".gain(", ".sometimes(fast(2)).gain(")
252
 
253
+ if any(word in prompt.lower() for word in ["slow", "chill", "ambient", "relaxed", "calm"]):
254
  if ".slow(" not in base_pattern:
255
  base_pattern = base_pattern.replace(".gain(", ".slow(2).gain(")
256
 
257
+ if any(word in prompt.lower() for word in ["reverb", "space", "room", "hall", "spacious"]):
258
  if ".room(" not in base_pattern:
259
+ base_pattern = base_pattern.replace(".gain(", ".room(0.7).gain(")
260
 
261
+ if any(word in prompt.lower() for word in ["delay", "echo", "repeat", "dub"]):
262
  if ".delay(" not in base_pattern:
263
  base_pattern = base_pattern.replace(".gain(", ".delay(0.25).gain(")
264
 
265
+ if any(word in prompt.lower() for word in ["filter", "sweep", "cutoff", "lpf", "filtered"]):
266
  if ".lpf(" not in base_pattern and ".cutoff(" not in base_pattern:
267
+ base_pattern = base_pattern.replace(".gain(", ".lpf(sine.range(400,1600).slow(8)).gain(")
268
 
269
+ if any(word in prompt.lower() for word in ["glitch", "degraded", "broken", "corrupt", "dirty"]):
270
  if ".degradeBy(" not in base_pattern:
271
+ base_pattern = base_pattern.replace(".gain(", ".degradeBy(0.4).gain(")
272
+
273
+ if any(word in prompt.lower() for word in ["pan", "stereo", "wide", "spatial"]):
274
+ if ".pan(" not in base_pattern:
275
+ base_pattern = base_pattern.replace(".gain(", ".pan(sine.slow(4)).gain(")
276
 
277
  # Add comment based on prompt
278
  comment_line = f"// {prompt[:50]}{'...' if len(prompt) > 50 else ''}"
 
334
  return "Please enter a description of the music you want to create."
335
 
336
  if use_ai:
337
+ # Use AI generation with better examples
338
  system_prompt = f"""Generate working Strudel live coding pattern for: {prompt}
339
  Genre: {genre}, Complexity: {complexity}
340
 
341
+ Example Strudel patterns:
342
+ s("bd*4, hh*8").gain(0.8)
343
+ stack(s("bd ~ sn ~"), n("0 2 4").s("sine").octave(3).gain(0.7))
344
+ n("[0 3 5 7]*2").s("sawtooth").octave(2).lpf(1200).gain(0.8).scale("a:minor")
345
 
346
+ Generate a {complexity} {genre} pattern:"""
347
 
348
  try:
349
  outputs = code_generator(
350
  system_prompt,
351
+ max_length=len(system_prompt.split()) + 80,
352
+ temperature=0.8,
353
  do_sample=True,
354
  top_p=0.9,
355
  num_return_sequences=1
 
358
  generated_text = outputs[0]['generated_text']
359
  strudel_code = generated_text[len(system_prompt):].strip()
360
 
361
+ # Clean the AI output more thoroughly
362
  lines = strudel_code.split('\n')
363
  clean_lines = []
364
+ for line in lines[:8]: # Limit to 8 lines
365
  line = line.strip()
366
+ # More robust pattern matching for Strudel code
367
  if line and (line.startswith('s(') or line.startswith('n(') or line.startswith('stack(') or
368
+ '.gain(' in line or '.s(' in line or '.octave(' in line or '.scale(' in line or
369
+ line.endswith(')') or line.endswith(',') or '.lpf(' in line):
370
  clean_lines.append(line)
371
+ # Stop at obvious non-Strudel patterns
372
+ elif any(stop_word in line.lower() for stop_word in ['function', 'var ', 'let ', 'const ', 'import', '//']):
373
+ break
374
 
375
  if clean_lines:
376
  strudel_code = '\n'.join(clean_lines)
377
  strudel_code = f"// AI Generated: {prompt}\n{strudel_code}"
378
  else:
379
+ # Fallback to curated patterns if AI fails
380
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
381
+ except Exception as e:
382
+ # Fallback to curated patterns if AI fails
383
+ print(f"AI generation failed: {e}")
384
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
385
  else:
386
+ # Use curated pattern generation
387
  strudel_code = generate_working_strudel_code(prompt, genre, complexity)
388
 
389
  # Create complete working template
 
396
  gr.Markdown("""
397
  # 🎡 CODEL: Strudel Code Generator
398
 
399
+ Generate high-quality Strudel live coding patterns!
400
 
401
+ βœ… **Premium curated patterns** - professional quality sounds
402
  πŸŽ›οΈ **Real Strudel syntax** - copy & paste ready
403
+ 🎨 **Reactive Hydra visuals** included
404
+ 🎡 **6 genres** with authentic patterns
405
+ πŸ€– **Optional AI generation** for creative variations
406
 
407
  **Usage:** Describe music β†’ Generate β†’ Copy to [strudel.cc](https://strudel.cc) β†’ Play!
408
  """)
 
417
 
418
  with gr.Row():
419
  genre_dropdown = gr.Dropdown(
420
+ choices=["techno", "house", "ambient", "breakbeat", "experimental", "hiphop"],
421
  value="techno",
422
  label="🎡 Genre"
423
  )
 
445
  label="πŸ‘οΈ Visual Style"
446
  )
447
 
448
+ generate_btn = gr.Button("🎡 Generate Premium Code", variant="primary", size="lg")
449
 
450
  with gr.Column():
451
  output_code = gr.Code(
452
+ label="βœ… Premium Strudel Code (Ready to Copy)",
453
  language="javascript",
454
  lines=18
455
  )
 
460
  2. **Go to** [strudel.cc](https://strudel.cc)
461
  3. **Paste** and **click the play button** ▢️
462
 
463
+ **πŸ”§ Pro Tips:**
464
+ - Change `.gain()` values (0.1 to 1.0) to balance levels
465
+ - Try different scales: "a:minor", "c:major", "d:minor"
466
+ - Use `.sometimes()` for variation: `.sometimes(fast(2))`
467
+ - Add effects: `.room()`, `.delay()`, `.lpf()`, `.degradeBy()`
468
  """)
469
 
470
+ # Enhanced examples
471
+ gr.Markdown("### πŸŽͺ Premium Examples (Pro Quality)")
472
  with gr.Row():
473
  working_examples = [
474
+ ["Driving techno with filter sweeps", "techno", "complex"],
475
+ ["Deep house with swing", "house", "moderate"],
476
+ ["Ethereal ambient soundscape", "ambient", "complex"],
477
+ ["Crunchy hip-hop beat", "hiphop", "moderate"],
478
+ ["Glitchy experimental textures", "experimental", "complex"],
479
  ]
480
 
481
  for example_text, example_genre, example_complexity in working_examples:
482
+ btn = gr.Button(f"πŸ”₯ {example_text}", size="sm")
483
  btn.click(
484
  lambda t=example_text, g=example_genre, c=example_complexity: (t, g, c),
485
  outputs=[prompt_input, genre_dropdown, complexity_dropdown]