client.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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
  11. PORT = 13676
  12. LAST_SAMP = 0
  13. FREQ = 0
  14. PHASE = 0
  15. RATE = 44100
  16. FPB = 64
  17. Z_SAMP = '\x00\x00\x00\x00'
  18. MAX = 0x7fffffff
  19. AMP = MAX
  20. MIN = -0x80000000
  21. def sigalrm(sig, frm):
  22. global FREQ
  23. FREQ = 0
  24. def lin_interp(frm, to, cnt):
  25. step = (to-frm)/float(cnt)
  26. samps = [0]*cnt
  27. for i in xrange(cnt):
  28. p = i / float(cnt-1)
  29. samps[i] = int(p*to + (1-p)*frm)
  30. return samps
  31. def sine(freq, phase, cnt):
  32. global RATE, AMP
  33. samps = [0]*cnt
  34. for i in xrange(cnt):
  35. samps[i] = int(AMP * math.sin(phase + 2 * math.pi * freq * i / RATE))
  36. return samps, phase + 2 * math.pi * freq * cnt / RATE
  37. def to_data(samps):
  38. return struct.pack('i'*len(samps), *samps)
  39. def gen_data(data, frames, time, status):
  40. global FREQ, PHASE, Z_SAMP, LAST_SAMP
  41. if FREQ == 0:
  42. PHASE = 0
  43. if LAST_SAMP == 0:
  44. return (Z_SAMP*frames, pyaudio.paContinue)
  45. fdata = lin_interp(LAST_SAMP, 0, frames)
  46. LAST_SAMP = fdata[-1]
  47. return (to_data(fdata), pyaudio.paContinue)
  48. fdata, PHASE = sine(FREQ, PHASE, frames)
  49. LAST_SAMP = fdata[-1]
  50. return (to_data(fdata), pyaudio.paContinue)
  51. pa = pyaudio.PyAudio()
  52. stream = pa.open(rate=RATE, channels=1, format=pyaudio.paInt32, output=True, frames_per_buffer=FPB, stream_callback=gen_data)
  53. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  54. signal.signal(signal.SIGALRM, sigalrm)
  55. while True:
  56. data, cli = sock.recvfrom(4096)
  57. pkt = Packet.FromStr(data)
  58. print 'From', cli, 'command', pkt.cmd
  59. if pkt.cmd == KA:
  60. pass
  61. elif pkt.cmd == PING:
  62. sock.sendto(data, cli)
  63. elif pkt.cmd == CMD.QUIT:
  64. break
  65. elif pkt.cmd == CMD.PLAY:
  66. dur = pkt.data[0]+pkt.data[1]/1000000.0
  67. FREQ = pkt.data[2]
  68. AMP = MAX * (pkt.data[2]/255.0)
  69. signal.setitimer(signal.ITIMER_REAL, dur)
  70. else:
  71. print 'Unknown cmd', pkt.cmd