import asyncio import audioop class VocoderEngine: def __init__(self, mode="emulator", host="127.0.0.1", port=2470): self.mode = mode self.host = host self.port = port self.transport = None self.coda_risposte = asyncio.Queue() # IL SEMAFORO ASINCRONO PER IL MULTI-UTENTE self.lock = asyncio.Lock() async def avvia(self): loop = asyncio.get_running_loop() class AmbedProtocol(asyncio.DatagramProtocol): def __init__(self, coda): self.coda = coda def connection_made(self, transport): pass def datagram_received(self, data, addr): self.coda.put_nowait(data) def error_received(self, exc): pass self.transport, _ = await loop.create_datagram_endpoint( lambda: AmbedProtocol(self.coda_risposte), remote_addr=(self.host, self.port) ) print(f"[Vocoder] Motore avviato. Modalità: {self.mode.upper()}") print(f"[Vocoder] Connesso a {self.host}:{self.port}") async def converti_rtp_in_ambe(self, rtp_payload_alaw): pcm_data = audioop.alaw2lin(rtp_payload_alaw, 2) if self.mode == "emulator": async with self.lock: # <--- Aspetta il suo turno se occupato self.transport.sendto(pcm_data) try: return await asyncio.wait_for(self.coda_risposte.get(), timeout=0.1) except asyncio.TimeoutError: return None async def converti_ambe_in_pcm(self, ambe_bytes): if self.mode == "emulator": async with self.lock: # <--- Aspetta il suo turno se occupato self.transport.sendto(ambe_bytes) try: return await asyncio.wait_for(self.coda_risposte.get(), timeout=0.1) except asyncio.TimeoutError: return None def ferma(self): if self.transport: self.transport.close() print("[Vocoder] Motore spento.")