forked from Tecnologias-multimedia/InterCom
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintercom_buffer.py
More file actions
76 lines (63 loc) · 3.1 KB
/
intercom_buffer.py
File metadata and controls
76 lines (63 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# Adding a buffer.
#
# The buffer allows to reorder the chunks if they are not transmitted
# in order by the network.
import sounddevice as sd
import numpy as np
import struct
from intercom import Intercom
if __debug__:
import sys
class Intercom_buffer(Intercom):
MAX_CHUNK_NUMBER = 65536
def init(self, args):
Intercom.init(self, args)
self.chunks_to_buffer = args.chunks_to_buffer
self.cells_in_buffer = self.chunks_to_buffer * 2
#self._buffer = [self.generate_zero_chunk()] * self.cells_in_buffer
self._buffer = [None] * self.cells_in_buffer
for i in range(self.cells_in_buffer):
self._buffer[i] = self.generate_zero_chunk()
self.packet_format = f"!H{self.samples_per_chunk}h"
if __debug__:
print(f"chunks_to_buffer={self.chunks_to_buffer}")
def receive_and_buffer(self):
message, source_address = self.receiving_sock.recvfrom(Intercom.MAX_MESSAGE_SIZE)
chunk_number, *chunk = struct.unpack(self.packet_format, message)
self._buffer[chunk_number % self.cells_in_buffer] = np.asarray(chunk).reshape(self.frames_per_chunk, self.number_of_channels)
return chunk_number
def send(self, indata):
message = struct.pack(self.packet_format, self.recorded_chunk_number, *(indata.flatten()))
self.recorded_chunk_number = (self.recorded_chunk_number + 1) % self.MAX_CHUNK_NUMBER
self.sending_sock.sendto(message, (self.destination_IP_addr, self.destination_port))
def feedback(self):
sys.stderr.write("."); sys.stderr.flush()
def play(self, outdata):
chunk = self._buffer[self.played_chunk_number % self.cells_in_buffer]
self._buffer[self.played_chunk_number % self.cells_in_buffer] = self.generate_zero_chunk()
self.played_chunk_number = (self.played_chunk_number + 1) % self.cells_in_buffer
outdata[:] = chunk
if __debug__:
self.feedback()
def record_send_and_play(self, indata, outdata, frames, time, status): # The recording is performed by sounddevice
self.send(indata)
self.play(outdata)
def run(self):
self.recorded_chunk_number = 0
self.played_chunk_number = 0
with sd.Stream(samplerate=self.frames_per_second, blocksize=self.frames_per_chunk, dtype=np.int16, channels=self.number_of_channels, callback=self.record_send_and_play):
print("-=- Press CTRL + c to quit -=-")
first_received_chunk_number = self.receive_and_buffer()
self.played_chunk_number = (first_received_chunk_number - self.chunks_to_buffer) % self.cells_in_buffer
while True:
self.receive_and_buffer()
def add_args(self):
parser = Intercom.add_args(self)
parser.add_argument("-cb", "--chunks_to_buffer", help="Number of chunks to buffer", type=int, default=32)
return parser
if __name__ == "__main__":
intercom = Intercom_buffer()
parser = intercom.add_args()
args = parser.parse_args()
intercom.init(args)
intercom.run()