mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 09:17:20 -05:00
WIP: Working Analog/Raw Source Audio Monitoring;
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user