Voice Recognition: Buka Tutup Classification#
Data Understanding#
1. Import Libraries#
Import library dasar untuk analisis data dan audio processing.
import os
import librosa
import librosa.display
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import IPython.display as ipd
sns.set(style="whitegrid")
plt.rcParams['figure.figsize'] = (10, 4)
Mempersiapkan lingkungan analisis dengan mengimpor berbagai library yang diperlukan, dimana librosa dijadikan sebagai library utama untuk menangani pemrosesan sinyal audio, sementara tools lainnya seperti pandas disiapkan untuk manipulasi data, numpy untuk komputasi numerik, serta matplotlib dan seaborn untuk keperluan visualisasi.
2. Setup Path Dataset#
Setup path dataset dan cek struktur folder datasetaudio.
import os
DATASET_PATH = "datasetaudio"
train_path = os.path.join(DATASET_PATH, "train")
if os.path.exists(DATASET_PATH):
print("Dataset structure:")
if os.path.exists(train_path):
print("Train folder:", os.listdir(train_path))
# Loop speaker
for speaker in os.listdir(train_path):
speaker_path = os.path.join(train_path, speaker)
if os.path.isdir(speaker_path):
print(f" └── {speaker}/ -> subfolders:", os.listdir(speaker_path))
# Loop action (buka/tutup)
for action in os.listdir(speaker_path):
action_path = os.path.join(speaker_path, action)
if os.path.isdir(action_path):
files = [f for f in os.listdir(action_path) if f.lower().endswith((".wav", ".mp3", ".flac"))]
print(f" └── {action}/ -> {len(files)} files")
else:
print("Train folder tidak ditemukan!")
else:
print(f"Dataset path '{DATASET_PATH}' tidak ditemukan!")
print("Current directory:", os.getcwd())
print("Files in current directory:", os.listdir('.'))
Dataset structure:
Train folder: ['asep', 'yotan']
└── asep/ -> subfolders: ['buka', 'tutup']
└── buka/ -> 50 files
└── tutup/ -> 50 files
└── yotan/ -> subfolders: ['buka', 'tutup']
└── buka/ -> 50 files
└── tutup/ -> 50 files
3. Cek Distribusi Data#
Analisis distribusi file audio per kelas dan split data train/validation.
def count_files_new(base_path):
counts = {}
for speaker in os.listdir(base_path):
speaker_path = os.path.join(base_path, speaker)
if not os.path.isdir(speaker_path):
continue
for action in os.listdir(speaker_path): # buka/tutup
action_path = os.path.join(speaker_path, action)
if not os.path.isdir(action_path):
continue
# hitung file audio
num_files = len([
f for f in os.listdir(action_path)
if f.lower().endswith((".wav", ".mp3", ".flac"))
])
key = f"{speaker}_{action}"
counts[key] = num_files
return counts
train_counts = count_files_new(train_path)
df_counts = pd.DataFrame({
'Label': list(train_counts.keys()),
'Jumlah': list(train_counts.values())
})
plt.figure(figsize=(10, 6))
sns.barplot(data=df_counts, x='Label', y='Jumlah')
plt.title("Distribusi Data per Speaker & Kelas (buka/tutup)")
plt.ylabel("Jumlah File")
plt.xticks(rotation=45)
plt.show()
# Hitung total untuk buka dan tutup secara global
total_buka = sum([v for k, v in train_counts.items() if "buka" in k])
total_tutup = sum([v for k, v in train_counts.items() if "tutup" in k])
print(f"Total data - Buka : {total_buka}")
print(f"Total data - Tutup: {total_tutup}")
print(f"Total keseluruhan: {sum(train_counts.values())} file")
Total data - Buka : 100
Total data - Tutup: 100
Total keseluruhan: 200 file
4. Contoh Audio + Metadata#
Play sample audio dan visualisasi waveform + spectrogram untuk setiap kelas.
import os
from IPython.display import Audio, display
DATASET_PATH = "datasetaudio"
train_path = os.path.join(DATASET_PATH, "train")
# urutan manusia: ke-2 -> index 1 (Python zero-based)
TARGET_INDEX = 1
VALID_EXTS = (".wav", ".mp3", ".flac", ".ogg", ".m4a")
def get_nth_audio_file(speaker, action, n=TARGET_INDEX):
folder = os.path.join(train_path, speaker, action)
if not os.path.isdir(folder):
return None, f"Folder tidak ditemukan: {folder}"
files = sorted([f for f in os.listdir(folder) if f.lower().endswith(VALID_EXTS)])
if len(files) == 0:
return None, f"Tidak ada file di: {folder}"
# jika kurang dari n+1 file, ambil file terakhir
idx = n if n < len(files) else (len(files) - 1)
return os.path.join(folder, files[idx]), None
speakers = ["asep", "yotan"]
actions = ["buka", "tutup"]
for sp in speakers:
for act in actions:
path, err = get_nth_audio_file(sp, act)
print(f"\nContoh: {sp} - {act}")
if err:
print(" Error:", err)
continue
print(" File:", path)
display(Audio(path))
Contoh: asep - buka
File: datasetaudio/train/asep/buka/Buka10.wav
Contoh: asep - tutup
File: datasetaudio/train/asep/tutup/Tutup10.wav
Contoh: yotan - buka
File: datasetaudio/train/yotan/buka/buka_10.wav
Contoh: yotan - tutup
File: datasetaudio/train/yotan/tutup/tutup_10.wav
5. Analisis Durasi dan Sample Rate#
Analisis statistik durasi audio dan konsistensi sample rate dataset.
import os
import librosa
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
DATASET_PATH = "datasetaudio"
train_path = os.path.join(DATASET_PATH, "train")
# -----------------------------------------
# 1. ANALISIS AUDIO (Struktur speaker/action)
# -----------------------------------------
def analyze_audio_stats_new(base_path):
data = []
for speaker in os.listdir(base_path):
speaker_path = os.path.join(base_path, speaker)
if not os.path.isdir(speaker_path):
continue
for action in os.listdir(speaker_path): # buka/tutup
action_path = os.path.join(speaker_path, action)
if not os.path.isdir(action_path):
continue
for fn in os.listdir(action_path):
fp = os.path.join(action_path, fn)
if not fn.lower().endswith((".wav", ".mp3", ".flac", ".ogg", ".m4a")):
continue
try:
y, sr = librosa.load(fp, sr=None)
duration = len(y) / sr
data.append({
'speaker': speaker,
'action': action,
'label': f"{speaker}_{action}",
'sr': sr,
'duration': duration,
'filename': fn
})
except Exception as e:
print("Gagal load:", fp, "| Error:", e)
return pd.DataFrame(data)
audio_stats = analyze_audio_stats_new(train_path)
# -----------------------------------------
# 2. STATISTIK PER LABEL
# -----------------------------------------
print("Statistik durasi per speaker-action:")
print(audio_stats.groupby('label')['duration'].describe())
# -----------------------------------------
# 3. PLOTTING
# -----------------------------------------
fig, axes = plt.subplots(1, 2, figsize=(16, 5))
# Histogram durasi berdasarkan label (speaker_action)
sns.histplot(data=audio_stats, x='duration', hue='label', bins=30, kde=True, ax=axes[0])
axes[0].set_title("Distribusi Durasi Audio per Speaker-Action")
axes[0].set_xlabel("Durasi (detik)")
# Jumlah file per label
sns.countplot(data=audio_stats, x='label', ax=axes[1])
axes[1].set_title("Jumlah File per Speaker-Action")
axes[1].set_xlabel("Label (speaker_action)")
axes[1].tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()
# -----------------------------------------
# 4. Informasi tambahan
# -----------------------------------------
print(f"\nSample-rate unik : {audio_stats['sr'].unique()}")
print(f"Total file audio : {len(audio_stats)}")
print("\nJumlah per speaker-action:")
print(audio_stats['label'].value_counts())
Statistik durasi per speaker-action:
count mean std min 25% 50% 75% \
label
asep_buka 50.0 2.247140 0.515910 1.387312 1.704 2.304000 2.593969
asep_tutup 50.0 2.307255 0.358984 1.365333 2.016 2.364000 2.487156
yotan_buka 50.0 1.436443 0.467269 0.885000 1.020 1.400000 1.513000
yotan_tutup 50.0 1.254245 0.350424 0.776458 0.928 1.291156 1.537500
max
label
asep_buka 3.280229
asep_tutup 3.218292
yotan_buka 2.802188
yotan_tutup 1.889000
Sample-rate unik : [48000]
Total file audio : 200
Jumlah per speaker-action:
label
asep_buka 50
asep_tutup 50
yotan_buka 50
yotan_tutup 50
Name: count, dtype: int64