main.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import audioHandler
  2. import serialHandler
  3. import mqttHandler
  4. import time
  5. import multiprocessing
  6. import numpy as np
  7. import sys, getopt
  8. framerate = 60 #Hz
  9. dataTime = 1/30
  10. graphs = True
  11. outDev = True
  12. brightness = 15
  13. filename = None
  14. try:
  15. opts, args = getopt.getopt(sys.argv[1:],"hsif:t:b:w:",["shadow=","input=","framerate=","time=","brightness=","write="])
  16. except getopt.GetoptError:
  17. print('main.py -s (shadow) -i (use input) -f --framerate <n=60>\n -t --time <t=0.033> -b --brightness <b=15> -w --write <filename.wav>')
  18. sys.exit(2)
  19. for opt, arg in opts:
  20. if opt == '-h':
  21. print('main.py -s (shadow) -i (use input) -f --framerate <n=60>\n -t --time <t=0.033> -b --brightness <b=15> -w --write <filename.wav>')
  22. sys.exit()
  23. elif opt in ("-s", "--shadow"):
  24. graphs = False
  25. elif opt in ("-i", "--input"):
  26. outDev = False
  27. elif opt in ("-f", "--framerate"):
  28. framerate = float(arg)
  29. elif opt in ("-t", "--time"):
  30. dataTime = float(arg)
  31. elif opt in ("-b", "--brightness"):
  32. brightness = int(arg)
  33. if brightness > 15:
  34. brightness = 15
  35. elif brightness < 0:
  36. brightness = 0
  37. elif opt in ("-w", "--write"):
  38. filename = arg
  39. import wave
  40. import pyaudio
  41. audio = audioHandler.Listener(dataTime, 30, not outDev)
  42. cube = serialHandler.SerialConnection()
  43. vis = serialHandler.Visualization()
  44. lamp = mqttHandler.RgbLamp("<mqtt server ip>")
  45. #audio.setBeatCb(lamp.onBeat)
  46. intervalTime = time.time()
  47. if graphs:
  48. import displayHandler
  49. window = displayHandler.Plot(count=5)
  50. window.addLabel(0, "x = f(t)", "t in s")
  51. window.addLabel(1, "x = f(f)", "f in Hz")
  52. window.addLabel(3, "Beat detection", "t in s")
  53. window.addLabel(4, "", "bpm")
  54. pitches = [(2**(1/12))**n * 220 for n in range(-12*2, 12*5)]
  55. octaves = [(2**(1/12))**n * 220 for n in range(-12*2, 12*5, 12)]
  56. octCount = len(octaves)
  57. audio.start()
  58. nFFT = audio.buffersize
  59. audio.fftSetLimits(nFFT, min(pitches), max(pitches))
  60. audio.agcFftSetLimits(60/60, 300/60)
  61. cube.connect()
  62. cube.setBrightness(brightness)
  63. if filename:
  64. wf = wave.open(filename, 'wb')
  65. wf.setnchannels(audio._device["channels"])
  66. wf.setsampwidth(audio.p.get_sample_size(pyaudio.paInt16))
  67. wf.setframerate(audio.getSampleRate())
  68. if graphs:
  69. x = [x / audio.getSampleRate() for x in range(len(audio.left ))]
  70. lineAmpL = window.addLine(0, x, -1.5, 1.5, 'r-')
  71. lineAmpR = window.addLine(0, x, -1.5, 1.5, 'g-')
  72. x = [x * audio.getSampleRate() / nFFT for x in range(audio.fftMin, audio.fftMax)]
  73. lineFft = window.addLine(1, x, 0, 1, 'r-', 'log')
  74. x = ["{:.0f}\n{:.0f}".format(a, b) for a,b in zip(octaves, octaves[1:])]
  75. #barsFft = window.addBars(2, x, 0, 1, 0.5, -0.25, 'r')
  76. x = ['as','h','c','cis','d','es', 'e', 'f', 'fis', 'g', 'gis', 'a']
  77. colors = ['r', 'g', 'b', 'y']
  78. barsPitch = [window.addBars(2, x, 0, 1, 0.25, -0.5+1/4*(i+1), colors[i]) for i in range(4)]
  79. lineAgc = window.addLine(3, [x * audio._dataTime for x in range(audio._agcLen)], 0, 2)
  80. x = [x / audio._dataTime / audio.beatnFFT * 60 for x in range(audio.beatFftMin, audio.beatFftMax)]
  81. lineAgcFft = window.addLine(4, x, 0, 1, 'r-')
  82. #delay to gather sound data
  83. time.sleep(0.1)
  84. sums = np.zeros((4, 12))
  85. mean = (0,0)
  86. avg = [0]*len(octaves)
  87. def loop():
  88. global intervalTime, avg, sums, mean
  89. if audio.hasNewData():
  90. left, right, fft = np.copy(audio.left), np.copy(audio.right), np.copy(audio.fft)
  91. avg = audio.fftGroup(fft, octaves)
  92. mean = np.mean(np.absolute(left)),np.mean(np.absolute(right))
  93. if filename:
  94. wf.writeframes(audio._buf)
  95. if graphs:
  96. lineAmpL.set_ydata(left)
  97. lineAmpR.set_ydata(right)
  98. lineFft.set_ydata(fft[audio.fftMin-1:audio.fftMax])
  99. #for b in range(octCount - 1):
  100. #barsFft[b].set_height(avg[b])
  101. lineAgc.set_ydata(audio._agcMaxima / audio.meanAmp)
  102. lineAgcFft.set_ydata(np.abs(audio.agcFFT[audio.beatFftMin:audio.beatFftMax]) / audio.meanAmp * 10)
  103. sums = np.zeros((4, 12))
  104. for i, p in enumerate(audio.fftGroup(fft, pitches)):
  105. sums[int(i/12*4/octCount)][(i+1) % 12] += p
  106. #order = np.argsort(np.abs(audio.agcFFT[audio.beatFftMin:audio.beatFftMax]))
  107. #print(order)
  108. vis.matrix *= 0.7
  109. for k in range(4):
  110. #mn = min(sums[k])
  111. #diff = max(sums[k]) - mn
  112. #sums[k] = (sums[k] - mn)
  113. if graphs:
  114. for i in range(12):
  115. barsPitch[k][i].set_height(sums[k][i])
  116. vis.matrix += vis.noteCircle(sums[k], 3-k)
  117. vis.matrix += vis.ampPyramid((avg[0]*2,avg[1]*2,*mean))
  118. np.clip(vis.matrix, 0, 1, out=vis.matrix)
  119. cube.send(vis.matrix)
  120. if time.time() - intervalTime > 60:
  121. if not cube.isConnected():
  122. print("lost serial connection, retrying to connect...")
  123. cube.connect()
  124. audio.stop()
  125. audio.start()
  126. intervalTime = time.time()
  127. try:
  128. if graphs:
  129. window.show(loop, framerate)
  130. else:
  131. i = 0
  132. while True:
  133. startTime = time.time()
  134. loop()
  135. runTime = time.time() - startTime
  136. if runTime < 1/framerate:
  137. time.sleep(1/framerate-runTime)
  138. i+=1
  139. if i >= framerate*30:
  140. print("agc: {:6.1%} \tvolume: {:7.1%}".format(audio.getAgc(), audio.getVolume()))
  141. i = 1
  142. except KeyboardInterrupt:
  143. audio.closeStream()
  144. if filename:
  145. wf.close()
  146. except:
  147. print("Unexpected error:", sys.exc_info()[0])
  148. input("Press enter to continue...")
  149. raise