FOBI

FOBI

การตรวจจับเสียงพูดและบันทึกเป็นไฟล์เสียง

การจะพูดคุยกับผู้ใช้งานได้นั้นเราจำเป็นต้องฟังผู้ใช้งานให้รู้เรื่องเสียก่อนว่าผู้ใช้งาน ต้องการอะไรจากเรา เราจึงจะสามารถตอบคำถาม พูดคุยหรือทำตามคำสั่งผู้ใช้งานได้ และนั่นทำให้เราจึงจำเป็นต้องมีการตรวจจับเสียงพูด โดย เราจะใช้ Pyaudio ซึางเป็น Library สำหรับภาษา Python ที่ต้องนำมาอัดเสียงผู้ใช่้งานว่ากำลังพูดอะไร โดยจะเก็บเป็นไฟล์นามสกุล .wav

Pyaudio

การติดตั้ง Pyaudio

ในการติดตั้งบน Raspberry pi เราจะใช้คำสั่ง

pip install PyAudio

Version ที่ใช้งานในขณะนั้นคือ V.0.2.11

การบันทึกเป็นไฟล์เสียง

จากตัวอย่างโค้ดด้านล่างจะเห็นได้ว่าได้ทำการทดลองบันทึกเสียง 5 วินาที และบันทึกเป็นไฟล์เสียง output.wav หากต้องบันทึกไฟล์เสียงการมากกว่า 5 วินาที สามารถปรับได้ที่ RECORD_SECONDS

ตัวอย่าง

import pyaudio
import wave

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()

stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

print("* recording")

frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    frames.append(data)

print("* done recording")

stream.stop_stream()
stream.close()
p.terminate()

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

ตรวจจับเสียงพูด

เพื่อจะใช้การจับเสียงพูดแท่นการตั้งเวลาในการอัดเสียง โดยใช้ Library numpy ในการคำนวณหาค่าสูงสุดเพื่อหาค่าของเลเวลของเสียงแล้วนำมาใช้ในการจับเสียงพูด

ตัวอย่าง

import math, numpy as np

data = stream.read(CHUNK, exception_on_overflow=False)
data_conv  = np.fromstring(data, dtype=np.int16)
max = np.max(data_conv)     
frames.append(data)

เมื่อนำโค้ดรวมเข้าด้วยกันจะได้ดั่งนี้

ตัวอย่าง

import pyaudio
import wave
import math, numpy as np
import time

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE =48000

p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

STATE ="start"
frames = []
t = float(0)
t1 = float(0)

while True:
    data = stream.read(CHUNK, exception_on_overflow=False)
    data_conv  = np.fromstring(data, dtype=np.int16)
    max = np.max(data_conv)
    frames.append(data)

    if STATE == "start":
        frames = []
        t = time.time()
        STATE = "rec"

    elif time.time()-t > float(3)  and STATE == "rec" and max < 7000:
        STATE = "start"   

    elif max => 7000 :
        STATE = "wait"

    elif STATE =="wait" and max<7000:
        t1 = time.time() 
        STATE = "save"

    elif max < 7000 and STATE =="save" and time.time()-t1 > float(1) :
        STATE = "start"
        wf = wave.open('output.wav', 'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))

stream.stop_stream()
stream.close()
p.terminate()

1. if จะเข้ามาทำก็ต่อเมื่อ STATE == “start” จะเริ่มเก็บ frames, เริ่มจำเวลา และจะเปลี่ยนค่าใน STATE จาก STATE = “start” เป็น STATE = “rec”

if STATE == "start":
  frames = []
  t = time.time()
  STATE = "rec"

2. elif ตัวแรกจะเข้ามาทำก็ต่อเมื่อ time.time()-t มากกว่า 3 และ STATE == “rec” และ max น้อยกว่า 7000 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “rec” เป็น STATE = “start”

elif time.time()-t > float(3)  and STATE == "rec" and max < 7000:
  STATE = "start"

3. elif ตัวที่สองจะเข้ามาทำก็ต่อเมื่อ max มีค่ามากกว่าหรือเท่ากับ 7000 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “start” เป็น STATE = “wait”

elif max => 7000 :
  STATE = "wait"

4. elif ตัวที่สามจะเข้ามาทำก็ต่อเมื่อ STATE == “wait” และ max มีค่าน้อยกว่า 7000 เมื่อเข้ามาทำใน elif เริ่มจับเวลา t1 และเปลี่ยนค่าใน STATE จาก STATE = “wait” เป็น STATE = “save”

elif STATE =="wait" and max<7000:
  t1 = time.time() 
  STATE = "save"

5. elif ตัวที่สี่จะเข้ามาทำก็ต่อเมื่อ max มีค่าน้อยกว่า 7000 และ STATE == “save” และ time.time()-t1 มากกว่า 3 เมื่อเข้ามาทำใน elif จะเปลี่ยนค่าใน STATE จาก STATE = “save” เป็น STATE = “start” และบันทึกเป็นไฟล์เสียง output.wav

elif max < 7000 and STATE =="save" and time.time()-t1 > float(1) :
  STATE = "start"
  wf = wave.open('output.wav', 'wb')
  wf.setnchannels(CHANNELS)
  wf.setsampwidth(p.get_sample_size(FORMAT))
  wf.setframerate(RATE)
  wf.writeframes(b''.join(frames))