def test_alaw2lin(self): encoded = b"\x00\x03\x24\x2a\x51\x54\x55\x58\x6b\x71\x7f" b"\x80\x83\xa4\xaa\xd1\xd4\xd5\xd8\xeb\xf1\xff" src = [ -688, -720, -2240, -4032, -9, -3, -1, -27, -244, -82, -106, 688, 720, 2240, 4032, 9, 3, 1, 27, 244, 82, 106, ] for w in 1, 2, 4: self.assertEqual(audioop.alaw2lin(encoded, w), packs[w](*(x << (w * 8) >> 13 for x in src))) encoded = bytes(range(256)) for w in 2, 4: decoded = audioop.alaw2lin(encoded, w) self.assertEqual(audioop.lin2alaw(decoded, w), encoded)
def test_alaw2lin(self): encoded = b'\x00\x03\x24\x2a\x51\x54\x55\x58\x6b\x71\x7f'\ b'\x80\x83\xa4\xaa\xd1\xd4\xd5\xd8\xeb\xf1\xff' src = [-688, -720, -2240, -4032, -9, -3, -1, -27, -244, -82, -106, 688, 720, 2240, 4032, 9, 3, 1, 27, 244, 82, 106] for w in 1, 2, 4: self.assertEqual(audioop.alaw2lin(encoded, w), packs[w](*(x << (w * 8) >> 13 for x in src))) encoded = ''.join(chr(x) for x in xrange(256)) for w in 2, 4: decoded = audioop.alaw2lin(encoded, w) self.assertEqual(audioop.lin2alaw(decoded, w), encoded)
def test_alaw2lin(self): # Cursory d = audioop.lin2alaw(data[0], 1) self.assertEqual(audioop.alaw2lin(d, 1), data[0]) if endian == 'big': self.assertEqual(audioop.alaw2lin(d, 2), b'\x00\x08\x01\x08\x02\x10') self.assertEqual(audioop.alaw2lin(d, 4), b'\x00\x08\x00\x00\x01\x08\x00\x00\x02\x10\x00\x00') else: self.assertEqual(audioop.alaw2lin(d, 2), b'\x08\x00\x08\x01\x10\x02') self.assertEqual(audioop.alaw2lin(d, 4), b'\x00\x00\x08\x00\x00\x00\x08\x01\x00\x00\x10\x02')
def bytes_to_channels(fmtChunk: FmtChunk, raw_samples: bytes, size) -> list: if int(fmtChunk.data.bits_per_sample / 8) > 0: sample_len = int(fmtChunk.data.bits_per_sample / 8) else: sample_len = 0 samples = [] if sample_len > 0: for i in range(int(size / sample_len)): sample = raw_samples[i * sample_len:i * sample_len + sample_len] if fmtChunk.data.audio_format == 1: if sample_len == 1: converted_sample = int.from_bytes( sample, byteorder="little", signed=False) else: converted_sample = int.from_bytes( sample, byteorder="little", signed=True) elif fmtChunk.data.audio_format == 3: if sample_len == 4: converted_sample = struct.unpack("f", sample)[0] else: converted_sample = struct.unpack("d", sample)[0] elif fmtChunk.data.audio_format == 6: converted_sample = int.from_bytes(audioop.alaw2lin( sample, sample_len), byteorder="little", signed=True) elif fmtChunk.data.audio_format == 7: converted_sample = int.from_bytes(audioop.ulaw2lin( sample, sample_len), byteorder="little", signed=True) else: print( "Format zapisu danych w pliku nie jest wspierany") raise Exception samples.append(converted_sample) else: if fmtChunk.data.audio_format == 2: ret = audioop.adpcm2lin(raw_samples, fmtChunk.data.bits_per_sample, None) samples_lin = ret[0] for i in range(int(len(samples_lin) / 8)): sample = samples_lin[i * 8:i * 8 + 8] converted_sample = int.from_bytes(sample, byteorder="little", signed=True) samples.append(converted_sample) else: print("Format zapisu danych w pliku nie jest wspierany") raise Exception channels = [] for c in range(fmtChunk.data.num_channels): channels.append(samples[c::fmtChunk.data.num_channels]) return channels
def compress(self): read = wave.open(self.create_wave(), 'rb') string_wav = np.fromstring(read.readframes(-1), 'Int16') if (self.compression_mod == "a-LAW"): compressed_string = audioop.lin2alaw(string_wav, read.getsampwidth()) compressed_string = audioop.alaw2lin(compressed_string, read.getsampwidth()) self.working_signal = np.frombuffer(compressed_string, dtype='Int16') if (self.compression_mod == "u-LAW"): compressed_string = audioop.lin2ulaw(string_wav, read.getsampwidth()) compressed_string = audioop.ulaw2lin(compressed_string, read.getsampwidth()) self.working_signal = np.frombuffer(compressed_string, dtype='Int16') if (self.compression_mod == "ADPCM"): compressed_string = audioop.lin2adpcm(string_wav, read.getsampwidth(), None) compressed_string = audioop.adpcm2lin(compressed_string[0], read.getsampwidth(), None) self.working_signal = np.frombuffer(compressed_string[0], dtype='Int16')
def decode(self, encoded_frame): return [ AudioFrame(channels=1, data=audioop.alaw2lin(encoded_frame.data, 2), sample_rate=8000, timestamp=encoded_frame.timestamp) ]
def _inout(self, linear, stream_time, userdata): # logger.debug('audio capture %d', len(linear)) self._ts += 160 if self.media and (self.media.hasYourFormat(self._pcmu) or self.media.hasYourFormat(self._pcma)): linear8, self._resample1 = audiospeex.resample( linear, input_rate=44100, output_rate=8000, state=self._resample1 ) if self.media.hasYourFormat(self._pcmu): fmt, payload = self._pcmu, audioop.lin2ulaw(linear8, 2) elif self.media.hasYourFormat(self._pcma): fmt, payload = self._pcma, audioop.lin2alaw(linear8, 2) self.media.send(payload=payload, ts=self._ts, marker=False, fmt=fmt) if self._queue: fmt, packet = self._queue.pop(0) linear8 = None if str(fmt.name).lower() == "pcmu" and fmt.rate == 8000 or fmt.pt == 0: linear8 = audioop.ulaw2lin(packet.payload, 2) elif str(fmt.name).lower() == "pcma" and fmt.rate == 8000 or fmt.pt == 8: linear8 = audioop.alaw2lin(packet.payload, 2) if linear8: linear, self._resample2 = audiospeex.resample( linear8, input_rate=8000, output_rate=44100, state=self._resample2 ) # logger.debug('audio play %d', len(linear)) return linear return ""
def _inout(self, linear, stream_time, userdata): # logger.debug('audio capture %d', len(linear)) self._ts += 160 if self.media and (self.media.hasYourFormat(self._pcmu) or self.media.hasYourFormat(self._pcma)): if self._outqueue: # logger.debug('sending packet from out queue, not mic') linear8 = self._outqueue.pop(0) else: linear8, self._resample1 = audiospeex.resample(linear, input_rate=self.sample_rate, output_rate=8000, state=self._resample1) if self.media.hasYourFormat(self._pcmu): fmt, payload = self._pcmu, audioop.lin2ulaw(linear8, 2) elif self.media.hasYourFormat(self._pcma): fmt, payload = self._pcma, audioop.lin2alaw(linear8, 2) self.media.send(payload=payload, ts=self._ts, marker=False, fmt=fmt) if self._queue: fmt, packet = self._queue.pop(0) linear8 = None if str(fmt.name).lower() == 'pcmu' and fmt.rate == 8000 or fmt.pt == 0: linear8 = audioop.ulaw2lin(packet.payload, 2) elif str(fmt.name).lower() == 'pcma' and fmt.rate == 8000 or fmt.pt == 8: linear8 = audioop.alaw2lin(packet.payload, 2) if linear8: self._record.write(linear8) if self._thqueue is not None: self._thqueue.put(linear8) linear, self._resample2 = audiospeex.resample(linear8, input_rate=8000, output_rate=self.sample_rate, state=self._resample2) # logger.debug('audio play %d', len(linear)) return linear return ''
def test_a_law_companding(self): quantization_channels = 256 compression_param = 83.7 waveform = self.waveform.clone() if not waveform.is_floating_point(): waveform = waveform.to(torch.get_default_dtype()) waveform /= torch.abs(waveform).max() self.assertTrue(waveform.min() >= -1. and waveform.max() <= 1.) waveform_a = transforms.ALawEncoding(quantization_channels, compression_param)(waveform) self.assertTrue(waveform_a.min() >= 0. and waveform_a.max() <= quantization_channels) waveform_exp = transforms.ALawDecoding(quantization_channels, compression_param)(waveform_a) self.assertTrue(waveform_exp.min() >= -1. and waveform_exp.max() <= 1.) segment_length = 1 small_int_waveform = waveform.to(torch.uint8) waveform_bytes = bytearray(small_int_waveform[0, :]) encoded = audioop.lin2alaw(waveform_bytes, segment_length) torch_encoded = transforms.ALawEncoding(quantization_channels, compression_param)(small_int_waveform) self.assertEqual(torch.tensor(list(encoded)), torch_encoded[0]) decoded = audioop.alaw2lin(encoded, segment_length) torch_decoded = transforms.ALawDecoding(quantization_channels, compression_param)(torch_encoded) self.assertEqual(torch.tensor(list(decoded)), torch_decoded[0])
def decode(self, payload): assert isinstance(payload, bytes), "payload is not an instance of bytes" if len(payload) != 160: log.msg("alaw: short read on decode, %d != 160" % len(payload), system="codec") return audioop.alaw2lin(payload, 2)
def test_alaw2lin(self): encoded = ( b'\x00\x03$*QTUXkq\x7f\x80\x83\xa4\xaa\xd1\xd4\xd5\xd8\xeb\xf1\xff' ) src = [ -688, -720, -2240, -4032, -9, -3, -1, -27, -244, -82, -106, 688, 720, 2240, 4032, 9, 3, 1, 27, 244, 82, 106 ] for w in (1, 2, 3, 4): decoded = packs[w](*(x << w * 8 >> 13 for x in src)) self.assertEqual(audioop.alaw2lin(encoded, w), decoded) self.assertEqual(audioop.alaw2lin(bytearray(encoded), w), decoded) self.assertEqual(audioop.alaw2lin(memoryview(encoded), w), decoded) encoded = bytes(range(256)) for w in (2, 3, 4): decoded = audioop.alaw2lin(encoded, w) self.assertEqual(audioop.lin2alaw(decoded, w), encoded)
def testalaw2lin(data): if verbose: print 'alaw2lin' # Cursory d = audioop.lin2alaw(data[0], 1) if audioop.alaw2lin(d, 1) != data[0]: return 0 return 1
def decode(self, encoded_frame): frame = AudioFrame( channels=1, data=audioop.alaw2lin(encoded_frame.data, 2), sample_rate=SAMPLE_RATE) frame.pts = encoded_frame.timestamp frame.time_base = TIME_BASE return [frame]
def messageHandler(conn): # this is to deal with a single incoming TCP or UDP message global fifo, previous, missed, state # the actual packet length will not be 2048 bytes, but depends on the format and number of audio samples buf = sock.recv(2048) if len(buf) < 12: return # see https://en.wikipedia.org/wiki/RTP_payload_formats (version, type, counter, timestamp, id) = struct.unpack('BBHII', buf[0:12]) if version != 128: raise RuntimeError('unsupported packet version') fragment = bytearray(buf[12:]) with fifolock: if not id in fifo: fifo[id] = RingBuffer( id, rate) # make a buffer that can hold one second of audio previous[id] = None state[id] = None missed[id] = 0 if type == 0: # type=0 PCMU audio 1 8000 any 20 ITU-T G.711 PCM μ-Law audio 64 kbit/s RFC 3551 fragment = audioop.ulaw2lin(fragment, 2) fragment, state[id] = audioop.ratecv(fragment, 2, 1, 8000, 44100, state[id]) dat = np.frombuffer(fragment, np.int16) elif type == 1: # type=8 PCMA audio 1 8000 any 20 ITU-T G.711 PCM A-Law audio 64 kbit/s RFC 3551 fragment = audioop.alaw2lin(fragment, 2) fragment, state[id] = audioop.ratecv(fragment, 2, 1, 8000, 44100, state[id]) dat = np.frombuffer(fragment, np.int16) elif type == 11: # type=11 L16 audio 1 44100 any 20 Linear PCM 16-bit audio 705.6 kbit/s, uncompressed RFC 3551, Page 27 dat = np.frombuffer(fragment, np.int16) else: raise RuntimeError('unsupported RTP packet type') if not previous[id] == None: for missing in range(previous[id] + 1 - counter, 0): logger.debug('missed packet from %d' % (id)) # See https://en.wikipedia.org/wiki/Comfort_noise missing_dat = np.random.random( len(dat)) # FIXME these are only positive missing_dat *= np.linalg.norm(dat) / np.linalg.norm( missing_dat) missing_timestamp = timestamp + missing * len( dat) * 1000 / 44100 missed[id] += 1 fifo[id].push(missing_dat.astype(np.int16), missing_timestamp) previous[id] = counter fifo[id].push(dat, timestamp)
def saveFile(self, fichWAV): self.save = False resp = "".join(self.liSave) tx = audioop.lin2alaw(resp, 2) frames = audioop.alaw2lin(tx, 2) wf = wave.open(fichWAV, "wb") wf.setnchannels(1) wf.setsampwidth(self.samplewith) wf.setframerate(16000) wf.writeframes(frames) wf.close()
def micFinal(self): self.stream.stop_stream() self.stream.close() self.p.terminate() resp = "".join(self.datos) tx = audioop.lin2alaw(resp, 2) frames = audioop.alaw2lin(tx, 2) io = StringIO.StringIO() wf = wave.open(io, 'wb') wf.setnchannels(self.CHANNELS) wf.setsampwidth(self.p.get_sample_size(self.FORMAT)) wf.setframerate(self.RATE) wf.writeframes(frames) self.wav = io.getvalue() wf.close() self.centesimas = len(self.datos) * self.CHUNK * 100 / self.RATE
def micFinal(self): self.stream.stop_stream() self.stream.close() self.p.terminate() resp = b"".join(self.datos) tx = audioop.lin2alaw(resp, 2) frames = audioop.alaw2lin(tx, 2) io = BytesIO() wf = wave.open(io, "wb") wf.setnchannels(self.CHANNELS) wf.setsampwidth(self.p.get_sample_size(self.FORMAT)) wf.setframerate(self.RATE) wf.writeframes(frames) self.wav = io.getvalue() wf.close() self.centesimas = len(self.datos) * self.CHUNK * 100 / self.RATE
def _read_stream(stream): try: data = stream.read(65535) data = bytearray(data) # skip ip header (4x val of ihl field in ip hdr, plus 8 byte udp hdr) ihl = int(data[0]) & 0x0f data = data[(4 * ihl) + 8:] v = data[0] >> 6 if v == 2: cc = (data[0]) & 0x0f pt = data[1] & 0x7f print "v=" + str(v) + ", pt=" + str(pt) data = data[12:] # skip over fixed hdr len if cc > 0: data = data[cc * 4:] # TODO: what about profile specific extensions? idx = stream.fileno() file_name = "/tmp/out-" + str(idx) + ".wav" if idx not in wav_files: wav = wave.open(file_name, "wb") wav.setparams((1, 2, 8000, 0, 'NONE', 'NONE')) wav_files[idx] = wav t = Thread(target=_recognize, args=(file_name, idx)) t.daemon = True t.start() wav = wav_files[idx] strdata = "".join(map(chr, data)) pcm = audioop.alaw2lin(strdata, 2) wav.writeframes(pcm) # else: # not an rtp packet except IOError: pass
def VoiceStream(self): udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp.bind(('', 60006)) silence = chr(0) * 2 while self.keepThreadRunning: try: udpData, addr = udp.recvfrom(self.CHUNK+8) #print("Recibiendo datos de: ",addr) if(self.IPAddr != addr[0]): soundData = audioop.alaw2lin(udpData[8:], 2) #audio a reproducir decodificado if(self.stoDict.get(addr)== None): self.addToStoDict(addr) sto = self.stoDict.get(addr) sto.write(soundData, self.CHUNK) free = sto.get_write_available() # Esto es por si viene audio vacio if free > self.CHUNK: # Is there a lot of space in the buffer? tofill = free - self.CHUNK sto.write(silence * tofill) # Fill it with silence except Exception : traceback.print_exc()
def _alaw2lin(self, data): import audioop return audioop.alaw2lin(data, 2)
def test_alaw2lin(self): # Cursory d = audioop.lin2alaw(data[0], 1) self.assertEqual(audioop.alaw2lin(d, 1), data[0])
def decode(self, bytes): if len(bytes) != 160: log.msg("alaw: short read on decode, %d != 160"%len(bytes), system="codec") return audioop.alaw2lin(bytes, 2)
"Все ищут во мне тайну. А во мне нет тайны, во мне все просто и ясно. Никаких тайн. Я привык с жизнью " "встречаться прямо. Не отличая большого от малого."), audio_config=tts_pb2.AudioConfig( audio_encoding=tts_pb2.ALAW, sample_rate_hertz=sample_rate, ), ) pyaudio_lib = pyaudio.PyAudio() f = pyaudio_lib.open(output=True, channels=1, format=pyaudio.paInt16, rate=sample_rate) stub = tts_pb2_grpc.TextToSpeechStub( grpc.secure_channel(endpoint, grpc.ssl_channel_credentials())) request = build_request() metadata = authorization_metadata(api_key, secret_key, "tinkoff.cloud.tts") responses = stub.StreamingSynthesize(request, metadata=metadata) for key, value in responses.initial_metadata(): if key == "x-audio-duration-seconds": print("Estimated audio duration is {:.2f} seconds".format( float(value))) break for stream_response in responses: pcm_chunk = audioop.alaw2lin(stream_response.audio_chunk, 2) f.write(pcm_chunk) f.stop_stream() f.close()
def parsePCMA(self, packet): data = audioop.alaw2lin(packet.payload, 1) data = audioop.bias(data, 1, 128) self.pmin.write(packet.timestamp, data)
start = time.time() while True: if time.time() - send_t > 1: s.sendto(b'', ('255.255.255.255', 18294)) send_t = time.time() try: m = s.recvfrom(1024) except timeout: m = None if m and len(m[0]) > 0: t = time.time() print '%0.3f' % (t - start), m[1], len(m[0]) s.sendto(sine_packet, m[1]) start = t m = audioop.alaw2lin(m[0][8:], 2) for i in range(len(m) / 2): sample = audioop.getsample(m, 2, i) outfile.write('%6d\n' % sample) if not stream_started: stream.start() stream.write(m) outfile2.write(m)
def decode(self, data): return AudioFrame(channels=1, data=audioop.alaw2lin(data, 2), sample_rate=8000)
def recThreaded(info): cmd = info[0] filepath = info[3] filename = '' info.append(filename) writer = None datetimenow = datetime.datetime.now() if (cmd["dir"] == 'out'): filename = (cmd["dir"] + '_' + cmd["local_number"] + '_' + cmd["remote_number"] + '_' + cmd["device"] + '_' + datetimenow.strftime('%Y-%m-%d_%H_%M_%S') + '.wav') else: filename = (cmd["dir"] + '_' + cmd["remote_number"] + '_' + cmd["local_number"] + '_' + cmd["device"] + '_' + datetimenow.strftime('%Y-%m-%d_%H_%M_%S') + '.wav') info[4] = filename if (platform.system() == 'Windows'): filepath = filepath + '\\' + datetimenow.strftime('%Y-%m-%d') if (not os.path.exists(filepath)): os.makedirs(filepath) info[3] = filepath filepath = filepath + '\\' + filename else: filepath = filepath + '/' + datetimenow.strftime('%Y-%m-%d') if (not os.path.exists(filepath)): os.makedirs(filepath) info[3] = filepath filepath = filepath + '/' + filename info.append(filepath) codec = cmd["codec"].lower() if (codec == 'pcmu' or codec == 'pcma'): writer = wave.open(filepath, 'wb') writer.setparams((1, 2, 8000, 8000 * 1, 'NONE', 'not compressed')) else: ecodec = 'pcm_s16le' if (sys.byteorder == 'big'): ecodec = 'pcm_s16be' # ar = None if (codec == 'g723'): codec = codec + '_1' elif ('g726' in codec): if (sys.byteorder == 'little'): codec = 'g726le' else: codec = 'g726' #-nostats -loglevel 0 # , '-nostats' # , '-loglevel', '0' command = [ 'ffmpeg', '-f', codec, '-ac', '1', '-i', '-', '-ar', '8k', '-ac', '1', '-acodec', ecodec, filepath ] writer = sb.Popen(command, stdin=sb.PIPE) while not info[1]: ''' data = info[2].recv(1024) # print(str(len(data))) if (cmd["codec"] == 'PCMU'): # f.write(data[12:]) writer.writeframes(audioop.ulaw2lin(data[12:], 2)) elif (cmd["codec"] == 'PCMA'): # f.write(data[12:]) writer.writeframes(audioop.alaw2lin(data[12:], 2)) elif (cmd["codec"] == 'G722'): writer.stdin.write(data[12:]) else: writer.stdin.write(data[12:]) ''' try: data = info[2].recv(1024) if (len(data) < 1): break if (codec == 'pcmu'): writer.writeframes(audioop.ulaw2lin(data[12:], 2)) elif (codec == 'pcma'): writer.writeframes(audioop.alaw2lin(data[12:], 2)) else: # G722, G723, G726-32 writer.stdin.write(data[12:]) except OSError as e: print('UDP socket status: ' + e.strerror) if (e.errno == 10038): print('Check writer status: ' + str(writer is None)) try: writer.stdin.close() writer.wait() except: if (writer is not None): writer.close() print("UDP terminated: {0} / {1}".format(e.errno, e.strerror)) print("UDP terminated normally.") break else: print("recThreaded errno: {0} / {1}".format( e.errno, e.strerror)) continue try: writer.stdin.close() writer.wait() except: if (writer is not None): writer.close() if (info[2] is not None): info[2].close() print("Recorder Thread Terminated..." + str(info[0]))
def a_law_compress(np_array, sample_width): compressed = audioop.lin2alaw(np_array, sample_width) return np.frombuffer(audioop.alaw2lin(compressed, sample_width), dtype=np.int16)
def recThreaded(info): cmd = info[0] sock = info[2] filepath = info[3] filename = '' writer = None datetimenow = datetime.datetime.now() if (cmd["dir"] == 'out'): filename = (cmd["dir"] + '_' + cmd["local_number"] + '_' + cmd["remote_number"] + '_' + cmd["device"] + '_' + datetimenow.strftime('%Y-%m-%d_%H_%M_%S') + '.wav') else: filename = (cmd["dir"] + '_' + cmd["remote_number"] + '_' + cmd["local_number"] + '_' + cmd["device"] + '_' + datetimenow.strftime('%Y-%m-%d_%H_%M_%S') + '.wav') if (platform.system() == 'Windows'): filepath = filepath + '\\' + datetimenow.strftime('%Y-%m-%d') if (not os.path.exists(filepath)): os.makedirs(filepath) filepath = filepath + '\\' + filename else: filepath = filepath + '/' + datetimenow.strftime('%Y-%m-%d') if (not os.path.exists(filepath)): os.makedirs(filepath) filepath = filepath + '/' + filename if (cmd["codec"] == 'PCMU' or cmd["codec"] == 'PCMA'): # f = open(filepath, 'wb') writer = wave.open(filepath, 'wb') writer.setparams((1, 2, 8000, 8000 * 1, 'NONE', 'not compressed')) else: codec = cmd["codec"].lower() ar = None if (codec == 'g723'): codec = codec + '_1' elif ('g726' in codec): if (sys.byteorder == 'little'): codec = 'g726le' else: codec = 'g726' # command = ['ffmpeg' # , '-f', codec # , '-ar', '6k' # , '-ac', '1' # , '-i', '-' # , '-ar', '8k' # , '-ac', '1' # , '-acodec' # , 'pcm_s16le' # , filepath] # writer = sb.Popen(command, stdin=sb.PIPE) writer = wave.open(filepath, 'wb') writer.setparams((1, 2, 8000, 8000 * 1, 'NONE', 'not compressed')) ff = FFmpeg(inputs={'pipe:0': 'f=g722 ac=1'}, outputs={'pipe:1': 'ar=8k ac=1 acodec=pcm_s16le'}) print(str(ff)) while not info[1]: try: data = sock.recv(1024) # print(str(len(data))) if (cmd["codec"] == 'PCMU'): # f.write(data[12:]) writer.writeframes(audioop.ulaw2lin(data[12:], 2)) elif (cmd["codec"] == 'PCMA'): # f.write(data[12:]) writer.writeframes(audioop.alaw2lin(data[12:], 2)) elif (cmd["codec"].lower() == 'g722'): # writer.stdin.write(data[12:]) stdout, stderr = ff.run(input_data=data[12:], stdout=sb.PIPE) writer.writeframes(stdout, 2) print('CODEC2: ' + cmd["codec"]) else: # writer.stdin.write(data[12:]) continue except OSError as e: if (e.errno == 10038): # if (f is not None): # f.close() if (writer is not None): try: # if (writer.stdin is not None): # writer.stdin.close() # writer.wait() pass except: writer.close() print("UDP terminated: {0} / {1}".format(e.errno, e.strerror)) print("UDP terminated normally.") break else: print("recThreaded errno: {0} / {1}".format( e.errno, e.strerror)) continue # if (f is not None): # f.close() if (writer is not None): try: # if (writer.stdin is not None): # writer.stdin.close() # writer.wait() pass except: writer.close() if (sock is not None): sock.close() print("Recorder Thread Terminated..." + str(info[0]))
def pcap2wav(param_sip_file, param_rtp_file, param_out_file): file_sip = gzip.open(param_sip_file, 'rb') pcap = dpkt.pcap.Reader(file_sip) sip_sessions = {} for ts, buf in pcap: eth = dpkt.ethernet.Ethernet(buf) ip = eth.data if ip.p == socket.IPPROTO_UDP: if ip.udp.dport == 5060: sip_msg = SipMessage(ip.udp.data.decode('utf-8'), src_ip=ipaddress.ip_address(ip.src), dst_ip=ipaddress.ip_address(ip.dst), timestamp=ts) if 'Call-ID' in sip_msg.headers: callid = sip_msg.headers['Call-ID'] if callid not in sip_sessions: sip_sessions[callid] = SipSession(callid) sip_sessions[callid].AddMessage(sip_msg) else: print('SIP message without call-id!') file_sip.close() print('SIP sessions found:') for session in sip_sessions: print( session, str(sip_sessions[session].initiator_ip) + '->' + str(sip_sessions[session].target_ip)) print(' RTP Streams:') if len(sip_sessions[session].sdp) != 2: print('Error: more or less than 2 RTP streams per channel!') # exit() for sdp_request_index in sip_sessions[session].sdp: print( ' ', sip_sessions[session].requests[sdp_request_index].source_ip, ':', sip_sessions[session].requests[sdp_request_index]. sdp_data.media_descriptions['audio'].port) jb_size_ms = 100 # jitterbuffer in ms wav_file = wave.open(param_out_file, 'wb') sample_rate_ms = 8 sample_width = 2 wav_file.setsampwidth(sample_width) wav_file.setnchannels(1) wav_file.setframerate(sample_rate_ms * 1000) # jb double size # Первый джиттербуффер находится в нулевой точке # второй - в jb_samples точке jb_samples = int(sample_rate_ms * jb_size_ms) jb = bytearray(jb_samples * 2) jb_cur = 0 jb_start = 0 jb_end = jb_start + jb_samples - 1 jb_first_sample = 0 # Первый RTP семпл first_packet_time = 0 unpack_ushort = struct.Struct('<h').unpack_from pack_ushort = struct.Struct('<h').pack_into for session_id in sip_sessions: session = sip_sessions[session_id] rtp_stream = {} rtp_ports = [] # Получаем список стримов ртп for sdp_index in session.sdp: rtp_ports.append(session.requests[sdp_index].sdp_data. media_descriptions['audio'].port) file_rtp = open(param_rtp_file, 'rb') pcap = dpkt.pcap.Reader(file_rtp) jb_start_ms = 0 packets_in_jb = 0 jb_skipped_samples = 0 seqno = 0 for abs_ts, buf in pcap: seqno += 1 ts = int(abs_ts * 1000 - first_packet_time) # Время прибытия первого пакета в разговор if first_packet_time == 0: print("First packet time: ", abs_ts) first_packet_time = abs_ts * 1000 ts = 0 jb_start_ms = ts out_buffer = bytes(jb_samples * 2) # Восстанавливаем естественное течение времени. # Очередной пакет - нам нужно понять, что делать # Есть три варианта # jb_start_ms =< ts < jb_start_ms + jb_size_ms # 1 - пакет не попадает в наш джиттербуфер (пришел раньше, чем начало JB). Его придётся дропнуть. # Этого не должно произойти, т.к. все пакеты сохранены в порядке прибытия if ts < jb_start_ms: print("Packet time:", ts, " Jitterbuffer range:", jb_start_ms, jb_start_ms + jb_size_ms * 2, ': Skipped.') continue # 2 - пакет не попадает в наш джиттербуфер (пришел позже, чем конец JB). Тогда нужно флашить джиттербуфер до тех пор, пока мы не сможем этот пакет принять while ts >= jb_start_ms + jb_size_ms * 2: # flush_jb() jb_result = bytearray(jb_samples * sample_width) for flush_ssrc in rtp_stream: out_buf = audioop.alaw2lin( rtp_stream[flush_ssrc].jb[0:jb_samples], 2) jb_result = audioop.add(jb_result, out_buf, 2) # Перемещаем данные из джиттербуфера в начало rtp_stream[flush_ssrc].jb[0:jb_samples] = rtp_stream[ flush_ssrc].jb[jb_samples:jb_samples * 2] rtp_stream[flush_ssrc].jb[jb_samples:jb_samples * 2] = bytearray(jb_samples) wav_file.writeframes(jb_result) # print ("JB Flushed at ",jb_start_ms,'-',jb_start_ms+jb_size_ms,'ts=',ts,'packets=',packets_in_jb, 'seqno=',seqno) packets_in_jb = 0 jb_start_ms += jb_size_ms # 3 - пакет попадает в наш джиттербуфер, тогда его нужно туда добавить # Наполняем джиттербуферы информацией за последние jb_size_ms * 2 миллисекунд # Разбираем пакет на запчасти eth = dpkt.ethernet.Ethernet(buf) ip = eth.data if ip.p == socket.IPPROTO_UDP: if ip.udp.dport in rtp_ports: packets_in_jb += 1 rtp_data = dpkt.rtp.RTP(ip.udp.data) ssrc = rtp_data.ssrc if ssrc not in rtp_stream: rtp_stream[ssrc] = namedtuple('RtpStream', [ 'last_seqno', 'jb', 'first_rtp_timestamp', 'first_cap_timestamp', 'mix_start_sample' ]) rtp_stream[ssrc].last_seqno = 0 rtp_stream[ssrc].jb = bytearray( jb_samples) # *2 todo:fix! # Таймстемп из RTP rtp_stream[ssrc].first_rtp_timestamp = rtp_data.ts # Таймстемп из файла rtp_stream[ssrc].first_cap_timestamp = ts # Вычисляем номер стартового семпла в выходном потоке # Берем время фактического получения пакета, добавляем размер життербуфера и умножаем на количество семплов в секунде. # Если добавлять джиттербуфер ко всем потокам, то мы просто смещаем весь микс на ширину життербуфера. Поэтому его добавлять не будем. rtp_stream[ssrc].mix_start_sample = int( (ts) * sample_rate_ms) # Вычисляем номер семпла в выходном потоке, куда должен быть замикширован текущий семпл # todo: оно не учитывает различный битрейт! # Преобразуем таймстемп пакета # Таймстемп пакета представляет из себя номер семпла. Зная первый таймстемп out_file_sample_num = rtp_data.ts - rtp_stream[ ssrc].first_rtp_timestamp + rtp_stream[ ssrc].mix_start_sample # print( ts, jb_start_ms,jb_start_ms + jb_size_ms * 2, out_file_sample_num, out_file_sample_num/sample_rate_ms ) # Проверяем, попадает ли полученный нами пакет в нижнюю границу джиттербуфера if out_file_sample_num < (jb_start_ms) * sample_rate_ms: print("Error: RTP #", rtp_data.seq, 'timestamp lower than expected', ts, jb_start_ms, jb_start_ms + jb_size_ms * 2, out_file_sample_num / sample_rate_ms) rtp_stream[ssrc].mix_start_sample += len(rtp_data.data) continue # Проверяем, попадает ли полученный нами пакет в верхнюю границу джиттербуфера if out_file_sample_num >= (jb_start_ms + jb_size_ms * 2) * sample_rate_ms - len( rtp_data.data): # Если вдруг этот пакет переполняет джиттербуфер - делаем вид, что его не было. rtp_stream[ssrc].mix_start_sample -= len(rtp_data.data) print("Clock drift: RTP ", ssrc, "#", rtp_data.seq, 'timestamp higher than expected ', ts, jb_start_ms, jb_start_ms + jb_size_ms * 2, out_file_sample_num / sample_rate_ms, (jb_start_ms + jb_size_ms * 2) * sample_rate_ms - out_file_sample_num) continue # Фигачим семпл в джиттербуфер rtp_stream[ssrc].jb[out_file_sample_num - jb_start_ms * sample_rate_ms:out_file_sample_num - jb_start_ms * sample_rate_ms + len(rtp_data.data)] = rtp_data.data file_rtp.close()
def decode(self, bytes): if len(bytes) != 160: log.msg("alaw: short read on decode, %d != 160" % len(bytes), system="codec") return audioop.alaw2lin(bytes, 2)
def _alaw2lin(self, data): with warnings.catch_warnings(): warnings.simplefilter('ignore', category=DeprecationWarning) import audioop return audioop.alaw2lin(data, 2)
def _convert(data: bytes, width: int) -> bytes: return audioop.alaw2lin(data, width)