print('Hello world!')import numpy as np
import scipy.io.wavfile as wav
# Audio settings
sample_rate = 44100
bpm = 105
beat_duration = 60 / bpm # Duration of one beat in seconds
bar_duration = beat_duration * 4 # 4 beats per bar
total_bars = 4
total_duration = bar_duration * total_bars
total_samples = int(sample_rate * total_duration)
t = np.linspace(0, total_duration, total_samples, endpoint=False)
audio_buffer = np.zeros(total_samples)
def add_percussion(frequency, position, duration, amplitude, decay=10.0):
idx_start = int(position * sample_rate)
idx_end = min(idx_start + int(duration * sample_rate), total_samples)
if idx_start >= total_samples:
return
t_perc = np.linspace(0, (idx_end - idx_start) / sample_rate, idx_end - idx_start, endpoint=False)
wave = np.sin(2 * np.pi * frequency * t_perc) * np.exp(-decay * t_perc)
audio_buffer[idx_start:idx_end] += wave * amplitude
def add_log_drum(frequency, position, duration, amplitude):
idx_start = int(position * sample_rate)
idx_end = min(idx_start + int(duration * sample_rate), total_samples)
if idx_start >= total_samples:
return
t_perc = np.linspace(0, (idx_end - idx_start) / sample_rate, idx_end - idx_start, endpoint=False)
# Pitch sweep for that classic Amapiano log drum weight
f_sweep = frequency * np.exp(-4.0 * t_perc)
phase = 2 * np.pi * np.cumsum(f_sweep) / sample_rate
wave = np.sin(phase) * np.exp(-2.0 * t_perc)
audio_buffer[idx_start:idx_end] += wave * amplitude
# Build the 4-bar Afro percussion loop
for bar in range(total_bars):
bar_start = bar * bar_duration
# 1. Kicks (The structural heartbeat)
add_percussion(75, bar_start + beat_duration * 0.0, 0.25, 0.7, decay=8.0)
add_percussion(75, bar_start + beat_duration * 1.5, 0.20, 0.6, decay=9.0)
add_percussion(75, bar_start + beat_duration * 2.0, 0.25, 0.7, decay=8.0)
add_percussion(75, bar_start + beat_duration * 3.5, 0.20, 0.6, decay=9.0)
# 2. Rimshots / Snares (Classic Afro syncopation)
add_percussion(350, bar_start + beat_duration * 0.75, 0.12, 0.4, decay=20.0)
add_percussion(350, bar_start + beat_duration * 1.5, 0.12, 0.5, decay=20.0)
add_percussion(350, bar_start + beat_duration * 2.75, 0.12, 0.4, decay=20.0)
add_percussion(350, bar_start + beat_duration * 3.5, 0.12, 0.5, decay=20.0)
# 3. Shakers (Constant groove element)
for step in range(16):
shaker_pos = bar_start + step * (beat_duration / 4)
shaker_amp = 0.15 if step % 2 == 0 else 0.08
add_percussion(4500, shaker_pos, 0.05, shaker_amp, decay=60.0)
# 4. Amapiano Log Drum Pattern (Vibe accentuation)
if bar % 2 == 0:
add_log_drum(90, bar_start + beat_duration * 0.0, 0.3, 0.8)
add_log_drum(90, bar_start + beat_duration * 0.75, 0.2, 0.7)
add_log_drum(80, bar_start + beat_duration * 2.0, 0.3, 0.8)
add_log_drum(100, bar_start + beat_duration * 2.5, 0.2, 0.6)
else:
add_log_drum(90, bar_start + beat_duration * 0.0, 0.3, 0.8)
add_log_drum(90, bar_start + beat_duration * 1.5, 0.2, 0.7)
add_log_drum(80, bar_start + beat_duration * 2.0, 0.3, 0.8)
add_log_drum(110, bar_start + beat_duration * 3.25, 0.15, 0.6)
add_log_drum(95, bar_start + beat_duration * 3.5, 0.15, 0.7)
# Normalize audio to prevent clipping
audio_buffer = audio_buffer / np.max(np.abs(audio_buffer))
audio_int16 = (audio_buffer * 32767).astype(np.int16)
# Save the file
wav.write("school_street_afro_riddim.wav", sample_rate, audio_int16)
To embed this project on your website, copy the following code and paste it into your website's HTML: