@ -41,7 +41,6 @@ import struct
import subprocess
import wave
import logging
from bitarray import bitarray
logger = logging . getLogger ( __name__ )
@ -63,55 +62,12 @@ DV3K_AUDIO_FIELD_ID = 0x00
DV3K_SAMPLES_PER_FRAME = 160
DV3K_RATEP_DMR = bytes ( [
0x61 , 0x00 , 0x0D , 0x00 , 0x0A ,
0x01 , 0x30 , 0x07 , 0x63 , 0x40 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x48
DV3K_RATET_DMR = bytes ( [
0x61 , 0x00 , 0x02 , 0x00 , 0x09 , 0x21
] )
DV3K_PRODID_REQ = bytes ( [ 0x61 , 0x00 , 0x01 , 0x00 , 0x30 ] )
AMBE_SILENCE = bytes ( [ 0xAC , 0xAA , 0x40 , 0x20 , 0x00 , 0x44 , 0x40 , 0x80 , 0x80 ] )
def _interleave_ambe_to_dmr ( frames_data ) :
'''
Convert raw AMBE + 2 frames ( 9 bytes / 72 bits each , from DV3000 ) to DMR burst format .
DMR voice bursts carry 3 AMBE frames per burst ( 216 bits = 2 x 108 bits ) .
The 3 frames are interleaved : burst_payload [ i * 3 + j ] = frame [ j ] . bit [ i ]
where i = 0. .71 ( bit index within frame ) , j = 0. .2 ( frame index ) .
This matches ETSI TS 102 361 - 1 voice burst payload format .
The output is compatible with readAMBE . readSingleFile ( ) which splits
the data into 108 - bit pairs for mk_voice . pkt_gen ( ) .
'''
result = bitarray ( endian = ' big ' )
for idx in range ( 0 , len ( frames_data ) , 3 ) :
f0 = frames_data [ idx ] if idx < len ( frames_data ) else AMBE_SILENCE
f1 = frames_data [ idx + 1 ] if idx + 1 < len ( frames_data ) else AMBE_SILENCE
f2 = frames_data [ idx + 2 ] if idx + 2 < len ( frames_data ) else AMBE_SILENCE
b0 = bitarray ( endian = ' big ' )
b0 . frombytes ( f0 )
b1 = bitarray ( endian = ' big ' )
b1 . frombytes ( f1 )
b2 = bitarray ( endian = ' big ' )
b2 . frombytes ( f2 )
burst = bitarray ( 216 , endian = ' big ' )
burst . setall ( False )
for i in range ( 72 ) :
burst [ i * 3 + 0 ] = b0 [ i ]
burst [ i * 3 + 1 ] = b1 [ i ]
burst [ i * 3 + 2 ] = b2 [ i ]
result . extend ( burst )
return result . tobytes ( )
def _get_tts_lang ( announcement_language ) :
if announcement_language in _LANG_MAP :
@ -248,15 +204,15 @@ def _encode_ambe_ambeserver(wav_path, ambe_path, host, port):
return False
try :
sock . sendto ( DV3K_RATE P _DMR, ( host , port ) )
sock . sendto ( DV3K_RATE T _DMR, ( host , port ) )
data , addr = sock . recvfrom ( 1024 )
if data [ 0 ] != DV3K_START_BYTE :
logger . error ( ' (TTS-AMBESERVER) Error configurando RATE P DMR' )
logger . error ( ' (TTS-AMBESERVER) Error configurando RATE T DMR' )
sock . close ( )
return False
logger . info ( ' (TTS-AMBESERVER) RATE P DMR (AMBE+2 ) configurado' )
logger . info ( ' (TTS-AMBESERVER) RATE T DMR (AMBE+2 tabla 33 ) configurado' )
except socket . timeout :
logger . error ( ' (TTS-AMBESERVER) Timeout configurando RATE P ' )
logger . error ( ' (TTS-AMBESERVER) Timeout configurando RATE T ' )
sock . close ( )
return False
@ -319,14 +275,9 @@ def _encode_ambe_ambeserver(wav_path, ambe_path, host, port):
return False
try :
interleaved = _interleave_ambe_to_dmr ( _ambe_frames )
with open ( ambe_path , ' wb ' ) as f :
f . write ( interleaved )
_bursts = len ( _ambe_frames ) / / 3
if len ( _ambe_frames ) % 3 :
_bursts + = 1
logger . info ( ' (TTS-AMBESERVER) Entrelazado DMR: %d frames -> %d bursts ( %d bytes) ' ,
len ( _ambe_frames ) , _bursts , len ( interleaved ) )
for frame in _ambe_frames :
f . write ( frame )
except Exception as e :
logger . error ( ' (TTS-AMBESERVER) Error escribiendo archivo AMBE: %s ' , e )
return False