client.py 2.0 KB

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