sahakan's picture
Update app.py
5aad0dd verified
import os
import numpy as np
import matplotlib.pyplot as plt
import streamlit as st
import tempfile
import librosa
from scipy.signal import butter, filtfilt, wiener
from scipy.io.wavfile import write
# ตั้งค่าหน้าเพจ
st.set_page_config(page_title="การลดเสียงรบกวนและแยกเสียงพูด", page_icon="🎧", layout="wide")
st.title("🎧 การลดเสียงรบกวนและแยกเสียงพูด")
st.write("แอปนี้ใช้ Digital Signal Processing (DSP) เพื่อลดเสียงรบกวนจากไฟล์เสียง โดยใช้ Bandpass Filter, Wiener Filter และ Spectral Subtraction")
# 📌 ตรวจสอบและสร้างโฟลเดอร์ `/tmp/` หรือ `./temp/`
output_folder = "/tmp" if os.getenv("SYSTEM") == "spaces" else "./temp"
os.makedirs(output_folder, exist_ok=True)
# 📌 ฟังก์ชัน Bandpass Filter (รับค่า Lowcut & Highcut จากผู้ใช้)
def bandpass_filter(audio_signal, sample_rate, lowcut, highcut, order=5):
nyquist = 0.5 * sample_rate
low = lowcut / nyquist
high = highcut / nyquist
b, a = butter(order, [low, high], btype='band')
return filtfilt(b, a, audio_signal)
# 📌 ฟังก์ชัน Wiener Filter
def apply_wiener_filter(audio_signal):
return wiener(audio_signal)
# 📌 ฟังก์ชัน Spectral Subtraction
def spectral_subtraction(audio_signal, sample_rate):
D = librosa.stft(audio_signal)
magnitude, phase = np.abs(D), np.angle(D)
noise_profile = np.mean(magnitude[:, :5], axis=1, keepdims=True)
magnitude_denoised = np.maximum(magnitude - noise_profile, 0)
return librosa.istft(magnitude_denoised * np.exp(1j * phase))
# 📌 ฟังก์ชันแสดง Waveform
def plot_waveform(audio_signal, sample_rate, title="Waveform"):
plt.figure(figsize=(10, 3))
time = np.linspace(0, len(audio_signal) / sample_rate, num=len(audio_signal))
plt.plot(time, audio_signal, color='b')
plt.xlabel("Time (seconds)")
plt.ylabel("Amplitude")
plt.title(title)
plt.grid(alpha=0.3)
st.pyplot(plt)
# 📌 ฟังก์ชันประมวลผลไฟล์เสียง
def process_audio(audio_file):
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file:
tmp_file.write(audio_file.getvalue())
tmp_file_path = tmp_file.name
# โหลดไฟล์เสียง
waveform, sample_rate = librosa.load(tmp_file_path, sr=None, mono=True)
# แสดงข้อมูลไฟล์เสียง
st.write(f"🔊 Sample rate: {sample_rate} Hz, ⏱️ ความยาว: {len(waveform)/sample_rate:.2f} วินาที")
# แสดงเสียงต้นฉบับ
st.audio(tmp_file_path, format="audio/wav")
# แสดง Waveform ก่อนประมวลผล
st.markdown("### 📊 กราฟสัญญาณเสียงต้นฉบับ")
plot_waveform(waveform, sample_rate, title="Original Waveform")
# 🛠 เลือกเทคนิค DSP
st.markdown("### ⚙️ ตัวเลือกการแยกเสียง")
use_bandpass = st.checkbox("ใช้ Bandpass Filter", value=True)
use_wiener = st.checkbox("ใช้ Wiener Filter", value=True)
use_spectral = st.checkbox("ใช้ Spectral Subtraction", value=True)
# 📌 ตั้งค่าความถี่ Bandpass Filter (ผู้ใช้สามารถปรับได้)
if use_bandpass:
st.markdown("#### 🎛 ปรับค่าความถี่ของ Bandpass Filter")
col1, col2 = st.columns(2)
with col1:
lowcut = st.slider("เลือกความถี่ต่ำสุด (Lowcut)", min_value=50, max_value=1000, value=300, step=10)
with col2:
highcut = st.slider("เลือกความถี่สูงสุด (Highcut)", min_value=1000, max_value=8000, value=3000, step=100)
# 🔥 ประมวลผลเสียง
st.markdown("### 🛠 กำลังแยกเสียง...")
with st.spinner("กำลังประมวลผลเสียง..."):
processed_waveform = waveform.copy()
if use_bandpass:
processed_waveform = bandpass_filter(processed_waveform, sample_rate, lowcut, highcut)
if use_wiener:
processed_waveform = apply_wiener_filter(processed_waveform)
if use_spectral:
processed_waveform = spectral_subtraction(processed_waveform, sample_rate)
processed_waveform /= np.max(np.abs(processed_waveform)) # Normalize
# 🔊 แสดงเสียงที่แยกแล้ว
st.markdown("### 🎧 เสียงที่แยกแล้ว")
output_path = os.path.join(output_folder, "separated_audio.wav")
# บันทึกไฟล์ `.wav` แบบ `PCM_16`
write(output_path, sample_rate, (processed_waveform * 32767).astype(np.int16))
st.audio(output_path, format="audio/wav")
# แสดง Waveform หลังการแยกเสียง
st.markdown("### 📊 กราฟสัญญาณเสียงหลังการแยกเสียง")
plot_waveform(processed_waveform, sample_rate, title="Separated Waveform")
# ปุ่มดาวน์โหลดไฟล์เสียง
with open(output_path, "rb") as file:
st.download_button(label="⬇️ ดาวน์โหลดเสียงที่แยกแล้ว", data=file, file_name="separated_audio.wav", mime="audio/wav")
# ลบไฟล์ชั่วคราว
os.remove(tmp_file_path)
# UI สำหรับอัปโหลดไฟล์เสียง
st.markdown("## 📤 อัปโหลดไฟล์เสียงที่ต้องการแยก")
uploaded_file = st.file_uploader("เลือกไฟล์เสียง (.wav, .mp3, .flac)", type=["wav", "mp3", "flac"])
if uploaded_file is not None:
process_audio(uploaded_file)