ss
Browse files- __pycache__/beat_analysis.cpython-310.pyc +0 -0
- __pycache__/emotionanalysis.cpython-310.pyc +0 -0
- app.py +48 -16
- beat_analysis.py +35 -11
__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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
248 |
-
|
249 |
-
Time slips
|
250 |
-
|
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 |
-
|
446 |
-
if len(
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
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.
|
36 |
-
'rock': (0.
|
37 |
-
'country': (0.
|
38 |
-
'disco': (
|
39 |
-
'metal': (0.
|
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.
|
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
|
282 |
-
#
|
283 |
-
|
284 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|