WIP: Source Audio Monitoring on V2.1b;

This commit is contained in:
lwvmobile
2023-08-09 01:14:00 -04:00
parent 152f0ea7f6
commit 7d6269efad
7 changed files with 109 additions and 114 deletions

View File

@@ -414,6 +414,10 @@ 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;
//
int audio_out_idx;
int audio_out_idx2;
int audio_out_idxR;

View File

@@ -26,9 +26,11 @@ void closePulseOutput (dsd_opts * opts)
{
pa_simple_free (opts->pulse_digi_dev_out);
if (opts->dmr_stereo == 1)
{
pa_simple_free (opts->pulse_digi_dev_outR);
}
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);
}
void closePulseInput (dsd_opts * opts)
@@ -47,10 +49,9 @@ void openPulseOutput(dsd_opts * opts)
tt.channels = opts->pulse_digi_out_channels; //doing tests with 2 channels at 22050 for 44100 audio default in pulse
tt.rate = opts->pulse_digi_rate_out; //48000, switches to 8000 when using RTL dongle
if (opts->monitor_input_audio == 1)
{
opts->pulse_raw_dev_out = pa_simple_new(NULL, "DSD-FME3", PA_STREAM_PLAYBACK, NULL, "Raw Audio Out", &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);
//tt
pa_channel_map* left = 0; //NULL and 0 are same in this context

View File

@@ -744,10 +744,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
}
@@ -783,10 +779,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
}
@@ -818,10 +810,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)
@@ -854,10 +842,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)
@@ -896,20 +880,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);
}
}
@@ -936,10 +912,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);
}
}
@@ -965,20 +937,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);
}
@@ -1001,10 +965,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);
}
@@ -1021,10 +981,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
}
@@ -1046,10 +1002,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);
}
@@ -1066,10 +1018,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);
}
@@ -1091,10 +1039,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);
}
@@ -1111,10 +1055,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);
}
@@ -1140,10 +1080,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);
}
@@ -1157,10 +1093,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);
}
@@ -1186,10 +1118,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
}
@@ -1226,10 +1154,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);
}
@@ -1242,10 +1166,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);
}
@@ -1323,11 +1243,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+D-STAR ", 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)
@@ -1342,11 +1257,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "-D-STAR ", 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)
@@ -1361,11 +1271,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "+D-STAR_HD ", 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)
@@ -1380,11 +1285,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
printFrameSync (opts, state, "-D-STAR_HD ", 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

@@ -621,7 +621,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;
@@ -715,6 +715,11 @@ initState (dsd_state * state)
//Upsampled Audio Smoothing
state->audio_smoothing = 0;
//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 = malloc (sizeof (short) * 1000000);
state->audio_out_bufR = malloc (sizeof (short) * 1000000);
memset (state->audio_out_buf, 0, 100 * sizeof (short));
@@ -1129,6 +1134,9 @@ usage ()
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
printf (" -w <file> Output synthesized speech to a .wav file, legacy auto modes only.\n");
printf (" -8 Enable Experimental Source Audio Monitor (OSS and Pulse Audio at 48k1)\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 XDMA 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");
@@ -1230,9 +1238,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");
@@ -1300,6 +1305,8 @@ if (opts->audio_in_type == 1)
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
@@ -1492,6 +1499,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

@@ -2331,15 +2331,22 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n");
}
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");
}
if (opts->audio_out_type == 5)
{
printw ("| OSS Audio Output: [%2i] kHz [1] Channel", SAMPLE_RATE_OUT/1000);
if (opts->frame_provoice == 1 || opts->monitor_input_audio == 1)
printw (" - Analog RMS: %04ld Analog", opts->rtl_rms);
if (state->audio_smoothing == 1) printw (" - Smoothing On");
printw (" \n");
}
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,6 +17,29 @@
#include "dsd.h"
long int raw_rms(int16_t *samples, int len, int step) //use samplespersymbol as len
{
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;
rms = (long int)sqrt((p-err) / len);
if (rms < 0) rms = 150;
return rms;
}
int
getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{
@@ -247,6 +270,52 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
}
//Source Audio Monitoring
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;
//make it a little quieter
for (int x = 0; x < 960; x++)
state->analog_out[x] /= 4;
//seems to be working now, but RMS values are lower on actual analog signal than on no signal but noise
if ( opts->rtl_rms > opts->rtl_squelch_level )
{
if (opts->audio_out_type == 1)
pa_simple_write(opts->pulse_raw_dev_out, state->analog_out, 960*2, NULL);
//NOTE: I haven't personally tested this in Cygwin, so it might suck or lag, who knows
if (opts->audio_out_type == 5)
write (opts->audio_out_fd, state->analog_out, 960*2);
}
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

View File

@@ -190,9 +190,9 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
if (opts->audio_out_type == 0)
{
pa_simple_write(opts->pulse_digi_dev_out, analog1, 960*2, NULL);
pa_simple_write(opts->pulse_digi_dev_out, analog2, 960*2, NULL);
pa_simple_write(opts->pulse_digi_dev_out, analog3, 960*2, NULL);
pa_simple_write(opts->pulse_raw_dev_out, analog1, 960*2, NULL);
pa_simple_write(opts->pulse_raw_dev_out, analog2, 960*2, NULL);
pa_simple_write(opts->pulse_raw_dev_out, analog3, 960*2, NULL);
}
if (opts->audio_out_type == 5)