feat: fix CallerID dinamico su PBX e aggiunto AGC audio bidirezionale
This commit is contained in:
@@ -199,7 +199,6 @@ class SessionManager:
|
||||
sess = self.sessioni[call_id]
|
||||
if sess.ptt_attivo and self.openbridge:
|
||||
self.openbridge.chiudi_flusso_chiamata(sess)
|
||||
# Rilascia la porta del pool associata a questa chiamata
|
||||
self.vocoder.rilascia_porta(f"SIP_{call_id}")
|
||||
del self.sessioni[call_id]
|
||||
|
||||
@@ -245,8 +244,8 @@ class SessionManager:
|
||||
f"Max-Forwards: 70\r\nFrom: {sess.dialog_from}\r\nTo: {sess.dialog_to}\r\n"
|
||||
f"Call-ID: {sess.call_id}\r\nCSeq: {sess.local_cseq} INVITE\r\n"
|
||||
f"Contact: <sip:gateway@127.0.0.1:{SIP_PORT}>\r\n"
|
||||
f"Remote-Party-ID: \"{testo_display}\" <sip:000@127.0.0.1>;party=called;screen=yes;privacy=off\r\n"
|
||||
f"P-Asserted-Identity: \"{testo_display}\" <sip:000@127.0.0.1>\r\n"
|
||||
f"Remote-Party-ID: \"{testo_display}\" <sip:{sess.tg_destinazione}@{sess.ip_vps}>;party=called;screen=yes;privacy=off\r\n"
|
||||
f"P-Asserted-Identity: \"{testo_display}\" <sip:{sess.tg_destinazione}@{sess.ip_vps}>\r\n"
|
||||
f"Content-Type: application/sdp\r\nContent-Length: {len(sdp)}\r\n\r\n{sdp}")
|
||||
self.sip_transport.sendto(sip_reinvite.encode('utf-8'), sess.sip_client_addr)
|
||||
|
||||
@@ -256,7 +255,7 @@ class SessionManager:
|
||||
for sess in ascoltatori:
|
||||
if sess.ultimo_src_id != src_id:
|
||||
sess.ultimo_src_id = src_id
|
||||
self.notifica_display(sess, f"RX: {src_id}")
|
||||
self.notifica_display(sess, f"CID:{src_id}")
|
||||
asyncio.create_task(self.processa_audio_dmr(ambe_frames, ascoltatori))
|
||||
|
||||
async def processa_audio_dmr(self, ambe_27_bytes, ascoltatori):
|
||||
@@ -264,7 +263,6 @@ class SessionManager:
|
||||
tg_arrivo = ascoltatori[0].tg_destinazione
|
||||
|
||||
try:
|
||||
# 1. Decodifichiamo prima tutti e 3 i frame del superframe DMR
|
||||
frames_pcm = []
|
||||
for i in range(0, len(ambe_27_bytes), 9):
|
||||
frame_9 = ambe_27_bytes[i:i+9]
|
||||
@@ -279,10 +277,20 @@ class SessionManager:
|
||||
pcm_data = await self.vocoder.converti_ambe_in_pcm(f"TG_{tg_arrivo}", frame_7)
|
||||
if pcm_data and len(pcm_data) >= 2:
|
||||
if len(pcm_data) % 2 != 0: pcm_data = pcm_data[:-1]
|
||||
|
||||
# --- INIZIO AGC DMR -> SIP ---
|
||||
livello_rms = audioop.rms(pcm_data, 2)
|
||||
if livello_rms > 18000:
|
||||
pcm_data = audioop.mul(pcm_data, 2, 0.4)
|
||||
elif livello_rms > 12000:
|
||||
pcm_data = audioop.mul(pcm_data, 2, 0.7)
|
||||
elif livello_rms < 300:
|
||||
pcm_data = audioop.mul(pcm_data, 2, 0.0)
|
||||
# --- FINE AGC ---
|
||||
|
||||
pcma_data = audioop.lin2alaw(pcm_data, 2)
|
||||
frames_pcm.append(pcma_data)
|
||||
|
||||
# 2. Spediamo i pacchetti RTP cadenzandoli a ritmo di 19ms (sgranatura)
|
||||
for idx, pcma_data in enumerate(frames_pcm):
|
||||
for sess in ascoltatori:
|
||||
header = bytearray(12)
|
||||
@@ -298,7 +306,6 @@ class SessionManager:
|
||||
sess.rtp_seq = (sess.rtp_seq + 1) % 65536
|
||||
sess.rtp_timestamp = (sess.rtp_timestamp + 160) % 4294967296
|
||||
|
||||
# Attesa di ~19ms tra un frame audio e il successivo (tranne l'ultimo)
|
||||
if idx < len(frames_pcm) - 1:
|
||||
await asyncio.sleep(0.019)
|
||||
|
||||
@@ -307,7 +314,26 @@ class SessionManager:
|
||||
async def processa_audio_rtp(self, sess, rtp_payload):
|
||||
if not sess.ptt_attivo: return
|
||||
try:
|
||||
# *** PASSIAMO IL CALL ID PER IL POOL ***
|
||||
# --- INIZIO AGC SIP -> DMR ---
|
||||
# Decodifichiamo G.711a in PCM lineare temporaneamente per calcolare il volume
|
||||
pcm_lineare = audioop.alaw2lin(rtp_payload, 2)
|
||||
livello_rms = audioop.rms(pcm_lineare, 2)
|
||||
|
||||
if livello_rms > 18000:
|
||||
pcm_lineare = audioop.mul(pcm_lineare, 2, 0.4)
|
||||
elif livello_rms > 12000:
|
||||
pcm_lineare = audioop.mul(pcm_lineare, 2, 0.7)
|
||||
elif livello_rms > 500 and livello_rms < 3000:
|
||||
# Piccolo booster se il microfono SIP è basso
|
||||
pcm_lineare = audioop.mul(pcm_lineare, 2, 1.5)
|
||||
elif livello_rms < 150:
|
||||
# Noise gate
|
||||
pcm_lineare = audioop.mul(pcm_lineare, 2, 0.0)
|
||||
|
||||
# Ricodifichiamo in formato PCMA/A-Law prima di passarlo al vocoder
|
||||
rtp_payload = audioop.lin2alaw(pcm_lineare, 2)
|
||||
# --- FINE AGC ---
|
||||
|
||||
ambe_bytes = await asyncio.wait_for(
|
||||
self.vocoder.converti_rtp_in_ambe(f"SIP_{sess.call_id}", rtp_payload), timeout=0.1
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user