이번에는 microphone과 python의 sounddevice 라이브러리를 이용한 소리 탐지 소스를 만들어 보았습니다.

우선 설치부터 해야지요~

운영체제마다 조금씩 다르지만 맥기준으로 설명하겠습니다.

우선 sounddevice를 microphone과 연결하기 위한 portaudio를 설치해줍니다.

brew install portaudio 명령을 통해 설치를 해줍니다.

그리고 자신의 파이썬 환경에 sounddevice설치를 위해 pip install sounddevice 를 통해 라이브러리를 설치해줍니다.

이제 제가 간단히 테스트해본 코드를 봅시다.

우선 필요한 라이브러리들을 임포트해줍니다.

import time
import sounddevice as sd
import numpy as np

그리고 몇 초단위로 코드를 진행할 것인지 duration을 정해줍니다.

duration = 3  # seconds

저는 3초로 했습니다.

while True:

    present_wave = []
    compare_wave = []

    def print_sound(indata, outdata, frames, time, status):
        volume_norm = np.linalg.norm(indata)*10
        print("|" * int(volume_norm))

    with sd.Stream(callback=print_sound):
        sd.sleep(duration * 1000)

그리고 반복문으로 반복해줍니다.

이렇게 하면

마이크로폰으로 들어오는 input stream을 파이프 기호로 표시해줍니다.

이런식으로 말이죠

여기에 여러분이 원하는 기능을 추가할 수 있습니다.

저는 3초동안 불규칙한 웨이브가 감지되면 udp 소켓으로 데이터를 보내도록 코드를 만들었습니다.

아래는 전체코드입니다.

# Print out realtime audio volume as ascii bars
import time
import sounddevice as sd
import numpy as np
import copy
import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cli = ("127.0.0.1", 9999)
data = b'True'

error_wave = ''

gijunjum = 1000

duration = 3  # seconds

prev_wave = []

init = True

while True:

    present_wave = []
    compare_wave = []

    def print_sound(indata, outdata, frames, time, status):
        volume_norm = np.linalg.norm(indata)*10
        print("|" * int(volume_norm))

        present_wave.append(gijunjum - volume_norm)

    with sd.Stream(callback=print_sound):
        sd.sleep(duration * 1000)

    if init is True:
        prev_wave = copy.copy(present_wave)
        init = False

    try:
        for idx, each in enumerate(present_wave):
            compare_wave.append(each - prev_wave[idx])
    except IndexError:
        pass

    temp = 0
    total_change = 0
    for cw in compare_wave:
        if abs(cw - temp) > 4:
            total_change = total_change + 1

        temp = cw

    if total_change > 30:
        print("sound detect!!")
        client_socket.sendto(data, cli)

    time.sleep(0.01)

여기까지 마치겠습니다. 끝~!