|
import os |
|
import numpy as np |
|
import zipfile |
|
from pydub import AudioSegment |
|
import streamlit as st |
|
from io import BytesIO |
|
|
|
|
|
def generate_gaussian_noise(duration, sample_rate=44100, std_dev=0.1): |
|
"""Generate Gaussian noise.""" |
|
samples = np.random.normal(0, std_dev, size=(duration * sample_rate,)) |
|
audio_segment = AudioSegment( |
|
samples.tobytes(), |
|
frame_rate=sample_rate, |
|
sample_width=2, |
|
channels=1 |
|
) |
|
return audio_segment |
|
|
|
def generate_impulse_noise(duration, sample_rate=44100, impulse_rate=0.05): |
|
"""Generate impulse noise.""" |
|
samples = np.zeros(int(duration * sample_rate)) |
|
num_impulses = int(sample_rate * duration * impulse_rate) |
|
impulse_indices = np.random.randint(0, len(samples), num_impulses) |
|
samples[impulse_indices] = np.random.uniform(-1, 1, size=num_impulses) |
|
|
|
audio_segment = AudioSegment( |
|
samples.tobytes(), |
|
frame_rate=sample_rate, |
|
sample_width=2, |
|
channels=1 |
|
) |
|
return audio_segment |
|
|
|
def add_noise(audio_file, noise_type='gaussian', noise_level=0.1, start_time=None, end_time=None): |
|
"""Add noise to a clean audio file.""" |
|
audio = AudioSegment.from_file(audio_file) |
|
duration = len(audio) |
|
|
|
|
|
if start_time is not None and end_time is not None: |
|
start_time = int(start_time * 1000) |
|
end_time = int(end_time * 1000) |
|
if start_time < 0 or end_time > duration or start_time >= end_time: |
|
st.error("Invalid start or end time.") |
|
return None |
|
noise_duration = (end_time - start_time) // 1000 |
|
else: |
|
start_time = 0 |
|
end_time = duration |
|
noise_duration = duration // 1000 |
|
|
|
|
|
if noise_type == 'gaussian': |
|
noise = generate_gaussian_noise(noise_duration) |
|
elif noise_type == 'impulse': |
|
noise = generate_impulse_noise(noise_duration) |
|
else: |
|
st.error("Invalid noise type.") |
|
return None |
|
|
|
|
|
noise_array = np.array(noise.get_array_of_samples()) |
|
noise_array = noise_array * noise_level / np.max(np.abs(noise_array)) |
|
noise_array = np.clip(noise_array, -1.0, 1.0) |
|
|
|
noise = AudioSegment( |
|
noise_array.tobytes(), |
|
frame_rate=noise.frame_rate, |
|
sample_width=noise.sample_width, |
|
channels=noise.channels |
|
) |
|
|
|
|
|
silence = AudioSegment.silent(duration=end_time - start_time) |
|
noisy_segment = silence.overlay(noise) |
|
|
|
noisy_audio = audio[:start_time] + noisy_segment + audio[end_time:] |
|
return noisy_audio |
|
|
|
|
|
def main(): |
|
st.title("🎵 Audio Noise Generator") |
|
st.sidebar.title("Instructions") |
|
st.sidebar.write(""" |
|
- Upload one or more audio files (.wav or .mp3). |
|
- Choose noise type (Gaussian or Impulse). |
|
- Add noise to the full audio or a specific time duration. |
|
- Save the processed audio files. |
|
""") |
|
|
|
|
|
uploaded_files = st.file_uploader("Upload Audio Files", type=["wav", "mp3"], accept_multiple_files=True) |
|
|
|
|
|
noise_type = st.selectbox("Select Noise Type", ["gaussian", "impulse"]) |
|
|
|
|
|
noise_level = st.slider("Select Noise Level", 0.01, 1.0, 0.1, 0.01) |
|
|
|
|
|
add_to_specific_duration = st.checkbox("Add noise to specific duration") |
|
if add_to_specific_duration: |
|
start_time = st.number_input("Start Time (in seconds)", min_value=0.0, value=0.0, step=0.1) |
|
end_time = st.number_input("End Time (in seconds)", min_value=0.1, value=1.0, step=0.1) |
|
else: |
|
start_time, end_time = None, None |
|
|
|
|
|
if st.button("Process Audio"): |
|
if uploaded_files: |
|
zip_buffer = BytesIO() |
|
with zipfile.ZipFile(zip_buffer, "w") as zf: |
|
for uploaded_file in uploaded_files: |
|
st.write(f"Processing {uploaded_file.name}...") |
|
audio_data = BytesIO(uploaded_file.read()) |
|
|
|
noisy_audio = add_noise(audio_data, noise_type, noise_level, start_time, end_time) |
|
if noisy_audio: |
|
|
|
base_name, ext = os.path.splitext(uploaded_file.name) |
|
output_name = f"{noise_type}_{base_name}.wav" |
|
|
|
|
|
buffer = BytesIO() |
|
noisy_audio.export(buffer, format="wav") |
|
buffer.seek(0) |
|
|
|
|
|
zf.writestr(output_name, buffer.read()) |
|
st.success(f"Added {noise_type} noise to {uploaded_file.name}.") |
|
|
|
zip_buffer.seek(0) |
|
st.write("### Download All Processed Files") |
|
st.download_button( |
|
label="Download All as ZIP", |
|
data=zip_buffer, |
|
file_name="processed_audio_files.zip", |
|
mime="application/zip" |
|
) |
|
else: |
|
st.warning("Please upload at least one audio file.") |
|
|
|
if __name__ == "__main__": |
|
main() |
|
|