diff --git a/include/dsd.h b/include/dsd.h index 72db1f3..00ba309 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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 diff --git a/src/dsd_audio.c b/src/dsd_audio.c index 7b1faa1..4995d93 100644 --- a/src/dsd_audio.c +++ b/src/dsd_audio.c @@ -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 diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 5b786c8..122e463 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -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); } diff --git a/src/dsd_main.c b/src/dsd_main.c index c72cbde..8cee11f 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -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 Output synthesized speech to a .wav file, FDMA modes only.\n"); printf (" -7 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 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; diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 2b35848..0321ad4 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -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) { diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index 176bea0..4b3fec3 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -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; imonitor_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