| import gradio as gr |
| import requests |
| import json |
|
|
| def generate_strudel_code(user_text): |
| """Generate Strudel code using Hugging Face API""" |
| |
| |
| simple_patterns = { |
| "drum": 'sound("bd hh sd hh")', |
| "beat": 'sound("bd ~ sd ~")', |
| "melody": 'note("c d e f g a b c5")', |
| "bass": 'note("c2 ~ c2 g2").sound("sawtooth")', |
| "piano": 'note("c e g c5").sound("piano")', |
| "ambient": 'note("c e g").slow(4).room(0.8)', |
| "fast": 'note("c d e f g a b c5").fast(2)', |
| "jazz": 'note("c e g b d5 f5").slow(2)' |
| } |
| |
| |
| user_lower = user_text.lower() |
| for keyword, pattern in simple_patterns.items(): |
| if keyword in user_lower: |
| return pattern |
| |
| |
| return 'note("c d e f").sound("triangle")' |
|
|
| def create_simple_player_html(strudel_code): |
| """Create a simple HTML player""" |
| return f''' |
| <div style="background: #2d2d2d; padding: 20px; border-radius: 8px; color: white; font-family: Arial;"> |
| <h3>🎵 Your Strudel Code:</h3> |
| <div style="background: #1a1a1a; padding: 15px; border-radius: 4px; font-family: monospace; margin: 10px 0;"> |
| {strudel_code} |
| </div> |
| |
| <div style="text-align: center; margin: 20px 0;"> |
| <button onclick="playMusic()" style="background: #4CAF50; color: white; border: none; padding: 12px 24px; border-radius: 4px; font-size: 16px; margin: 5px; cursor: pointer;"> |
| ▶️ Play |
| </button> |
| <button onclick="stopMusic()" style="background: #f44336; color: white; border: none; padding: 12px 24px; border-radius: 4px; font-size: 16px; margin: 5px; cursor: pointer;"> |
| ⏹️ Stop |
| </button> |
| </div> |
| |
| <div id="status" style="text-align: center; margin: 10px 0;">Ready to play</div> |
| |
| <div style="margin-top: 20px; padding: 15px; background: #1a1a1a; border-radius: 4px;"> |
| <strong>How to use:</strong><br> |
| 1. Click the ▶️ Play button<br> |
| 2. Allow audio permissions if prompted<br> |
| 3. Enjoy your generated music!<br> |
| 4. Click ⏹️ Stop to stop playback |
| </div> |
| </div> |
| |
| <script src="https://unpkg.com/@strudel/core"></script> |
| <script src="https://unpkg.com/@strudel/webaudio"></script> |
| |
| <script> |
| let isPlaying = false; |
| let currentPattern = null; |
| |
| async function playMusic() {{ |
| const status = document.getElementById('status'); |
| |
| if (isPlaying) {{ |
| status.innerHTML = "Already playing!"; |
| return; |
| }} |
| |
| try {{ |
| status.innerHTML = "Starting audio..."; |
| |
| // Initialize Web Audio |
| const audioContext = new (window.AudioContext || window.webkitAudioContext)(); |
| if (audioContext.state === 'suspended') {{ |
| await audioContext.resume(); |
| }} |
| |
| // Simple audio generation using Web Audio API directly |
| const oscillator = audioContext.createOscillator(); |
| const gainNode = audioContext.createGain(); |
| |
| oscillator.connect(gainNode); |
| gainNode.connect(audioContext.destination); |
| |
| // Create a simple melody based on the Strudel code |
| const code = "{strudel_code}"; |
| let frequency = 440; // Default A4 |
| |
| if (code.includes('c')) frequency = 261.63; // C4 |
| if (code.includes('d')) frequency = 293.66; // D4 |
| if (code.includes('e')) frequency = 329.63; // E4 |
| if (code.includes('f')) frequency = 349.23; // F4 |
| if (code.includes('g')) frequency = 392.00; // G4 |
| |
| oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime); |
| oscillator.type = code.includes('sawtooth') ? 'sawtooth' : 'sine'; |
| |
| gainNode.gain.setValueAtTime(0.1, audioContext.currentTime); |
| gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 3); |
| |
| oscillator.start(audioContext.currentTime); |
| oscillator.stop(audioContext.currentTime + 3); |
| |
| currentPattern = oscillator; |
| isPlaying = true; |
| status.innerHTML = "🎵 Playing..."; |
| |
| setTimeout(() => {{ |
| isPlaying = false; |
| status.innerHTML = "Finished playing"; |
| }}, 3000); |
| |
| }} catch (error) {{ |
| console.error('Audio error:', error); |
| status.innerHTML = "Audio error - try clicking play again"; |
| }} |
| }} |
| |
| function stopMusic() {{ |
| if (currentPattern) {{ |
| try {{ |
| currentPattern.stop(); |
| }} catch (e) {{ |
| // Pattern might already be stopped |
| }} |
| currentPattern = null; |
| }} |
| isPlaying = false; |
| document.getElementById('status').innerHTML = "Stopped"; |
| }} |
| </script> |
| ''' |
|
|
| def process_text_input(user_input): |
| """Process user input and return playable HTML""" |
| if not user_input.strip(): |
| return "Please enter a description of the music you want!" |
| |
| |
| strudel_code = generate_strudel_code(user_input) |
| |
| |
| player_html = create_simple_player_html(strudel_code) |
| |
| return player_html |
|
|
| |
| with gr.Blocks(title="Text to Strudel") as app: |
| |
| gr.Markdown("# 🎵 Simple Text to Music") |
| gr.Markdown("Describe music and get a playable result!") |
| |
| with gr.Row(): |
| user_input = gr.Textbox( |
| label="What music do you want?", |
| placeholder="Try: 'drum beat', 'piano melody', 'bass line', 'ambient sounds'", |
| lines=2 |
| ) |
| |
| generate_btn = gr.Button("🎵 Make Music", variant="primary") |
| |
| output_html = gr.HTML(value="<p>Enter a description above and click 'Make Music'!</p>") |
| |
| generate_btn.click( |
| fn=process_text_input, |
| inputs=[user_input], |
| outputs=[output_html] |
| ) |
| |
| |
| gr.Markdown("### Try these:") |
| |
| with gr.Row(): |
| ex1 = gr.Button("🥁 Drum Beat") |
| ex2 = gr.Button("🎹 Piano Melody") |
| ex3 = gr.Button("🎸 Bass Line") |
| ex4 = gr.Button("🌙 Ambient") |
| |
| ex1.click(lambda: ["drum beat", process_text_input("drum beat")], outputs=[user_input, output_html]) |
| ex2.click(lambda: ["piano melody", process_text_input("piano melody")], outputs=[user_input, output_html]) |
| ex3.click(lambda: ["bass line", process_text_input("bass line")], outputs=[user_input, output_html]) |
| ex4.click(lambda: ["ambient sounds", process_text_input("ambient sounds")], outputs=[user_input, output_html]) |
|
|
| if __name__ == "__main__": |
| app.launch() |