jacob-c commited on
Commit
6ac84ae
·
1 Parent(s): 3db0204
__pycache__/beat_analysis.cpython-310.pyc CHANGED
Binary files a/__pycache__/beat_analysis.cpython-310.pyc and b/__pycache__/beat_analysis.cpython-310.pyc differ
 
__pycache__/emotionanalysis.cpython-310.pyc CHANGED
Binary files a/__pycache__/emotionanalysis.cpython-310.pyc and b/__pycache__/emotionanalysis.cpython-310.pyc differ
 
app.py CHANGED
@@ -230,11 +230,30 @@ ONLY WRITE THE ACTUAL LYRICS. NO EXPLANATIONS OR META-TEXT.
230
  # Create phrase examples
231
  num_phrases = len(lyric_templates)
232
 
233
- # Create a more direct prompt with examples
 
 
 
 
 
 
 
 
 
 
 
234
  prompt = f"""Write song lyrics for a {genre} song in {key} {mode} with tempo {tempo} BPM. The emotion is {emotion} and theme is {theme}.
235
 
236
  I need EXACTLY {num_phrases} lines of lyrics - one line for each musical phrase. Not one more, not one less.
237
 
 
 
 
 
 
 
 
 
238
  FORMAT:
239
  - Just write {num_phrases} plain text lines
240
  - Each line should be simple song lyrics (no annotations, no numbers, no labeling)
@@ -244,13 +263,13 @@ FORMAT:
244
  - Don't include line numbers
245
 
246
  EXAMPLE OF WHAT I WANT (for a {num_phrases}-line song):
247
- Lost in the shadows of yesterday
248
- Dreams fade away like morning dew
249
- Time slips through fingers like desert sand
250
- Memories echo in empty rooms
251
  (... and so on for exactly {num_phrases} lines)
252
 
253
- JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES.
254
  """
255
 
256
  # Generate lyrics using the LLM model
@@ -427,6 +446,9 @@ JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES.
427
  clean_lines[i] = re.sub(r'</think>', '', clean_lines[i])
428
  clean_lines[i] = re.sub(r'\[thinking\]', '', clean_lines[i])
429
  clean_lines[i] = re.sub(r'\[/thinking\]', '', clean_lines[i])
 
 
 
430
 
431
  # 9. Filter out any remaining empty lines after tag removal
432
  clean_lines = [line for line in clean_lines if line.strip() and not line.isspace()]
@@ -440,17 +462,27 @@ JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES.
440
  # Keep the first num_required lines
441
  clean_lines = clean_lines[:num_required]
442
 
443
- # If we don't have enough lines, generate placeholders
444
  while len(clean_lines) < num_required:
445
- placeholder = f"Echoes of {emotion} fill the {genre} night"
446
- if len(clean_lines) > 0:
447
- # Try to make the placeholder somewhat related to previous lines
448
- last_words = [word for line in clean_lines[-1:] for word in line.split() if len(word) > 3]
449
- if last_words:
450
- import random
451
- word = random.choice(last_words)
452
- placeholder = f"{word.capitalize()} whispers through the {emotion} silence"
453
-
 
 
 
 
 
 
 
 
 
 
454
  clean_lines.append(placeholder)
455
 
456
  # Assemble final lyrics
 
230
  # Create phrase examples
231
  num_phrases = len(lyric_templates)
232
 
233
+ # Calculate the typical syllable range for this genre
234
+ if num_phrases > 0:
235
+ # Get max syllables per line from templates
236
+ max_syllables = max([t.get('max_expected', 8) for t in lyric_templates]) if lyric_templates[0].get('max_expected') else 8
237
+ min_syllables = min([t.get('min_expected', 3) for t in lyric_templates]) if lyric_templates[0].get('min_expected') else 3
238
+ avg_syllables = (min_syllables + max_syllables) // 2
239
+ else:
240
+ min_syllables = 3
241
+ max_syllables = 8
242
+ avg_syllables = 5
243
+
244
+ # Create a more direct prompt with examples and specific syllable count guidance
245
  prompt = f"""Write song lyrics for a {genre} song in {key} {mode} with tempo {tempo} BPM. The emotion is {emotion} and theme is {theme}.
246
 
247
  I need EXACTLY {num_phrases} lines of lyrics - one line for each musical phrase. Not one more, not one less.
248
 
249
+ CRITICAL INSTRUCTIONS:
250
+ - Each line MUST contain between {min_syllables}-{max_syllables} syllables (aim for {avg_syllables})
251
+ - Keep lines SHORT and SIMPLE - fewer syllables is better than too many
252
+ - Break complete thoughts across multiple lines instead of cramming them into one line
253
+ - Each line should flow naturally with the beat
254
+ - Make each line end at a natural pause point
255
+ - Use shorter words when possible
256
+
257
  FORMAT:
258
  - Just write {num_phrases} plain text lines
259
  - Each line should be simple song lyrics (no annotations, no numbers, no labeling)
 
263
  - Don't include line numbers
264
 
265
  EXAMPLE OF WHAT I WANT (for a {num_phrases}-line song):
266
+ Lost in the light ({min_syllables} syllables)
267
+ Waiting for the morning dew ({avg_syllables} syllables)
268
+ Time slips away ({min_syllables+1} syllables)
269
+ In the silence of my room ({avg_syllables} syllables)
270
  (... and so on for exactly {num_phrases} lines)
271
 
272
+ JUST THE PLAIN LYRICS, EXACTLY {num_phrases} LINES, KEEPING EACH LINE TO {min_syllables}-{max_syllables} SYLLABLES.
273
  """
274
 
275
  # Generate lyrics using the LLM model
 
446
  clean_lines[i] = re.sub(r'</think>', '', clean_lines[i])
447
  clean_lines[i] = re.sub(r'\[thinking\]', '', clean_lines[i])
448
  clean_lines[i] = re.sub(r'\[/thinking\]', '', clean_lines[i])
449
+
450
+ # Remove syllable count annotations
451
+ clean_lines[i] = re.sub(r'\s*\(\d+\s*syllables?\)', '', clean_lines[i])
452
 
453
  # 9. Filter out any remaining empty lines after tag removal
454
  clean_lines = [line for line in clean_lines if line.strip() and not line.isspace()]
 
462
  # Keep the first num_required lines
463
  clean_lines = clean_lines[:num_required]
464
 
465
+ # If we don't have enough lines, generate placeholders that fit the syllable count
466
  while len(clean_lines) < num_required:
467
+ i = len(clean_lines)
468
+ if i < len(lyric_templates):
469
+ template = lyric_templates[i]
470
+ target_syllables = min(max_syllables, (template.get('min_expected', 3) + template.get('max_expected', 8)) // 2)
471
+
472
+ if genre.lower() == 'pop':
473
+ if target_syllables <= 4:
474
+ placeholder = "Lost in the night" # 4 syllables
475
+ else:
476
+ placeholder = "Dancing in the moonlight" # 6 syllables
477
+ elif genre.lower() == 'rock':
478
+ placeholder = "Rocking to the beat" # 5 syllables
479
+ elif genre.lower() == 'country':
480
+ placeholder = "Down the old dirt road" # 5 syllables
481
+ else:
482
+ placeholder = f"Echoes of {emotion}" # ~4-5 syllables
483
+ else:
484
+ placeholder = "Whispers in the wind" # 5 syllables
485
+
486
  clean_lines.append(placeholder)
487
 
488
  # Assemble final lyrics
beat_analysis.py CHANGED
@@ -32,11 +32,11 @@ class BeatAnalyzer:
32
  # Genre-specific syllable-to-beat ratio guidelines
33
  self.genre_syllable_ratios = {
34
  # Supported genres with strong syllable-to-beat patterns
35
- 'pop': (0.9, 1.5, 2.2), # Pop tends to have more syllables per beat
36
- 'rock': (0.8, 1.2, 1.8), # Rock can vary widely but maintains beat alignment
37
- 'country': (0.8, 1.2, 1.6), # Country tends to be moderate and clear in syllable matching
38
- 'disco': (1.0, 1.5, 2.0), # Disco tends to have more syllables with clear beat patterns
39
- 'metal': (0.8, 1.5, 2.0), # Metal often has more syllables on strong beats
40
 
41
  # Other genres (analysis only, no lyrics generation)
42
  'hiphop': (1.8, 2.5, 3.5), # Hip hop often has many syllables per beat
@@ -49,7 +49,7 @@ class BeatAnalyzer:
49
  'electronic': (0.7, 1.0, 1.5), # Electronic music varies widely
50
  'classical': (0.7, 1.0, 1.4), # Classical can vary by subgenre
51
  'blues': (0.6, 0.8, 1.2), # Blues often extends syllables
52
- 'default': (0.9, 1.5, 2.0) # Default for unknown genres
53
  }
54
 
55
  # List of genres supported for lyrics generation
@@ -278,12 +278,24 @@ class BeatAnalyzer:
278
  # Estimate number of words based on beats (very rough estimate)
279
  est_words = max(1, int(num_beats * words_per_beat))
280
 
281
- # Estimate syllables - more flexible now, allowing for reasonable ranges
282
- # Typical song might have 1-3 syllables per beat
283
- min_syllables = num_beats
284
- max_syllables = num_beats * 3
 
 
 
 
 
 
 
 
285
 
286
  guide = f"~{est_words} words, ~{min_syllables}-{max_syllables} syllables | Pattern: {visual_pattern}"
 
 
 
 
287
  return guide
288
 
289
  def check_syllable_stress_match(self, text, template, genre="pop"):
@@ -303,14 +315,26 @@ class BeatAnalyzer:
303
  min_ratio, typical_ratio, max_ratio = self.genre_syllable_ratios['default']
304
 
305
  # Calculate flexible min and max syllable expectations based on genre
 
306
  min_expected = max(1, int(expected_count * min_ratio))
307
- max_expected = int(expected_count * max_ratio)
 
 
 
 
 
 
 
 
308
 
309
  # Check if syllable count falls within genre-appropriate range
310
  within_range = min_expected <= syllable_count <= max_expected
311
 
312
  # Consider typical ratio - how close are we to the ideal for this genre?
313
  ideal_count = int(expected_count * typical_ratio)
 
 
 
314
  closeness_to_ideal = 1.0 - min(abs(syllable_count - ideal_count) / (max_expected - min_expected + 1), 1.0)
315
 
316
  # Get detailed syllable breakdown for stress analysis
 
32
  # Genre-specific syllable-to-beat ratio guidelines
33
  self.genre_syllable_ratios = {
34
  # Supported genres with strong syllable-to-beat patterns
35
+ 'pop': (0.7, 1.2, 1.6), # Pop - more conservative range
36
+ 'rock': (0.7, 1.0, 1.5), # Rock - slightly reduced upper range
37
+ 'country': (0.7, 1.0, 1.3), # Country - clear and simple syllable patterns
38
+ 'disco': (0.8, 1.2, 1.5), # Disco - tighter range for better alignment
39
+ 'metal': (0.7, 1.2, 1.5), # Metal - reduced upper limit
40
 
41
  # Other genres (analysis only, no lyrics generation)
42
  'hiphop': (1.8, 2.5, 3.5), # Hip hop often has many syllables per beat
 
49
  'electronic': (0.7, 1.0, 1.5), # Electronic music varies widely
50
  'classical': (0.7, 1.0, 1.4), # Classical can vary by subgenre
51
  'blues': (0.6, 0.8, 1.2), # Blues often extends syllables
52
+ 'default': (0.7, 1.2, 1.6) # Default for unknown genres - more conservative
53
  }
54
 
55
  # List of genres supported for lyrics generation
 
278
  # Estimate number of words based on beats (very rough estimate)
279
  est_words = max(1, int(num_beats * words_per_beat))
280
 
281
+ # Estimate syllables - use more conservative ranges
282
+ # For 4/4 time signature, we want to encourage shorter phrases
283
+ if stress_pattern == "SWMW": # 4/4 time
284
+ min_syllables = max(1, int(num_beats * 0.7))
285
+ max_syllables = min(8, int(num_beats * 1.6))
286
+ else:
287
+ min_syllables = max(1, int(num_beats * 0.7))
288
+ max_syllables = int(num_beats * 1.5)
289
+
290
+ # Store these in the template for future reference
291
+ template['min_expected'] = min_syllables
292
+ template['max_expected'] = max_syllables
293
 
294
  guide = f"~{est_words} words, ~{min_syllables}-{max_syllables} syllables | Pattern: {visual_pattern}"
295
+
296
+ # Add additional guidance to the template for natural phrasing
297
+ template['phrasing_guide'] = "Keep lines short. Split complete thoughts across multiple lines."
298
+
299
  return guide
300
 
301
  def check_syllable_stress_match(self, text, template, genre="pop"):
 
315
  min_ratio, typical_ratio, max_ratio = self.genre_syllable_ratios['default']
316
 
317
  # Calculate flexible min and max syllable expectations based on genre
318
+ # Use more conservative ranges to avoid too many syllables
319
  min_expected = max(1, int(expected_count * min_ratio))
320
+ max_expected = min(8, int(expected_count * max_ratio))
321
+
322
+ # For 4/4 time signature, cap the max syllables per line
323
+ if template['stress_pattern'] == "SWMW": # 4/4 time
324
+ max_expected = min(max_expected, 8) # Cap at 8 syllables max for 4/4
325
+
326
+ # Record min and max expected in the template for future reference
327
+ template['min_expected'] = min_expected
328
+ template['max_expected'] = max_expected
329
 
330
  # Check if syllable count falls within genre-appropriate range
331
  within_range = min_expected <= syllable_count <= max_expected
332
 
333
  # Consider typical ratio - how close are we to the ideal for this genre?
334
  ideal_count = int(expected_count * typical_ratio)
335
+ # Ensure ideal count is also within our constrained range
336
+ ideal_count = max(min_expected, min(max_expected, ideal_count))
337
+
338
  closeness_to_ideal = 1.0 - min(abs(syllable_count - ideal_count) / (max_expected - min_expected + 1), 1.0)
339
 
340
  # Get detailed syllable breakdown for stress analysis