SDRTrunk .mbe File Replay Initial Commit; #298

This commit is contained in:
lwvmobile
2025-06-22 15:16:19 -04:00
parent 3a1d393a0f
commit 8a30115398
6 changed files with 645 additions and 30 deletions

View File

@@ -1153,6 +1153,8 @@ void PrintAMBEData (dsd_opts * opts, dsd_state * state, char *ambe_d);
void PrintIMBEData (dsd_opts * opts, dsd_state * state, char *imbe_d);
int readImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
int readAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d);
void keyring(dsd_opts * opts, dsd_state * state);
void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state);
void openMbeInFile (dsd_opts * opts, dsd_state * state);
void closeMbeOutFile (dsd_opts * opts, dsd_state * state);
void closeMbeOutFileR (dsd_opts * opts, dsd_state * state); //tdma slot 2
@@ -1412,10 +1414,12 @@ void decode_ars(dsd_opts * opts, dsd_state * state, uint8_t * input, int len);
char * getTime();
char * getTimeC();
char * getTimeN(time_t t);
char * getTimeF(time_t t);
char * getDate();
char * getDateH();
char * getDateS();
char * getDateN(time_t t);
char * getDateF(time_t t);
//event history functions
void init_event_history (Event_History_I * event_struct, uint8_t start, uint8_t stop);

View File

@@ -617,7 +617,8 @@ void watchdog_event_current (dsd_opts * opts, dsd_state * state, uint8_t slot)
event_struct->Event_History_Items[0].source_id = source_id;
event_struct->Event_History_Items[0].target_id = target_id;
event_struct->Event_History_Items[0].channel = channel; //need to add this to trunking messages, if tuned from call grant
event_struct->Event_History_Items[0].event_time = time(NULL);
if (opts->playfiles == 0) //if playing back .mbe files with a time in it, don't set this
event_struct->Event_History_Items[0].event_time = time(NULL);
sprintf (event_struct->Event_History_Items[0].sysid_string, "%s", sysid_string);
sprintf (event_struct->Event_History_Items[0].src_str, "%s", src_str);
sprintf (event_struct->Event_History_Items[0].tgt_str, "%s", tgt_str);

View File

@@ -16,6 +16,8 @@
*/
#include "dsd.h"
#include "p25p1_const.h" //for imbe fr (7200)
#include "dmr_const.h" //for ambe+2 fr
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
{
@@ -244,9 +246,17 @@ openMbeInFile (dsd_opts * opts, dsd_state * state)
opts->mbe_in_f = fopen (opts->mbe_in_file, "ro");
if (opts->mbe_in_f == NULL)
{
fprintf (stderr,"Error: could not open %s\n", opts->mbe_in_file);
}
fprintf (stderr,"Error: could not open %s\n", opts->mbe_in_file);
//this will check the last 4 characters of the opts->mbe_in_file string
char ext[5]; memset(ext, 0, sizeof(ext));
uint16_t str_len = strlen((const char*)opts->mbe_in_file);
uint16_t ext_ptr = str_len - 4;
strncpy (ext, opts->mbe_in_file+ext_ptr, 4);
//debug
// fprintf (stderr, "EXT: %s;", ext);
// read cookie
cookie[0] = fgetc (opts->mbe_in_f);
@@ -254,26 +264,27 @@ openMbeInFile (dsd_opts * opts, dsd_state * state)
cookie[2] = fgetc (opts->mbe_in_f);
cookie[3] = fgetc (opts->mbe_in_f);
cookie[4] = 0;
//ambe+2
if (strstr (cookie, ".amb") != NULL)
{
state->mbe_file_type = 1;
}
//p1 and pv
else if (strstr (cookie, ".imb") != NULL)
{
state->mbe_file_type = 0;
}
//d-star ambe
else if (strstr (cookie, ".dmb") != NULL)
{
state->mbe_file_type = 2;
}
//sdrtrunk formated mbe json file
else if (strncmp (".mbe", ext, 4) == 0)
state->mbe_file_type = 3;
else
{
state->mbe_file_type = -1;
fprintf (stderr,"Error - unrecognized file type\n");
}
{
state->mbe_file_type = -1;
fprintf (stderr,"Error - unrecognized file type\n");
//try SDRTrunk JSON format as last resort
state->mbe_file_type = 3;
}
}
@@ -323,6 +334,9 @@ void openMbeOutFile (dsd_opts * opts, dsd_state * state)
char * timestr; //add timestr here, so we can assign it and also free it to prevent memory leak
char * datestr;
//random element of filename, so two files won't overwrite one another
uint16_t random_number = rand() & 0xFFFF;
timestr = getTime();
datestr = getDate();
@@ -350,7 +364,7 @@ void openMbeOutFile (dsd_opts * opts, dsd_state * state)
state->tgcount = 0;
sprintf (opts->mbe_out_file, "%s %s S1%s", datestr, timestr, ext);
sprintf (opts->mbe_out_file, "%s_%s_%04X_S1%s", datestr, timestr, random_number, ext);
sprintf (opts->mbe_out_path, "%s%s", opts->mbe_out_dir, opts->mbe_out_file);
@@ -385,6 +399,9 @@ void openMbeOutFileR (dsd_opts * opts, dsd_state * state)
char * timestr; //add timestr here, so we can assign it and also free it to prevent memory leak
char * datestr;
//random element of filename, so two files won't overwrite one another
uint16_t random_number = rand() & 0xFFFF;
timestr = getTime();
datestr = getDate();
@@ -412,7 +429,7 @@ void openMbeOutFileR (dsd_opts * opts, dsd_state * state)
state->tgcount = 0;
sprintf (opts->mbe_out_fileR, "%s %s S2%s", datestr, timestr, ext);
sprintf (opts->mbe_out_fileR, "%s_%s_%04X_S2%s", datestr, timestr, random_number, ext);
sprintf (opts->mbe_out_path, "%s%s", opts->mbe_out_dir, opts->mbe_out_fileR);
@@ -488,8 +505,9 @@ SNDFILE * close_and_rename_wav_file(SNDFILE * wav_file, char * wav_out_filename,
{
sf_close(wav_file);
char * datestr = getDate();
char * timestr = getTime();
time_t event_time = event_struct->Event_History_Items[0].event_time;
char * datestr = getDateF(event_time);
char * timestr = getTimeF(event_time);
uint16_t random_number = rand();
uint32_t source_id = event_struct->Event_History_Items[0].source_id;
@@ -849,4 +867,574 @@ uint16_t parse_raw_user_string (char * input, uint8_t * output)
if (shift) output[len-1] <<= 4;
return len;
}
uint16_t ambe2_str_to_decode(dsd_opts * opts, dsd_state * state, char * ambe_str, uint8_t * ks, uint16_t ks_idx, uint8_t dmra)
{
UNUSED(opts);
char ambe_fr[4][24]; memset (ambe_fr, 0, sizeof(ambe_fr));
uint8_t dibit_pair = 0;
uint8_t dibit1 = 0, dibit2 = 0;
const int *w, *x, *y, *z;
w = rW;
x = rX;
y = rY;
z = rZ;
for (size_t i = 0; i < 18; i++)
{
char octet_char[2];
octet_char[1] = 0;
strncpy (octet_char, ambe_str+i, 1);
sscanf (octet_char, "%hhX", &dibit_pair);
dibit1 = (dibit_pair >> 2) & 0x3;
dibit2 = (dibit_pair >> 0) & 0x3;
//debug
// fprintf (stderr, "\n dibit_pair: %X = %d, %d;", dibit_pair, dibit1, dibit2);
//load into ambe_fr
ambe_fr[*w][*x] = (1 & (dibit1 >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & (dibit1 >> 0)); // bit 0
w++;
x++;
y++;
z++;
ambe_fr[*w][*x] = (1 & (dibit2 >> 1)); // bit 1
ambe_fr[*y][*z] = (1 & (dibit2 >> 0)); // bit 0
w++;
x++;
y++;
z++;
//working now!
}
char ambe_d[49]; memset(ambe_d, 0, sizeof(ambe_d));
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
state->errs2 = state->errs;
mbe_demodulateAmbe3600x2450Data (ambe_fr);
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
state->debug_audio_errors += state->errs2;
//keystream application
for (uint8_t i = 0; i < 49; i++)
ambe_d[i] ^= ks[(ks_idx++)%3000];
//DMRA or P25 KS, skip the left over 7 bits from a byte
if (dmra == 1)
ks_idx += 7;
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
PrintAMBEData (opts, state, ambe_d);
//convert and save to .amb file if desired
if (opts->mbe_out_f != NULL)
saveAmbe2450Data (opts, state, ambe_d);
//audio out stack
if (opts->floating_point == 0)
processAudio(opts, state);
if (opts->wav_out_f != NULL)
writeSynthesizedVoice (opts, state);
if (opts->audio_out == 1 && opts->floating_point == 0)
playSynthesizedVoiceMS (opts, state);
if (opts->floating_point == 1)
{
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l));
playSynthesizedVoiceFM (opts, state);
}
//else if not floating point audio or audio out, then purge the audio buffers before they overflow and segfault
else if (opts->audio_out == 0)
{
if (state->audio_out_idx2 >= 800000)
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
}
return ks_idx; //return current ks_idx
}
uint16_t imbe_str_to_decode(dsd_opts * opts, dsd_state * state, char * imbe_str, uint8_t * ks, uint16_t ks_idx)
{
UNUSED(opts);
char imbe_fr[8][23]; memset (imbe_fr, 0, sizeof(imbe_fr));
uint8_t dibit_pair = 0;
uint8_t dibit1 = 0, dibit2 = 0;
const int *w, *x, *y, *z;
w = iW;
x = iX;
y = iY;
z = iZ;
for (size_t i = 0; i < 36; i++)
{
char octet_char[2];
octet_char[1] = 0;
strncpy (octet_char, imbe_str+i, 1);
sscanf (octet_char, "%hhX", &dibit_pair);
dibit1 = (dibit_pair >> 2) & 0x3;
dibit2 = (dibit_pair >> 0) & 0x3;
//debug
// fprintf (stderr, "\n dibit_pair: %X = %d, %d;", dibit_pair, dibit1, dibit2);
//load into imbe_fr
imbe_fr[*w][*x] = (1 & (dibit1 >> 1)); // bit 1
imbe_fr[*y][*z] = (1 & (dibit1 >> 0)); // bit 0
w++;
x++;
y++;
z++;
imbe_fr[*w][*x] = (1 & (dibit2 >> 1)); // bit 1
imbe_fr[*y][*z] = (1 & (dibit2 >> 0)); // bit 0
w++;
x++;
y++;
z++;
//working now!
}
char imbe_d[88]; memset(imbe_d, 0, sizeof(imbe_d));
state->errs = mbe_eccImbe7200x4400C0 (imbe_fr);
state->errs2 = state->errs;
mbe_demodulateImbe7200x4400Data (imbe_fr);
state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
state->debug_audio_errors += state->errs2;
//keystream application
for (uint8_t i = 0; i < 88; i++)
imbe_d[i] ^= ks[(ks_idx++)%3000];
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
PrintIMBEData (opts, state, imbe_d);
//convert and save to .imb file if desired
if (opts->mbe_out_f != NULL)
saveImbe4400Data (opts, state, imbe_d);
//audio out stack
if (opts->floating_point == 0)
processAudio(opts, state);
if (opts->wav_out_f != NULL)
writeSynthesizedVoice (opts, state);
if (opts->audio_out == 1 && opts->floating_point == 0)
playSynthesizedVoiceMS (opts, state);
if (opts->floating_point == 1)
{
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l));
playSynthesizedVoiceFM (opts, state);
}
//else if not floating point audio or audio out, then purge the audio buffers before they overflow and segfault
else if (opts->audio_out == 0)
{
if (state->audio_out_idx2 >= 800000)
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
}
return ks_idx; //return current ks_idx
}
void read_sdrtrunk_json_format (dsd_opts * opts, dsd_state * state)
{
char * source_str = calloc(0x100000, sizeof(char));
size_t source_size;
int8_t protocol = -1;
uint32_t source = 0; UNUSED(source);
uint32_t target = 0; UNUSED(target);
int8_t gi = -1; UNUSED(gi);
uint8_t is_enc = 0; UNUSED(is_enc);
uint8_t is_dmra = 1; //Denny, we need an MFID in the JSON file plz
uint8_t alg_id = 0;
uint16_t key_id = 0;
unsigned long long int iv_hex = 0;
int rc4_db = 256;
int rc4_mod = 13;
time_t event_time = time(NULL); UNUSED(event_time);
//for event history items
state->dmr_color_code = 0;
state->lastsrc = 0;
state->lasttg = 0;
state->gi[0] = -1;
state->synctype = -1;
state->lastsynctype = -1;
//watchdog for event history
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
uint8_t ks[3000]; memset (ks, 0, sizeof(ks));
uint16_t ks_idx = 0; //keystream index value
source_size = fread (source_str, 1, 0x100000, opts->mbe_in_f);
//debug
// fprintf (stderr, " Source Size: %d.\n", source_size);
// fprintf (stderr, "\n");
char * str_buffer = calloc(source_size, sizeof(char));
str_buffer = strtok(source_str, "{ \""); //value after initial { open bracket
//debug print current str_buffer
// fprintf (stderr, "%s", str_buffer);
for (size_t i = 0; i < source_size; i++)
{
//debug print current str_buffer
// fprintf (stderr, "%s", str_buffer);
//compare and set items accordingly
if (strncmp ("protocol", str_buffer, 8) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
//debug print current str_buffer
fprintf (stderr, "\n Protocol: %s", str_buffer);
//compare protocol and set to proper codec etc
if (strncmp ("APCO25-PHASE1", str_buffer, 13) == 0)
{
//set IMBE protocol here
protocol = 1;
//rc4 dropbyte and key len mod
rc4_db = 267;
rc4_mod = 13;
state->synctype = 0;
state->lastsynctype = 0;
}
if (strncmp ("APCO25-PHASE2", str_buffer, 13) == 0)
{
//set AMBE+2 protocol here
protocol = 2;
//rc4 dropbyte and key len mod
rc4_db = 256;
rc4_mod = 13;
state->synctype = 35;
state->lastsynctype = 35;
}
if (strncmp ("DMR", str_buffer, 3) == 0)
{
//set AMBE+2 protocol here
protocol = 2;
//rc4 dropbyte and key len mod
rc4_db = 256;
rc4_mod = 9;
state->synctype = 10;
state->lastsynctype = 10;
}
//open .imb or .amb file, if desired, but only after setting a synctype
if (state->synctype != -1)
{
//if converting to .amb or .imb, open that file format as well
if ((opts->mbe_out_dir[0] != 0) && (opts->mbe_out_f == NULL))
openMbeOutFile (opts, state);
}
}
if (strncmp ("call_type", str_buffer, 9) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
//set gi value based on this
if (strncmp ("GROUP", str_buffer, 5) == 0)
gi = 0;
else gi = 1;
state->gi[0] = gi;
//debug set value
// fprintf (stderr, " GI: %d;", gi);
//debug print current str_buffer
fprintf (stderr, "\n Call Type: %s", str_buffer);
}
if (strncmp ("encrypted", str_buffer, 9) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
//set enc value based on this
if (strncmp ("true", str_buffer, 4) == 0)
is_enc = 1;
else is_enc = 0;
//reset other enc variables (filled in later on if available)
alg_id = 0;
key_id = 0;
iv_hex = 0;
//debug set value
// fprintf (stderr, " ENC: %d;", is_enc);
//debug print current str_buffer
fprintf (stderr, "\n Encryption: %s", str_buffer);
}
if (strncmp ("to", str_buffer, 2) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
target = strtol (str_buffer, NULL, 10);
state->lasttg = target;
//debug set value
// fprintf (stderr, " Target: %d;", target);
//debug print current str_buffer
fprintf (stderr, "\n To: %s", str_buffer);
}
if (strncmp ("from", str_buffer, 4) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
source = strtol (str_buffer, NULL, 10);
state->lastsrc = source;
//debug set value
// fprintf (stderr, " Source: %d;", source);
//debug print current str_buffer
fprintf (stderr, "\n From: %s", str_buffer);
}
if (strncmp ("encryption_algorithm", str_buffer, 20) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
alg_id = strtol (str_buffer, NULL, 10);
//debug set value
fprintf (stderr, "\n Alg ID: %02X;", alg_id);
//debug print current str_buffer
// fprintf (stderr, "\n Encryption Alg: %s", str_buffer);
}
if (strncmp ("encryption_key_id", str_buffer, 17) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
key_id = strtol (str_buffer, NULL, 10);
//debug set value
fprintf (stderr, "\n Key ID: %04X;", key_id);
//debug print current str_buffer
// fprintf (stderr, "\n Encryption KID: %s", str_buffer);
}
if (strncmp ("encryption_mi", str_buffer, 13) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
uint16_t iv_len = strlen((const char*)str_buffer);
char iv_str[20]; memset(iv_str, 0, sizeof(iv_str));
//debug this str_buffer len
// fprintf (stderr, " IV STR LEN: %d;", iv_len);
if (iv_len == 18) //P25 MI has an extra zero byte (two zeroes) appended to MI, remove those
iv_len = 16;
strncpy(iv_str, str_buffer, iv_len); //copy out final IV value from the MI
iv_hex = strtoull (iv_str, NULL, 16); //Note: The 16 here is for base 16 (hex), not 16 chars
//debug set value
fprintf (stderr, "\n IV: %016llX;", iv_hex); //not really needed if loaded into array
//debug print current str_buffer
// fprintf (stderr, "\n Encryption MI/IV: %s", str_buffer);
//WIP: This is the last field of enc, so we create a new keystream here, if needed
state->currentslot = 0;
state->payload_algid = alg_id;
state->payload_mi = iv_hex;
state->payload_keyid = key_id;
if (state->keyloader == 1)
keyring(opts, state);
//TODO: Handle multi keystream creation with a new function
uint8_t ks_bytes[375]; memset(ks_bytes, 0, sizeof(ks_bytes));
uint8_t kiv[15]; memset(kiv, 0, sizeof(kiv));
//Test: Setup a simple RC4 for now (working)
if ( (alg_id == 0xAA || alg_id == 0x21) && state->R != 0 )
{
//load key into key portion of kiv
kiv[0] = ((state->R & 0xFF00000000) >> 32);
kiv[1] = ((state->R & 0xFF000000) >> 24);
kiv[2] = ((state->R & 0xFF0000) >> 16);
kiv[3] = ((state->R & 0xFF00) >> 8);
kiv[4] = ((state->R & 0xFF) >> 0);
//load the str_buffer into the IV portion of kiv
parse_raw_user_string(str_buffer, kiv+5);
rc4_block_output (rc4_db, rc4_mod, 375, kiv, ks_bytes);
unpack_byte_array_into_bit_array(ks_bytes, ks, 375);
} //end test
//reset ks_idx to 0
ks_idx = 0;
}
if (strncmp ("hex", str_buffer, 3) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
if (protocol == 1) //P25p1 IMBE
{
//debug print current str_buffer
// fprintf (stderr, "\n IMBE HEX: %s", str_buffer);
//36 hex characters on 'hex' which is the IMBE interleaved C codewords
ks_idx = imbe_str_to_decode(opts, state, str_buffer, ks, ks_idx);
}
else if (protocol == 2) //P25p2 AMBE
{
//debug print current str_buffer
// fprintf (stderr, "\n AMBE HEX: %s", str_buffer);
//18 hex characters on 'hex' which is the AMBE interleaved C codewords
ks_idx = ambe2_str_to_decode(opts, state, str_buffer, ks, ks_idx, is_dmra);
}
}
if (strncmp ("time", str_buffer, 4) == 0)
{
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
char time_str[20]; memset(time_str, 0, sizeof(time_str));
strncpy(time_str, str_buffer, 10); //full string is 13, but not copying milliseconds to match time(NULL)
event_time = strtol (time_str, NULL, 10);
//working now with tweak
state->event_history_s[0].Event_History_Items[0].event_time = event_time;
//debug set value
// fprintf (stderr, " Time: %ld;", event_time);
//what is actual time_t for time(NULL);
// fprintf (stderr, " Time(NULL): %ld;", time(NULL));
//convert to legible time and date format
char * timestr = getTimeN(event_time); UNUSED(timestr);
char * datestr = getDateN(event_time); UNUSED(datestr);
//user legible time
fprintf (stderr, " Date: %s Time: %s;", datestr, timestr);
if (timestr != NULL)
{
free (timestr);
timestr = NULL;
}
if (datestr != NULL)
{
free (datestr);
datestr = NULL;
}
//debug print current str_buffer
// fprintf (stderr, "\n Time: %s", str_buffer);
}
str_buffer = strtok(NULL, " : \""); //next value after any : "" string
if (str_buffer == NULL)
break;
//exit loop if signal
if (exitflag == 1)
break;
}
//free allocated memory from the source string
if (source_str != NULL)
{
free (source_str);
source_str = NULL;
}
//watchdog for event history
watchdog_event_history(opts, state, 0);
watchdog_event_current(opts, state, 0);
//if .imb or .amb file open, close it now
if (opts->mbe_out_f != NULL)
closeMbeOutFile (opts, state);
//end line break
fprintf (stderr, "\n");
}

View File

@@ -1412,7 +1412,7 @@
printf (" -n <float> Audio Analog Output Gain (Default: 0 = Auto; 0-100%% )\n");
//printf (" -w <file> Output synthesized speech to a .wav file, FDMA modes only.\n"); //disabled
printf (" -6 <file> Output raw audio .wav file (48K/1). (WARNING! Large File Sizes 1 Hour ~= 360 MB)\n");
printf (" -7 <dir> Create/Use Custom directory for Per Call decoded .wav file saving.\n");
// printf (" -7 <dir> Create/Use Custom directory for Per Call decoded .wav file saving.\n"); //disabled
printf (" (Use ./folder for Nested Directory!)\n");
printf (" (Use /path/to/folder for hard coded directory!)\n");
printf (" (Use Before the -P option!)\n");
@@ -2223,17 +2223,17 @@
fprintf (stderr,"Writing + Appending Event History to file %s\n", opts.event_out_file);
break;
case '7': //make a custom wav file directory in the current working directory -- use this before -P
strncpy(opts.wav_out_dir, optarg, 511);
opts.wav_out_dir[511] = '\0';
if (stat(opts.wav_out_dir, &st) == -1)
{
fprintf (stderr, "%s directory does not exist\n", opts.wav_out_dir);
fprintf (stderr, "Creating directory %s to save wav files\n", opts.wav_out_dir);
mkdir(opts.wav_out_dir, 0700);
}
else fprintf (stderr,"Writing wav decoded audio files to directory %s\n", opts.wav_out_dir);
break;
// case '7': //make a custom wav file directory in the current working directory -- use this before -P
// strncpy(opts.wav_out_dir, optarg, 511);
// opts.wav_out_dir[511] = '\0';
// if (stat(opts.wav_out_dir, &st) == -1)
// {
// fprintf (stderr, "%s directory does not exist\n", opts.wav_out_dir);
// fprintf (stderr, "Creating directory %s to save wav files\n", opts.wav_out_dir);
// mkdir(opts.wav_out_dir, 0700);
// }
// else fprintf (stderr,"Writing wav decoded audio files to directory %s\n", opts.wav_out_dir);
// break;
case 'P': //Per Call Wav Files
sprintf (wav_file_directory, "%s", opts.wav_out_dir);

View File

@@ -68,6 +68,7 @@ void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
int i;
char imbe_d[88];
char ambe_d[49];
srand(time(NULL)); //random seed for some file names using random numbers in file name
for (i = state->optind; i < argc; i++)
{
@@ -100,6 +101,10 @@ void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
playSynthesizedVoiceFM (opts, state);
}
}
else if (state->mbe_file_type == 3)
{
read_sdrtrunk_json_format (opts, state);
}
else if (state->mbe_file_type > 0) //ambe files
{
readAmbe2450Data (opts, state, ambe_d);

View File

@@ -79,3 +79,20 @@ char * getDateN(time_t t)
return curr;
}
//get HHmmss timestamp no colon (file operations)
char * getTimeF(time_t t)
{
char * curr = calloc(7, sizeof(char));
struct tm * ptm = localtime(& t);
sprintf(curr,"%02d%02d%02d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return curr;
}
//get YYYYMMDD without hyphen (file operations)
char * getDateF(time_t t)
{
char * curr = calloc(25, sizeof(char));
struct tm * ptm = localtime(& t);
sprintf(curr,"%04d%02d%02d", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday);
return curr;
}