123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- import pyaudio
- import serial
- from serial import SerialException
- import _thread
- import struct
- import numpy as np
- import math
- import time
- import random
- import paho.mqtt.client as mqtt
- from beatDetection import SimpleBeatDetection
- nFFT = 512
- CHUNKSIZE = nFFT * 4 # fixed chunk size
- SAMPLERATE = 44100
- FORMAT = pyaudio.paInt16
- # initialize portaudio
- p = pyaudio.PyAudio()
- MAX_y = 2.0 ** (p.get_sample_size(pyaudio.paInt16) * 8 - 1)
- ser = None
- portName="COM7"
- while not ser:
- try:
- ser = serial.Serial(portName, 115200)
- except serial.SerialException:
- print(portName, " not available")
- portName="COM" + input("COM")
- print("Connected to ", ser.name)
- info = p.get_host_api_info_by_index(0)
- numdevices = info.get('deviceCount')
- #for each audio device, determine if is an input or an output and add it to the appropriate list and dictionary
- DEVICE = -1
- for i in range (0,numdevices):
- info = p.get_device_info_by_host_api_device_index(0,i)
- if info.get('maxInputChannels')>0:
- print ("Input Device id ", i, " - ", info.get('name'))
- if "High" in info.get('name'):
- DEVICE = i
- #if p.get_device_info_by_host_api_device_index(0,i).get('maxOutputChannels')>0:
- # print ("Output Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0,i).get('name'))
- if DEVICE == -1:
- DEVICE = int(input("Device? "))
- stream = p.open(format=pyaudio.paInt16, channels=2, rate=SAMPLERATE, input=True,input_device_index=DEVICE, frames_per_buffer=CHUNKSIZE)
- devinfo = p.get_device_info_by_index(DEVICE)
- print ("Selected device is ",devinfo.get('name'), " at ", SAMPLERATE, " Hz")
- if p.is_format_supported(SAMPLERATE, # Sample rate
- input_device=devinfo["index"],
- input_channels=devinfo['maxInputChannels'],
- input_format=pyaudio.paInt16):
- print ('Audio seems to be ok!')
- def read():
- while 1:
- if ser.inWaiting()>0:
- print(ser.read(ser.inWaiting()).decode("utf-8"))
- time.sleep(.1)
- _thread.start_new_thread( read, () )
- def write(val):
- ser.write((int(val)&0xFF).to_bytes(1, byteorder='big', signed=False))
- def writeInt(val):
- ser.write((int(val)&0xFFFF).to_bytes(2, byteorder='big', signed=False))
- def writeLng(val):
- ser.write((int(val)&0xFFFFFFFF).to_bytes(4, byteorder='big', signed=False))
-
- def on_message(mqttc, obj, msg):
- print(msg)
-
- def on_log(mqttc, obj, level, string):
- print(string)
- def on_connect(client, userdata, flags, rc):
- print("Connected with result code "+str(rc))
- mqttc.subscribe("Timer/#", 2)
- mqttc.subscribe("Pc/#", 2)
- # If you want to use a specific client id, use
- # mqttc = mqtt.Client("client-id")
- # but note that the client id must be unique on the broker. Leaving the client
- # id parameter empty will generate a random id for you.
- mqttc = mqtt.Client()
- mqttc.on_message = on_message
- mqttc.on_connect = on_connect
- # Uncomment to enable debug messages
- #mqttc.on_log = on_log
- mqttc.connect_async("192.168.0.2", 1883, 60)
- mqttc.loop_start()
-
-
- sbd = SimpleBeatDetection(100)
-
-
- val=[0]*64
- ser.write(b'~u~t~c ')
- timeout = 0
- oldBeat = False
- tBeat = 0
- nBeat = 0
- while 1:
- #start = time.time()
- N = int(max(stream.get_read_available() / nFFT, 1) * nFFT)
- data = stream.read(N)
-
- y = np.array(struct.unpack("%dh" % (N * 2), data)) / MAX_y
- y_L = y[::2]
- y_R = y[1::2]
- Y_L = np.fft.fft(y_L, nFFT)
- Y_R = np.fft.fft(y_R, nFFT)
- Y = abs(np.hstack((Y_L[int(-nFFT / 2):-1], Y_R[0:int(nFFT / 2)])))
-
- buf = []
-
- for z in range(4):
- for y in range(4):
- for x in range(4):
- if x in [1,2]:
- if y == 0:
- a=np.sum(Y[259:266])/30*16 - z*4 + 32 #right channel
- elif y == 1:
- a=np.sum(Y[256:259])/40*16 - z*4 + 32
- elif y == 2:
- a=np.sum(Y[252:256])/40*16 - z*4 + 32 #left channel
- else:
- a=np.sum(Y[240:247])/30*16 - z*4 + 32
- else:
- if y == 0:
- a=np.sum(Y[264:270])/20*16 - z*4 + 32 #right channel
- elif y == 1:
- a=np.sum(Y[258:264])/40*16 - z*4 + 32
- elif y == 2:
- a=np.sum(Y[247:253])/40*16 - z*4 + 32 #left channel
- else:
- a=np.sum(Y[236:242])/20*16 - z*4 + 32
-
- if a>val[x+y*4+z*16]:
- val[x+y*4+z*16]=a
- else:
- a=val[x+y*4+z*16]=val[x+y*4+z*16] * 0.8 + a * 0.2
-
- if a<32 : a = 32
- elif a>47 : a = 47
- buf.append(int(a))
- ser.write(b'~a')
- ser.write(bytearray(buf))
-
- s = sum(buf)
-
- if s == 32*64:
- timeout += 1
- else:
- timeout = 0
-
-
- signal = np.frombuffer(data, np.int16)
- beat = sbd.detect_beat(signal)
-
- if beat == 0:
- tBeat += 1
-
- if beat == True and timeout == 0 and tBeat > 3:
-
- tBeat = 0
- nBeat += 1
- json = "{\"spot\":[{\"color\":" + str(256*256-1) + ",\"radius\":" + str(int(s/64-32)*3+2) + ",\"pos\":" + str(10 + nBeat%4 * 10) + ",\"keep\":0}],\"speed\":40}"
- #print(" ------------------ " + json)
- mqttc.publish("RgbLamp/spot", json)
- oldBeat = beat
-
- if timeout > 1000:
- time.sleep(0.3)
- else:
- time.sleep(0.015)
-
- # close stream
- stream.stop_stream()
- stream.close()
- p.terminate()
- ser.close()
|