audio-data-quality-tool / demo /generate_sample_data.py
ManuBo's picture
v0.2.0: quality score and integration
b89a72f
Raw
History Blame Contribute Delete
4.89 kB
from __future__ import annotations
import numpy as np
from scipy.io import wavfile
from pathlib import Path
OUTPUT_DIR = Path(__file__).parent / "sample_data"
SR = 22050
def make_speech_like(duration_s: float, sr: int = SR) -> np.ndarray:
"""Generate a speech-like signal with drifting pitch and irregular envelope."""
n_samples = int(sr * duration_s)
f0_base = 150.0
f0_drift = np.cumsum(np.random.randn(n_samples) * 0.05)
f0_drift = f0_drift - np.mean(f0_drift)
f0_curve = f0_base + np.clip(f0_drift, -40, 40)
phase = np.cumsum(2 * np.pi * f0_curve / sr)
signal = 0.30 * np.sin(phase)
signal += 0.15 * np.sin(2 * phase + np.random.uniform(0, np.pi))
signal += 0.08 * np.sin(3 * phase + np.random.uniform(0, np.pi))
signal += 0.04 * np.sin(5 * phase + np.random.uniform(0, np.pi))
syllable_rate = np.random.uniform(3.0, 5.0)
n_syllables = int(duration_s * syllable_rate) + 1
envelope = np.zeros(n_samples)
samples_per_syl = n_samples // n_syllables
for i in range(n_syllables):
start = i * samples_per_syl
length = int(samples_per_syl * np.random.uniform(0.4, 0.9))
end = min(start + length, n_samples)
win = np.hanning(end - start)
amplitude = np.random.uniform(0.5, 1.0)
envelope[start:end] += win * amplitude
envelope = np.clip(envelope, 0, 1)
signal *= envelope
noise_level = 0.03 * np.random.uniform(0.8, 1.2)
signal += noise_level * np.random.randn(n_samples)
peak = np.max(np.abs(signal))
if peak > 0:
signal = signal / peak * 0.5
return signal
def save_wav(filename: str, audio: np.ndarray, sr: int = SR):
audio_16 = np.clip(audio * 32767, -32768, 32767).astype(np.int16)
filepath = OUTPUT_DIR / filename
wavfile.write(str(filepath), sr, audio_16)
print(" Created: %s (%.1fs, %dHz)" % (filename, len(audio) / sr, sr))
def main():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
print("Generating sample audio data...\n")
for i in range(1, 4):
audio = make_speech_like(3.0 + i * 0.5)
save_wav("good_%02d_clean_speech.wav" % i, audio)
audio = make_speech_like(3.0)
noisy_low = audio + 0.1 * np.random.randn(len(audio))
save_wav("noisy_01_low_snr.wav", noisy_low / np.max(np.abs(noisy_low)) * 0.8)
noisy_high = audio + 0.3 * np.random.randn(len(audio))
save_wav("noisy_02_very_low_snr.wav", noisy_high / np.max(np.abs(noisy_high)) * 0.8)
audio = make_speech_like(3.0)
clipped = np.clip(audio * 2.0, -0.99, 0.99)
save_wav("clipped_01_hard_clip.wav", clipped)
audio2 = make_speech_like(2.5)
clipped2 = np.clip(audio2 * 1.5, -0.99, 0.99)
save_wav("clipped_02_soft_clip.wav", clipped2)
audio = make_speech_like(2.0)
padded_lead = np.concatenate([np.zeros(SR * 2), audio])
save_wav("silence_01_long_leading.wav", padded_lead)
padded_trail = np.concatenate([audio, np.zeros(SR * 3)])
save_wav("silence_02_long_trailing.wav", padded_trail)
audio1 = make_speech_like(1.5)
audio2 = make_speech_like(1.5)
gapped = np.concatenate([audio1, np.zeros(SR * 3), audio2])
save_wav("silence_03_internal_gap.wav", gapped)
tiny = make_speech_like(0.2)
save_wav("duration_01_too_short.wav", tiny)
long_audio = np.tile(make_speech_like(5.0), 8)
save_wav("duration_02_too_long.wav", long_audio)
audio = make_speech_like(3.0, sr=11025)
save_wav("samplerate_01_wrong.wav", audio, sr=11025)
audio = make_speech_like(3.0)
quiet = audio * 0.02
save_wav("loudness_01_too_quiet.wav", quiet)
loud = audio * 0.99
save_wav("loudness_02_too_loud.wav", loud)
audio = make_speech_like(3.0)
save_wav("duplicate_01_original.wav", audio)
dup = audio + 0.001 * np.random.randn(len(audio))
save_wav("duplicate_02_near_copy.wav", dup)
t = np.linspace(0, 3.0, int(SR * 3.0), endpoint=False)
metallic = 0.5 * np.random.randn(len(t))
metallic *= 0.5 + 0.5 * np.sin(2 * np.pi * 4 * t)
save_wav("artifact_01_metallic.wav", metallic / np.max(np.abs(metallic)) * 0.7)
# Upsampled file: generate at 8kHz then save at 22050Hz
audio_8k = make_speech_like(3.0, sr=8000)
from scipy.signal import resample
upsampled = resample(audio_8k, int(len(audio_8k) * SR / 8000))
save_wav("upsampled_01_fake_22k.wav", upsampled / np.max(np.abs(upsampled)) * 0.5)
# Stereo file (most TTS expects mono)
mono = make_speech_like(3.0)
stereo = np.stack([mono, mono], axis=-1)
stereo_16 = np.clip(stereo * 32767, -32768, 32767).astype(np.int16)
wavfile.write(str(OUTPUT_DIR / "channel_01_stereo.wav"), SR, stereo_16)
print(" Created: channel_01_stereo.wav (3.0s, %dHz, stereo)" % SR)
print("\nDone. Generated %d sample files in %s" % (
len(list(OUTPUT_DIR.glob("*.wav"))), OUTPUT_DIR))
if __name__ == "__main__":
main()