DeepSeekOracle commited on
Commit
df31c21
·
verified ·
1 Parent(s): bcaca9e

Update ldq_percussion.py

Browse files
Files changed (1) hide show
  1. ldq_percussion.py +25 -32
ldq_percussion.py CHANGED
@@ -19,25 +19,26 @@ def generate_kick(features: Dict[str, Any], sr: int, duration: float = 0.5) -> n
19
  area = cv2.contourArea(largest)
20
  perimeter = cv2.arcLength(largest, True)
21
 
22
- # Fundamental frequency from contour area (30-60 Hz)
23
- f0 = 30 + (area / 10000) * 30
24
- # Modulation index from perimeter
25
- mod_idx = 0.5 + (perimeter / 100) * 2.0
26
- # Decay time from area
27
  decay = 0.3 + (area / 50000) * 0.4
28
 
29
  n = int(sr * duration)
30
  t = np.linspace(0, duration, n)
31
 
32
- # FM synthesis: carrier = f0, modulator = f0 * 2
33
  carrier = np.sin(2 * np.pi * f0 * t)
34
  modulator = np.sin(2 * np.pi * f0 * 2 * t)
35
  kick = np.sin(2 * np.pi * f0 * t + mod_idx * modulator)
36
 
37
- # Exponential decay
38
- envelope = np.exp(-t * decay * 10)
39
  kick *= envelope
40
 
 
 
 
41
  return kick
42
 
43
  def generate_snare(features: Dict[str, Any], sr: int, duration: float = 0.15) -> np.ndarray:
@@ -46,19 +47,8 @@ def generate_snare(features: Dict[str, Any], sr: int, duration: float = 0.15) ->
46
  if not lines:
47
  return np.zeros(int(sr * duration))
48
 
49
- # Count intersections
50
- intersections = []
51
- for i in range(len(lines)):
52
- for j in range(i+1, len(lines)):
53
- x1, y1, x2, y2 = lines[i][0]
54
- x3, y3, x4, y4 = lines[j][0]
55
- # Simple intersection check (line segments)
56
- # For brevity, we approximate with angle detection
57
- pass
58
-
59
- # Approximate intersection count from line density
60
  n_lines = len(lines)
61
- intersection_count = max(1, int(n_lines * 0.5))
62
 
63
  # Center frequency from average line angle
64
  angles = []
@@ -67,14 +57,15 @@ def generate_snare(features: Dict[str, Any], sr: int, duration: float = 0.15) ->
67
  angle = math.degrees(math.atan2(y2-y1, x2-x1)) % 180
68
  angles.append(angle)
69
  avg_angle = np.mean(angles) if angles else 45
70
- center_freq = 200 + (avg_angle / 180) * 200 # 200-400 Hz
71
 
72
- # Bandpassed noise burst
73
- noise = np.random.normal(0, 1, int(sr * duration))
74
- # Simple bandpass approximation (for demo)
75
- noise = noise * 0.5 # Reduce amplitude
76
- envelope = np.exp(-np.linspace(0, duration, len(noise)) * 8)
77
- snare = noise * envelope * 0.3
 
78
 
79
  return snare
80
 
@@ -95,17 +86,19 @@ def generate_hihats(features: Dict[str, Any], sr: int, bpm: float, duration: flo
95
  beats = duration * (bpm / 60)
96
  n_ticks = int(beats * subdivision)
97
 
98
- # Amplitude from brightness
99
- amp = 0.1 + brightness * 0.2
100
 
101
  # Generate pulse train
102
  hihat = np.zeros(int(sr * duration))
103
  for i in range(n_ticks):
104
  pos = int(i * sr * 60 / (bpm * subdivision))
105
  if pos < len(hihat):
106
- # Short square wave pulse
107
- pulse_len = int(sr * 0.01)
108
  end = min(pos + pulse_len, len(hihat))
109
- hihat[pos:end] += amp * 0.5
 
 
110
 
111
  return hihat
 
19
  area = cv2.contourArea(largest)
20
  perimeter = cv2.arcLength(largest, True)
21
 
22
+ # Tuned for less buzz: lower modulation index
23
+ f0 = 30 + (area / 10000) * 30 # 30-60 Hz
24
+ mod_idx = 0.3 + (perimeter / 100) * 1.0 # Lower modulation
 
 
25
  decay = 0.3 + (area / 50000) * 0.4
26
 
27
  n = int(sr * duration)
28
  t = np.linspace(0, duration, n)
29
 
30
+ # FM synthesis with softer carrier
31
  carrier = np.sin(2 * np.pi * f0 * t)
32
  modulator = np.sin(2 * np.pi * f0 * 2 * t)
33
  kick = np.sin(2 * np.pi * f0 * t + mod_idx * modulator)
34
 
35
+ # Exponential decay with longer tail
36
+ envelope = np.exp(-t * decay * 8)
37
  kick *= envelope
38
 
39
+ # Soft clipping to reduce harshness
40
+ kick = np.tanh(kick * 0.8) / np.tanh(0.8)
41
+
42
  return kick
43
 
44
  def generate_snare(features: Dict[str, Any], sr: int, duration: float = 0.15) -> np.ndarray:
 
47
  if not lines:
48
  return np.zeros(int(sr * duration))
49
 
50
+ # Use low-frequency sawtooth with fast decay for a softer snare
 
 
 
 
 
 
 
 
 
 
51
  n_lines = len(lines)
 
52
 
53
  # Center frequency from average line angle
54
  angles = []
 
57
  angle = math.degrees(math.atan2(y2-y1, x2-x1)) % 180
58
  angles.append(angle)
59
  avg_angle = np.mean(angles) if angles else 45
60
+ center_freq = 150 + (avg_angle / 180) * 150 # 150-300 Hz (lower for less buzz)
61
 
62
+ # Sawtooth with fast decay
63
+ n = int(sr * duration)
64
+ t = np.linspace(0, duration, n)
65
+ snare = np.sin(2 * np.pi * center_freq * t) * 0.5
66
+ snare += np.random.normal(0, 0.1, n) # Small noise component
67
+ envelope = np.exp(-t * 15)
68
+ snare *= envelope
69
 
70
  return snare
71
 
 
86
  beats = duration * (bpm / 60)
87
  n_ticks = int(beats * subdivision)
88
 
89
+ # Amplitude from brightness (reduced for less buzz)
90
+ amp = 0.05 + brightness * 0.1
91
 
92
  # Generate pulse train
93
  hihat = np.zeros(int(sr * duration))
94
  for i in range(n_ticks):
95
  pos = int(i * sr * 60 / (bpm * subdivision))
96
  if pos < len(hihat):
97
+ # Short triangle wave pulse (smoother than square)
98
+ pulse_len = int(sr * 0.015)
99
  end = min(pos + pulse_len, len(hihat))
100
+ t_pulse = np.linspace(0, 0.015, pulse_len)
101
+ pulse = np.sin(2 * np.pi * 8000 * t_pulse) * amp * 0.3
102
+ hihat[pos:end] += pulse[:end-pos]
103
 
104
  return hihat