Spaces:
Runtime error
Runtime error
File size: 6,189 Bytes
3cecacc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
import os
import glob
import torch
import torchaudio
import librosa
import numpy as np
from torch.utils.data import Dataset
import torch
import torchaudio
from transformers import Wav2Vec2FeatureExtractor
import scipy.signal as signal
import scipy.signal
import random
class FakeMusicCapsDataset(Dataset):
def __init__(self, file_paths, labels, sr=16000, target_duration=10.0):
self.file_paths = file_paths
self.labels = labels
self.sr = sr
self.target_samples = int(target_duration * sr) # Fixed length: 10 seconds
self.processor = Wav2Vec2FeatureExtractor.from_pretrained("m-a-p/MERT-v1-95M", trust_remote_code=True)
def __len__(self):
return len(self.file_paths)
def pre_emphasis(self, x, alpha=0.97):
return np.append(x[0], x[1:] - alpha * x[:-1])
def highpass_filter(self, y, sr, cutoff=1000, order=5):
if isinstance(sr, np.ndarray):
sr = np.mean(sr)
if not isinstance(sr, (int, float)):
raise ValueError(f"[ERROR] sr must be a number, but got {type(sr)}: {sr}")
if sr <= 0:
raise ValueError(f"Invalid sample rate: {sr}. It must be greater than 0.")
nyquist = 0.5 * sr
if cutoff <= 0 or cutoff >= nyquist:
print(f"[WARNING] Invalid cutoff frequency {cutoff}, adjusting...")
cutoff = max(10, min(cutoff, nyquist - 1))
normal_cutoff = cutoff / nyquist
b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
y_filtered = signal.lfilter(b, a, y)
return y_filtered
# ์๊ฐ ์กฐ์ (Time Stretch), ์ดํ๋ผ์ด์ ์กฐ์ (EQ), ๋ฆฌ๋ฒ๋ธ ์ถ๊ฐ
def augment_audio(self, y, sr):
if isinstance(y, torch.Tensor):
y = y.numpy() # Tensor โ Numpy ๋ณํ
if random.random() < 0.5: # ์๊ฐ ์กฐ์ (Time Stretch)
rate = random.uniform(0.8, 1.2)
y = librosa.effects.time_stretch(y=y, rate=rate)
if random.random() < 0.5: # ํผ์น ์ํํธ (Pitch Shift)
n_steps = random.randint(-2, 2)
y = librosa.effects.pitch_shift(y=y, sr=sr, n_steps=n_steps)
if random.random() < 0.5: # ํ์ดํธ ๋
ธ์ด์ฆ ์ถ๊ฐ (White Noise Addition)
noise_level = np.random.uniform(0.001, 0.005)
y = y + np.random.normal(0, noise_level, y.shape)
return torch.tensor(y, dtype=torch.float32) # ๋ค์ Tensor๋ก ๋ณํ
def __getitem__(self, idx):
audio_path = self.file_paths[idx]
label = self.labels[idx]
waveform, sr = torchaudio.load(audio_path)
target_sr = self.processor.sampling_rate
if sr != target_sr:
resampler = torchaudio.transforms.Resample(orig_freq=sr, new_freq=target_sr)
waveform = resampler(waveform)
waveform = waveform.mean(dim=0).squeeze(0)
if label == 0:
waveform = self.augment_audio(waveform, self.sr)
if label == 1:
waveform = self.highpass_filter(waveform, self.sr)
# waveform = self.pre_emphasis(waveform)
waveform = self.augment_audio(waveform, self.sr)
# if label == 1:
# waveform = self.pre_emphasis(waveform)
# waveform = torch.tensor(waveform, dtype=torch.float32)
current_samples = waveform.shape[0]
if current_samples > self.target_samples:
waveform = waveform[:self.target_samples] # Truncate
elif current_samples < self.target_samples:
pad_length = self.target_samples - current_samples
waveform = torch.nn.functional.pad(waveform, (0, pad_length)) # Pad
if isinstance(waveform, torch.Tensor):
waveform = waveform.numpy() # Tensor์ผ ๊ฒฝ์ฐ์๋ง ๋ณํ
print(waveform.shape)
inputs = self.processor(waveform, sampling_rate=target_sr, return_tensors="pt", padding=True)
print(inputs["input_values"].shape)
return inputs["input_values"].squeeze(0), torch.tensor(label, dtype=torch.long) # [1, time] โ [time]
@staticmethod
def collate_fn(batch, target_samples=16000 * 10):
inputs, labels = zip(*batch) # Unzip batch
processed_inputs = []
for waveform in inputs:
current_samples = waveform.shape[0]
if current_samples > target_samples:
start_idx = (current_samples - target_samples) // 2
cropped_waveform = waveform[start_idx:start_idx + target_samples]
else:
pad_length = target_samples - current_samples
cropped_waveform = torch.nn.functional.pad(waveform, (0, pad_length))
processed_inputs.append(cropped_waveform)
processed_inputs = torch.stack(processed_inputs) # [batch, target_samples]
labels = torch.tensor(labels, dtype=torch.long) # [batch]
return processed_inputs, labels
def preprocess_audio(audio_path, target_sr=16000, max_length=160000):
"""
์ค๋์ค๋ฅผ ๋ชจ๋ธ ์
๋ ฅ์ ๋ง๊ฒ ๋ณํ
- target_sr: 16kHz๋ก ๋ณํ
- max_length: ์ต๋ ๊ธธ์ด 160000 (10์ด)
"""
waveform, sr = torchaudio.load(audio_path)
# Resample if needed
if sr != target_sr:
waveform = torchaudio.transforms.Resample(orig_freq=sr, new_freq=target_sr)(waveform)
# Convert to mono
waveform = waveform.mean(dim=0).unsqueeze(0) # (1, sequence_length)
current_samples = waveform.shape[1]
if current_samples > max_length:
start_idx = (current_samples - max_length) // 2
waveform = waveform[:, start_idx:start_idx + max_length]
elif current_samples < max_length:
pad_length = max_length - current_samples
waveform = torch.nn.functional.pad(waveform, (0, pad_length))
return waveform
def collect_files(base_path):
real_files = glob.glob(os.path.join(base_path, "real", "**", "*.wav"), recursive=True)
gen_files = glob.glob(os.path.join(base_path, "generative", "**", "*.wav"), recursive=True)
real_labels = [0] * len(real_files)
gen_labels = [1] * len(gen_files)
return real_files + gen_files, real_labels + gen_labels
|