* Update adn.cfg
* Update replit.md
* Update config.py
* Update bridge_master.py
* Fix: corregir indentacion en llamada a _handleRecording linea 2846
* Mover configuracion de locuciones y grabaciones a voice.cfg
* Nuevo archivo voice.cfg con configuracion de locuciones y grabaciones
* Cargar locuciones/grabaciones desde voice.cfg (opcional, con fallback a defaults)
* Actualizar documentacion: voice.cfg separado de adn.cfg
* Agregar configuracion TTS (4 slots) en voice.cfg
* Leer configuracion TTS desde voice.cfg
* Nuevo modulo TTS: texto -> gTTS -> WAV -> vocoder -> AMBE
* Agregar gTTS a dependencias
* Integrar sistema TTS con scheduling y playback
* Agregar configuracion AMBEServer (DV3000 remoto via UDP) en voice.cfg
* Leer configuracion TTS_AMBESERVER_HOST/PORT desde voice.cfg
* Agregar cliente AMBEServer UDP (protocolo DV3000) para codificacion AMBE
* Fix: apply DMR 3-way interleave to AMBE frames from DV3000
DV3000 outputs raw 72-bit AMBE+2 frames but DMR voice bursts
require 3 frames interleaved into 216-bit payloads.
Interleave: burst_payload[i*3+j] = frame[j].bit[i] (ETSI TS 102 361-1)
Also uses proper AMBE silence frame for padding incomplete triplets.
* Fix: use RATET 33 (DMR AMBE+2) instead of RATEP (D-Star)
The DV3000 was being configured with RATEP parameters that correspond
to D-Star AMBE codec, not DMR AMBE+2. G4KLX AMBETools uses RATET 33
(rate table entry 33) for DMR which selects the correct codec.
Also removed incorrect interleaving - DMR voice bursts use raw AMBE
frames without additional interleaving (confirmed by G4KLX wav2ambe).
* Add reload_voice_config() for hot-reload of voice.cfg
* Hot-reload voice.cfg: auto-detect changes every 15s without restart
Checks voice.cfg mtime every 15 seconds. When changed, reloads all
voice/TTS config, stops old LoopingCall tasks and starts new ones
with updated settings. No server restart needed.
* Fix: resolve AMBEServer host explicitly, strip whitespace/quotes
Adds socket.gethostbyname() to resolve DNS or validate IP before
using it in sendto(). Also strips whitespace and quotes from host
value to prevent hidden characters from config parsing.
* Change default TG from 214 to 2 in voice.cfg
* Improve playFileOnRequest: add file existence check, better logging, catch all exceptions
* Filter announcements by TG: only send to peers active on matching talkgroup
* Filter announcements/TTS by active BRIDGES: only send to systems with static or active dynamic TG
* Add TTS_VOLUME parameter (tts_engine.py): adjustable dB volume for TTS audio
* Add TTS_VOLUME parameter (config.py): adjustable dB volume for TTS audio
* Add TTS_VOLUME parameter (config/voice.cfg): adjustable dB volume for TTS audio
* Run TTS conversion (gTTS+ffmpeg+AMBEServer) in separate thread via deferToThread to avoid blocking reactor
* TTS dual-slot: send announcements on both TS1 and TS2 based on active BRIDGES per system
* Remove TTS_ANNOUNCEMENT*_TIMESLOT: TS now auto-detected from BRIDGES (config.py)
* Remove TTS_ANNOUNCEMENT*_TIMESLOT: TS now auto-detected from BRIDGES (config/voice.cfg)
* Remove TTS_ANNOUNCEMENT*_TIMESLOT: TS now auto-detected from BRIDGES (bridge_master.py)
* Announcements dual-slot: auto-detect TS from BRIDGES, remove ANNOUNCEMENT*_TIMESLOT (bridge_master.py)
* Announcements dual-slot: auto-detect TS from BRIDGES, remove ANNOUNCEMENT*_TIMESLOT (config.py)
* Announcements dual-slot: auto-detect TS from BRIDGES, remove ANNOUNCEMENT*_TIMESLOT (config/voice.cfg)
* Fix on-demand playback timing drift: use absolute timing instead of sleep(0.058) to prevent audio cuts on long files
* Add broadcast queue: prevent simultaneous announcements causing audio micro-cuts. All announcements (AMBE + TTS) now queue sequentially with 1.5s gap between them.
* Fix frame interval: 54ms->60ms (DMR standard) + absolute timing on all voice functions to eliminate micro-cuts
* Adjust frame interval: 60ms->58ms for optimal playback speed on all voice functions
* Remove noisy ROUTER debug logs that block reactor and cause voice micro-cuts: eliminate hundreds of 'no change'/'NO ACTION' debug lines per cycle
* Move rule_timer_loop, statTrimmer, kaReporting to background threads to prevent reactor blocking during voice broadcasts - all logs preserved
* Fix RuntimeError: dictionary changed size during iteration - use list(BRIDGES) for thread-safe iteration in all functions that access BRIDGES
* Revert bridge_master.py to state of commit ce9e9b09e0
* Skip rule_timer_loop during active voice traffic to prevent GIL contention micro-cuts - all logs preserved
* Batch ROUTER debug logs into single write to reduce GIL contention during voice traffic - all log content preserved
* Add TTS_SPEED config for speech rate control (atempo filter in ffmpeg)
* Add TTS_SPEED config for speech rate control (atempo filter in ffmpeg)
* Add TTS_SPEED config for speech rate control (atempo filter in ffmpeg)