mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-12 16:57:23 -05:00
Tweaks to AGF function; Misc;
This commit is contained in:
@@ -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);
|
||||
|
||||
212
src/dsd_audio2.c
212
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 <math.h>
|
||||
|
||||
//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++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
// }
|
||||
@@ -1200,7 +1200,7 @@ usage ()
|
||||
printf (" -d <dir> Create mbe data files, use this directory (TDMA version is experimental)\n");
|
||||
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
printf (" -g <float> Audio output gain (SHORT) -- (default = 0 = auto, disable = -1)\n");
|
||||
printf (" -g <float> Audio Base Gain (FLOAT) -- (0 - 45)\n"); //re-write this to make it clear!
|
||||
printf (" -g <float> Audio Manual Gain (FLOAT) -- (0 = 100\%)(Manual = 1 - 50)\n");
|
||||
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");
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user