From e0c2e740d284a8e14134b1768dbe4fa2c28790b0 Mon Sep 17 00:00:00 2001 From: lwvmobile <59371473+lwvmobile@users.noreply.github.com> Date: Sun, 13 Feb 2022 14:31:15 -0500 Subject: [PATCH] Add Github Build Version Add Github Build Version Work on Pulse Audio System (Testing 2 Channel Stereo Output) Work on NCurses Terminal (Still Work to Do) Include install.sh and rebuild.sh scripts --- include/dsd.h | 5 +++ install.sh | 2 +- rebuild.sh | 17 ++++++++ src/dsd_audio.c | 51 +++++++++++++--------- src/dsd_frame_sync.c | 3 +- src/dsd_main.c | 25 ++++++++--- src/dsd_ncurses.c | 101 ++++++++++++++++++++++++++++++++++++++++--- src/dsd_symbol.c | 22 +--------- 8 files changed, 170 insertions(+), 56 deletions(-) create mode 100644 rebuild.sh diff --git a/include/dsd.h b/include/dsd.h index af929d4..edbca21 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -152,6 +152,10 @@ typedef struct int pulse_raw_rate_out; int pulse_digi_rate_in; int pulse_digi_rate_out; + int pulse_raw_in_channels; + int pulse_raw_out_channels; + int pulse_digi_in_channels; + int pulse_digi_out_channels; int pulse_flush; pa_simple *pulse_raw_dev_in; pa_simple *pulse_raw_dev_out; @@ -242,6 +246,7 @@ typedef struct //input sample buffer for monitoring Input short input_sample_buffer; //HERE HERE + short pulse_raw_out_buffer; //HERE HERE //float *input_sample_buffer; //HERE HERE #ifdef TRACE_DSD diff --git a/install.sh b/install.sh index bb75ed0..ab0230b 100644 --- a/install.sh +++ b/install.sh @@ -1,4 +1,4 @@ -#/bin/bash +#! /bin/bash clear echo DSD-FME Digital Speech Decoder - Florida Man Edition Auto Installer echo MBELib is considered a requirement on this build. diff --git a/rebuild.sh b/rebuild.sh new file mode 100644 index 0000000..2a332d1 --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,17 @@ +#! /bin/bash +clear +echo DSD-FME Digital Speech Decoder - Florida Man Edition +echo Automatic Git Pull and Rebuild +echo +sleep 1 +##Open your clone folder## +git pull https://github.com/lwvmobile/dsd-fme pulseaudio +sleep 2 +##cd into your build folder## +cd build +##cmake usually isn't necesary, but could be if I update the cmakelist.txt +cmake .. +make -j `nproc` +sudo make install +sudo ldconfig + diff --git a/src/dsd_audio.c b/src/dsd_audio.c index 60043b2..6415813 100644 --- a/src/dsd_audio.c +++ b/src/dsd_audio.c @@ -26,11 +26,11 @@ void openPulseOutput(dsd_opts * opts) { ss.format = PA_SAMPLE_S16NE; - ss.channels = 1; + ss.channels = opts->pulse_raw_out_channels; //doing tests with 2 channels at 22050 for 44100 audio default in pulse ss.rate = opts->pulse_raw_rate_out; //48000 tt.format = PA_SAMPLE_S16NE; - tt.channels = 1; + 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 //fprintf (stderr,"digi rate out = %d\n", opts->pulse_digi_rate_out); @@ -49,32 +49,34 @@ void openPulseInput(dsd_opts * opts) { zz.format = PA_SAMPLE_S16NE; - zz.channels = 1; + zz.channels = opts->pulse_raw_in_channels; zz.rate = opts->pulse_raw_rate_in; //48000 cc.format = PA_SAMPLE_S16NE; - cc.channels = 1; + cc.channels = opts->pulse_digi_in_channels; cc.rate = opts->pulse_digi_rate_in; //48000 //zz - if (opts->monitor_input_audio == 1) + if (opts->monitor_input_audio == 2) { - opts->pulse_raw_dev_in = pa_simple_new(NULL, "DSD FME", PA_STREAM_RECORD, NULL, "Raw Audio In", &zz, NULL, NULL, NULL); + opts->pulse_raw_dev_in = pa_simple_new(NULL, "DSD FME", PA_STREAM_RECORD, NULL, "Raw Audio In", &zz, NULL, NULL, NULL); } //cc - opts->pulse_digi_dev_in = pa_simple_new(NULL, "DSD FME", PA_STREAM_RECORD, NULL, "Digi Audio In", &cc, NULL, NULL, NULL); + opts->pulse_digi_dev_in = pa_simple_new(NULL, "DSD FME", PA_STREAM_RECORD, NULL, "Audio In", &cc, NULL, NULL, NULL); } void playRawAudio(dsd_opts * opts, dsd_state * state) { short obuf, outl, i, sample2, something; - something = state->samplesPerSymbol / 1; //was this what it was? - + something = state->samplesPerSymbol / 1; //1 for buffer steal loops, 5 for rtl loop + //something = 1; if (opts->audio_in_type == 0 && opts->audio_out_type == 0){ //hack, but might as well for this particular type since its nearly perfect for (i=0; i < something; i++){ //read (opts->audio_in_fd, &sample2, 2); //reading here seems to get same speed as gfsk modulation - pa_simple_read(opts->pulse_raw_dev_in, &sample2, 2, NULL ); - obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + //pa_simple_read(opts->pulse_raw_dev_in, &state->pulse_raw_out_buffer, 2, NULL ); + //obuf = state->pulse_raw_out_buffer / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + //obuf = state->input_sample_buffer; + obuf = state->pulse_raw_out_buffer; //write (opts->audio_out_fd, (void*)&obuf, 2); pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, 2, NULL); } @@ -82,8 +84,9 @@ void playRawAudio(dsd_opts * opts, dsd_state * state) { #ifdef USE_PORTAUDIO if (opts->audio_in_type == 2 && opts->audio_out_type == 0){ //hack, but might as well for this particular type since its nearly perfect for (i=0; i < something * 5; i++){ //not sure if this should be 'something' or something * 5 like is was with OSS - Pa_ReadStream( opts->audio_in_pa_stream, &sample2, 1 ); //reading here seems to get same speed as gfsk modulation - obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + //Pa_ReadStream( opts->audio_in_pa_stream, &sample2, 1 ); //reading here seems to get same speed as gfsk modulation + obuf = state->pulse_raw_out_buffer; + //obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping //write (opts->audio_out_fd, (void*)&obuf, 2); pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, 2, NULL); } @@ -91,8 +94,9 @@ void playRawAudio(dsd_opts * opts, dsd_state * state) { if (opts->audio_in_type == 0 && opts->audio_out_type == 2){ //hack, but might as well for this particular type since its nearly perfect for (i=0; i < something; i++){ //read (opts->audio_in_fd, &sample2, 2); //reading here seems to get same speed as gfsk modulation - pa_simple_read(opts->pulse_raw_dev_in, &sample2, 2, NULL ); - obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + //pa_simple_read(opts->pulse_raw_dev_in, &sample2, 2, NULL ); + //obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + obuf = state->pulse_raw_out_buffer; Pa_StartStream( opts->audio_out_pa_stream ); //no promises this work Pa_WriteStream( opts->audio_out_pa_stream, (void*)&obuf, 2); //no promises this work } @@ -100,14 +104,16 @@ void playRawAudio(dsd_opts * opts, dsd_state * state) { if (opts->audio_in_type == 2 && opts->audio_out_type == 2){ //hack, but might as well for this particular type since its nearly perfect for (i=0; i < something * 5; i++){ //not sure if this should be 'something' or something * 5 like is was with OSS - Pa_ReadStream( opts->audio_in_pa_stream, &sample2, 1 ); //reading here seems to get same speed as gfsk modulation - obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + //Pa_ReadStream( opts->audio_in_pa_stream, &sample2, 1 ); //reading here seems to get same speed as gfsk modulation + //obuf = sample2 / 4; //dividing here 'quietens' it down a little bit, helps with clicking and clipping + obuf = state->pulse_raw_out_buffer; Pa_StartStream( opts->audio_out_pa_stream ); //no promises this work Pa_WriteStream( opts->audio_out_pa_stream, (void*)&obuf, 2); //no promises this work } } #endif - + something = state->samplesPerSymbol / 5; //change to 5 for rtl samples, flips back to 1 up top next loop + //something = 1; if (opts->audio_in_type == 1 || opts->audio_in_type == 3){ //only plays at 83% and sounds like s sadly, but can't get samples directly from sdr when its already being polled for samples //also, can't get samples from stdin more than once either it seems, unless I borked it when I tried it earlier, so lumping it in here as well for (i=0; i < something; i++) @@ -116,7 +122,7 @@ void playRawAudio(dsd_opts * opts, dsd_state * state) { outl = sizeof(obuf) ; //obuf length, I think its always equal to 2 if (opts->audio_out_type == 0){ //write (opts->audio_out_fd, (void*)&obuf, outl); - pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, 2, NULL); + pa_simple_write(opts->pulse_raw_dev_out, (void*)&obuf, outl, NULL); //fprintf (stderr,"writing samples"); } @@ -399,10 +405,13 @@ playSynthesizedVoice (dsd_opts * opts, dsd_state * state) #endif } else - //if (opts->monitor_input_audio == 1){ + if (opts->monitor_input_audio == 1){ //pa_simple_flush(opts->pulse_raw_dev_in, NULL); //pa_simple_flush(opts->pulse_raw_dev_out, NULL); - //} + //state->pulse_raw_out_buffer = 0; + //pa_simple_write(opts->pulse_raw_dev_out, (void*)&state->pulse_raw_out_buffer, 2, NULL); + + } pa_simple_write(opts->pulse_digi_dev_out, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2), NULL); //Yay! It works. state->audio_out_idx = 0; } diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 1c150a1..f9a7f38 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -187,7 +187,8 @@ getFrameSync (dsd_opts * opts, dsd_state * state) //fprintf (stderr,"now=%d\n", now); //okay, so this is incrementing as expected if ( opts->monitor_input_audio == 1 && (time(NULL) - now) > 1 ) //okay, still something going on, still doing the read part for some reason { - //playRawAudio(opts, state); //this is on line 21 in dsd_audio.c + playRawAudio(opts, state); //this is on line 21 in dsd_audio.c + //fprintf( stderr, "Farts"); } t++; diff --git a/src/dsd_main.c b/src/dsd_main.c index d94b6dd..f6bf2e5 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -64,6 +64,7 @@ char * FM_banner[9] = { " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ", " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗", " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝", + "https://github.com/lwvmobile/dsd-fme/tree/pulseaudio " }; @@ -188,9 +189,14 @@ initOpts (dsd_opts * opts) opts->rtl_udp_port = 6020; //set UDP port for RTL remote opts->rtl_bandwidth = 48; //48000 default value opts->pulse_raw_rate_in = 48000; - opts->pulse_raw_rate_out = 48000; - opts->pulse_digi_rate_in = 48000; - opts->pulse_digi_rate_out = 48000; //need to copy this to rtl type in and change rate out to 8000 + opts->pulse_raw_rate_out = 48000; //doing tests with 2 channels at 24000 for 48000 audio default in pulse + opts->pulse_digi_rate_in = 24000; + opts->pulse_digi_rate_out = 24000; //need to copy this to rtl type in and change rate out to 8000 + opts->pulse_raw_in_channels = 1; + opts->pulse_raw_out_channels = 1; + opts->pulse_digi_in_channels = 2; + opts->pulse_digi_out_channels = 2; + opts->pulse_flush = 1; //set 0 to flush, 1 for flushed opts->use_ncurses_terminal = 0; //ncurses terminal disabled by default, call with -N } @@ -300,7 +306,7 @@ initState (dsd_state * state) void usage () { - fprintf (stderr, "\nFME build:%s", GIT_TAG); + fprintf (stderr, "Github Build Version: %s \n", GIT_TAG); fprintf (stderr,"\n"); fprintf (stderr,"Usage: dsd [options] Live scanner mode\n"); fprintf (stderr," or: dsd [options] -r Read/Play saved mbe data from file(s)\n"); @@ -399,6 +405,9 @@ liveScanner (dsd_opts * opts, dsd_state * state) if(opts->audio_in_type == 3) { opts->pulse_digi_rate_out = 8000; //rtl currently needs rate out to be 8000, will investigate this further + opts->pulse_digi_out_channels = 1; //don't know if it matters here or not + opts->pulse_raw_rate_out = 8000; + opts->pulse_raw_out_channels = 1; open_rtlsdr_stream(opts); } #endif @@ -584,9 +593,11 @@ main (int argc, char **argv) fprintf (stderr,"%s%s \n", FM_banner[i], KCYN); } fprintf (stderr,"%s", KNRM); //change back to normal + fprintf (stderr, "%s \n", FM_banner[7]); //pretty_colors(); //fprintf (stderr,"Digital Speech Decoder 1.7.0-dev (build:%s)\n", GIT_TAG); fprintf (stderr,"Digital Speech Decoder: Florida Man Edition\n"); + fprintf (stderr, "Github Build Version: %s \n", GIT_TAG); fprintf (stderr,"mbelib version %s\n", versionstr); initOpts (&opts); @@ -683,8 +694,9 @@ main (int argc, char **argv) case 'W': //monitor_input_audio if no sync opts.monitor_input_audio = 0; - //fprintf (stderr,"Monitor Source Audio if no sync detected (WIP!)\n"); - fprintf (stderr,"Monitor Source Audio Currently Disabled in Pulse Audio Builds.\n"); + //fprintf (stderr,"Monitor Source Audio Enabled (WIP!) Sounds bad.\n"); + //fprintf (stderr,"Monitor Source Audio may cause decoding issues.\n"); + fprintf (stderr,"Monitor Source Audio currently disabled in Pulse Audio Builds.\n"); break; case 'N': @@ -1052,6 +1064,7 @@ main (int argc, char **argv) if (opts.playfiles == 1) { opts.pulse_digi_rate_out = 8000; //need set to 8000 for amb/imb playback + opts.pulse_digi_out_channels = 1; openPulseOutput(&opts); //need to open it up for output playMbeFiles (&opts, &state, argc, argv); } diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 4f1117c..deb3e66 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -36,6 +36,31 @@ char * FM_bannerN[9] = { " ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ", " ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗", " ╚═════╝ ╚═════╝ ╚═════╝    ╚═╝ ╚═╝ ╚═╝╚══════╝", + "https://github.com/lwvmobile/dsd-fme/tree/pulseaudio " +}; + +char * SyncTypes[20] = { + "P25P1_SYNC", + "INV_P25P1_SYNC", + "X2TDMA_BS/MS_DATA_SYNC", + "INV_X2TDMA_BS/MS_DATA_SYNC", + "X2TDMA_BS/MS_VOICE_SYNC", + "INV_X2TDMA_BS/MS_VOICE_SYNC", + "DSTAR_SYNC", + "INV_DSTAR_SYNC", + "NXDN_BS_VOICE_SYNC", //8 + "INV_NXDN_BS_VOICE_SYNC", //9 + "DMR_BS/MS_DATA_SYNC", + "INV_DMR_BS/MS_DATA_SYNC", + "DMR_BS/MS_VOICE_SYNC", + "INV_DMR_BS/MS_VOICE_SYNC", + "PROVOICE_SYNC", //14 + "INV_PROVOICE_SYNC", //15 + "NXDN_BS_DATA_SYNC", //16 + "INV_NXDN_BS_DATA_SYNC", //17 + "DSTAR_HD", + "INV_DSTAR_HD" + }; time_t nowN; @@ -57,7 +82,7 @@ char * getTimeN(void) //get pretty hh:mm:ss timestamp void ncursesOpen () { mbe_printVersion (versionstr); - //setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); initscr(); //Initialize NCURSES screen window start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style @@ -72,21 +97,83 @@ void ncursesOpen () void ncursesPrinter (dsd_opts * opts, dsd_state * state) { + int level; + level = (int) state->max / 164; erase(); //disabling until wide support can be built for LM, etc. $(ncursesw5-config --cflags --libs) - //printw("%s \n", FM_bannerN[0]); //top line in white + //printw ("%s \n", FM_bannerN[0]); //top line in white //attron(COLOR_PAIR(4)); //for (short int i = 1; i < 7; i++) { //following lines in cyan //printw("%s \n", FM_bannerN[i]); } //attroff(COLOR_PAIR(4)); - printw("Digital Speech Decoder: Florida Man Edition\n"); - printw("mbelib version %s\n", versionstr); - printw("Time: "); - printw("%s ", getTimeN()); + printw ("%s \n", FM_bannerN[7]); //http link + printw ("Digital Speech Decoder: Florida Man Edition\n"); + printw ("Github Build Version: %s \n", GIT_TAG); + printw ("mbelib version %s\n", versionstr); + printw ("Time: "); + printw ("%s ", getTimeN()); + if (SyncTypes[state->lastsynctype] != NULL) + { + printw ("%s \n", SyncTypes[state->lastsynctype]); + //printw("%s ", state->ftype); //moved to front, some ftype strings have spaces in front of them, and others dont + /* Not sure if I'm going to use the error bars yet + if (opts->errorbars == 1) + { + printw("-"); //AFAIK, errorbars==1 is the internal value for if a system has inverted signal types, not at all misleading + } + else + { + printw("+"); + } + */ + if (1 == 1){ //figure out method that will tell me when is active and when not active, maybe carrier but this doesn't print anyways unless activity + attron(COLOR_PAIR(3)); + } + printw ("%s %s\n", state->ftype, state->fsubtype); //some ftype strings have extra spaces in them + if (state->lasttg < 0) //triggers compiler warning: comparison between pointer and integer + { + //sprintf(state->ftype, ) + //state->lasttg = state->ftype; //warning: assignment to ‘int’ from ‘char * + state->lasttg = 0; + } + printw ("TG [%7i] RID [%12i] \n", state->lasttg, state->lastsrc); //variables to fill with info from other system types too + //printw ("TG [%s] \n", state->lasttg); + //printw ("TDMA activity: %s %s \n", state->slot0light, state->slot1light); + printw("In Level: [%2i%%] ", level); + printw ("Voice Error [%s] \n", state->err_str); //no idea if this shows anything outside of TDMA or P1 or what + if (1 == 1){ //same as above + attroff(COLOR_PAIR(3)); + } + } + + /* if (state->lastsynctype == 8 ||state->lastsynctype == 9 ||state->lastsynctype == 16 ||state->lastsynctype == 17) { - printw("NXDN"); + if (state->samplesPerSymbol == 20) + { + //sprintf (state->ftype, " NXDN48 "); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, " -NXDN48 ", synctest_pos + 1, modulation); + printw("NXDN48 "); + printw("%s \n", SyncTypes[state->lastsynctype]); + printw("%s ", state->ftype); + } + } + else + { + //sprintf (state->ftype, " NXDN96 "); + if (opts->errorbars == 1) + { + //printFrameSync (opts, state, " -NXDN96 ", synctest_pos + 1, modulation); + printw("NXDN96 "); + printw("%s ", SyncTypes[state->lastsynctype]); + printw("%s ", state->ftype); + } + } } + */ + printw("\n"); //line return //add other interesting info to put here diff --git a/src/dsd_symbol.c b/src/dsd_symbol.c index 810506b..a9a474e 100644 --- a/src/dsd_symbol.c +++ b/src/dsd_symbol.c @@ -16,22 +16,6 @@ */ #include "dsd.h" -/* -pa_simple *c; -pa_sample_spec cc; - -void openPulseDigi(dsd_opts * opts){ - - cc.format = PA_SAMPLE_S16NE; - cc.channels = 1; - //cc.rate = 48000; //for some reason, if INPUT is 8000, and output is 48000, sounds correct on NXDN48 - cc.rate = opts->pulse_digi_rate_in; - - c = pa_simple_new(NULL, "DSD FME", PA_STREAM_RECORD, NULL, "Digi Audio In", &cc, NULL, NULL, NULL); - -} -*/ - int getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) @@ -100,6 +84,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) if(opts->audio_in_type == 0) { pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL ); + state->pulse_raw_out_buffer = sample; //steal raw out buffer sample here? } else if (opts->audio_in_type == 1) { result = sf_read_short(opts->audio_in_file, &sample, 1); @@ -236,7 +221,6 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) sum += sample; count++; } - //state->input_sample_buffer = sum; //maybe find correct placement for this? } if (state->samplesPerSymbol == 5) //provoice or gfsk { @@ -245,7 +229,6 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) sum += sample; count++; } - //state->input_sample_buffer = sum; } else { @@ -256,7 +239,6 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) if ((i >= state->symbolCenter - 1) && (i <= state->symbolCenter + 2)) { sum += sample; - //state->input_sample_buffer = sum; count++; } @@ -301,7 +283,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync) state->lastsample = sample; //steal sample here for rtl input or stdin input state->input_sample_buffer = sample; //sample or sum, honestly this seemt to be best place to grab this sadly, sounds terrible most everywhere else - } // for + } symbol = (sum / count);