client.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # A simple client that generates sine waves via python-pyaudio
  2. import signal
  3. import pyaudio
  4. import sys
  5. import socket
  6. import time
  7. import math
  8. import struct
  9. import socket
  10. from packet import Packet, CMD, stoi
  11. PORT = 13676
  12. STREAMS = 1
  13. IDENT = 'TONE'
  14. if len(sys.argv) > 1:
  15. UID = sys.argv[1].ljust(24, '\x00')
  16. else:
  17. UID = '\x00'*24
  18. LAST_SAMP = 0
  19. FREQ = 0
  20. PHASE = 0
  21. RATE = 44100
  22. FPB = 64
  23. Z_SAMP = '\x00\x00\x00\x00'
  24. MAX = 0x7fffffff
  25. AMP = MAX
  26. MIN = -0x80000000
  27. def sigalrm(sig, frm):
  28. global FREQ
  29. FREQ = 0
  30. def lin_interp(frm, to, cnt):
  31. step = (to-frm)/float(cnt)
  32. samps = [0]*cnt
  33. for i in xrange(cnt):
  34. p = i / float(cnt-1)
  35. samps[i] = int(p*to + (1-p)*frm)
  36. return samps
  37. def sine(freq, phase, cnt):
  38. global RATE, AMP
  39. samps = [0]*cnt
  40. for i in xrange(cnt):
  41. samps[i] = int(AMP * math.sin(phase + 2 * math.pi * freq * i / RATE))
  42. return samps, phase + 2 * math.pi * freq * cnt / RATE
  43. def to_data(samps):
  44. return struct.pack('i'*len(samps), *samps)
  45. def gen_data(data, frames, time, status):
  46. global FREQ, PHASE, Z_SAMP, LAST_SAMP
  47. if FREQ == 0:
  48. PHASE = 0
  49. if LAST_SAMP == 0:
  50. return (Z_SAMP*frames, pyaudio.paContinue)
  51. fdata = lin_interp(LAST_SAMP, 0, frames)
  52. LAST_SAMP = fdata[-1]
  53. return (to_data(fdata), pyaudio.paContinue)
  54. fdata, PHASE = sine(FREQ, PHASE, frames)
  55. LAST_SAMP = fdata[-1]
  56. return (to_data(fdata), pyaudio.paContinue)
  57. pa = pyaudio.PyAudio()
  58. stream = pa.open(rate=RATE, channels=1, format=pyaudio.paInt32, output=True, frames_per_buffer=FPB, stream_callback=gen_data)
  59. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  60. sock.bind(('', PORT))
  61. signal.signal(signal.SIGALRM, sigalrm)
  62. while True:
  63. data = ''
  64. while not data:
  65. try:
  66. data, cli = sock.recvfrom(4096)
  67. except socket.error:
  68. pass
  69. pkt = Packet.FromStr(data)
  70. print 'From', cli, 'command', pkt.cmd
  71. if pkt.cmd == CMD.KA:
  72. pass
  73. elif pkt.cmd == CMD.PING:
  74. sock.sendto(data, cli)
  75. elif pkt.cmd == CMD.QUIT:
  76. break
  77. elif pkt.cmd == CMD.PLAY:
  78. dur = pkt.data[0]+pkt.data[1]/1000000.0
  79. FREQ = pkt.data[2]
  80. AMP = MAX * (pkt.data[3]/255.0)
  81. signal.setitimer(signal.ITIMER_REAL, dur)
  82. elif pkt.cmd == CMD.CAPS:
  83. data = [0] * 8
  84. data[0] = STREAMS
  85. data[1] = stoi(IDENT)
  86. for i in xrange(len(UID)/4):
  87. data[i+2] = stoi(UID[4*i:4*(i+1)])
  88. sock.sendto(str(Packet(CMD.CAPS, *data)), cli)
  89. else:
  90. print 'Unknown cmd', pkt.cmd