Spaces:
Running
Running
| 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) | |