audio.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import pyaudio
  2. import serial
  3. from serial import SerialException
  4. import _thread
  5. import struct
  6. import numpy as np
  7. import math
  8. import time
  9. import random
  10. import paho.mqtt.client as mqtt
  11. from beatDetection import SimpleBeatDetection
  12. nFFT = 512
  13. CHUNKSIZE = nFFT * 4 # fixed chunk size
  14. SAMPLERATE = 44100
  15. FORMAT = pyaudio.paInt16
  16. # initialize portaudio
  17. p = pyaudio.PyAudio()
  18. MAX_y = 2.0 ** (p.get_sample_size(pyaudio.paInt16) * 8 - 1)
  19. ser = None
  20. portName="COM7"
  21. while not ser:
  22. try:
  23. ser = serial.Serial(portName, 115200)
  24. except serial.SerialException:
  25. print(portName, " not available")
  26. portName="COM" + input("COM")
  27. print("Connected to ", ser.name)
  28. info = p.get_host_api_info_by_index(0)
  29. numdevices = info.get('deviceCount')
  30. #for each audio device, determine if is an input or an output and add it to the appropriate list and dictionary
  31. DEVICE = -1
  32. for i in range (0,numdevices):
  33. info = p.get_device_info_by_host_api_device_index(0,i)
  34. if info.get('maxInputChannels')>0:
  35. print ("Input Device id ", i, " - ", info.get('name'))
  36. if "High" in info.get('name'):
  37. DEVICE = i
  38. #if p.get_device_info_by_host_api_device_index(0,i).get('maxOutputChannels')>0:
  39. # print ("Output Device id ", i, " - ", p.get_device_info_by_host_api_device_index(0,i).get('name'))
  40. if DEVICE == -1:
  41. DEVICE = int(input("Device? "))
  42. stream = p.open(format=pyaudio.paInt16, channels=2, rate=SAMPLERATE, input=True,input_device_index=DEVICE, frames_per_buffer=CHUNKSIZE)
  43. devinfo = p.get_device_info_by_index(DEVICE)
  44. print ("Selected device is ",devinfo.get('name'), " at ", SAMPLERATE, " Hz")
  45. if p.is_format_supported(SAMPLERATE, # Sample rate
  46. input_device=devinfo["index"],
  47. input_channels=devinfo['maxInputChannels'],
  48. input_format=pyaudio.paInt16):
  49. print ('Audio seems to be ok!')
  50. def read():
  51. while 1:
  52. if ser.inWaiting()>0:
  53. print(ser.read(ser.inWaiting()).decode("utf-8"))
  54. time.sleep(.1)
  55. _thread.start_new_thread( read, () )
  56. def write(val):
  57. ser.write((int(val)&0xFF).to_bytes(1, byteorder='big', signed=False))
  58. def writeInt(val):
  59. ser.write((int(val)&0xFFFF).to_bytes(2, byteorder='big', signed=False))
  60. def writeLng(val):
  61. ser.write((int(val)&0xFFFFFFFF).to_bytes(4, byteorder='big', signed=False))
  62. def on_message(mqttc, obj, msg):
  63. print(msg)
  64. def on_log(mqttc, obj, level, string):
  65. print(string)
  66. def on_connect(client, userdata, flags, rc):
  67. print("Connected with result code "+str(rc))
  68. mqttc.subscribe("Timer/#", 2)
  69. mqttc.subscribe("Pc/#", 2)
  70. # If you want to use a specific client id, use
  71. # mqttc = mqtt.Client("client-id")
  72. # but note that the client id must be unique on the broker. Leaving the client
  73. # id parameter empty will generate a random id for you.
  74. mqttc = mqtt.Client()
  75. mqttc.on_message = on_message
  76. mqttc.on_connect = on_connect
  77. # Uncomment to enable debug messages
  78. #mqttc.on_log = on_log
  79. mqttc.connect_async("192.168.0.2", 1883, 60)
  80. mqttc.loop_start()
  81. sbd = SimpleBeatDetection(100)
  82. val=[0]*64
  83. ser.write(b'~u~t~c ')
  84. timeout = 0
  85. oldBeat = False
  86. tBeat = 0
  87. nBeat = 0
  88. while 1:
  89. #start = time.time()
  90. N = int(max(stream.get_read_available() / nFFT, 1) * nFFT)
  91. data = stream.read(N)
  92. y = np.array(struct.unpack("%dh" % (N * 2), data)) / MAX_y
  93. y_L = y[::2]
  94. y_R = y[1::2]
  95. Y_L = np.fft.fft(y_L, nFFT)
  96. Y_R = np.fft.fft(y_R, nFFT)
  97. Y = abs(np.hstack((Y_L[int(-nFFT / 2):-1], Y_R[0:int(nFFT / 2)])))
  98. buf = []
  99. for z in range(4):
  100. for y in range(4):
  101. for x in range(4):
  102. if x in [1,2]:
  103. if y == 0:
  104. a=np.sum(Y[259:266])/30*16 - z*4 + 32 #right channel
  105. elif y == 1:
  106. a=np.sum(Y[256:259])/40*16 - z*4 + 32
  107. elif y == 2:
  108. a=np.sum(Y[252:256])/40*16 - z*4 + 32 #left channel
  109. else:
  110. a=np.sum(Y[240:247])/30*16 - z*4 + 32
  111. else:
  112. if y == 0:
  113. a=np.sum(Y[264:270])/20*16 - z*4 + 32 #right channel
  114. elif y == 1:
  115. a=np.sum(Y[258:264])/40*16 - z*4 + 32
  116. elif y == 2:
  117. a=np.sum(Y[247:253])/40*16 - z*4 + 32 #left channel
  118. else:
  119. a=np.sum(Y[236:242])/20*16 - z*4 + 32
  120. if a>val[x+y*4+z*16]:
  121. val[x+y*4+z*16]=a
  122. else:
  123. a=val[x+y*4+z*16]=val[x+y*4+z*16] * 0.8 + a * 0.2
  124. if a<32 : a = 32
  125. elif a>47 : a = 47
  126. buf.append(int(a))
  127. ser.write(b'~a')
  128. ser.write(bytearray(buf))
  129. s = sum(buf)
  130. if s == 32*64:
  131. timeout += 1
  132. else:
  133. timeout = 0
  134. signal = np.frombuffer(data, np.int16)
  135. beat = sbd.detect_beat(signal)
  136. if beat == 0:
  137. tBeat += 1
  138. if beat == True and timeout == 0 and tBeat > 3:
  139. tBeat = 0
  140. nBeat += 1
  141. 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}"
  142. #print(" ------------------ " + json)
  143. mqttc.publish("RgbLamp/spot", json)
  144. oldBeat = beat
  145. if timeout > 1000:
  146. time.sleep(0.3)
  147. else:
  148. time.sleep(0.015)
  149. # close stream
  150. stream.stop_stream()
  151. stream.close()
  152. p.terminate()
  153. ser.close()