Spaces:
Running
Running
File size: 13,624 Bytes
c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 86efccf c3a0586 78132f8 86efccf c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 78132f8 86efccf c3a0586 78132f8 86efccf c3a0586 86efccf c3a0586 78132f8 86efccf 78132f8 86efccf 78132f8 c3a0586 78132f8 c3a0586 78132f8 c3a0586 07477a1 c3a0586 78132f8 c3a0586 |
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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
import os
import numpy as np
import matplotlib.pyplot as plt
import streamlit as st
import tempfile
import soundfile as sf
from scipy.io import wavfile
from scipy import signal
# ตั้งค่าหน้าเพจ
st.set_page_config(
page_title="Speech Separation Demo App",
page_icon="🎧",
layout="wide",
initial_sidebar_state="expanded"
)
# สไตล์ CSS
st.markdown("""
<style>
.main-header {
font-size: 2.5rem;
color: #1E88E5;
text-align: center;
}
.sub-header {
font-size: 1.5rem;
color: #42A5F5;
}
.success-text {
color: #4CAF50;
font-weight: bold;
}
.info-text {
color: #2196F3;
}
</style>
""", unsafe_allow_html=True)
# ส่วนหัวแอป
st.markdown('<p class="main-header">🎧 Speech Separation Demo</p>', unsafe_allow_html=True)
st.markdown("""
แอปนี้แสดงการสาธิตการแยกเสียงพูดจากเสียงรบกวน โดยใช้การประมวลผลสัญญาณดิจิทัลพื้นฐาน
ตัวอย่างนี้ใช้ตัวกรองความถี่แบบช่องผ่าน (Bandpass filter) เพื่อลดเสียงรบกวน
""")
st.markdown("---")
# สร้างโฟลเดอร์สำหรับเก็บไฟล์ชั่วคราว
os.makedirs("./temp", exist_ok=True)
# ฟังก์ชันเพิ่มเสียงรบกวน
def add_noise(signal, noise_factor=0.01):
"""เพิ่มเสียงรบกวนให้กับสัญญาณเสียง"""
noise = np.random.normal(0, noise_factor, signal.shape)
return signal + noise
# ฟังก์ชันแยกเสียงพูดด้วยตัวกรองความถี่แบบช่องผ่าน
def filter_speech(audio_signal, sample_rate, lowcut=300, highcut=3000, order=5):
"""
แยกเสียงพูดด้วยตัวกรองความถี่แบบช่องผ่าน
เสียงพูดมนุษย์ส่วนใหญ่มีความถี่อยู่ระหว่าง 300-3000 Hz
"""
nyquist = 0.5 * sample_rate
low = lowcut / nyquist
high = highcut / nyquist
# ออกแบบตัวกรอง Butterworth
b, a = signal.butter(order, [low, high], btype='band')
# ใช้ตัวกรองกับสัญญาณ
filtered_signal = signal.filtfilt(b, a, audio_signal)
return filtered_signal
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
try:
# โหลดไฟล์เสียง
sample_rate, waveform = wavfile.read(tmp_file_path)
# เปลี่ยนเป็น float และ normalize ถ้าจำเป็น
if waveform.dtype == np.int16:
waveform = waveform.astype(np.float32) / 32768.0
elif waveform.dtype == np.int32:
waveform = waveform.astype(np.float32) / 2147483648.0
# ถ้าเป็น stereo ให้แปลงเป็น mono
if len(waveform.shape) > 1 and waveform.shape[1] > 1:
waveform = np.mean(waveform, axis=1)
# แสดงข้อมูลไฟล์เสียง
st.markdown('<p class="sub-header">ข้อมูลไฟล์เสียง</p>', unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
st.write(f"🔊 Sample rate: {sample_rate} Hz")
with col2:
st.write(f"⏱️ ความยาว: {len(waveform)/sample_rate:.2f} วินาที")
# ตัดเสียงถ้ายาวเกินไป (สำหรับ demo)
max_length = 10 * sample_rate # สูงสุด 10 วินาที
if len(waveform) > max_length:
st.warning(f"ตัดเสียงให้เหลือ 10 วินาทีแรกเพื่อให้การประมวลผลเร็วขึ้น")
waveform = waveform[:max_length]
st.markdown('<p class="sub-header">เสียงต้นฉบับ</p>', unsafe_allow_html=True)
# แสดงกราฟเสียงต้นฉบับ
fig, ax = plt.subplots(figsize=(10, 2))
ax.plot(waveform)
ax.set_title("Original Waveform")
ax.set_xlabel("Samples")
ax.set_ylabel("Amplitude")
ax.grid(True, alpha=0.3)
st.pyplot(fig)
# ให้เล่นเสียงต้นฉบับ
st.audio(tmp_file_path, format="audio/wav")
# เพิ่มเสียงรบกวน (สำหรับการทดสอบถ้าต้องการ)
st.markdown('<p class="sub-header">ตัวเลือกการเพิ่มเสียงรบกวน</p>', unsafe_allow_html=True)
add_noise_option = st.checkbox("เพิ่มเสียงรบกวนเพื่อการทดสอบ", value=False)
if add_noise_option:
noise_factor = st.slider("ระดับเสียงรบกวน", min_value=0.001, max_value=0.1, value=0.01, step=0.001)
noisy_waveform = add_noise(waveform, noise_factor)
st.markdown('<p class="sub-header">เสียงที่มีเสียงรบกวน</p>', unsafe_allow_html=True)
# แสดงกราฟเสียงที่มีเสียงรบกวน
fig, ax = plt.subplots(figsize=(10, 2))
ax.plot(noisy_waveform)
ax.set_title("Noisy Waveform")
ax.set_xlabel("Samples")
ax.set_ylabel("Amplitude")
ax.grid(True, alpha=0.3)
st.pyplot(fig)
# บันทึกเสียงที่มีเสียงรบกวน
noisy_path = "./temp/noisy_audio.wav"
sf.write(noisy_path, noisy_waveform, sample_rate)
st.audio(noisy_path, format="audio/wav")
else:
noisy_waveform = waveform # ใช้เสียงต้นฉบับถ้าไม่เพิ่มเสียงรบกวน
# ตั้งค่าพารามิเตอร์ตัวกรอง
st.markdown('<p class="sub-header">ปรับแต่งตัวกรองความถี่</p>', unsafe_allow_html=True)
col1, col2, col3 = st.columns(3)
with col1:
lowcut = st.slider("ความถี่ต่ำสุด (Hz)", min_value=50, max_value=500, value=300, step=10)
with col2:
highcut = st.slider("ความถี่สูงสุด (Hz)", min_value=1000, max_value=8000, value=3000, step=100)
with col3:
filter_order = st.slider("ระดับความแรงของตัวกรอง", min_value=1, max_value=10, value=5, step=1)
# ทำนาย (แยกเสียง)
st.markdown('<p class="sub-header">กำลังแยกเสียง...</p>', unsafe_allow_html=True)
# แสดง spinner ขณะประมวลผล
with st.spinner('กำลังแยกเสียง...'):
# ใช้ตัวกรองความถี่แบบช่องผ่าน
separated_waveform = filter_speech(noisy_waveform, sample_rate, lowcut, highcut, filter_order)
# Normalize
separated_waveform = separated_waveform / np.max(np.abs(separated_waveform))
st.markdown('<p class="sub-header">ผลลัพธ์การแยกเสียง</p>', unsafe_allow_html=True)
st.markdown('<p class="success-text">แยกเสียงสำเร็จ! 🎉</p>', unsafe_allow_html=True)
# แสดงกราฟเสียงที่แยกแล้ว
fig, ax = plt.subplots(figsize=(10, 2))
ax.plot(separated_waveform, color='green')
ax.set_title("Separated Waveform")
ax.set_xlabel("Samples")
ax.set_ylabel("Amplitude")
ax.grid(True, alpha=0.3)
st.pyplot(fig)
# บันทึกเสียงที่แยกแล้ว
output_path = "./temp/separated_audio.wav"
sf.write(output_path, separated_waveform, sample_rate)
# เล่นเสียงที่แยกแล้ว
st.markdown("### เสียงที่แยกแล้ว")
st.audio(output_path, format="audio/wav")
# เปรียบเทียบเสียงต้นฉบับและเสียงที่แยกแล้ว
st.markdown("### เปรียบเทียบเสียงต้นฉบับและเสียงที่แยกแล้ว")
# แสดงกราฟเปรียบเทียบ
fig, ax = plt.subplots(2, 1, figsize=(10, 4), sharex=True)
ax[0].plot(noisy_waveform)
ax[0].set_title("Original/Noisy Waveform")
ax[0].set_ylabel("Amplitude")
ax[0].grid(True, alpha=0.3)
ax[1].plot(separated_waveform, color='green')
ax[1].set_title("Separated Waveform")
ax[1].set_xlabel("Samples")
ax[1].set_ylabel("Amplitude")
ax[1].grid(True, alpha=0.3)
plt.tight_layout()
st.pyplot(fig)
# แสดงการวิเคราะห์ความถี่ (สเปกโตรแกรม)
st.markdown("### การวิเคราะห์ความถี่")
fig, ax = plt.subplots(2, 1, figsize=(10, 6))
# สเปกโตรแกรมของเสียงที่มีเสียงรบกวน
ax[0].specgram(noisy_waveform, Fs=sample_rate, NFFT=1024, noverlap=512, cmap='viridis')
ax[0].set_title("Spectrogram of Noisy Audio")
ax[0].set_ylabel("Frequency (Hz)")
# สเปกโตรแกรมของเสียงที่แยกแล้ว
ax[1].specgram(separated_waveform, Fs=sample_rate, NFFT=1024, noverlap=512, cmap='viridis')
ax[1].set_title("Spectrogram of Separated Audio")
ax[1].set_xlabel("Time (s)")
ax[1].set_ylabel("Frequency (Hz)")
plt.tight_layout()
st.pyplot(fig)
# ให้ดาวน์โหลดไฟล์เสียงที่แยกแล้ว
with open(output_path, "rb") as file:
st.download_button(
label="⬇️ ดาวน์โหลดเสียงที่แยกแล้ว",
data=file,
file_name="separated_audio.wav",
mime="audio/wav"
)
except Exception as e:
st.error(f"เกิดข้อผิดพลาด: {e}")
finally:
# ลบไฟล์ชั่วคราว
if os.path.exists(tmp_file_path):
os.remove(tmp_file_path)
# ส่วนหลักของแอป
def main():
# แสดงข้อมูลแอป
st.sidebar.image("https://img.icons8.com/fluency/96/000000/audio-wave.png", width=100)
st.sidebar.title("เกี่ยวกับแอปนี้")
st.sidebar.info(
"""
แอปนี้เป็นเดโมอย่างง่ายของการแยกเสียงพูดออกจากเสียงรบกวน โดยใช้เทคนิคการประมวลผลสัญญาณดิจิทัลพื้นฐาน
**วิธีใช้:**
1. อัปโหลดไฟล์เสียงที่มีเสียงรบกวน
2. (ตัวเลือก) เพิ่มเสียงรบกวนสำหรับการทดสอบ
3. ปรับแต่งพารามิเตอร์ของตัวกรองความถี่
4. ดูผลลัพธ์และดาวน์โหลดเสียงที่แยกแล้ว
"""
)
# อัปโหลดไฟล์เสียง
st.markdown('<p class="sub-header">อัปโหลดไฟล์เสียง</p>', unsafe_allow_html=True)
uploaded_file = st.file_uploader("เลือกไฟล์เสียงที่มีเสียงรบกวน", type=["wav", "mp3", "ogg", "flac"])
if uploaded_file is not None:
st.markdown('<p class="success-text">อัปโหลดไฟล์สำเร็จ! กำลังเริ่มประมวลผล...</p>', unsafe_allow_html=True)
process_audio(uploaded_file)
# รันแอป
if __name__ == "__main__":
main() |