issacneedsbread's picture
Update app.py
532b865 verified
import gradio as gr
import numpy as np
from scipy import signal
def generate_cylinder_noise(duration_sec: float, rpm: float, sr=44100):
# Calculate rotational parameters
rotation_period = 60 / rpm # Time for one full rotation
samples_per_rotation = int(sr * rotation_period)
num_rotations = int(duration_sec / rotation_period)
# Create fundamental mechanical noise pattern
t = np.linspace(0, rotation_period, samples_per_rotation)
# Base waveform with up-down pattern
fundamental = 0.5 * signal.sawtooth(2 * np.pi * 1/rotation_period * t, width=0.5)
# Add gravelly texture using modulated noise
brown_noise = np.cumsum(np.random.normal(0, 1, samples_per_rotation))
brown_noise /= np.max(np.abs(brown_noise)) # Normalize
# Combine elements with mechanical harmonics
pattern = (
fundamental * 0.7 +
brown_noise * 0.3 +
0.2 * np.sin(2 * np.pi * 3/rotation_period * t) # 3rd harmonic
)
# Add periodic needle drag (repeating every rotation)
drag_frequency = rpm/60 * 8 # 8 drags per rotation
drag = 0.3 * signal.square(2 * np.pi * drag_frequency * t, duty=0.1)
# Create full pattern
full_waveform = np.tile(pattern + drag, num_rotations)
remaining_samples = int((duration_sec % rotation_period) * sr)
if remaining_samples > 0:
full_waveform = np.concatenate([full_waveform, pattern[:remaining_samples]])
# Apply mechanical filtering
b, a = signal.butter(2, [80, 2500], btype='bandpass', fs=sr)
filtered = signal.lfilter(b, a, full_waveform)
# Add rotational speed fluctuations
warp = 0.05 * np.sin(2 * np.pi * 0.2 * np.arange(len(filtered)) / sr)
warped = np.interp(
np.arange(len(filtered)) * (1 + warp),
np.arange(len(filtered)),
filtered
)
# Normalize and add final grit
warped = warped / np.max(np.abs(warped))
warped = np.tanh(warped * 3) # Soft clipping
return warped, sr
def create_audio(duration: float, rpm: float):
audio, sr = generate_cylinder_noise(duration, rpm)
return (sr, audio)
demo = gr.Interface(
fn=create_audio,
inputs=[
gr.Slider(1, 30, value=5, label="Duration (seconds)"),
gr.Slider(90, 160, value=120, label="Cylinder RPM")
],
outputs=gr.Audio(label="Mechanical Cylinder Noise"),
title="Rotational Wax Cylinder Noise Generator",
description="Generate authentic rotational mechanical noise with adjustable RPM",
allow_flagging="never"
)
if __name__ == "__main__":
demo.launch()