diff --git a/include/dsd.h b/include/dsd.h index 76f374e..76a79b3 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -908,12 +908,12 @@ void playSynthesizedVoiceFS (dsd_opts * opts, dsd_state * state); //float stere void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state); //float stereo mix 3v2 DMR void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state); //float stereo mix 4v2 P25p2 void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state); //float mono +void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot); //float gain control //new short stuff void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state); //short stereo mix void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state); //short stereo mix 3v2 DMR void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state); //short stereo mix 4v2 P25p2 -void upsampleS (short invalue, short prev, short outbuf[6]); //upsample 8k to 48k short in M17 - +void upsampleS (short invalue, short prev, short outbuf[6]); //upsample 8k to 48k short // void openAudioOutDevice (dsd_opts * opts, int speed); void openAudioInDevice (dsd_opts * opts); diff --git a/src/dsd_audio2.c b/src/dsd_audio2.c index 3f0c011..032fe79 100644 --- a/src/dsd_audio2.c +++ b/src/dsd_audio2.c @@ -6,52 +6,43 @@ * * * LWVMOBILE - * 2023-07 DSD-FME Florida Man Edition + * 2023-08 DSD-FME Florida Man Edition *-----------------------------------------------------------------------------*/ #include "dsd.h" #include -//TODO: Test All voice decoders with all combos (short mono, short stereo, float mono, float stereo) -//CHECKLIST(PULSE): DMR BS(OK) DMR MS (OK) P25p1 (OK) P25p2 (OK) YSF (OK) NXDN (OK) M17 (short only!) pV (OK) dPMR (OK) MBEplayback (OK) X2-TDMA (who cares lol) D-STAR (OK) //TODO: WAV File saving (works fine on shorts, but on float, writing short to wav is not auto-gained, //so super quiet, either convert to float wav files, or run processAudio AFTER memcpy of the temp_buf) -//TODO: Continue to work on AGF function for best gain/normalization - -//TODO: Either clear out stale s_l4 and f_l4 buffers or push playback on them somehow (particularly DMR) -//stale buffered audio may be present when playing voice in slot 2 but the last sample isn't played but -//is later played when the DMR BS loop resumes on a new call in slot 1...may need to expand the BS loop to cover an extra tdma frame to force the push -//or just clear the stale values upon exit of the BS loop - +//simple method -- produces cleaner results, but can be muted (or very loud) at times +//has manual control only, no auto gain void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot) { - int i, run; - run = 1; - float empty[160]; - memset (empty, 0.1f, sizeof(empty)); - + int i; float mmax = 0.75f; float mmin = -0.75f; - float aavg = 0.0f; //average of the absolute value - float df; //decimation value - df = 8000.0f; //test value -- this would be the ideal perfect value if everybody spoke directly into the mic at a reasonable volume + float df = 3276.7f; - if (slot == 0) - df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gain); - if (slot == 1) - df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gainR); + //Default gain value of 1.0f on audio_gain == 0 + float gain = 1.0f; - //this comparison is to determine whether or not to run gain on 'empty' samples (2v last 2, silent frames, etc) - if (memcmp(empty, samp, sizeof(empty)) == 0) run = 0; - if (run == 0) goto AGF_END; + //make it so that gain is 1.0f on 25.0f aout, and 2.0f on 50 aout + if (opts->audio_gain != 0 && slot == 0) + gain = state->aout_gain / 25.0f; + + if (opts->audio_gain != 0 && slot == 1) + gain = state->aout_gainR / 25.0f; + + //mono output handles slightly different, need to further decimate + if (opts->pulse_digi_out_channels == 1) + df *= 4.0f; for (i = 0; i < 160; i++) { - - samp[i] = samp[i] / df; - - aavg += fabsf(samp[i]); + //simple decimation + samp[i] /= df; + samp[i] *= 0.65f; //simple clipping if (samp[i] > mmax) @@ -59,30 +50,11 @@ void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot) if (samp[i] < mmin) samp[i] = mmin; - //may have been a tad too loud on the high end - // samp[i] *= 0.5f; //testing various values here - + //user gain factor + samp[i] *= gain; + } - aavg /= 160.0f; - - if (slot == 0) - { - if (aavg < 0.075f && state->aout_gain < 42.0f) state->aout_gain += 1.0f; - if (aavg >= 0.075f && state->aout_gain > 1.0f) state->aout_gain -= 1.0f; - } - - if (slot == 1) - { - if (aavg < 0.075f && state->aout_gainR < 42.0f) state->aout_gainR += 1.0f; - if (aavg >= 0.075f && state->aout_gainR > 1.0f) state->aout_gainR -= 1.0f; - } - - //debug - // fprintf (stderr, "\nS%d - DF = %f AAVG = %f", slot, df, aavg); - - AGF_END: ; //do nothing - } //float stereo mix 3v2 DMR @@ -884,6 +856,12 @@ void soft_tonef (float samp[160], int n, int ID, int AD) int i; float step1, step2, amplitude, freq1, freq2; + float gain = 1.0f; + + //needs opts and state to work....don't feel like doing the changes + // if (opts->audio_gain != 0 && slot == 0) + // gain = state->aout_gain / 25.0f; + // Synthesize tones freq1 = 31.25 * ID; freq2 = freq1; step1 = 2 * M_PI * freq1 / 8000.0f; @@ -894,7 +872,137 @@ void soft_tonef (float samp[160], int n, int ID, int AD) { samp[i] = (float) ( amplitude * (sin((n) * step1)/2 + sin((n) * step2)/2) ); samp[i] /= 8000.0f; + samp[i] *= gain; n++; } -} \ No newline at end of file +} + +//older version, does better at normalizing audio, but also sounds 'flatter' and 'muddier' +//probably too much compression and adjustments on the sine wave +// void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot) +// { +// int i, j, run; +// run = 1; +// float empty[160]; +// memset (empty, 0.1f, sizeof(empty)); + +// float mmax = 0.75f; +// float mmin = -0.75f; +// float aavg = 0.0f; //average of the absolute value +// float df; //decimation value +// df = 3276.7f; //test value -- this would be the ideal perfect value if everybody spoke directly into the mic at a reasonable volume + +// //this comparison is to determine whether or not to run gain on 'empty' samples (2v last 2, silent frames, etc) +// if (memcmp(empty, samp, sizeof(empty)) == 0) run = 0; +// if (run == 0) goto AGF_END; + +// for (j = 0; j < 8; j++) +// { + +// if (slot == 0) +// df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gain); +// if (slot == 1) +// df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gainR); + +// for (i = 0; i < 20; i++) +// { + +// samp[(j*20)+i] = samp[(j*20)+i] / df; + +// aavg += fabsf(samp[i]); + +// //simple clipping +// if (samp[(j*20)+i] > mmax) +// samp[(j*20)+i] = mmax; +// if (samp[(j*20)+i] < mmin) +// samp[(j*20)+i] = mmin; + +// } //i loop + +// aavg /= 20.0f; //optimal value? + +// //debug +// // fprintf (stderr, "\nS%d - DF = %f AAVG = %f", slot, df, aavg); + +// if (slot == 0) +// { +// if (aavg < 0.075f && state->aout_gain < 46.0f) state->aout_gain += 0.5f; +// if (aavg >= 0.075f && state->aout_gain > 1.0f) state->aout_gain -= 0.5f; +// } + +// if (slot == 1) +// { +// if (aavg < 0.075f && state->aout_gainR < 46.0f) state->aout_gainR += 0.5f; +// if (aavg >= 0.075f && state->aout_gainR > 1.0f) state->aout_gainR -= 0.5f; +// } + +// // aavg = 0.0f; //reset? + +// } //j loop + +// AGF_END: ; //do nothing + +// } + +//the previous version, not quite as good at audio gain normalization, but keeping it just in case +// void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot) +// { +// int i, run; +// run = 1; +// float empty[160]; +// memset (empty, 0.1f, sizeof(empty)); + +// float mmax = 0.75f; +// float mmin = -0.75f; +// float aavg = 0.0f; //average of the absolute value +// float df; //decimation value +// df = 8000.0f; //test value -- this would be the ideal perfect value if everybody spoke directly into the mic at a reasonable volume + +// if (slot == 0) +// df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gain); +// if (slot == 1) +// df = (384.0f / (float)opts->pulse_digi_out_channels) * (50.0f - state->aout_gainR); + +// //this comparison is to determine whether or not to run gain on 'empty' samples (2v last 2, silent frames, etc) +// if (memcmp(empty, samp, sizeof(empty)) == 0) run = 0; +// if (run == 0) goto AGF_END; + +// for (i = 0; i < 160; i++) +// { + +// samp[i] = samp[i] / df; + +// aavg += fabsf(samp[i]); + +// //simple clipping +// if (samp[i] > mmax) +// samp[i] = mmax; +// if (samp[i] < mmin) +// samp[i] = mmin; + +// //may have been a tad too loud on the high end +// // samp[i] *= 0.5f; //testing various values here + +// } + +// aavg /= 160.0f; + +// if (slot == 0) +// { +// if (aavg < 0.075f && state->aout_gain < 42.0f) state->aout_gain += 1.0f; +// if (aavg >= 0.075f && state->aout_gain > 1.0f) state->aout_gain -= 1.0f; +// } + +// if (slot == 1) +// { +// if (aavg < 0.075f && state->aout_gainR < 42.0f) state->aout_gainR += 1.0f; +// if (aavg >= 0.075f && state->aout_gainR > 1.0f) state->aout_gainR -= 1.0f; +// } + +// //debug +// // fprintf (stderr, "\nS%d - DF = %f AAVG = %f", slot, df, aavg); + +// AGF_END: ; //do nothing + +// } \ No newline at end of file diff --git a/src/dsd_main.c b/src/dsd_main.c index 39d7129..a2c8c10 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1200,7 +1200,7 @@ usage () printf (" -d Create mbe data files, use this directory (TDMA version is experimental)\n"); printf (" -r Read/Play saved mbe data from file(s)\n"); printf (" -g Audio output gain (SHORT) -- (default = 0 = auto, disable = -1)\n"); - printf (" -g Audio Base Gain (FLOAT) -- (0 - 45)\n"); //re-write this to make it clear! + printf (" -g Audio Manual Gain (FLOAT) -- (0 = 100\%)(Manual = 1 - 50)\n"); 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"); @@ -1346,9 +1346,9 @@ liveScanner (dsd_opts * opts, dsd_state * state) if (opts->floating_point == 1) { - //continue testing for as high as we can go without it suddenly clipping - opts->audio_gain /= 2.0f; - if (opts->audio_gain > 42.0f) opts->audio_gain = 42.0f; + // opts->audio_gain /= 2.0f; + if (opts->audio_gain > 50.0f) opts->audio_gain = 50.0f; + if (opts->audio_gain < 0.0f) opts->audio_gain = 0.0f; } #ifdef USE_RTLSDR diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 7daadcd..91aed4c 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3520,13 +3520,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } } - if (c == 43) //+ key, increment aout_gain + if (c == 43) //+ key, increment audio_gain { - // if (state->aout_gain < 50) - // state->aout_gain++; - // //probably won't use aout_gainR with new short and float systems - // if (state->aout_gainR < 50) - // state->aout_gainR++; if (opts->audio_gain < 50) opts->audio_gain++; @@ -3536,15 +3531,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } - if (c == 45) //- key, decrement aout_gain + if (c == 45) //- key, decrement audio_gain { - // if (state->aout_gain > 0) - // state->aout_gain--; - // //probably won't use aout_gainR with new short and float systems - // if (state->aout_gainR > 0) - // state->aout_gainR--; - if (opts->audio_gain > 1) + if (opts->audio_gain > 0) opts->audio_gain--; state->aout_gain = opts->audio_gain; diff --git a/src/dstar.c b/src/dstar.c index da6b620..3c0aeef 100644 --- a/src/dstar.c +++ b/src/dstar.c @@ -45,6 +45,10 @@ void processDSTAR(dsd_opts * opts, dsd_state * state) if (j == 20) processDSTAR_SD(opts, state, sd); + //since we are in a long loop, use this to improve response time in ncurses + if (opts->use_ncurses_terminal == 1) + ncursesPrinter(opts, state); + } fprintf (stderr, "\n");