ss
Browse files- README.md +12 -0
- app.py +24 -7
- beat_analysis.py +12 -5
README.md
CHANGED
|
@@ -28,6 +28,17 @@ This Hugging Face Space application analyzes music files and generates lyrics th
|
|
| 28 |
3. View the analysis results showing tempo, key, emotion, theme, and genre
|
| 29 |
4. Check the generated lyrics tailored to match your music
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
## Technical Details
|
| 32 |
|
| 33 |
This application uses:
|
|
@@ -44,6 +55,7 @@ See requirements.txt for detailed dependencies.
|
|
| 44 |
|
| 45 |
- Large audio files may take longer to process
|
| 46 |
- The quality of lyrics generation depends on the clarity of the audio and the detected musical features
|
|
|
|
| 47 |
|
| 48 |
## Credits
|
| 49 |
|
|
|
|
| 28 |
3. View the analysis results showing tempo, key, emotion, theme, and genre
|
| 29 |
4. Check the generated lyrics tailored to match your music
|
| 30 |
|
| 31 |
+
## Supported Genres
|
| 32 |
+
|
| 33 |
+
Lyrics generation is currently limited to the following genres:
|
| 34 |
+
- **Pop**
|
| 35 |
+
- **Rock**
|
| 36 |
+
- **Country**
|
| 37 |
+
- **Disco**
|
| 38 |
+
- **Metal**
|
| 39 |
+
|
| 40 |
+
These genres have consistent syllable-to-beat relationships that work well with our beat-matching algorithm. For other genres, the application will still provide music analysis, but lyrics generation will be disabled.
|
| 41 |
+
|
| 42 |
## Technical Details
|
| 43 |
|
| 44 |
This application uses:
|
|
|
|
| 55 |
|
| 56 |
- Large audio files may take longer to process
|
| 57 |
- The quality of lyrics generation depends on the clarity of the audio and the detected musical features
|
| 58 |
+
- Lyrics generation is restricted to specific genres (see Supported Genres section)
|
| 59 |
|
| 60 |
## Credits
|
| 61 |
|
app.py
CHANGED
|
@@ -151,12 +151,6 @@ def process_audio(audio_file):
|
|
| 151 |
genre_results_text = format_genre_results(top_genres)
|
| 152 |
primary_genre = top_genres[0][0]
|
| 153 |
|
| 154 |
-
# Generate lyrics using LLM
|
| 155 |
-
lyrics = generate_lyrics(music_analysis, primary_genre, duration)
|
| 156 |
-
|
| 157 |
-
# Create beat/stress/syllable matching analysis
|
| 158 |
-
beat_match_analysis = analyze_lyrics_rhythm_match(lyrics, lyric_templates, primary_genre)
|
| 159 |
-
|
| 160 |
# Prepare analysis summary
|
| 161 |
analysis_summary = f"""
|
| 162 |
### Music Analysis Results
|
|
@@ -184,6 +178,19 @@ def process_audio(audio_file):
|
|
| 184 |
- Phrase 2: {lyric_templates[1]['stress_pattern'] if len(lyric_templates) > 1 else 'N/A'}
|
| 185 |
"""
|
| 186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
return analysis_summary, lyrics, tempo, time_signature, emotion, theme, primary_genre, beat_match_analysis
|
| 188 |
|
| 189 |
except Exception as e:
|
|
@@ -594,13 +601,23 @@ def create_interface():
|
|
| 594 |
emotion_output, theme_output, genre_output, beat_match_output]
|
| 595 |
)
|
| 596 |
|
| 597 |
-
|
|
|
|
|
|
|
|
|
|
| 598 |
## How it works
|
| 599 |
1. Upload or record a music file
|
| 600 |
2. The system analyzes tempo, beats, time signature and other musical features
|
| 601 |
3. It detects emotion, theme, and music genre
|
| 602 |
4. Using beat patterns and syllable stress analysis, it generates perfectly aligned lyrics
|
| 603 |
5. Each line of the lyrics is matched to the beat pattern of the corresponding musical phrase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 604 |
""")
|
| 605 |
|
| 606 |
return demo
|
|
|
|
| 151 |
genre_results_text = format_genre_results(top_genres)
|
| 152 |
primary_genre = top_genres[0][0]
|
| 153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
# Prepare analysis summary
|
| 155 |
analysis_summary = f"""
|
| 156 |
### Music Analysis Results
|
|
|
|
| 178 |
- Phrase 2: {lyric_templates[1]['stress_pattern'] if len(lyric_templates) > 1 else 'N/A'}
|
| 179 |
"""
|
| 180 |
|
| 181 |
+
# Check if genre is supported for lyrics generation
|
| 182 |
+
# Use the supported_genres list from BeatAnalyzer
|
| 183 |
+
genre_supported = any(genre.lower() in primary_genre.lower() for genre in beat_analyzer.supported_genres)
|
| 184 |
+
|
| 185 |
+
# Generate lyrics only for supported genres
|
| 186 |
+
if genre_supported:
|
| 187 |
+
lyrics = generate_lyrics(music_analysis, primary_genre, duration)
|
| 188 |
+
beat_match_analysis = analyze_lyrics_rhythm_match(lyrics, lyric_templates, primary_genre)
|
| 189 |
+
else:
|
| 190 |
+
supported_genres_str = ", ".join([genre.capitalize() for genre in beat_analyzer.supported_genres])
|
| 191 |
+
lyrics = f"Lyrics generation is only supported for the following genres: {supported_genres_str}.\n\nDetected genre '{primary_genre}' doesn't have strong syllable-to-beat patterns required for our lyric generation algorithm."
|
| 192 |
+
beat_match_analysis = "Lyrics generation not available for this genre."
|
| 193 |
+
|
| 194 |
return analysis_summary, lyrics, tempo, time_signature, emotion, theme, primary_genre, beat_match_analysis
|
| 195 |
|
| 196 |
except Exception as e:
|
|
|
|
| 601 |
emotion_output, theme_output, genre_output, beat_match_output]
|
| 602 |
)
|
| 603 |
|
| 604 |
+
# Format supported genres for display
|
| 605 |
+
supported_genres_md = "\n".join([f"- {genre.capitalize()}" for genre in beat_analyzer.supported_genres])
|
| 606 |
+
|
| 607 |
+
gr.Markdown(f"""
|
| 608 |
## How it works
|
| 609 |
1. Upload or record a music file
|
| 610 |
2. The system analyzes tempo, beats, time signature and other musical features
|
| 611 |
3. It detects emotion, theme, and music genre
|
| 612 |
4. Using beat patterns and syllable stress analysis, it generates perfectly aligned lyrics
|
| 613 |
5. Each line of the lyrics is matched to the beat pattern of the corresponding musical phrase
|
| 614 |
+
|
| 615 |
+
## Supported Genres
|
| 616 |
+
**Note:** Lyrics generation is currently only supported for the following genres:
|
| 617 |
+
{supported_genres_md}
|
| 618 |
+
|
| 619 |
+
These genres have consistent syllable-to-beat patterns that work well with our algorithm.
|
| 620 |
+
For other genres, only music analysis will be provided.
|
| 621 |
""")
|
| 622 |
|
| 623 |
return demo
|
beat_analysis.py
CHANGED
|
@@ -32,25 +32,32 @@ class BeatAnalyzer:
|
|
| 32 |
|
| 33 |
# Genre-specific syllable-to-beat ratio guidelines
|
| 34 |
self.genre_syllable_ratios = {
|
| 35 |
-
#
|
| 36 |
'pop': (0.9, 1.5, 2.2), # Pop tends to have more syllables per beat
|
| 37 |
-
'rock': (0.8, 1.2, 1.8), # Rock can vary widely
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
'hiphop': (1.8, 2.5, 3.5), # Hip hop often has many syllables per beat
|
| 39 |
'rap': (2.0, 3.0, 4.0), # Rap often has very high syllable counts
|
| 40 |
'folk': (0.8, 1.0, 1.3), # Folk often has close to 1:1 ratio
|
| 41 |
-
'country': (0.8, 1.2, 1.6), # Country tends to be moderate
|
| 42 |
'jazz': (0.7, 1.0, 1.5), # Jazz can be very flexible
|
| 43 |
'reggae': (0.7, 1.0, 1.3), # Reggae often emphasizes specific beats
|
| 44 |
'soul': (0.8, 1.2, 1.6), # Soul music tends to be expressive
|
| 45 |
'r&b': (1.0, 1.5, 2.0), # R&B can have melisma
|
| 46 |
'electronic': (0.7, 1.0, 1.5), # Electronic music varies widely
|
| 47 |
-
'disco': (1.0, 1.5, 2.0), # Disco tends to have more syllables
|
| 48 |
'classical': (0.7, 1.0, 1.4), # Classical can vary by subgenre
|
| 49 |
-
'metal': (0.8, 1.5, 2.0), # Metal often has more syllables on strong beats
|
| 50 |
'blues': (0.6, 0.8, 1.2), # Blues often extends syllables
|
| 51 |
'default': (0.9, 1.5, 2.0) # Default for unknown genres
|
| 52 |
}
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
@lru_cache(maxsize=128)
|
| 55 |
def count_syllables(self, word):
|
| 56 |
"""Count syllables in a word using CMU dictionary if available, otherwise use rule-based method."""
|
|
|
|
| 32 |
|
| 33 |
# Genre-specific syllable-to-beat ratio guidelines
|
| 34 |
self.genre_syllable_ratios = {
|
| 35 |
+
# Supported genres with strong syllable-to-beat patterns
|
| 36 |
'pop': (0.9, 1.5, 2.2), # Pop tends to have more syllables per beat
|
| 37 |
+
'rock': (0.8, 1.2, 1.8), # Rock can vary widely but maintains beat alignment
|
| 38 |
+
'country': (0.8, 1.2, 1.6), # Country tends to be moderate and clear in syllable matching
|
| 39 |
+
'disco': (1.0, 1.5, 2.0), # Disco tends to have more syllables with clear beat patterns
|
| 40 |
+
'metal': (0.8, 1.5, 2.0), # Metal often has more syllables on strong beats
|
| 41 |
+
|
| 42 |
+
# Other genres (analysis only, no lyrics generation)
|
| 43 |
'hiphop': (1.8, 2.5, 3.5), # Hip hop often has many syllables per beat
|
| 44 |
'rap': (2.0, 3.0, 4.0), # Rap often has very high syllable counts
|
| 45 |
'folk': (0.8, 1.0, 1.3), # Folk often has close to 1:1 ratio
|
|
|
|
| 46 |
'jazz': (0.7, 1.0, 1.5), # Jazz can be very flexible
|
| 47 |
'reggae': (0.7, 1.0, 1.3), # Reggae often emphasizes specific beats
|
| 48 |
'soul': (0.8, 1.2, 1.6), # Soul music tends to be expressive
|
| 49 |
'r&b': (1.0, 1.5, 2.0), # R&B can have melisma
|
| 50 |
'electronic': (0.7, 1.0, 1.5), # Electronic music varies widely
|
|
|
|
| 51 |
'classical': (0.7, 1.0, 1.4), # Classical can vary by subgenre
|
|
|
|
| 52 |
'blues': (0.6, 0.8, 1.2), # Blues often extends syllables
|
| 53 |
'default': (0.9, 1.5, 2.0) # Default for unknown genres
|
| 54 |
}
|
| 55 |
|
| 56 |
+
# List of genres supported for lyrics generation
|
| 57 |
+
# These genres have the most predictable and consistent syllable-to-beat relationships,
|
| 58 |
+
# making them ideal for our beat-matching algorithm
|
| 59 |
+
self.supported_genres = ['pop', 'rock', 'country', 'disco', 'metal']
|
| 60 |
+
|
| 61 |
@lru_cache(maxsize=128)
|
| 62 |
def count_syllables(self, word):
|
| 63 |
"""Count syllables in a word using CMU dictionary if available, otherwise use rule-based method."""
|