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)

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: