Piano 음 재생 및 DB 속도 측정하기

Sharp GP2Y0A02YK0F IR 센서를 사용하였습니다. 해당 센서에 관한 정보는 아래 그림을 클릭하면 확인 할 수 있습니다.

import pymysql
import pygame
import spidev
import time

spi = spidev.SpiDev() 
spi.open(0, 0)
spi.max_speed_hz = 1000000

pygame.init()
pygame.mixer.init()

DISTANCE = [20, 30, 40]

sound_channel = pygame.mixer.Channel(0)
sound_list = ["piano-C4.wav", "piano-D4.wav", "piano-E4.wav", "piano-F4.wav"]
for i in range(4) :
    sound_list[i] = pygame.mixer.Sound(sound_list[i]);

cnx = pymysql.connect(host = '192.168.31.114',
                      user = 'lee',
                      password = 'cdt',
                      database = '78project',
                      autocommit = True
                      )

def readChannel(channel) :
  val = spi.xfer2([1, (8 + channel) << 4, 0])
  data = ((val[1] & 3) << 8) + val[2]
  return data

def measure_distance() :
  v = (readChannel(0) / 1023.0) * 3.3
  dist = 16.2537*v**4 - 129.893*v**3 + 382.268*v**2 - 512.611*v + 301.439
  return dist

def which() :
    distance = measure_distance()
    if distance > 130 :
        note = -1
    elif distance < DISTANCE[0] :
        note = 0
    elif distance < DISTANCE[1] :
        note = 1
    elif distance < DISTANCE[2] :
        note = 2
    else :
        note = 3
    return (note, distance)
    
def sound_on(idx) :
    sound_channel.play(sound_list[idx])

def sound_off(idx) :
    sound_channel.stop()

def replay(idx) :
    sound_channel.stop()
    sound_channel.play(sound_list[idx])
    
try:
    playing = -1
    note = -1
    start_time = time.time()
    
    while True:
        playing = note
        data = which()
        note = data[0]
        dist = data[1]
        
        with cnx.cursor() as cursor :
            # PUSH data to database
            sql = 'UPDATE changed_note SET note_id = ' + str(note) + ';'
            cursor.execute(sql)
            sql = 'SELECT * FROM changed_note;'
            cursor.execute(sql)
            rows = cursor.fetchone()

            # PULL data from database
            idx = int(rows[0])
            
            # Error if push & pull value don't match
            if note != idx :
                print("Database Error")
            #else :
                #print(idx)

            # Play & Replay & Stop playing
            if note == -1 :
                sound_off(note)
                
                if playing != note :
                    print("off")
                    print("distance: %dcm" %dist)
                
            elif playing == note :
                if sound_channel.get_busy() :
                    if time.time() - start_time > 0.5 :
                        replay(note)
                        start_time = time.time()

                        print("replay")
                        print("distance: %dcm" %dist)    
                        
                    else :
                        pass
            else :
                sound_off(playing)
                sound_on(note)
                start_time = time.time()

                print("change")
                print("distance: %dcm" %dist)
                    

except KeyboardInterrupt :
    pass

finally :
    cnx.close()
  • 음원은 freesound.org에서 무료로 다운 받았습니다.
  • 음 재생을 시현해 보기 위해 서버에 있는 78project 데이터베이스에 changed_note라는 table을 생성하였습니다. changed_note 데이터베이스에는 현재 재생되어야하는 음의 id를 저장합니다. (C4 : 0, D4 : 1, E4 : 2, F4 : 3, 아무 음 재생 안하는 경우 : -1)
  • 데이터베이스에 정보를 push 하고 pull 하는 유일한 이유는 통신 속도를 측정하기 위함입니다. push와 pull은 전체적인 기능에 다른 영향을 주지 않습니다.
  • 음원의 일부를 반복 재생하기 위해 0.5초를 재생한 뒤, 다시 처음부터 재생하도록 하였습니다. 하지만 stop 한 뒤 play 하는 데까지 약간의 지연 시간이 있기 때문에, 음이 연속적으로 재생되지 않는 문제를 보입니다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중