From 7d6269efaddb3add0646bdafe0ab6b0644156376 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 9 Aug 2023 01:14:00 -0400 Subject: [PATCH] WIP: Source Audio Monitoring on V2.1b; --- include/dsd.h | 4 ++ src/dsd_audio.c | 13 +++--- src/dsd_frame_sync.c | 100 ------------------------------------------- src/dsd_main.c | 22 ++++++++-- src/dsd_ncurses.c | 9 +++- src/dsd_symbol.c | 69 +++++++++++++++++++++++++++++ src/edacs-fme.c | 6 +-- 7 files changed, 109 insertions(+), 114 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index fe2f139..e168ebe 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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; diff --git a/src/dsd_audio.c b/src/dsd_audio.c index 80bf496..ac11ccf 100644 --- a/src/dsd_audio.c +++ b/src/dsd_audio.c @@ -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 diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 7287a03..d8c0b05 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -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); } diff --git a/src/dsd_main.c b/src/dsd_main.c index d4a9290..9561587 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -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 Read/Play saved mbe data from file(s)\n"); printf (" -g Audio output gain (default = 0 = auto, disable = -1)\n"); printf (" -w 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 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; diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index fd13c3f..c4444d0 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -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) { diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index 8379949..f83102b 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -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; 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; + + //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 diff --git a/src/edacs-fme.c b/src/edacs-fme.c index e52d666..0f727be 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -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)