Improvements to CLI input parsing and filtering
This commit is contained in:
parent
ac816f9207
commit
4763717b59
2
dsd.h
2
dsd.h
|
|
@ -256,3 +256,5 @@ void processProVoice (dsd_opts * opts, dsd_state * state);
|
|||
void processX2TDMAdata (dsd_opts * opts, dsd_state * state);
|
||||
void processX2TDMAvoice (dsd_opts * opts, dsd_state * state);
|
||||
void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
|
||||
short dmr_filter(short sample);
|
||||
short nxdn_filter(short sample);
|
||||
|
|
|
|||
144
dsd_audio.c
144
dsd_audio.c
|
|
@ -240,83 +240,78 @@ openAudioOutDevice (dsd_opts * opts, int speed)
|
|||
{
|
||||
// get info of device/file
|
||||
struct stat stat_buf;
|
||||
stat(opts->audio_out_dev, &stat_buf);
|
||||
if(S_ISREG(stat_buf.st_mode)) { // is this a regular file? then process with libsndfile.
|
||||
opts->audio_out_type = 1;
|
||||
opts->audio_out_file_info = calloc(1, sizeof(SF_INFO));
|
||||
opts->audio_out_file_info->samplerate = 48000;
|
||||
opts->audio_out_file_info->channels = 1;
|
||||
opts->audio_out_file_info->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
opts->audio_out_file = sf_open(opts->audio_out_dev, SFM_READ, opts->audio_out_file_info);
|
||||
if(opts->audio_out_file == NULL) {
|
||||
printf ("Error, couldn't open file %s\n", opts->audio_in_dev);
|
||||
}
|
||||
if(stat(opts->audio_out_dev, &stat_buf) != 0) {
|
||||
printf("Error, couldn't open %s\n", opts->audio_out_dev);
|
||||
exit(1);
|
||||
}
|
||||
else { // this is a device, use old handling
|
||||
|
||||
if( !(S_ISCHR(stat_buf.st_mode) || S_ISBLK(stat_buf.st_mode))) { // this is not a device
|
||||
printf("Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef SOLARIS
|
||||
sample_info_t aset, aget;
|
||||
|
||||
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
|
||||
if (opts->audio_out_fd == -1)
|
||||
{
|
||||
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// get current
|
||||
ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);
|
||||
|
||||
aset.record.sample_rate = speed;
|
||||
aset.play.sample_rate = speed;
|
||||
aset.record.channels = 1;
|
||||
aset.play.channels = 1;
|
||||
aset.record.precision = 16;
|
||||
aset.play.precision = 16;
|
||||
aset.record.encoding = AUDIO_ENCODING_LINEAR;
|
||||
aset.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
|
||||
if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
|
||||
{
|
||||
printf ("Error setting sample device parameters\n");
|
||||
exit (1);
|
||||
}
|
||||
sample_info_t aset, aget;
|
||||
|
||||
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
|
||||
if (opts->audio_out_fd == -1)
|
||||
{
|
||||
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
// get current
|
||||
ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);
|
||||
|
||||
aset.record.sample_rate = speed;
|
||||
aset.play.sample_rate = speed;
|
||||
aset.record.channels = 1;
|
||||
aset.play.channels = 1;
|
||||
aset.record.precision = 16;
|
||||
aset.play.precision = 16;
|
||||
aset.record.encoding = AUDIO_ENCODING_LINEAR;
|
||||
aset.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
|
||||
if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
|
||||
{
|
||||
printf ("Error setting sample device parameters\n");
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BSD) && !defined(__APPLE__)
|
||||
|
||||
int fmt;
|
||||
|
||||
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
|
||||
if (opts->audio_out_fd == -1)
|
||||
{
|
||||
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
|
||||
opts->audio_out = 0;
|
||||
}
|
||||
|
||||
fmt = 0;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
|
||||
{
|
||||
printf ("ioctl reset error \n");
|
||||
}
|
||||
fmt = speed;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl speed error \n");
|
||||
}
|
||||
fmt = 0;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl stereo error \n");
|
||||
}
|
||||
fmt = AFMT_S16_LE;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl setfmt error \n");
|
||||
}
|
||||
|
||||
|
||||
int fmt;
|
||||
|
||||
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
|
||||
if (opts->audio_out_fd == -1)
|
||||
{
|
||||
printf ("Error, couldn't open %s\n", opts->audio_out_dev);
|
||||
opts->audio_out = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fmt = 0;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
|
||||
{
|
||||
printf ("ioctl reset error \n");
|
||||
}
|
||||
fmt = speed;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl speed error \n");
|
||||
}
|
||||
fmt = 0;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl stereo error \n");
|
||||
}
|
||||
fmt = AFMT_S16_LE;
|
||||
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
|
||||
{
|
||||
printf ("ioctl setfmt error \n");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
printf ("Audio Out Device: %s\n", opts->audio_out_dev);
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +320,10 @@ openAudioInDevice (dsd_opts * opts)
|
|||
{
|
||||
// get info of device/file
|
||||
struct stat stat_buf;
|
||||
stat(opts->audio_in_dev, &stat_buf);
|
||||
if (stat(opts->audio_in_dev, &stat_buf) != 0) {
|
||||
printf("Error, couldn't open %s\n", opts->audio_in_dev);
|
||||
exit(1);
|
||||
}
|
||||
if(S_ISREG(stat_buf.st_mode)) { // is this a regular file? then process with libsndfile.
|
||||
opts->audio_in_type = 1;
|
||||
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
|
||||
|
|
@ -333,6 +331,7 @@ openAudioInDevice (dsd_opts * opts)
|
|||
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
|
||||
if(opts->audio_in_file == NULL) {
|
||||
printf ("Error, couldn't open file %s\n", opts->audio_in_dev);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else { // this is a device, use old handling
|
||||
|
|
@ -353,7 +352,8 @@ openAudioInDevice (dsd_opts * opts)
|
|||
}
|
||||
if (opts->audio_in_fd == -1)
|
||||
{
|
||||
printf ("Error, couldn't open /dev/audio\n");
|
||||
printf ("Error, couldn't open %s\n", opts->audio_in_dev);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// get current
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
// DMR filter
|
||||
#define NZEROS 60
|
||||
float ngain = 7.423339364f;
|
||||
static float xv[NZEROS+1];
|
||||
float xcoeffs[] =
|
||||
{ -0.0083649323f, -0.0265444850f, -0.0428141462f, -0.0537571943f,
|
||||
-0.0564141052f, -0.0489161045f, -0.0310068662f, -0.0043393881f,
|
||||
+0.0275375106f, +0.0595423283f, +0.0857543325f, +0.1003565948f,
|
||||
+0.0986944931f, +0.0782804830f, +0.0395670487f, -0.0136691535f,
|
||||
-0.0744390415f, -0.1331834575f, -0.1788967208f, -0.2005995448f,
|
||||
-0.1889627181f, -0.1378439993f, -0.0454976231f, +0.0847488694f,
|
||||
+0.2444859269f, +0.4209222342f, +0.5982295474f, +0.7593684540f,
|
||||
+0.8881539892f, +0.9712773915f, +0.9999999166f, +0.9712773915f,
|
||||
+0.8881539892f, +0.7593684540f, +0.5982295474f, +0.4209222342f,
|
||||
+0.2444859269f, +0.0847488694f, -0.0454976231f, -0.1378439993f,
|
||||
-0.1889627181f, -0.2005995448f, -0.1788967208f, -0.1331834575f,
|
||||
-0.0744390415f, -0.0136691535f, +0.0395670487f, +0.0782804830f,
|
||||
+0.0986944931f, +0.1003565948f, +0.0857543325f, +0.0595423283f,
|
||||
+0.0275375106f, -0.0043393881f, -0.0310068662f, -0.0489161045f,
|
||||
-0.0564141052f, -0.0537571943f, -0.0428141462f, -0.0265444850f,
|
||||
-0.0083649323f,
|
||||
};
|
||||
|
||||
// NXDN filter
|
||||
#define NXZEROS 134
|
||||
float nxgain = 15.95930463f;
|
||||
|
||||
static float nxv[NXZEROS+1];
|
||||
|
||||
float nxcoeffs[] =
|
||||
{ +0.031462429f, +0.031747267f, +0.030401148f, +0.027362877f,
|
||||
+0.022653298f, +0.016379869f, +0.008737200f, +0.000003302f,
|
||||
-0.009468531f, -0.019262057f, -0.028914291f, -0.037935027f,
|
||||
-0.045828927f, -0.052119261f, -0.056372283f, -0.058221106f,
|
||||
-0.057387924f, -0.053703443f, -0.047122444f, -0.037734535f,
|
||||
-0.025769308f, -0.011595336f, +0.004287292f, +0.021260954f,
|
||||
+0.038610717f, +0.055550276f, +0.071252765f, +0.084885375f,
|
||||
+0.095646450f, +0.102803611f, +0.105731303f, +0.103946126f,
|
||||
+0.097138329f, +0.085197939f, +0.068234131f, +0.046586711f,
|
||||
+0.020828821f, -0.008239664f, -0.039608255f, -0.072081234f,
|
||||
-0.104311776f, -0.134843790f, -0.162160200f, -0.184736015f,
|
||||
-0.201094346f, -0.209863285f, -0.209831516f, -0.200000470f,
|
||||
-0.179630919f, -0.148282051f, -0.105841323f, -0.052543664f,
|
||||
+0.011020985f, +0.083912428f, +0.164857408f, +0.252278939f,
|
||||
+0.344336996f, +0.438979335f, +0.534000832f, +0.627109358f,
|
||||
+0.715995947f, +0.798406824f, +0.872214756f, +0.935487176f,
|
||||
+0.986548646f, +1.024035395f, +1.046939951f, +1.054644241f,
|
||||
+1.046939951f, +1.024035395f, +0.986548646f, +0.935487176f,
|
||||
+0.872214756f, +0.798406824f, +0.715995947f, +0.627109358f,
|
||||
+0.534000832f, +0.438979335f, +0.344336996f, +0.252278939f,
|
||||
+0.164857408f, +0.083912428f, +0.011020985f, -0.052543664f,
|
||||
-0.105841323f, -0.148282051f, -0.179630919f, -0.200000470f,
|
||||
-0.209831516f, -0.209863285f, -0.201094346f, -0.184736015f,
|
||||
-0.162160200f, -0.134843790f, -0.104311776f, -0.072081234f,
|
||||
-0.039608255f, -0.008239664f, +0.020828821f, +0.046586711f,
|
||||
+0.068234131f, +0.085197939f, +0.097138329f, +0.103946126f,
|
||||
+0.105731303f, +0.102803611f, +0.095646450f, +0.084885375f,
|
||||
+0.071252765f, +0.055550276f, +0.038610717f, +0.021260954f,
|
||||
+0.004287292f, -0.011595336f, -0.025769308f, -0.037734535f,
|
||||
-0.047122444f, -0.053703443f, -0.057387924f, -0.058221106f,
|
||||
-0.056372283f, -0.052119261f, -0.045828927f, -0.037935027f,
|
||||
-0.028914291f, -0.019262057f, -0.009468531f, +0.000003302f,
|
||||
+0.008737200f, +0.016379869f, +0.022653298f, +0.027362877f,
|
||||
+0.030401148f, +0.031747267f, +0.031462429f,
|
||||
};
|
||||
|
||||
short dsd_input_filter(short sample, int mode);
|
||||
|
||||
short
|
||||
dmr_filter(short sample)
|
||||
{
|
||||
return dsd_input_filter(sample, 1);
|
||||
}
|
||||
|
||||
short
|
||||
nxdn_filter(short sample)
|
||||
{
|
||||
return dsd_input_filter(sample, 2);
|
||||
}
|
||||
|
||||
|
||||
short
|
||||
dsd_input_filter(short sample, int mode)
|
||||
{
|
||||
float sum; int i;
|
||||
float gain;
|
||||
int zeros;
|
||||
float *v, *coeffs;
|
||||
switch(mode) {
|
||||
case 1:
|
||||
gain = ngain;
|
||||
v = xv;
|
||||
coeffs = xcoeffs;
|
||||
zeros = NZEROS;
|
||||
break;
|
||||
case 2:
|
||||
gain = nxgain;
|
||||
v = nxv;
|
||||
coeffs = nxcoeffs;
|
||||
zeros = NXZEROS;
|
||||
break;
|
||||
default:
|
||||
return sample;
|
||||
}
|
||||
|
||||
for (i = 0; i < zeros; i++)
|
||||
v[i] = v[i+1];
|
||||
|
||||
v[zeros] = sample; // unfiltered sample in
|
||||
sum = 0.0f;
|
||||
|
||||
for (i = 0; i <= zeros; i++)
|
||||
sum += (coeffs[i] * v[i]);
|
||||
|
||||
return sum / ngain; // filtered sample out
|
||||
}
|
||||
33
dsd_main.c
33
dsd_main.c
|
|
@ -257,13 +257,13 @@ usage ()
|
|||
printf ("Decoder options:\n");
|
||||
printf (" -fa Auto-detect frame type (default)\n");
|
||||
printf (" -f1 Decode only P25 Phase 1\n");
|
||||
printf (" -fd Decode only D-STAR*\n");
|
||||
printf (" -fd Decode only D-STAR\n");
|
||||
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
|
||||
printf (" -fn Decode only NXDN96 (12.5 kHz)\n");
|
||||
printf (" -fp Decode only ProVoice*\n");
|
||||
printf (" -fr Decode only DMR/MOTOTRBO\n");
|
||||
printf (" -fx Decode only X2-TDMA\n");
|
||||
printf (" -l Disable cosine filter (improves D-STAR performance)*\n");
|
||||
printf (" -l Disable DMR/MOTOTRBO and NXDN input filtering\n");
|
||||
printf (" -ma Auto-select modulation optimizations (default)\n");
|
||||
printf (" -mc Use only C4FM modulation optimizations\n");
|
||||
printf (" -mg Use only GFSK modulation optimizations\n");
|
||||
|
|
@ -409,13 +409,16 @@ main (int argc, char **argv)
|
|||
printf ("Setting datascope frame rate to %i frame per second.\n", opts.scoperate);
|
||||
break;
|
||||
case 'i':
|
||||
sscanf (optarg, "%s", opts.audio_in_dev);
|
||||
strncpy(opts.audio_in_dev, optarg, 1023);
|
||||
opts.audio_in_dev[1023] = '\0';
|
||||
break;
|
||||
case 'o':
|
||||
sscanf (optarg, "%s", opts.audio_out_dev);
|
||||
strncpy(opts.audio_out_dev, optarg, 1023);
|
||||
opts.audio_out_dev[1023] = '\0';
|
||||
break;
|
||||
case 'd':
|
||||
sscanf (optarg, "%s", opts.mbe_out_dir);
|
||||
strncpy(opts.mbe_out_dir, optarg, 1023);
|
||||
opts.mbe_out_dir[1023] = '\0';
|
||||
printf ("Writing mbe data files to directory %s\n", opts.mbe_out_dir);
|
||||
break;
|
||||
case 'g':
|
||||
|
|
@ -440,7 +443,8 @@ main (int argc, char **argv)
|
|||
printf ("Disabling audio output to soundcard.\n");
|
||||
break;
|
||||
case 'w':
|
||||
sscanf (optarg, "%s", opts.wav_out_file);
|
||||
strncpy(opts.wav_out_file, optarg, 1023);
|
||||
opts.wav_out_file[1023] = '\0';
|
||||
printf ("Writing audio to file %s\n", opts.wav_out_file);
|
||||
openWavOutFile (&opts, &state);
|
||||
break;
|
||||
|
|
@ -448,7 +452,8 @@ main (int argc, char **argv)
|
|||
sscanf (optarg, "%d", &opts.serial_baud);
|
||||
break;
|
||||
case 'C':
|
||||
sscanf (optarg, "%s", opts.serial_dev);
|
||||
strncpy(opts.serial_dev, optarg, 1023);
|
||||
opts.serial_dev[1023] = '\0';
|
||||
break;
|
||||
case 'R':
|
||||
sscanf (optarg, "%d", &opts.resume);
|
||||
|
|
@ -675,14 +680,24 @@ main (int argc, char **argv)
|
|||
opts.split = 1;
|
||||
opts.playoffset = 0;
|
||||
opts.delay = 0;
|
||||
openAudioOutDevice (&opts, 8000);
|
||||
if(strlen(opts.wav_out_file) > 0) {
|
||||
openWavOutFile (&opts, &state);
|
||||
}
|
||||
else {
|
||||
openAudioOutDevice (&opts, 8000);
|
||||
}
|
||||
}
|
||||
else if (strcmp (opts.audio_in_dev, opts.audio_out_dev) != 0)
|
||||
{
|
||||
opts.split = 1;
|
||||
opts.playoffset = 0;
|
||||
opts.delay = 0;
|
||||
openAudioOutDevice (&opts, 8000);
|
||||
if(strlen(opts.wav_out_file) > 0) {
|
||||
openWavOutFile (&opts, &state);
|
||||
}
|
||||
else {
|
||||
openAudioOutDevice (&opts, 8000);
|
||||
}
|
||||
openAudioInDevice (&opts);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
42
dsd_symbol.c
42
dsd_symbol.c
|
|
@ -90,43 +90,13 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
|||
// printf("res: %zd\n, offset: %lld", result, sf_seek(opts->audio_in_file, 0, SEEK_CUR));
|
||||
if (opts->use_cosine_filter)
|
||||
{
|
||||
#define NZEROS 60
|
||||
#define GAIN 7.423339364e+00
|
||||
|
||||
static float xv[NZEROS+1];
|
||||
|
||||
static float xcoeffs[] =
|
||||
{ -0.0083649323, -0.0265444850, -0.0428141462, -0.0537571943,
|
||||
-0.0564141052, -0.0489161045, -0.0310068662, -0.0043393881,
|
||||
+0.0275375106, +0.0595423283, +0.0857543325, +0.1003565948,
|
||||
+0.0986944931, +0.0782804830, +0.0395670487, -0.0136691535,
|
||||
-0.0744390415, -0.1331834575, -0.1788967208, -0.2005995448,
|
||||
-0.1889627181, -0.1378439993, -0.0454976231, +0.0847488694,
|
||||
+0.2444859269, +0.4209222342, +0.5982295474, +0.7593684540,
|
||||
+0.8881539892, +0.9712773915, +0.9999999166, +0.9712773915,
|
||||
+0.8881539892, +0.7593684540, +0.5982295474, +0.4209222342,
|
||||
+0.2444859269, +0.0847488694, -0.0454976231, -0.1378439993,
|
||||
-0.1889627181, -0.2005995448, -0.1788967208, -0.1331834575,
|
||||
-0.0744390415, -0.0136691535, +0.0395670487, +0.0782804830,
|
||||
+0.0986944931, +0.1003565948, +0.0857543325, +0.0595423283,
|
||||
+0.0275375106, -0.0043393881, -0.0310068662, -0.0489161045,
|
||||
-0.0564141052, -0.0537571943, -0.0428141462, -0.0265444850,
|
||||
-0.0083649323,
|
||||
};
|
||||
|
||||
float sum; int i;
|
||||
|
||||
for (i = 0; i < NZEROS; i++)
|
||||
xv[i] = xv[i+1];
|
||||
|
||||
xv[NZEROS] = sample; // unfiltered sample in
|
||||
sum = 0.0;
|
||||
|
||||
for (i = 0; i <= NZEROS; i++)
|
||||
sum += (xcoeffs[i] * xv[i]);
|
||||
|
||||
sample = sum / GAIN; // filtered sample out
|
||||
if (state->lastsynctype >= 10 && state->lastsynctype <= 13)
|
||||
sample = dmr_filter(sample);
|
||||
else if (state->lastsynctype == 8 || state->lastsynctype == 9 ||
|
||||
state->lastsynctype == 16 || state->lastsynctype == 17)
|
||||
sample = nxdn_filter(sample);
|
||||
}
|
||||
|
||||
if ((sample > state->max) && (have_sync == 1) && (state->rf_mod == 0))
|
||||
{
|
||||
sample = state->max;
|
||||
|
|
|
|||
Loading…
Reference in New Issue