jacob-c commited on
Commit
3db0204
·
1 Parent(s): 8c42b47
__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
 
app.py CHANGED
@@ -101,22 +101,6 @@ def process_audio(audio_file):
101
  # Analyze music with MusicAnalyzer
102
  music_analysis = music_analyzer.analyze_music(audio_file)
103
 
104
- # Extract time signature from MusicAnalyzer result
105
- time_signature = music_analysis["rhythm_analysis"]["estimated_time_signature"]
106
-
107
- # Ensure time signature is one of the supported ones (4/4, 3/4, 2/4, 6/8)
108
- if time_signature not in ["4/4", "3/4", "2/4", "6/8"]:
109
- time_signature = "4/4" # Default to 4/4 if unsupported
110
- music_analysis["rhythm_analysis"]["estimated_time_signature"] = time_signature
111
-
112
- # Analyze beat patterns and create lyrics template using MusicAnalyzer's time signature
113
- beat_analysis = beat_analyzer.analyze_beat_pattern(audio_file, time_signature=time_signature)
114
- lyric_templates = beat_analyzer.create_lyric_template(beat_analysis)
115
-
116
- # Store these in the music_analysis dict for use in lyrics generation
117
- music_analysis["beat_analysis"] = beat_analysis
118
- music_analysis["lyric_templates"] = lyric_templates
119
-
120
  # Extract key information
121
  tempo = music_analysis["rhythm_analysis"]["tempo"]
122
  emotion = music_analysis["emotion_analysis"]["primary_emotion"]
@@ -151,6 +135,27 @@ def process_audio(audio_file):
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
 
101
  # Analyze music with MusicAnalyzer
102
  music_analysis = music_analyzer.analyze_music(audio_file)
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  # Extract key information
105
  tempo = music_analysis["rhythm_analysis"]["tempo"]
106
  emotion = music_analysis["emotion_analysis"]["primary_emotion"]
 
135
  genre_results_text = format_genre_results(top_genres)
136
  primary_genre = top_genres[0][0]
137
 
138
+ # Override time signature for pop and disco genres to always be 4/4
139
+ if any(genre.lower() in primary_genre.lower() for genre in ['pop', 'disco']):
140
+ music_analysis["rhythm_analysis"]["estimated_time_signature"] = "4/4"
141
+ time_signature = "4/4"
142
+ else:
143
+ # Use detected time signature for other genres
144
+ time_signature = music_analysis["rhythm_analysis"]["estimated_time_signature"]
145
+
146
+ # Ensure time signature is one of the supported ones (4/4, 3/4, 6/8)
147
+ if time_signature not in ["4/4", "3/4", "6/8"]:
148
+ time_signature = "4/4" # Default to 4/4 if unsupported
149
+ music_analysis["rhythm_analysis"]["estimated_time_signature"] = time_signature
150
+
151
+ # Analyze beat patterns and create lyrics template using the time signature
152
+ beat_analysis = beat_analyzer.analyze_beat_pattern(audio_file, time_signature=time_signature)
153
+ lyric_templates = beat_analyzer.create_lyric_template(beat_analysis)
154
+
155
+ # Store these in the music_analysis dict for use in lyrics generation
156
+ music_analysis["beat_analysis"] = beat_analysis
157
+ music_analysis["lyric_templates"] = lyric_templates
158
+
159
  # Prepare analysis summary
160
  analysis_summary = f"""
161
  ### Music Analysis Results
beat_analysis.py CHANGED
@@ -15,12 +15,11 @@ except LookupError:
15
  class BeatAnalyzer:
16
  def __init__(self):
17
  # Mapping for standard stress patterns by time signature
18
- # Simplified to only include 4/4, 3/4, 2/4, and 6/8
19
  self.stress_patterns = {
20
  # Format: Strong (1.0), Medium (0.5), Weak (0.0)
21
  "4/4": [1.0, 0.0, 0.5, 0.0], # Strong, weak, medium, weak
22
  "3/4": [1.0, 0.0, 0.0], # Strong, weak, weak
23
- "2/4": [1.0, 0.0], # Strong, weak
24
  "6/8": [1.0, 0.0, 0.0, 0.5, 0.0, 0.0] # Strong, weak, weak, medium, weak, weak
25
  }
26
 
@@ -58,6 +57,28 @@ class BeatAnalyzer:
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."""
@@ -157,11 +178,6 @@ class BeatAnalyzer:
157
  stress = "M" # Medium
158
  else: # Other beats (weak)
159
  stress = "W" # Weak
160
- elif time_signature == "2/4":
161
- if metrical_position == 0: # First beat (strongest)
162
- stress = "S" # Strong
163
- else: # Second beat (weak)
164
- stress = "W" # Weak
165
  else:
166
  # Default pattern for other time signatures
167
  if metrical_position == 0:
 
15
  class BeatAnalyzer:
16
  def __init__(self):
17
  # Mapping for standard stress patterns by time signature
18
+ # Simplified to only include 4/4, 3/4, and 6/8
19
  self.stress_patterns = {
20
  # Format: Strong (1.0), Medium (0.5), Weak (0.0)
21
  "4/4": [1.0, 0.0, 0.5, 0.0], # Strong, weak, medium, weak
22
  "3/4": [1.0, 0.0, 0.0], # Strong, weak, weak
 
23
  "6/8": [1.0, 0.0, 0.0, 0.5, 0.0, 0.0] # Strong, weak, weak, medium, weak, weak
24
  }
25
 
 
57
  # making them ideal for our beat-matching algorithm
58
  self.supported_genres = ['pop', 'rock', 'country', 'disco', 'metal']
59
 
60
+ # Common time signatures and their beat patterns with weights for prior probability
61
+ # Simplified to only include 4/4, 3/4, and 6/8
62
+ self.common_time_signatures = {
63
+ "4/4": {"beats_per_bar": 4, "beat_pattern": [1.0, 0.2, 0.5, 0.2], "weight": 0.55},
64
+ "3/4": {"beats_per_bar": 3, "beat_pattern": [1.0, 0.2, 0.3], "weight": 0.30},
65
+ "6/8": {"beats_per_bar": 6, "beat_pattern": [1.0, 0.2, 0.3, 0.8, 0.2, 0.3], "weight": 0.15}
66
+ }
67
+
68
+ # Add common accent patterns for different time signatures
69
+ self.accent_patterns = {
70
+ "4/4": [[1, 0, 0, 0], [1, 0, 2, 0], [1, 0, 2, 0, 3, 0, 2, 0]],
71
+ "3/4": [[1, 0, 0], [1, 0, 2]],
72
+ "6/8": [[1, 0, 0, 2, 0, 0], [1, 0, 0, 2, 0, 3]]
73
+ }
74
+
75
+ # Expected rhythm density (relative note density per beat) for different time signatures
76
+ self.rhythm_density = {
77
+ "4/4": [1.0, 0.7, 0.8, 0.6],
78
+ "3/4": [1.0, 0.6, 0.7],
79
+ "6/8": [1.0, 0.5, 0.4, 0.8, 0.5, 0.4]
80
+ }
81
+
82
  @lru_cache(maxsize=128)
83
  def count_syllables(self, word):
84
  """Count syllables in a word using CMU dictionary if available, otherwise use rule-based method."""
 
178
  stress = "M" # Medium
179
  else: # Other beats (weak)
180
  stress = "W" # Weak
 
 
 
 
 
181
  else:
182
  # Default pattern for other time signatures
183
  if metrical_position == 0:
emotionanalysis.py CHANGED
@@ -36,19 +36,17 @@ class MusicAnalyzer:
36
  self.key_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
37
 
38
  # Common time signatures and their beat patterns with weights for prior probability
39
- # Simplified to only include 4/4, 3/4, 2/4, and 6/8
40
  self.common_time_signatures = {
41
  "4/4": {"beats_per_bar": 4, "beat_pattern": [1.0, 0.2, 0.5, 0.2], "weight": 0.45},
42
  "3/4": {"beats_per_bar": 3, "beat_pattern": [1.0, 0.2, 0.3], "weight": 0.25},
43
- "2/4": {"beats_per_bar": 2, "beat_pattern": [1.0, 0.3], "weight": 0.15},
44
- "6/8": {"beats_per_bar": 6, "beat_pattern": [1.0, 0.2, 0.3, 0.8, 0.2, 0.3], "weight": 0.15}
45
  }
46
 
47
  # Add common accent patterns for different time signatures
48
  self.accent_patterns = {
49
  "4/4": [[1, 0, 0, 0], [1, 0, 2, 0], [1, 0, 2, 0, 3, 0, 2, 0]],
50
  "3/4": [[1, 0, 0], [1, 0, 2]],
51
- "2/4": [[1, 0], [1, 2]],
52
  "6/8": [[1, 0, 0, 2, 0, 0], [1, 0, 0, 2, 0, 3]]
53
  }
54
 
@@ -56,8 +54,7 @@ class MusicAnalyzer:
56
  self.rhythm_density = {
57
  "4/4": [1.0, 0.7, 0.8, 0.6],
58
  "3/4": [1.0, 0.6, 0.7],
59
- "6/8": [1.0, 0.5, 0.4, 0.8, 0.5, 0.4],
60
- "2/4": [1.0, 0.6]
61
  }
62
 
63
  def load_audio(self, file_path, sr=22050, duration=None):
@@ -343,16 +340,10 @@ class MusicAnalyzer:
343
  for ts in self.common_time_signatures:
344
  score = 0
345
 
346
- if ts == "4/4" or ts == "2/4":
347
- # Look for ratios close to 2 or 4
348
  for ratio in tempo_ratios:
349
- if abs(ratio - 2) < 0.2 or abs(ratio - 4) < 0.2:
350
- score += 1
351
-
352
- elif ts == "3/4" or ts == "6/8":
353
- # Look for ratios close to 3 or 6
354
- for ratio in tempo_ratios:
355
- if abs(ratio - 3) < 0.2 or abs(ratio - 6) < 0.3:
356
  score += 1
357
 
358
  # Normalize score
@@ -440,7 +431,7 @@ class MusicAnalyzer:
440
  def _estimate_from_tempo(self, tempo):
441
  """Use tempo to help estimate likely time signature"""
442
  # Statistical tendencies: slower tempos often in compound meters (6/8)
443
- # Fast tempos often favor simple meters (2/4)
444
 
445
  scores = {}
446
 
@@ -449,7 +440,6 @@ class MusicAnalyzer:
449
  scores = {
450
  "4/4": 0.5,
451
  "3/4": 0.4,
452
- "2/4": 0.3,
453
  "6/8": 0.7
454
  }
455
  elif 70 <= tempo <= 120:
@@ -457,14 +447,12 @@ class MusicAnalyzer:
457
  scores = {
458
  "4/4": 0.7,
459
  "3/4": 0.6,
460
- "2/4": 0.4,
461
  "6/8": 0.3
462
  }
463
  else:
464
- # Fast tempos favor simpler meters
465
  scores = {
466
- "4/4": 0.6,
467
- "2/4": 0.7,
468
  "3/4": 0.4,
469
  "6/8": 0.2
470
  }
 
36
  self.key_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
37
 
38
  # Common time signatures and their beat patterns with weights for prior probability
39
+ # Simplified to only include 4/4, 3/4, and 6/8
40
  self.common_time_signatures = {
41
  "4/4": {"beats_per_bar": 4, "beat_pattern": [1.0, 0.2, 0.5, 0.2], "weight": 0.45},
42
  "3/4": {"beats_per_bar": 3, "beat_pattern": [1.0, 0.2, 0.3], "weight": 0.25},
43
+ "6/8": {"beats_per_bar": 6, "beat_pattern": [1.0, 0.2, 0.3, 0.8, 0.2, 0.3], "weight": 0.30}
 
44
  }
45
 
46
  # Add common accent patterns for different time signatures
47
  self.accent_patterns = {
48
  "4/4": [[1, 0, 0, 0], [1, 0, 2, 0], [1, 0, 2, 0, 3, 0, 2, 0]],
49
  "3/4": [[1, 0, 0], [1, 0, 2]],
 
50
  "6/8": [[1, 0, 0, 2, 0, 0], [1, 0, 0, 2, 0, 3]]
51
  }
52
 
 
54
  self.rhythm_density = {
55
  "4/4": [1.0, 0.7, 0.8, 0.6],
56
  "3/4": [1.0, 0.6, 0.7],
57
+ "6/8": [1.0, 0.5, 0.4, 0.8, 0.5, 0.4]
 
58
  }
59
 
60
  def load_audio(self, file_path, sr=22050, duration=None):
 
340
  for ts in self.common_time_signatures:
341
  score = 0
342
 
343
+ if ts == "4/4" or ts == "6/8":
344
+ # Look for ratios close to 4 or 6
345
  for ratio in tempo_ratios:
346
+ if abs(ratio - 4) < 0.2 or abs(ratio - 6) < 0.3:
 
 
 
 
 
 
347
  score += 1
348
 
349
  # Normalize score
 
431
  def _estimate_from_tempo(self, tempo):
432
  """Use tempo to help estimate likely time signature"""
433
  # Statistical tendencies: slower tempos often in compound meters (6/8)
434
+ # Fast tempos favor 4/4
435
 
436
  scores = {}
437
 
 
440
  scores = {
441
  "4/4": 0.5,
442
  "3/4": 0.4,
 
443
  "6/8": 0.7
444
  }
445
  elif 70 <= tempo <= 120:
 
447
  scores = {
448
  "4/4": 0.7,
449
  "3/4": 0.6,
 
450
  "6/8": 0.3
451
  }
452
  else:
453
+ # Fast tempos favor 4/4
454
  scores = {
455
+ "4/4": 0.8,
 
456
  "3/4": 0.4,
457
  "6/8": 0.2
458
  }