WIP: Working Analog/Raw Source Audio Monitoring;

This commit is contained in:
lwvmobile
2023-08-08 22:52:32 -04:00
parent af271f62f3
commit 14b4af8b33
6 changed files with 82 additions and 126 deletions

View File

@@ -427,6 +427,9 @@ typedef struct
float *audio_out_temp_buf_p;
float audio_out_temp_bufR[160];
float *audio_out_temp_buf_pR;
//analog/raw signal audio buffers
short analog_out[960];
int analog_sample_counter;
//new stereo float sample storage
float f_l[160]; //single sample left
float f_r[160]; //single sample right

View File

@@ -26,7 +26,7 @@ pa_sample_spec ff; //float
void closePulseOutput (dsd_opts * opts)
{
pa_simple_free (opts->pulse_digi_dev_out);
if (opts->frame_provoice == 1) //EDACS analog calls
if (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) //EDACS analog calls and/or monitoring source analog audio
pa_simple_free (opts->pulse_raw_dev_out);
}
@@ -50,9 +50,9 @@ void openPulseOutput(dsd_opts * opts)
ff.channels = opts->pulse_digi_out_channels;
ff.rate = opts->pulse_digi_rate_out;
//reconfigured to open when using edacs so we can have a analog audio out that runs at 48k1 and not 8k1 float/short
if (opts->frame_provoice == 1)
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME3", PA_STREAM_PLAYBACK, NULL, "EDACS/Analog", &ss, NULL, NULL, NULL);
//reconfigured to open when using edacs or raw analog monitor so we can have a analog audio out that runs at 48k1 and not 8k1 float/short
if (opts->frame_provoice == 1 || opts->monitor_input_audio == 1)
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME3", PA_STREAM_PLAYBACK, NULL, "Analog", &ss, 0, NULL, NULL);
pa_channel_map* fl = 0; //NULL and 0 are same in this context
pa_channel_map* ss = 0; //NULL and 0 are same in this context

View File

@@ -743,10 +743,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
fprintf (stderr, " P2 Missing Parameters ");
fprintf (stderr, "%s", KNRM);
}
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (35); //35
}
@@ -782,10 +778,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
state->lastsynctype = 36; //36
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (36); //36
}
@@ -817,10 +809,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+dPMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 21;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (21);
}
if(strcmp(synctest12, DPMR_FRAME_SYNC_3) == 0)
@@ -853,10 +841,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
}
state->lastsynctype = 25;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (25);
}
if(strcmp(synctest12, INV_DPMR_FRAME_SYNC_3) == 0)
@@ -895,20 +879,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//state->firstframe = 1;
}
state->lastsynctype = 33; //33
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (33); //33
}
else //inverted MS voice frame
{
sprintf(state->ftype, "DMR MS");
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (32);
}
}
@@ -935,10 +911,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//state->firstframe = 1;
}
state->lastsynctype = 34;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (34);
}
}
@@ -964,20 +936,12 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (32);
}
else //inverted MS data frame
{
sprintf(state->ftype, "DMR MS");
state->lastsynctype = 33;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (33);
}
@@ -1000,10 +964,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 10;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (10);
}
@@ -1020,10 +980,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 11;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (11); //11
}
@@ -1045,10 +1001,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 33;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (33);
}
@@ -1065,10 +1017,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (32);
}
@@ -1090,10 +1038,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//printFrameSync (opts, state, "+DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 33;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (33);
}
@@ -1110,10 +1054,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (32);
}
@@ -1139,10 +1079,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 12;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (12);
}
@@ -1156,10 +1092,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 13;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (13);
}
@@ -1185,10 +1117,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (32); //treat Direct Mode same as MS mode for now
}
@@ -1225,10 +1153,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
state->firstframe = 1;
}
state->lastsynctype = 32;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (32);
}
@@ -1241,10 +1165,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
//printFrameSync (opts, state, "-DMR ", synctest_pos + 1, modulation);
}
state->lastsynctype = 33;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
state->last_cc_sync_time = time(NULL);
return (33);
}
@@ -1322,11 +1242,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+DSTAR VOICE ", synctest_pos + 1, modulation);
}
state->lastsynctype = 6;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (6);
}
if (strcmp (synctest, INV_DSTAR_SYNC) == 0)
@@ -1341,11 +1256,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "-DSTAR VOICE ", synctest_pos + 1, modulation);
}
state->lastsynctype = 7;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (7);
}
if (strcmp (synctest, DSTAR_HD) == 0)
@@ -1360,11 +1270,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+DSTAR HEADER", synctest_pos + 1, modulation);
}
state->lastsynctype = 18;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (18);
}
if (strcmp (synctest, INV_DSTAR_HD) == 0)
@@ -1379,11 +1284,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "-DSTAR HEADER", synctest_pos + 1, modulation);
}
state->lastsynctype = 19;
if ( opts->monitor_input_audio == 1)
{
pa_simple_flush(opts->pulse_raw_dev_out, NULL);
}
return (19);
}

View File

@@ -661,7 +661,7 @@ initOpts (dsd_opts * opts)
opts->dmr_mute_encL = 1;
opts->dmr_mute_encR = 1;
opts->monitor_input_audio = 0;
opts->monitor_input_audio = 0; //enable with -8
opts->inverted_p2 = 0;
opts->p2counter = 0;
@@ -785,6 +785,10 @@ initState (dsd_state * state)
state->audio_out_bufR = malloc (sizeof (short) * 1000000);
memset (state->audio_out_buf, 0, 100 * sizeof (short));
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
//analog/raw signal audio buffers
state->analog_sample_counter = 0; //when it reaches 960, then dump the raw/analog audio signal and reset
memset (state->analog_out, 0, sizeof(state->analog_out) );
//
state->audio_out_buf_p = state->audio_out_buf + 100;
state->audio_out_buf_pR = state->audio_out_bufR + 100;
state->audio_out_float_buf = malloc (sizeof (float) * 1000000);
@@ -1204,6 +1208,9 @@ usage ()
printf (" -w <file> Output synthesized speech to a .wav file, FDMA modes only.\n");
printf (" -7 <dir> Create/Use Custom directory for Per Call decoded .wav file saving.\n");
printf (" (Single Nested Directory Only! Use Before the -P option!)\n");
printf (" -8 Enable Experimental Source Audio Monitor (Pulse Audio Output Only!)\n");
printf (" (Caution! May Cause High CPU usage or break when using RTL input!)\n");
printf (" (Its recommended to use Squelch in SDR++ or GQRX, etc, if monitoring mixed analog/digital)\n");
printf (" -P Enable Per Call WAV file saving in AUTO and NXDN decoding classes\n");
printf (" (Per Call can only be used in Ncurses Terminal!)\n");
printf (" (Running in console will use static wav files)\n");
@@ -1309,9 +1316,6 @@ usage ()
printf (" \n");
printf (" -3 Disable DMR Late Entry Encryption Identifiers (VC6 Single Burst) \n");
printf (" Note: Disable this if false positives on Voice ENC occur. \n");
// printf (" -3 Enable DMR Late Entry Encryption Identifiers (VC6 Single Burst) \n");
// printf (" Note: This is experimental and may produce false positives depending on system type, notably TXI. \n");
// printf (" Use -0 or -4 options above instead if needed. \n");
printf ("\n");
printf (" Trunking Options:\n");
printf (" -C <file> Import Channel to Frequency Map (channum, freq) from csv file. (Capital C) \n");
@@ -1356,6 +1360,8 @@ liveScanner (dsd_opts * opts, dsd_state * state)
{
open_rtlsdr_stream(opts);
opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again
//safety disable due to HIGH CPU usage this causes when using RTL input
if (opts->monitor_input_audio == 1) opts->monitor_input_audio = 0;
}
#endif
@@ -1555,6 +1561,13 @@ main (int argc, char **argv)
//NOTE: The 'K' option for single BP key has been swapped to 'b'
//'K' is now used for hexidecimal key.csv imports
//experimental audio monitoring
case '8':
opts.monitor_input_audio = 1;
fprintf (stderr,"Experimental Raw Analog Source Monitoring Enabled (Pulse Audio Only!)\n");
fprintf (stderr,"WARNING! May Cause HIGH CPU Usage and/or break when using RTL Input\n");
break;
//rc4 enforcement on DMR (due to missing the PI header)
case '0':
state.M = 0x21;

View File

@@ -2310,7 +2310,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw (" \n");
}
if (opts->audio_out_type == 0 && opts->frame_provoice == 1)
if ( opts->audio_out_type == 0 && (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) )
{
printw ("| Pulse Audio Output: %i kHz; %i Ch; RMS: %04ld Analog", opts->pulse_raw_rate_out/1000, opts->pulse_raw_out_channels, opts->rtl_rms);
printw (" \n");
@@ -2328,7 +2328,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->monitor_input_audio == 1)
{
printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n");
printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected (WIP)\n");
}
if (opts->mbe_out_dir[0] != 0 && opts->dmr_stereo == 0)
{

View File

@@ -17,25 +17,27 @@
#include "dsd.h"
//testing sending samples into this to get an RMS value
int disctap_rms(int16_t *samples, int len, int step) //use samplespersymbol as len
/* largely lifted from rtl_power */
long int raw_rms(int16_t *samples, int len, int step) //use samplespersymbol as len
{
int i;
long p, t, s;
double dc, err;
int i;
long int rms;
long p, t, s;
double dc, err;
p = t = 0L;
for (i=0; i<len; i+=step) {
s = (long)samples[i];
t += s;
p += s * s;
}
/* correct for dc offset in squares */
dc = (double)(t*step) / (double)len;
err = t * 2 * dc - dc * dc * len;
p = t = 0L;
for (i=0; i<len; i+=step) {
s = (long)samples[i];
t += s;
p += s * s;
}
/* correct for dc offset in squares */
dc = (double)(t*step) / (double)len;
err = t * 2 * dc - dc * dc * len;
return (int)sqrt((p-err) / len);
rms = (long int)sqrt((p-err) / len);
if (rms < 0) rms = 150;
return rms;
}
int
@@ -269,6 +271,44 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
}
//LM server reports massive 'Q overrun, queueing locally' and CPU usage spikes to over 40% on pulse audio daemon
//main issue appears to be using this with rtl input -- issues due to threading, or sampling rate? or just rtl_fm doing its thing and causing issues?
//works fine when using SDR++ as input on the remote and NOT when using rtl direct input
//Went back and tested EDACS analog calls with RTL input, and it doesn't even flinch there or cause any HIGH CPU usage, so no idea why it does so here
if (have_sync == 0 && opts->monitor_input_audio == 1)
{
//sanity check to prevent an overflow
if (state->analog_sample_counter > 959)
state->analog_sample_counter = 959;
state->analog_out[state->analog_sample_counter++] = sample;
if (state->analog_sample_counter == 960)
{
//get an rms value if not using the rtl built in version
if (opts->audio_in_type != 3)
opts->rtl_rms = raw_rms(state->analog_out, 960, 1);
//debug
// opts->rtl_rms = 101;
//seems to be working now, but RMS values are lower on actual analog signal than on no signal but noise
if ( (opts->audio_out_type == 0) && (opts->rtl_rms > opts->rtl_squelch_level) )
pa_simple_write(opts->pulse_raw_dev_out, state->analog_out, 960*2, NULL);
memset (state->analog_out, 0, sizeof(state->analog_out));
state->analog_sample_counter = 0;
}
}
if (have_sync == 1 && opts->monitor_input_audio == 1)
{
//zero out and reset counter
memset (state->analog_out, 0, sizeof(state->analog_out));
state->analog_sample_counter = 0;
}
if (opts->use_cosine_filter)
{
if ( (state->lastsynctype >= 10 && state->lastsynctype <= 13) || state->lastsynctype == 32 || state->lastsynctype == 33