Spaces:
Running
Running
File size: 2,295 Bytes
91491b1 | 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 | """
audio_processor.py
==================
Utilitas untuk preprocessing audio chunk sebelum dianalisis.
"""
import numpy as np
import librosa
import io
import soundfile as sf
from typing import Tuple, Optional
def bytes_to_audio(audio_bytes: bytes) -> Tuple[np.ndarray, int]:
"""
Konversi bytes audio ke numpy array PCM.
Mendukung format: WAV, MP3, OGG, FLAC.
Returns:
Tuple (audio_array float32 mono, sample_rate)
"""
buffer = io.BytesIO(audio_bytes)
# Coba baca dengan soundfile terlebih dahulu
try:
audio, sr = sf.read(buffer, dtype='float32')
except Exception:
# Fallback ke librosa (lebih lambat tapi mendukung lebih banyak format)
buffer.seek(0)
audio, sr = librosa.load(buffer, sr=None, mono=True)
return audio, sr
# Konversi stereo ke mono jika diperlukan
if audio.ndim == 2:
audio = np.mean(audio, axis=1)
return audio, sr
def normalize_audio(audio: np.ndarray) -> np.ndarray:
"""
Normalisasi amplitudo audio ke range [-1.0, 1.0].
Mencegah saturasi dan memastikan konsistensi input model.
"""
max_val = np.max(np.abs(audio))
if max_val > 0:
audio = audio / max_val
return audio
def split_audio_chunks(
audio: np.ndarray,
sample_rate: int,
chunk_duration: float = 2.0,
overlap: float = 0.5
) -> list:
"""
Bagi audio panjang menjadi chunks kecil dengan overlap.
Args:
audio : Array audio PCM
sample_rate : Sample rate (Hz)
chunk_duration: Durasi setiap chunk (detik)
overlap : Overlap antar chunk (detik)
Returns:
List of numpy arrays, masing-masing adalah satu chunk
"""
chunk_samples = int(chunk_duration * sample_rate)
hop_samples = int((chunk_duration - overlap) * sample_rate)
chunks = []
start = 0
while start + chunk_samples <= len(audio):
chunk = audio[start:start + chunk_samples]
chunks.append(chunk)
start += hop_samples
# Tambahkan sisa audio jika belum masuk (dengan padding)
if start < len(audio):
remainder = audio[start:]
padded = np.pad(remainder, (0, chunk_samples - len(remainder)))
chunks.append(padded)
return chunks
|