Last active
April 22, 2016 14:21
-
-
Save abhigenie92/5ef6ac6f535a8c70509ff6de3e3da05b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from twisted.internet.protocol import ClientFactory | |
import pdb,json | |
from twisted.protocols.basic import NetstringReceiver | |
from twisted.internet.defer import inlineCallbacks | |
from twisted.internet.threads import deferToThread | |
from Queue import Queue | |
# audio imports | |
import pyaudio,wave,threading | |
class AudioClient(NetstringReceiver): | |
#audio parameters | |
CHUNK = 1024 | |
FORMAT = pyaudio.paInt16 | |
CHANNELS = 1 | |
## initialisation | |
def __init__(self,factory,canvas_obj): | |
'''initiates with factory and canvas object | |
Reasons: | |
factory: | |
canvas object: | |
''' | |
self.factory = factory | |
self.canvas_obj=canvas_obj | |
def connectionMade(self): | |
'''sends the username of the client to register the protocol at remore server with corresponding | |
address''' | |
print "Connected to audio remote server" | |
self.sendString(json.dumps({'username':self.factory.username})) | |
# start recording and sending audio | |
if self.factory.canvas_obj.allow_all or self.factory.canvas_obj.client_state=='server' \ | |
or self.factory.canvas_obj.client_audio_send: | |
self.start_audio_stream() | |
# start receiving and playing audio | |
self.receive_audio_stream() | |
## record and send | |
def start_audio_stream(self): | |
'''creates an audio stream for sending data | |
A callback is defined on send_audio_data() to send the stream | |
''' | |
# create PyAudio Object | |
self.send_stream_Pyobj=pyaudio.PyAudio() | |
self.send_rate=int(self.send_stream_Pyobj.get_device_info_by_index(0)['defaultSampleRate']/4) | |
# create stream | |
self.send_stream=self.send_stream_Pyobj.open(format=self.FORMAT,channels=self.CHANNELS, | |
rate=self.send_rate,input=True,frames_per_buffer=self.CHUNK,output=False) | |
# start the stream | |
self.send_stream.start_stream() | |
self.send_audio_data_thread = threading.Thread(name='send_audio_data'\ | |
,target=self.send_audio_data) | |
self.send_audio_data_thread.daemon=True | |
self.send_audio_data_thread.start() | |
@inlineCallbacks | |
def send_audio_data(self): | |
'''sends the audio chunk to remote server as string''' | |
while True: | |
audio_data = yield self.send_stream.read(self.CHUNK) | |
self.sendString(audio_data) | |
## receive and play | |
def receive_audio_stream(self): | |
''' 1. creates an audio stream for receiving data | |
2. creates an audio queue | |
3. initiates a thread for playing the received audio | |
''' | |
# create PyAudio Object | |
self.receive_stream_Pyobj=pyaudio.PyAudio() | |
self.receive_rate=int(self.receive_stream_Pyobj.get_device_info_by_index(0)['defaultSampleRate']/4) | |
# create stream | |
self.stream_receive = self.receive_stream_Pyobj.open(format=self.FORMAT,channels=self.CHANNELS, | |
rate=self.receive_rate,output=True,input=False) | |
# start the receiving stream | |
self.stream_receive.start_stream() | |
# create a queue which gets filled in from data received | |
self.recv_audio_queue=DeferredQueue() # queue that stores the audio received | |
# create and start the thread for playing the received audio | |
self.play_audio_received_thread = threading.Thread(name='play_audio_received'\ | |
,target=self.play_audio_received) | |
self.play_audio_received_thread.daemon=True | |
self.play_audio_received_thread.start() | |
def stringReceived(self,data): | |
'''appends the audio string received to queue(recv_audio_queue) which is played by | |
play_audio_received thread''' | |
self.recv_audio_queue.put(data) | |
def play_audio_received(self): | |
while True: | |
data=self.recv_audio_queue.get() # get data from queue | |
self.stream_receive.write(data) | |
self.recv_audio_queue.task_done() | |
## close streams, terminate pyaudio objects and stop threads | |
def connectionLost(self, reason): | |
# close send audio if exists | |
try: | |
self.send_stream.stop_stream() | |
self.send_stream.close() | |
self.send_stream_Pyobj.terminate() | |
except: | |
print "Send audio stream and object doesn't exist" | |
# close receive audio stream and thread | |
try: | |
self.stream_receive.stop_stream() | |
self.stream_receive.close() | |
self.receive_stream_Pyobj.terminate() | |
self.play_audio_received_thread.stopped=True | |
except: | |
print "Receive audio stream and object doesn't exist" | |
class AudioClientFactory(ClientFactory): | |
def __init__(self, canvas_obj,username): | |
self.canvas_obj = canvas_obj | |
self.username=username | |
def buildProtocol(self, addr): | |
self.protocol=AudioClient(self,self.canvas_obj) | |
return self.protocol | |
if __name__ == '__main__': | |
from twisted.internet import reactor | |
reactor.connectTCP("127.0.0.1",3036,AudioClientFactory('junkcanvas_obj','something')) | |
reactor.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment