Add DMR/P25p2 Stereo Channel Patch;

This commit is contained in:
lwvmobile 2024-03-26 17:39:34 -04:00
parent 1a0baf0a17
commit c0f9818cf3
9 changed files with 669 additions and 174 deletions

View File

@ -484,8 +484,8 @@ typedef struct
//new stereo short sample storage
short s_l[160]; //single sample left
short s_r[160]; //single sample right
short s_l4[4][160]; //quad sample for up to a P25p2 4V
short s_r4[4][160]; //quad sample for up to a P25p2 4V
short s_l4[18][160]; //quad sample for up to a P25p2 4V
short s_r4[18][160]; //quad sample for up to a P25p2 4V
//new stereo short sample storage tapped from 48_k internal upsampling
short s_lu[160*6]; //single sample left
short s_ru[160*6]; //single sample right
@ -712,6 +712,7 @@ typedef struct
int p2_vch_chan_num; //vch channel number (0 or 1, not the 0-11 TS)
int ess_b[2][96]; //external storage for ESS_B fragments
int fourv_counter[2]; //external reference counter for ESS_B fragment collection
int voice_counter[2]; //external reference counter for 18V x 2 P25p2 Superframe
int p2_is_lcch; //flag to tell us when a frame is lcch and not sacch
//iden freq storage for frequency calculations
@ -1009,6 +1010,7 @@ void playSynthesizedVoiceMSR (dsd_opts * opts, dsd_state * state); //short mon
void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state); //short stereo mix
void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state); //short stereo mix 3v2 DMR
void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state); //short stereo mix 4v2 P25p2
void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state); //short stereo mix 18V Superframe
void upsampleS (short invalue, short prev, short outbuf[6]); //upsample 8k to 48k short
//
void openAudioOutDevice (dsd_opts * opts, int speed);

View File

@ -1035,8 +1035,8 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
//CHEAT: Using the slot on/off, use that to set encL or encR back on
//as a simple way to turn off voice synthesis in a particular slot
//its not really 'disabled', we just aren't playing it
if (opts->slot1_on == 0) encL = 1;
if (opts->slot2_on == 0) encR = 1;
// if (opts->slot1_on == 0) encL = 1;
// if (opts->slot2_on == 0) encR = 1;
//WIP: Mute if on B list (or not W list)
char modeL[8];
@ -1073,12 +1073,67 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
if (strcmp(modeL, "B") == 0) encL = 1;
if (strcmp(modeR, "B") == 0) encR = 1;
//check to see if we need to enable slot and toggle slot preference here
//this method will always favor slot 2 (this is a patch anyways, so....meh)
// if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
//check to see if we need to enable slot and toggle slot preference here
//if both groups allowed, then give no preference to either one (not sure this is needed now)
// if ( (strcmp(modeL, "A") == 0) && (strcmp(modeR, "A") == 0) )
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
// else if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// else if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
// else //if any other condition, then give no preference to either one
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
//if TG Hold in place, mute anything but that TG #132
if (state->tg_hold != 0 && state->tg_hold != TGL) encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR) encR = 1;
//likewise, override and unmute if TG hold matches TG
if (state->tg_hold != 0 && state->tg_hold == TGL) encL = 0;
if (state->tg_hold != 0 && state->tg_hold == TGR) encR = 0;
if (state->tg_hold != 0 && state->tg_hold != TGL)
encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR)
encR = 1;
//likewise, override and unmute if TG hold matches TG (and turn on slot and set preference)
if (state->tg_hold != 0 && state->tg_hold == TGL)
{
encL = 0;
opts->slot1_on = 1;
opts->slot_preference = 0;
}
else if (state->tg_hold != 0 && state->tg_hold == TGR)
{
encR = 0;
opts->slot2_on = 1;
opts->slot_preference = 1;
}
else //otherwise, reset slot preference to either or (both slots enabled)
{
opts->slot_preference = 2;
}
//test hpf
if (opts->use_hpf_d == 1)
@ -1092,35 +1147,108 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
hpf_dR(state, state->s_r4[2], 160);
}
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
{
if (!encL)
stereo_samp1[i*2+0] = state->s_l4[0][i];
if (!encR)
stereo_samp1[i*2+1] = state->s_r4[0][i];
}
//convert the left or right channel to both channels if single voice under certain conditions, if defined to do so
#define DMR_STEREO_OUTPUT
for (i = 0; i < 160; i++)
{
if (!encL)
stereo_samp2[i*2+0] = state->s_l4[1][i];
if (!encR)
stereo_samp2[i*2+1] = state->s_r4[1][i];
}
#ifdef DMR_STEREO_OUTPUT
if (encL) memset (state->s_l4, 0, sizeof(state->s_l4));
if (encR) memset (state->s_r4, 0, sizeof(state->s_r4));
//this is for playing single voice over both channels, or when to keep them seperated
if (opts->slot1_on == 0 && opts->slot2_on == 1 && encR == 0) //slot 1 is hard off and slot 2 is on
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (opts->slot1_on == 1 && opts->slot2_on == 0 && encL == 0) //slot 2 is hard off and slot 1 is on
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 0 && state->dmrburstL == 16 && encL == 0) //slot 1 is preferred, and voice in slot 1
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 1 && state->dmrburstR == 16 && encR == 0) //slot 2 is preferred, and voice in slot 2
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (state->dmrburstL == 16 && state->dmrburstR != 16 && encL == 0) //voice in left, no voice in right
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (state->dmrburstR == 16 && state->dmrburstL != 16 && encR == 0) //voice in right, no voice in left
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
//else if voice in both, and both slots on, and no preference on slot, then regular stereo interleave (left and right channels)
for (i = 0; i < 160; i++)
//if both slots are the same now, then let's decimate the audio to keep the audio level consistent
// if (memcmp (state->s_l4, state->s_r4, sizeof(state->s_l4)) == 0)
// {
// for (int j = 0; j < 3; j++)
// {
// for (i = 0; i < 160; i++)
// {
// state->s_l4[j][i] *= 0.85;
// state->s_r4[j][i] *= 0.85;
// }
// }
// }
#endif
//check this last
if (opts->slot1_on == 0 && opts->slot2_on == 0) //both slots are hard off, disable playback
{
if (!encL)
stereo_samp3[i*2+0] = state->s_l4[2][i];
if (!encR)
stereo_samp3[i*2+1] = state->s_r4[2][i];
encL = 1;
encR = 1;
}
//at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions
if (encL && encR)
goto SS3_END;
//test hpf
// if (opts->use_hpf_d == 1)
// {
// hpf_dL(state, state->s_l4[0], 160);
// hpf_dL(state, state->s_l4[1], 160);
// hpf_dL(state, state->s_l4[2], 160);
// hpf_dR(state, state->s_r4[0], 160);
// hpf_dR(state, state->s_r4[1], 160);
// hpf_dR(state, state->s_r4[2], 160);
// }
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp1[i*2+0] = state->s_l4[0][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp1[i*2+1] = state->s_r4[0][i];
}
for (i = 0; i < 160; i++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp2[i*2+0] = state->s_l4[1][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp2[i*2+1] = state->s_r4[1][i];
}
for (i = 0; i < 160; i++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp3[i*2+0] = state->s_l4[2][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp3[i*2+1] = state->s_r4[2][i];
}
if (opts->audio_out_type == 0) //Pulse Audio
{
pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*2, NULL);
@ -1397,6 +1525,284 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
}
//short stereo mix 18v superframe
void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state)
{
//NOTE: This will run once every superframe during a sacch field
//exact implementation to be determined
int i, j;
uint8_t encL, encR;
short stereo_sf[18][320]; //8k 2-channel stereo interleave mix for full superframe
// memset (stereo_sf, 1, 18*sizeof(short)); //I don't think 18*sizeof(short) was large enough, should probably be 18*320*sizeof(short)
memset (stereo_sf, 0, sizeof(stereo_sf));
short empty[320];
memset (empty, 0, sizeof(empty));
//p25p2 enc checkdown for whether or not to fill the stereo sample or not for playback or writing
encL = encR = 1;
if (state->payload_algid == 0 || state->payload_algid == 0x80)
encL = 0;
if (state->payload_algidR == 0 || state->payload_algidR == 0x80)
encR = 0;
//checkdown to see if we can lift the 'mute' if a key is available
if (encL)
{
if (state->payload_algid == 0xAA)
{
if (state->R != 0)
{
encL = 0;
}
}
}
if (encR)
{
if (state->payload_algidR == 0xAA)
{
if (state->RR != 0)
{
encR = 0;
}
}
}
//WIP: Mute if on B list (or not W list)
char modeL[8];
sprintf (modeL, "%s", "");
char modeR[8];
sprintf (modeR, "%s", "");
int TGL = state->lasttg;
int TGR = state->lasttgR;
//if we are using allow/whitelist mode, then write 'B' to mode for block
//comparison below will look for an 'A' to write to mode if it is allowed
if (opts->trunk_use_allow_list == 1)
{
sprintf (modeL, "%s", "B");
sprintf (modeR, "%s", "B");
}
for (i = 0; i < state->group_tally; i++)
{
if (state->group_array[i].groupNumber == TGL)
{
strcpy (modeL, state->group_array[i].groupMode);
// break; //need to keep going to check other potential slot group
}
if (state->group_array[i].groupNumber == TGR)
{
strcpy (modeR, state->group_array[i].groupMode);
// break; //need to keep going to check other potential slot group
}
}
//flag either left or right as 'enc' to mute if B
if (strcmp(modeL, "B") == 0) encL = 1;
if (strcmp(modeR, "B") == 0) encR = 1;
//check to see if we need to enable slot and toggle slot preference here
//this method will always favor slot 2 (this is a patch anyways, so....meh)
// if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
//check to see if we need to enable slot and toggle slot preference here
//if both groups allowed, then give no preference to either one (not sure this is needed now)
// if ( (strcmp(modeL, "A") == 0) && (strcmp(modeR, "A") == 0) )
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
// else if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// else if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
// else //if any other condition, then give no preference to either one
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
//if TG Hold in place, mute anything but that TG #132
if (state->tg_hold != 0 && state->tg_hold != TGL)
encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR)
encR = 1;
//likewise, override and unmute if TG hold matches TG (and turn on slot and set preference)
if (state->tg_hold != 0 && state->tg_hold == TGL)
{
encL = 0;
opts->slot1_on = 1;
opts->slot_preference = 0;
}
else if (state->tg_hold != 0 && state->tg_hold == TGR)
{
encR = 0;
opts->slot2_on = 1;
opts->slot_preference = 1;
}
else //otherwise, reset slot preference to either or (both slots enabled)
{
opts->slot_preference = 2;
}
//run hpf_d filter, if enabled
if (opts->use_hpf_d == 1)
{
for (j = 0; j < 18; j++)
{
hpf_dL(state, state->s_l4[j], 160);
hpf_dR(state, state->s_r4[j], 160);
}
}
//convert the left or right channel to both channels if single voice under certain conditions, if defined to do so
#define P2_STEREO_OUTPUT
#ifdef P2_STEREO_OUTPUT
if (encL) memset (state->s_l4, 0, sizeof(state->s_l4));
if (encR) memset (state->s_r4, 0, sizeof(state->s_r4));
//this is for playing single voice over both channels, or when to keep them seperated
if (opts->slot1_on == 0 && opts->slot2_on == 1 && encR == 0) //slot 1 is hard off and slot 2 is on
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (opts->slot1_on == 1 && opts->slot2_on == 0 && encL == 0) //slot 2 is hard off and slot 1 is on
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 0 && state->dmrburstL == 21 && encL == 0) //slot 1 is preferred, and voice in slot 1
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 1 && state->dmrburstR == 21 && encR == 0) //slot 2 is preferred, and voice in slot 2
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (state->dmrburstL == 21 && state->dmrburstR != 21 && encL == 0) //voice in left, no voice in right
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (state->dmrburstR == 21 && state->dmrburstL != 21 && encR == 0) //voice in right, no voice in left
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
//else if voice in both, and both slots on, and no preference on slot, then regular stereo interleave (left and right channels)
//if both slots are the same now, then let's decimate the audio to keep the audio level consistent
// if (memcmp (state->s_l4, state->s_r4, sizeof(state->s_l4)) == 0)
// {
// for (j = 0; j < 18; j++)
// {
// for (i = 0; i < 160; i++)
// {
// state->s_l4[j][i] *= 0.85;
// state->s_r4[j][i] *= 0.85;
// }
// }
// }
#endif
//check this last
if (opts->slot1_on == 0 && opts->slot2_on == 0) //both slots are hard off, disable playback
{
encL = 1;
encR = 1;
}
//at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions
if (encL && encR)
goto SS18_END;
//interleave left and right channels from the short storage area
for (j = 0; j < 18; j++)
{
for (i = 0; i < 160; i++)
{
#ifdef P2_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_sf[j][i*2+0] = state->s_l4[j][i];
#ifdef P2_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_sf[j][i*2+1] = state->s_r4[j][i];
}
}
if (opts->audio_out_type == 0) //Pulse Audio
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
pa_simple_write(opts->pulse_digi_dev_out, stereo_sf[j], 320*2, NULL);
}
}
if (opts->audio_out_type == 8) //UDP Audio
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
udp_socket_blaster (opts, state, 320*2, stereo_sf[j]);
}
}
if (opts->audio_out_type == 1 || opts->audio_out_type == 2) //STDOUT or OSS 8k/2channel
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
write (opts->audio_out_fd, stereo_sf[j], 320*2);
}
}
SS18_END:
//run cleanup since we pulled stuff from processAudio
state->audio_out_idx = 0;
state->audio_out_idxR = 0;
//set float temp buffer to baseline
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
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;
}
if (state->audio_out_idx2R >= 800000)
{
state->audio_out_float_buf_pR = state->audio_out_float_bufR + 100;
state->audio_out_buf_pR = state->audio_out_bufR + 100;
memset (state->audio_out_float_bufR, 0, 100 * sizeof (float));
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
state->audio_out_idx2R = 0;
}
}
//largely borrowed from Boatbod OP25 (simplified single tone ID version)
void soft_tonef (float samp[160], int n, int ID, int AD)
{

View File

@ -382,6 +382,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
}
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
//values displayed in ncurses terminal
// state->p25_vc_freq[0] = 0;
@ -965,6 +967,8 @@ initState (dsd_state * state)
}
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
state->K = 0;
state->R = 0;

View File

@ -2682,11 +2682,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{
printw ("| Voice Error: [%X][%X] Slot 1 (1)", state->errs&0xF, state->errs2&0xF);
if (opts->slot1_on == 0) printw (" OFF");
if (opts->slot1_on == 1) printw (" ON");
if (opts->slot1_on == 1) printw (" ON"); if (opts->slot_preference == 0) printw (" *Preferred");
printw ("\n");
printw ("| Voice Error: [%X][%X] Slot 2 (2)", state->errsR&0xF, state->errs2R&0xF);
if (opts->slot2_on == 0) printw (" OFF");
if (opts->slot2_on == 1) printw (" ON");
if (opts->slot2_on == 1) printw (" ON"); if (opts->slot_preference == 1) printw (" *Preferred");
printw ("\n");
}
printw ("------------------------------------------------------------------------------\n");
@ -3874,8 +3874,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//switching, but want to control each seperately plz
if (opts->slot1_on == 1)
{
opts->slot1_on = 0;
opts->slot_preference = 1; //slot 2
opts->slot1_on = 0; if (opts->slot_preference == 0) opts->slot_preference = 2;
// opts->slot_preference = 1; //slot 2
//clear any previously buffered audio
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
@ -3921,6 +3921,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
}
if (c == 51) //'3' key, toggle slot preference on 48k/1
{
if (opts->slot_preference == 1) opts->slot_preference = 0;
else opts->slot_preference = 1;
}
if (c == 43) //+ key, increment audio_gain
{

View File

@ -77,6 +77,13 @@ static uint32_t crc32mbf(uint8_t * buf, int len)
void processMPDU(dsd_opts * opts, dsd_state * state)
{
//p25p2 18v reset counters and buffers
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
opts->slot_preference = 2;
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces

View File

@ -11,6 +11,14 @@
void processTSBK(dsd_opts * opts, dsd_state * state)
{
//p25p2 18v reset counters and buffers
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
opts->slot_preference = 2;
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces

View File

@ -490,18 +490,27 @@ void process_4V (dsd_opts * opts, dsd_state * state)
// else state->dmrburstR = 21;
// }
// #endif
//unsure of the best location for these counter resets
if (state->voice_counter[0] >= 18)
state->voice_counter[0] = 0;
if (state->voice_counter[1] >= 18)
state->voice_counter[1] = 0;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
if(state->currentslot == 0)
{
memcpy(state->f_l4[0], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[0], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[0], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[0], state->s_ru, sizeof(state->s_ru));
}
@ -509,13 +518,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[1], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[1], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[1], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[1], state->s_ru, sizeof(state->s_ru));
}
@ -523,13 +534,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[2], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[2], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[2], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[2], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[2], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[2], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[2], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[2], state->s_ru, sizeof(state->s_ru));
}
@ -537,13 +550,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[3], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[3], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[3], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[3], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[3], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[3], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[3], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[3], state->s_ru, sizeof(state->s_ru));
}
@ -773,17 +788,26 @@ void process_2V (dsd_opts * opts, dsd_state * state)
// }
// #endif
//unsure of the best location for these counter resets
if (state->voice_counter[0] >= 18)
state->voice_counter[0] = 0;
if (state->voice_counter[1] >= 18)
state->voice_counter[1] = 0;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
if(state->currentslot == 0)
{
memcpy(state->f_l4[0], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[0], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[0], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[0], state->s_ru, sizeof(state->s_ru));
}
@ -791,17 +815,19 @@ void process_2V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[1], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[1], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[1], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[1], state->s_ru, sizeof(state->s_ru));
}
// if (state->currentslot == 0) state->voice_counter[0] = 0; if (state->currentslot == 1) state->voice_counter[1] = 0;
process_ESS(opts, state);
//reset drop bytes after a 2V
@ -908,10 +934,20 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine
//clear out stale voice samples left in the buffer and reset counter value
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
memset(state->s_l4, 0, sizeof(state->s_l4));
memset(state->s_r4, 0, sizeof(state->s_r4));
}
else if (duid_decoded == 13 && ((time(NULL) - state->last_active_time) > 2) && opts->p25_is_tuned == 0) //should we use && opts->p25_is_tuned == 1?
{
memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine
//clear out stale voice samples left in the buffer and reset counter value
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
memset(state->s_l4, 0, sizeof(state->s_l4));
memset(state->s_r4, 0, sizeof(state->s_r4));
}
if (duid_decoded == 0)
@ -998,6 +1034,8 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
state->p2_is_lcch = 0;
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
goto END;
}
@ -1017,8 +1055,22 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
if (sacch == 0 && ts_counter & 1 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 8000)
playSynthesizedVoiceFS4 (opts, state);
if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000)
playSynthesizedVoiceSS4 (opts, state);
// if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000)
// playSynthesizedVoiceSS4 (opts, state);
// fprintf (stderr, " VCH0: %d;", state->voice_counter[0]); //debug
// fprintf (stderr, " VCH1: %d;", state->voice_counter[1]); //debug
//this works, but may still have an element of 'dual voice stutter' which was my initial complaint, but shouldn't 'lag' during trunking operations (hopefully)
if ( (state->voice_counter[0] >= 18 || state->voice_counter[1] >= 18 ) && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000 && ts_counter & 1)
{
//debug test, see what each counter is at during playback on dual voice
// fprintf (stderr, " VC1: %02d; VC2: %02d;", state->voice_counter[0], state->voice_counter[1] );
playSynthesizedVoiceSS18 (opts, state);
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
}
//debug: fix burst indicator for ncurses if marginal signal
// if (voice)

View File

@ -154,16 +154,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -254,16 +254,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -390,16 +390,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -515,16 +515,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -646,16 +646,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -752,16 +752,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -922,16 +922,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -1124,16 +1124,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -1265,16 +1265,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@ -1394,16 +1394,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channelt & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channelt & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}

View File

@ -122,6 +122,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
@ -171,6 +172,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well
@ -230,6 +232,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0;
@ -258,6 +261,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0;
@ -370,19 +374,19 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
if (state->currentslot == 1)
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
}
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 1)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces
@ -512,6 +516,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
@ -552,6 +557,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20;
@ -608,6 +614,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well
@ -636,6 +643,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well
@ -737,6 +745,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->payload_keyid = 0;
state->dmrburstL = 24;
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->lastsrc = 0;
state->lasttg = 0;
@ -747,6 +756,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->payload_keyidR = 0;
state->dmrburstR = 24;
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->lastsrcR = 0;
state->lasttgR = 0;
@ -756,19 +766,19 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
if (state->currentslot == 0)
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
}
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 0)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces