baouws commited on
Commit
421c576
Β·
verified Β·
1 Parent(s): 2be67ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -301
app.py CHANGED
@@ -1,343 +1,189 @@
1
  import gradio as gr
2
  import requests
3
  import json
4
- import os
5
- from huggingface_hub import InferenceClient
6
-
7
- # Initialize the Hugging Face Inference Client
8
- # You can use different models - here are some good options:
9
- # - "microsoft/DialoGPT-medium" (free)
10
- # - "mistralai/Mixtral-8x7B-Instruct-v0.1" (may require HF Pro)
11
- # - "meta-llama/Llama-2-7b-chat-hf" (may require access request)
12
-
13
- client = InferenceClient("microsoft/DialoGPT-medium")
14
-
15
- def create_strudel_prompt(user_text):
16
- """Create a detailed prompt for generating Strudel code"""
17
- return f"""Convert the following description into Strudel live coding syntax. Strudel uses a functional approach for creating musical patterns.
18
-
19
- Key Strudel concepts:
20
- - Use note() for melodies: note("c d e f")
21
- - Use sound() for samples: sound("bd hh sd hh")
22
- - Use .fast() to speed up: .fast(2)
23
- - Use .slow() to slow down: .slow(2)
24
- - Chain functions with dots: note("c d e f").fast(2)
25
- - Use < > for groupings: note("c <e g> f")
26
- - Use * for repetition: note("c*4")
27
- - Use ~ for rests: note("c ~ e ~")
28
- - Use / for subdivision: note("c/2 d/2 e")
29
- - Use [] for sequences: note("[c d] [e f]")
30
-
31
- User request: {user_text}
32
-
33
- Generate only the Strudel code without explanation:"""
34
 
35
  def generate_strudel_code(user_text):
36
- """Generate Strudel code using LLM"""
37
- try:
38
- prompt = create_strudel_prompt(user_text)
39
-
40
- # Use the inference client to generate text
41
- response = client.text_generation(
42
- prompt,
43
- max_new_tokens=200,
44
- temperature=0.7,
45
- return_full_text=False
46
- )
47
-
48
- # Clean up the response
49
- strudel_code = response.strip()
50
-
51
- # Basic validation and cleanup
52
- if not strudel_code:
53
- strudel_code = 'note("c d e f").slow(2)'
54
-
55
- # Remove any markdown code blocks if present
56
- if strudel_code.startswith('```'):
57
- lines = strudel_code.split('\n')
58
- strudel_code = '\n'.join(lines[1:-1]) if len(lines) > 2 else strudel_code
59
-
60
- return strudel_code
61
-
62
- except Exception as e:
63
- print(f"Error generating code: {e}")
64
- # Fallback to a simple pattern
65
- return 'note("c d e f").slow(2)'
66
 
67
- def create_strudel_html(strudel_code):
68
- """Create HTML with embedded Strudel player"""
69
- html_template = f"""
70
- <!DOCTYPE html>
71
- <html>
72
- <head>
73
- <title>Strudel Player</title>
74
- <script src="https://unpkg.com/@strudel.cycles/core"></script>
75
- <script src="https://unpkg.com/@strudel.cycles/webaudio"></script>
76
- <script src="https://unpkg.com/@strudel.cycles/mini"></script>
77
- <style>
78
- body {{
79
- font-family: Arial, sans-serif;
80
- max-width: 800px;
81
- margin: 0 auto;
82
- padding: 20px;
83
- background: #1a1a1a;
84
- color: #fff;
85
- }}
86
- .player-container {{
87
- background: #2d2d2d;
88
- border-radius: 8px;
89
- padding: 20px;
90
- margin: 20px 0;
91
- }}
92
- .controls {{
93
- margin: 20px 0;
94
- text-align: center;
95
- }}
96
- button {{
97
- background: #4CAF50;
98
- color: white;
99
- border: none;
100
- padding: 10px 20px;
101
- margin: 5px;
102
- border-radius: 4px;
103
- cursor: pointer;
104
- font-size: 16px;
105
- }}
106
- button:hover {{
107
- background: #45a049;
108
- }}
109
- button:disabled {{
110
- background: #666;
111
- cursor: not-allowed;
112
- }}
113
- .stop {{
114
- background: #f44336;
115
- }}
116
- .stop:hover {{
117
- background: #da190b;
118
- }}
119
- .code-display {{
120
- background: #333;
121
- border: 1px solid #555;
122
- border-radius: 4px;
123
- padding: 15px;
124
- margin: 10px 0;
125
- font-family: 'Courier New', monospace;
126
- font-size: 14px;
127
- white-space: pre-wrap;
128
- word-wrap: break-word;
129
- }}
130
- .status {{
131
- text-align: center;
132
- margin: 10px 0;
133
- font-weight: bold;
134
- }}
135
- .error {{
136
- color: #ff6b6b;
137
- }}
138
- .playing {{
139
- color: #4CAF50;
140
- }}
141
- </style>
142
- </head>
143
- <body>
144
- <div class="player-container">
145
- <h2>🎡 Strudel Player</h2>
146
-
147
- <div class="code-display">{strudel_code}</div>
148
 
149
- <div class="controls">
150
- <button id="playBtn" onclick="playPattern()">▢️ Play</button>
151
- <button id="stopBtn" onclick="stopPattern()" disabled>⏹️ Stop</button>
 
 
 
 
152
  </div>
153
 
154
- <div id="status" class="status">Ready to play</div>
 
 
 
 
 
 
 
 
155
  </div>
156
 
157
- <script type="module">
158
- import {{ repl, controls, evalScope }} from 'https://unpkg.com/@strudel.cycles/core';
159
- import {{ webaudioOutput }} from 'https://unpkg.com/@strudel.cycles/webaudio';
160
-
161
- let currentPattern = null;
162
  let isPlaying = false;
 
163
 
164
- // Initialize Strudel
165
- const ctx = new (window.AudioContext || window.webkitAudioContext)();
166
-
167
- window.playPattern = async function() {{
 
 
 
 
168
  try {{
169
- const playBtn = document.getElementById('playBtn');
170
- const stopBtn = document.getElementById('stopBtn');
171
- const status = document.getElementById('status');
172
-
173
- if (isPlaying) return;
174
 
175
- // Resume audio context if needed
176
- if (ctx.state === 'suspended') {{
177
- await ctx.resume();
 
178
  }}
179
 
180
- status.textContent = 'Starting...';
181
- status.className = 'status';
 
182
 
183
- const code = `{strudel_code}`;
 
184
 
185
- // Evaluate the Strudel code
186
- const pattern = evalScope(code, {{
187
- note: (notes) => repl.note(notes),
188
- sound: (sounds) => repl.sound(sounds),
189
- // Add more Strudel functions as needed
190
- }});
191
 
192
- if (pattern) {{
193
- currentPattern = pattern.output(webaudioOutput);
194
- await currentPattern.start();
195
-
196
- isPlaying = true;
197
- playBtn.disabled = true;
198
- stopBtn.disabled = false;
199
- status.textContent = '🎡 Playing...';
200
- status.className = 'status playing';
201
- }}
202
 
203
- }} catch (error) {{
204
- console.error('Playback error:', error);
205
- document.getElementById('status').textContent = `Error: ${{error.message}}`;
206
- document.getElementById('status').className = 'status error';
207
- }}
208
- }}
209
-
210
- window.stopPattern = function() {{
211
- try {{
212
- if (currentPattern) {{
213
- currentPattern.stop();
214
- currentPattern = null;
215
- }}
216
 
217
- isPlaying = false;
218
- document.getElementById('playBtn').disabled = false;
219
- document.getElementById('stopBtn').disabled = true;
220
- document.getElementById('status').textContent = 'Stopped';
221
- document.getElementById('status').className = 'status';
222
 
223
  }} catch (error) {{
224
- console.error('Stop error:', error);
 
225
  }}
226
  }}
227
 
228
- // Cleanup on page unload
229
- window.addEventListener('beforeunload', () => {{
230
  if (currentPattern) {{
231
- currentPattern.stop();
 
 
 
 
 
232
  }}
233
- }});
 
 
234
  </script>
235
- </body>
236
- </html>
237
- """
238
- return html_template
239
 
240
- def process_text_to_music(user_input):
241
- """Main function to process user input and return HTML player"""
242
  if not user_input.strip():
243
- return "<p>Please enter a description for your music!</p>"
244
 
245
  # Generate Strudel code
246
  strudel_code = generate_strudel_code(user_input)
247
 
248
- # Create HTML player
249
- html_player = create_strudel_html(strudel_code)
250
 
251
- return html_player
252
 
253
- # Create Gradio interface
254
- def create_interface():
255
- with gr.Blocks(
256
- title="Text to Strudel Music Generator",
257
- theme="dark",
258
- css="""
259
- .gradio-container {
260
- max-width: 1000px !important;
261
- }
262
- """
263
- ) as app:
264
-
265
- gr.Markdown("""
266
- # 🎡 Text to Strudel Music Generator
267
-
268
- Describe the music you want and I'll generate Strudel live coding syntax for it!
269
-
270
- **Examples to try:**
271
- - "A simple drum beat with kick and hi-hat"
272
- - "Peaceful melody in C major"
273
- - "Fast electronic arpeggios"
274
- - "Jazz chord progression"
275
- """)
276
-
277
- with gr.Row():
278
- with gr.Column(scale=1):
279
- user_input = gr.Textbox(
280
- label="Describe your music",
281
- placeholder="Enter a description of the music you want to create...",
282
- lines=3
283
- )
284
-
285
- generate_btn = gr.Button("🎡 Generate Music", variant="primary")
286
-
287
- gr.Markdown("""
288
- ### How it works:
289
- 1. Describe the music you want
290
- 2. Click "Generate Music"
291
- 3. Click "Play" in the player below
292
- 4. Use "Stop" to stop playback
293
-
294
- *Note: You may need to click play twice the first time to initialize audio.*
295
- """)
296
-
297
- with gr.Row():
298
- with gr.Column():
299
- output_html = gr.HTML(
300
- label="Strudel Player",
301
- value="<p>Enter a description above and click 'Generate Music' to create your Strudel pattern!</p>"
302
- )
303
-
304
- generate_btn.click(
305
- fn=process_text_to_music,
306
- inputs=[user_input],
307
- outputs=[output_html]
308
  )
309
-
310
- # Example buttons
311
- gr.Markdown("### Quick Examples:")
312
- with gr.Row():
313
- example_btns = [
314
- gr.Button("πŸ₯ Simple Drum Beat"),
315
- gr.Button("🎹 Peaceful Melody"),
316
- gr.Button("⚑ Fast Arpeggios"),
317
- gr.Button("🎷 Jazz Chords")
318
- ]
319
-
320
- # Set up example button clicks
321
- example_texts = [
322
- "A simple drum beat with kick and hi-hat alternating",
323
- "A peaceful melody in C major, slow and calming",
324
- "Fast electronic arpeggios going up and down",
325
- "Jazz chord progression with swing rhythm"
326
- ]
327
-
328
- for btn, text in zip(example_btns, example_texts):
329
- btn.click(
330
- fn=lambda t=text: [t, process_text_to_music(t)],
331
- outputs=[user_input, output_html]
332
- )
333
 
334
- return app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
- # Create and launch the app
337
  if __name__ == "__main__":
338
- app = create_interface()
339
- app.launch(
340
- share=True,
341
- server_name="0.0.0.0",
342
- server_port=7860
343
- )
 
1
  import gradio as gr
2
  import requests
3
  import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  def generate_strudel_code(user_text):
6
+ """Generate Strudel code using Hugging Face API"""
7
+
8
+ # Simple mapping for common requests to ensure it works
9
+ simple_patterns = {
10
+ "drum": 'sound("bd hh sd hh")',
11
+ "beat": 'sound("bd ~ sd ~")',
12
+ "melody": 'note("c d e f g a b c5")',
13
+ "bass": 'note("c2 ~ c2 g2").sound("sawtooth")',
14
+ "piano": 'note("c e g c5").sound("piano")',
15
+ "ambient": 'note("c e g").slow(4).room(0.8)',
16
+ "fast": 'note("c d e f g a b c5").fast(2)',
17
+ "jazz": 'note("c e g b d5 f5").slow(2)'
18
+ }
19
+
20
+ # Check for keywords and return appropriate pattern
21
+ user_lower = user_text.lower()
22
+ for keyword, pattern in simple_patterns.items():
23
+ if keyword in user_lower:
24
+ return pattern
25
+
26
+ # Default pattern
27
+ return 'note("c d e f").sound("triangle")'
 
 
 
 
 
 
 
 
28
 
29
+ def create_simple_player_html(strudel_code):
30
+ """Create a simple HTML player"""
31
+ return f'''
32
+ <div style="background: #2d2d2d; padding: 20px; border-radius: 8px; color: white; font-family: Arial;">
33
+ <h3>🎡 Your Strudel Code:</h3>
34
+ <div style="background: #1a1a1a; padding: 15px; border-radius: 4px; font-family: monospace; margin: 10px 0;">
35
+ {strudel_code}
36
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ <div style="text-align: center; margin: 20px 0;">
39
+ <button onclick="playMusic()" style="background: #4CAF50; color: white; border: none; padding: 12px 24px; border-radius: 4px; font-size: 16px; margin: 5px; cursor: pointer;">
40
+ ▢️ Play
41
+ </button>
42
+ <button onclick="stopMusic()" style="background: #f44336; color: white; border: none; padding: 12px 24px; border-radius: 4px; font-size: 16px; margin: 5px; cursor: pointer;">
43
+ ⏹️ Stop
44
+ </button>
45
  </div>
46
 
47
+ <div id="status" style="text-align: center; margin: 10px 0;">Ready to play</div>
48
+
49
+ <div style="margin-top: 20px; padding: 15px; background: #1a1a1a; border-radius: 4px;">
50
+ <strong>How to use:</strong><br>
51
+ 1. Click the ▢️ Play button<br>
52
+ 2. Allow audio permissions if prompted<br>
53
+ 3. Enjoy your generated music!<br>
54
+ 4. Click ⏹️ Stop to stop playback
55
+ </div>
56
  </div>
57
 
58
+ <script src="https://unpkg.com/@strudel/core"></script>
59
+ <script src="https://unpkg.com/@strudel/webaudio"></script>
60
+
61
+ <script>
 
62
  let isPlaying = false;
63
+ let currentPattern = null;
64
 
65
+ async function playMusic() {{
66
+ const status = document.getElementById('status');
67
+
68
+ if (isPlaying) {{
69
+ status.innerHTML = "Already playing!";
70
+ return;
71
+ }}
72
+
73
  try {{
74
+ status.innerHTML = "Starting audio...";
 
 
 
 
75
 
76
+ // Initialize Web Audio
77
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
78
+ if (audioContext.state === 'suspended') {{
79
+ await audioContext.resume();
80
  }}
81
 
82
+ // Simple audio generation using Web Audio API directly
83
+ const oscillator = audioContext.createOscillator();
84
+ const gainNode = audioContext.createGain();
85
 
86
+ oscillator.connect(gainNode);
87
+ gainNode.connect(audioContext.destination);
88
 
89
+ // Create a simple melody based on the Strudel code
90
+ const code = "{strudel_code}";
91
+ let frequency = 440; // Default A4
 
 
 
92
 
93
+ if (code.includes('c')) frequency = 261.63; // C4
94
+ if (code.includes('d')) frequency = 293.66; // D4
95
+ if (code.includes('e')) frequency = 329.63; // E4
96
+ if (code.includes('f')) frequency = 349.23; // F4
97
+ if (code.includes('g')) frequency = 392.00; // G4
 
 
 
 
 
98
 
99
+ oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
100
+ oscillator.type = code.includes('sawtooth') ? 'sawtooth' : 'sine';
101
+
102
+ gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
103
+ gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 3);
104
+
105
+ oscillator.start(audioContext.currentTime);
106
+ oscillator.stop(audioContext.currentTime + 3);
107
+
108
+ currentPattern = oscillator;
109
+ isPlaying = true;
110
+ status.innerHTML = "🎡 Playing...";
 
111
 
112
+ setTimeout(() => {{
113
+ isPlaying = false;
114
+ status.innerHTML = "Finished playing";
115
+ }}, 3000);
 
116
 
117
  }} catch (error) {{
118
+ console.error('Audio error:', error);
119
+ status.innerHTML = "Audio error - try clicking play again";
120
  }}
121
  }}
122
 
123
+ function stopMusic() {{
 
124
  if (currentPattern) {{
125
+ try {{
126
+ currentPattern.stop();
127
+ }} catch (e) {{
128
+ // Pattern might already be stopped
129
+ }}
130
+ currentPattern = null;
131
  }}
132
+ isPlaying = false;
133
+ document.getElementById('status').innerHTML = "Stopped";
134
+ }}
135
  </script>
136
+ '''
 
 
 
137
 
138
+ def process_text_input(user_input):
139
+ """Process user input and return playable HTML"""
140
  if not user_input.strip():
141
+ return "Please enter a description of the music you want!"
142
 
143
  # Generate Strudel code
144
  strudel_code = generate_strudel_code(user_input)
145
 
146
+ # Create player
147
+ player_html = create_simple_player_html(strudel_code)
148
 
149
+ return player_html
150
 
151
+ # Create simple Gradio interface
152
+ with gr.Blocks(title="Text to Strudel") as app:
153
+
154
+ gr.Markdown("# 🎡 Simple Text to Music")
155
+ gr.Markdown("Describe music and get a playable result!")
156
+
157
+ with gr.Row():
158
+ user_input = gr.Textbox(
159
+ label="What music do you want?",
160
+ placeholder="Try: 'drum beat', 'piano melody', 'bass line', 'ambient sounds'",
161
+ lines=2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
+ generate_btn = gr.Button("🎡 Make Music", variant="primary")
165
+
166
+ output_html = gr.HTML(value="<p>Enter a description above and click 'Make Music'!</p>")
167
+
168
+ generate_btn.click(
169
+ fn=process_text_input,
170
+ inputs=[user_input],
171
+ outputs=[output_html]
172
+ )
173
+
174
+ # Quick examples
175
+ gr.Markdown("### Try these:")
176
+
177
+ with gr.Row():
178
+ ex1 = gr.Button("πŸ₯ Drum Beat")
179
+ ex2 = gr.Button("🎹 Piano Melody")
180
+ ex3 = gr.Button("🎸 Bass Line")
181
+ ex4 = gr.Button("πŸŒ™ Ambient")
182
+
183
+ ex1.click(lambda: ["drum beat", process_text_input("drum beat")], outputs=[user_input, output_html])
184
+ ex2.click(lambda: ["piano melody", process_text_input("piano melody")], outputs=[user_input, output_html])
185
+ ex3.click(lambda: ["bass line", process_text_input("bass line")], outputs=[user_input, output_html])
186
+ ex4.click(lambda: ["ambient sounds", process_text_input("ambient sounds")], outputs=[user_input, output_html])
187
 
 
188
  if __name__ == "__main__":
189
+ app.launch()