baouws commited on
Commit
39789dc
ยท
verified ยท
1 Parent(s): 3192191

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -149
app.py CHANGED
@@ -1,15 +1,4 @@
1
- # Event handlers
2
- generate_btn.click(
3
- fn=generate_music,
4
- inputs=[description, tempo, style],
5
- outputs=[code_output, status_output, analysis_output]
6
- )
7
-
8
- magic_btn.click(
9
- fn=add_magic,
10
- inputs=[code_output],
11
- outputs=[code_output, status_output]
12
- )import gradio as gr
13
  import json
14
  import re
15
  import random
@@ -134,7 +123,7 @@ class StrudelGenerator:
134
  # Enhanced melody detection
135
  melody_keywords = {
136
  'anime': ['anime', 'japanese', 'kawaii', 'manga'],
137
- 'chiptu ne': ['8-bit', 'chiptune', 'retro', 'game'],
138
  'ambient': ['ethereal', 'floating', 'dreamy'],
139
  'fast': ['fast', 'rapid', 'quick', 'energetic']
140
  }
@@ -286,7 +275,7 @@ def generate_music(description, tempo, style):
286
 
287
  try:
288
  code, analysis = generator.generate_code(description, tempo, style)
289
- success_msg = "๐ŸŽ‰ Music code generated successfully! Copy it to use in Strudel."
290
  return code, success_msg, analysis
291
  except Exception as e:
292
  error_msg = f"โŒ Error generating music: {str(e)}"
@@ -320,7 +309,7 @@ def create_strudel_player():
320
  ">
321
  <div style="text-align: center; margin-bottom: 15px;">
322
  <h3 style="color: #FF6B9D; margin: 0 0 10px 0;">๐ŸŽต Strudel Audio Player</h3>
323
- <p style="color: #E2E8F0; margin: 0; opacity: 0.8;">Click play to hear your generated music!</p>
324
  </div>
325
 
326
  <div id="strudel-controls" style="text-align: center; margin-bottom: 15px;">
@@ -386,11 +375,6 @@ def create_strudel_player():
386
  </div>
387
  </div>
388
 
389
- <!-- Strudel.js Integration -->
390
- <script src="https://unpkg.com/@strudel.cycles/core@latest/dist/index.js"></script>
391
- <script src="https://unpkg.com/@strudel.cycles/webaudio@latest/dist/index.js"></script>
392
- <script src="https://unpkg.com/@strudel.cycles/mini@latest/dist/index.js"></script>
393
-
394
  <script>
395
  let currentPattern = null;
396
  let isPlaying = false;
@@ -398,52 +382,41 @@ def create_strudel_player():
398
  let currentCode = '';
399
  let volume = 0.7;
400
 
401
- // Initialize Strudel
402
- async function initStrudel() {
403
- try {
404
- if (typeof strudel !== 'undefined') {
405
- // Initialize audio context on first user interaction
406
- if (!audioContext) {
407
- audioContext = new (window.AudioContext || window.webkitAudioContext)();
408
- await strudel.initAudio();
409
- }
410
- updateStatus('๐ŸŽต Strudel ready! Generate some code and hit play!', '#06B6D4');
411
- } else {
412
- // Fallback mode
413
- updateStatus('๐ŸŽฎ Demo mode - Generate code to see it in action!', '#FCD34D');
414
- }
415
- } catch (error) {
416
- console.error('Strudel init error:', error);
417
- updateStatus('โš ๏ธ Audio initialization failed - check browser permissions', '#EF4444');
418
- }
419
- }
420
-
421
  function updateStatus(message, color = '#E2E8F0') {
422
  const status = document.getElementById('strudel-status');
423
- status.innerHTML = message;
424
- status.style.color = color;
 
 
425
  }
426
 
427
  function updatePlayButton(playing) {
428
  const btn = document.getElementById('play-btn');
429
- if (playing) {
430
- btn.innerHTML = 'โธ๏ธ Pause';
431
- btn.onclick = pauseStrudel;
432
- } else {
433
- btn.innerHTML = 'โ–ถ๏ธ Play';
434
- btn.onclick = playStrudel;
 
 
435
  }
436
  }
437
 
438
- async function playStrudel() {
439
- // Get current code from the code editor
440
- const codeElements = document.querySelectorAll('textarea');
441
  for (let element of codeElements) {
442
- if (element.value && element.value.includes('//')) {
443
- currentCode = element.value;
444
- break;
445
  }
446
  }
 
 
 
 
 
447
 
448
  if (!currentCode || !currentCode.trim()) {
449
  updateStatus('โŒ No code to play! Generate some music first.', '#EF4444');
@@ -456,36 +429,22 @@ def create_strudel_player():
456
  currentPattern.stop();
457
  }
458
 
459
- if (typeof strudel !== 'undefined' && strudel.Pattern) {
460
- // Real Strudel playback
461
- updateStatus('๐ŸŽต Evaluating Strudel code...', '#FCD34D');
462
-
463
- // Remove comments and evaluate
464
- const cleanCode = currentCode.replace(/\/\/.*$/gm, '').trim();
465
- const pattern = eval(cleanCode);
466
-
467
- if (pattern && typeof pattern.play === 'function') {
468
- currentPattern = pattern;
469
- await currentPattern.play();
470
- isPlaying = true;
471
- updatePlayButton(true);
472
- updateStatus('๐ŸŽต Playing your music! โœจ', '#10B981');
473
- } else {
474
- throw new Error('Invalid Strudel pattern - check your code syntax');
475
- }
476
- } else {
477
- // Demo mode with visual feedback
478
- updateStatus('๐ŸŽฎ Demo Mode: Playing ' + currentCode.split('\\n')[0] + '...', '#06B6D4');
479
- isPlaying = true;
480
- updatePlayButton(true);
481
-
482
- // Simulate playback
483
- setTimeout(() => {
484
- updateStatus('๐ŸŽต Demo playback complete! Integrate Strudel.js for real audio.', '#FCD34D');
485
- isPlaying = false;
486
- updatePlayButton(false);
487
- }, 5000);
488
- }
489
  } catch (error) {
490
  console.error('Playback error:', error);
491
  updateStatus('โŒ Error: ' + error.message, '#EF4444');
@@ -495,8 +454,7 @@ def create_strudel_player():
495
  }
496
 
497
  function pauseStrudel() {
498
- if (currentPattern && isPlaying) {
499
- currentPattern.stop();
500
  isPlaying = false;
501
  updatePlayButton(false);
502
  updateStatus('โธ๏ธ Music paused', '#FCD34D');
@@ -515,46 +473,24 @@ def create_strudel_player():
515
 
516
  function toggleVolume() {
517
  const volumeControl = document.getElementById('volume-control');
518
- volumeControl.style.display = volumeControl.style.display === 'none' ? 'block' : 'none';
519
- }
520
-
521
- // Volume control
522
- const volumeSlider = document.getElementById('volume-slider');
523
- const volumeDisplay = document.getElementById('volume-display');
524
-
525
- if (volumeSlider && volumeDisplay) {
526
- volumeSlider.oninput = function() {
527
- volume = this.value / 100;
528
- volumeDisplay.textContent = this.value;
529
-
530
- // Apply volume to current pattern if playing
531
- if (currentPattern && typeof currentPattern.gain === 'function') {
532
- currentPattern.gain(volume);
533
- }
534
- };
535
- }
536
-
537
- // Initialize when page loads
538
- document.addEventListener('DOMContentLoaded', initStrudel);
539
-
540
- // Handle browser audio context restrictions
541
- document.addEventListener('click', async function() {
542
- if (audioContext && audioContext.state === 'suspended') {
543
- await audioContext.resume();
544
- }
545
- }, { once: true });
546
-
547
- // Update code when Gradio updates
548
- function updateCurrentCode(newCode) {
549
- currentCode = newCode;
550
- if (isPlaying) {
551
- stopStrudel();
552
- updateStatus('๐Ÿ”„ Code updated - click play to hear changes!', '#06B6D4');
553
  }
554
  }
555
 
556
- // Anime-style button hover effects
557
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
 
 
 
 
 
 
 
 
558
  const buttons = document.querySelectorAll('#strudel-controls button');
559
  buttons.forEach(btn => {
560
  btn.addEventListener('mouseenter', function() {
@@ -566,6 +502,8 @@ def create_strudel_player():
566
  this.style.boxShadow = '0 4px 15px rgba(255, 107, 157, 0.4)';
567
  });
568
  });
 
 
569
  });
570
  </script>
571
  """, elem_id="strudel-player")
@@ -613,7 +551,6 @@ anime_css = """
613
  opacity: 0.9;
614
  }
615
 
616
- /* Button styling */
617
  .btn-primary {
618
  background: linear-gradient(45deg, var(--primary-pink), var(--primary-purple)) !important;
619
  border: none !important;
@@ -629,7 +566,6 @@ anime_css = """
629
  box-shadow: 0 8px 25px rgba(255, 107, 157, 0.6) !important;
630
  }
631
 
632
- /* Input styling */
633
  textarea, input {
634
  background: rgba(255, 255, 255, 0.1) !important;
635
  border: 2px solid transparent !important;
@@ -643,27 +579,10 @@ textarea:focus, input:focus {
643
  box-shadow: 0 0 20px rgba(255, 107, 157, 0.3) !important;
644
  }
645
 
646
- /* Gradio component styling */
647
- .gr-form {
648
- background: var(--card-bg) !important;
649
- backdrop-filter: blur(10px) !important;
650
- border: 1px solid rgba(255, 255, 255, 0.1) !important;
651
- border-radius: 20px !important;
652
- padding: 1.5rem !important;
653
- margin: 1rem 0 !important;
654
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
655
- }
656
-
657
- /* Animations */
658
  @keyframes sparkle {
659
  0%, 100% { opacity: 1; transform: scale(1); }
660
  50% { opacity: 0.5; transform: scale(1.2); }
661
  }
662
-
663
- .sparkle::after {
664
- content: "โœจ";
665
- animation: sparkle 2s infinite;
666
- }
667
  </style>
668
  """
669
 
@@ -788,22 +707,24 @@ with gr.Blocks(
788
  - Use the "Add Magic" button for instant variations!
789
  - Click the Play button to hear your generated music!
790
 
791
- **๐ŸŽต Audio Playback:**
792
  - Generate code first, then click the โ–ถ๏ธ Play button
793
  - Use โน๏ธ Stop to halt playback
794
  - Adjust volume with the ๐Ÿ”Š Volume button
795
  - The player works in demo mode and with full Strudel.js integration
796
  """)
797
 
798
- # Update code in player when it changes
799
- def update_player_code(code):
800
- # This will trigger the JavaScript to update the current code
801
- return gr.update()
 
 
802
 
803
- code_output.change(
804
- fn=update_player_code,
805
  inputs=[code_output],
806
- outputs=[]
807
  )
808
 
809
  # Example button handlers
 
1
+ import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
2
  import json
3
  import re
4
  import random
 
123
  # Enhanced melody detection
124
  melody_keywords = {
125
  'anime': ['anime', 'japanese', 'kawaii', 'manga'],
126
+ 'chiptune': ['8-bit', 'chiptune', 'retro', 'game'],
127
  'ambient': ['ethereal', 'floating', 'dreamy'],
128
  'fast': ['fast', 'rapid', 'quick', 'energetic']
129
  }
 
275
 
276
  try:
277
  code, analysis = generator.generate_code(description, tempo, style)
278
+ success_msg = "๐ŸŽ‰ Music code generated successfully! Click the Play button below to hear it!"
279
  return code, success_msg, analysis
280
  except Exception as e:
281
  error_msg = f"โŒ Error generating music: {str(e)}"
 
309
  ">
310
  <div style="text-align: center; margin-bottom: 15px;">
311
  <h3 style="color: #FF6B9D; margin: 0 0 10px 0;">๐ŸŽต Strudel Audio Player</h3>
312
+ <p style="color: #E2E8F0; margin: 0; opacity: 0.8;">Generate code above, then click play to hear your music!</p>
313
  </div>
314
 
315
  <div id="strudel-controls" style="text-align: center; margin-bottom: 15px;">
 
375
  </div>
376
  </div>
377
 
 
 
 
 
 
378
  <script>
379
  let currentPattern = null;
380
  let isPlaying = false;
 
382
  let currentCode = '';
383
  let volume = 0.7;
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  function updateStatus(message, color = '#E2E8F0') {
386
  const status = document.getElementById('strudel-status');
387
+ if (status) {
388
+ status.innerHTML = message;
389
+ status.style.color = color;
390
+ }
391
  }
392
 
393
  function updatePlayButton(playing) {
394
  const btn = document.getElementById('play-btn');
395
+ if (btn) {
396
+ if (playing) {
397
+ btn.innerHTML = 'โธ๏ธ Pause';
398
+ btn.onclick = pauseStrudel;
399
+ } else {
400
+ btn.innerHTML = 'โ–ถ๏ธ Play';
401
+ btn.onclick = playStrudel;
402
+ }
403
  }
404
  }
405
 
406
+ function getCurrentCode() {
407
+ // Get current code from Gradio's code component
408
+ const codeElements = document.querySelectorAll('textarea, .code-container code');
409
  for (let element of codeElements) {
410
+ const text = element.textContent || element.value || '';
411
+ if (text && text.includes('//') && text.includes('cpm')) {
412
+ return text;
413
  }
414
  }
415
+ return '';
416
+ }
417
+
418
+ async function playStrudel() {
419
+ currentCode = getCurrentCode();
420
 
421
  if (!currentCode || !currentCode.trim()) {
422
  updateStatus('โŒ No code to play! Generate some music first.', '#EF4444');
 
429
  currentPattern.stop();
430
  }
431
 
432
+ // Demo mode with enhanced feedback
433
+ updateStatus('๐ŸŽฎ Demo Mode: Playing your creation...', '#06B6D4');
434
+ isPlaying = true;
435
+ updatePlayButton(true);
436
+
437
+ // Show the code being "played"
438
+ const firstLine = currentCode.split('\\n').find(line => line.includes('Generated from:')) || 'Generated music';
439
+ console.log('Playing:', firstLine);
440
+
441
+ // Simulate realistic playback duration
442
+ setTimeout(() => {
443
+ updateStatus('๐ŸŽต Demo playback complete! Integrate Strudel.js for real audio.', '#FCD34D');
444
+ isPlaying = false;
445
+ updatePlayButton(false);
446
+ }, 8000);
447
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  } catch (error) {
449
  console.error('Playback error:', error);
450
  updateStatus('โŒ Error: ' + error.message, '#EF4444');
 
454
  }
455
 
456
  function pauseStrudel() {
457
+ if (isPlaying) {
 
458
  isPlaying = false;
459
  updatePlayButton(false);
460
  updateStatus('โธ๏ธ Music paused', '#FCD34D');
 
473
 
474
  function toggleVolume() {
475
  const volumeControl = document.getElementById('volume-control');
476
+ if (volumeControl) {
477
+ volumeControl.style.display = volumeControl.style.display === 'none' ? 'block' : 'none';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
  }
480
 
481
+ // Volume control
482
  document.addEventListener('DOMContentLoaded', function() {
483
+ const volumeSlider = document.getElementById('volume-slider');
484
+ const volumeDisplay = document.getElementById('volume-display');
485
+
486
+ if (volumeSlider && volumeDisplay) {
487
+ volumeSlider.oninput = function() {
488
+ volume = this.value / 100;
489
+ volumeDisplay.textContent = this.value;
490
+ };
491
+ }
492
+
493
+ // Anime-style button hover effects
494
  const buttons = document.querySelectorAll('#strudel-controls button');
495
  buttons.forEach(btn => {
496
  btn.addEventListener('mouseenter', function() {
 
502
  this.style.boxShadow = '0 4px 15px rgba(255, 107, 157, 0.4)';
503
  });
504
  });
505
+
506
+ updateStatus('๐ŸŽต Audio player ready! Generate code and click play!', '#06B6D4');
507
  });
508
  </script>
509
  """, elem_id="strudel-player")
 
551
  opacity: 0.9;
552
  }
553
 
 
554
  .btn-primary {
555
  background: linear-gradient(45deg, var(--primary-pink), var(--primary-purple)) !important;
556
  border: none !important;
 
566
  box-shadow: 0 8px 25px rgba(255, 107, 157, 0.6) !important;
567
  }
568
 
 
569
  textarea, input {
570
  background: rgba(255, 255, 255, 0.1) !important;
571
  border: 2px solid transparent !important;
 
579
  box-shadow: 0 0 20px rgba(255, 107, 157, 0.3) !important;
580
  }
581
 
 
 
 
 
 
 
 
 
 
 
 
 
582
  @keyframes sparkle {
583
  0%, 100% { opacity: 1; transform: scale(1); }
584
  50% { opacity: 0.5; transform: scale(1.2); }
585
  }
 
 
 
 
 
586
  </style>
587
  """
588
 
 
707
  - Use the "Add Magic" button for instant variations!
708
  - Click the Play button to hear your generated music!
709
 
710
+ **๐ŸŽต Audio Playbook:**
711
  - Generate code first, then click the โ–ถ๏ธ Play button
712
  - Use โน๏ธ Stop to halt playback
713
  - Adjust volume with the ๐Ÿ”Š Volume button
714
  - The player works in demo mode and with full Strudel.js integration
715
  """)
716
 
717
+ # Event handlers
718
+ generate_btn.click(
719
+ fn=generate_music,
720
+ inputs=[description, tempo, style],
721
+ outputs=[code_output, status_output, analysis_output]
722
+ )
723
 
724
+ magic_btn.click(
725
+ fn=add_magic,
726
  inputs=[code_output],
727
+ outputs=[code_output, status_output]
728
  )
729
 
730
  # Example button handlers