Squashed commit of the following:

commit 95d46fb35d
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Mon Mar 25 17:48:57 2024 -0400

    Enable HPF_D by default; Increase manual analog gain to 50;

commit 1f37837664
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Mon Mar 25 08:43:17 2024 -0400

    Enable HPF_D on M17 Voice;

commit 9bbe4de7fd
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Sun Mar 24 16:08:16 2024 -0400

    EDACS: Digitize Analog For Analysis of 'Data Burst' Like Behavior;

commit 9249b7a943
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Sun Mar 24 12:28:26 2024 -0400

    Simply Mono Short Playback;

commit 89ad0f17e3
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Sat Mar 23 21:12:44 2024 -0400

    Add HPF to SS4, SS3, and SS Audio Methods;

commit e8184c7fbd
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Sat Mar 23 17:13:44 2024 -0400

    RTL - Add The Sample / Volume Multiplier as a user configurable option;

commit ee04d11116
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 23:15:04 2024 -0400

    Fix HPF_D so it actually works correctly;

commit e549b21497
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 20:11:34 2024 -0400

    Make Analog Auto Gain Control Mostly Tolerable;

commit 2f9e0525fe
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 18:20:38 2024 -0400

    User Toggle HPF on Digital;

commit ff58d3a6fa
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 18:10:15 2024 -0400

    User Toggles and Displays for Filters;

commit b6fc17c506
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 15:55:09 2024 -0400

    More Analog Manual Audio Gain Tweaks;

commit 076b9fbf04
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 06:26:10 2024 -0400

    Add SQL Hit on EDACS if Colors Disabled;

commit 59fe47ef05
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Fri Mar 22 02:23:08 2024 -0400

    Disable HPF Test on Digital Voice;

commit 4a63068ce1
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 23:39:43 2024 -0400

    Misc Code Organizing; audio_gainA Tweaks;

commit 3585e7e594
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 13:18:31 2024 -0400

    Test Tweak to RTL Sample Multiplier;

commit fa5b25283f
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 13:18:07 2024 -0400

    Adjust Manual Mic Gain on M17 Encoder; Ncurses Display;

commit c985fea035
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 12:34:01 2024 -0400

    Misc Notes on using raw_rms values during testing;

commit b273e5b7be
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 12:31:33 2024 -0400

    Bugfix for EDACS Analog Segfault when using the digitize function for an extended period;

commit eadf3fdf23
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 10:12:04 2024 -0400

    Analog Gain Has Own Variable; Ncurses Keys; Misc;

commit 0debcc647e
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 08:49:51 2024 -0400

    Filtering Misc Cleanup;

commit 98e10b2627
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Thu Mar 21 00:02:21 2024 -0400

    Automatic Gain On Analog WIP; Manual Gain Control;

commit 89736ae543
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Wed Mar 20 10:22:20 2024 -0400

    Passband Filter Testing on Raw Analog / EDACS / M17 Encoder;

commit 43f6218129
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Wed Mar 20 09:03:02 2024 -0400

    Passband and Notch Filter Setup; Debug Output;

commit 35a1b53867
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 19 22:35:36 2024 -0400

    HPF: Only Use On RTL Input when M17 Encoder Uses It;

commit b9949f0d80
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 19 17:31:59 2024 -0400

    Disable LFP on EDACS Analog Out;

commit 3666740674
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 19 13:42:07 2024 -0400

    Test HPF On Digital Voice Out;

commit ef13343925
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 19 12:46:27 2024 -0400

    RTL_FM Input for Analog/M17 Encoder;

commit 2b7de90474
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 19 11:03:55 2024 -0400

    New Analog Audio Filters WIP;
This commit is contained in:
lwvmobile 2024-03-26 17:36:04 -04:00
parent 3b9f9f5a3b
commit 7dd0de67b6
19 changed files with 943 additions and 297 deletions

View File

@ -78,7 +78,7 @@ Detailed Setup:
```
RTL-SDR options:
Usage: rtl:dev:freq:gain:ppm:bw:sq:udp
Usage: rtl:dev:freq:gain:ppm:bw:sq:vol
NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended
dev <num> RTL-SDR Device Index Number
freq <num> RTL-SDR Frequency (851800000 or 851.8M)
@ -86,9 +86,9 @@ RTL-SDR options:
ppm <num> RTL-SDR PPM Error (default = 0)
bw <num> RTL-SDR Bandwidth kHz (default = 12)(8, 12, 16, 24)
sq <num> RTL-SDR Squelch Level vs RMS Value (Optional)
udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)
Example: dsd-fme-zdev -fs -i rtl -C cap_plus_channel.csv -T
Example: dsd-fme-zdev -fp -i rtl:0:851.375M:22:-2:24:0:6021
vol <num> RTL-SDR Sample 'Volume' Multiplier (default = 1)(1,2,3)
Example: dsd-fme -fs -i rtl -C cap_plus_channel.csv -T
Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:24:0:2
```

View File

@ -86,6 +86,35 @@
extern volatile uint8_t exitflag; //fix for issue #136
//new audio filter stuff from: https://github.com/NedSimao/FilteringLibrary
typedef struct {
float coef[2];
float v_out[2];
}LPFilter;
typedef struct {
float coef;
float v_out[2];
float v_in[2];
}HPFilter;
typedef struct {
LPFilter lpf;
HPFilter hpf;
float out_in;
}PBFilter;
typedef struct {
float alpha;
float beta;
float vin[3];
float vout[3];
}NOTCHFilter;
//end new filters
//group csv import struct
typedef struct
{
@ -231,6 +260,7 @@ typedef struct
FILE *symbol_out_f;
float audio_gain;
float audio_gainR;
float audio_gainA;
int audio_out;
int dmr_stereo_wav;
char wav_out_dir[512];
@ -285,6 +315,7 @@ typedef struct
int rtl_started;
long int rtl_rms;
int monitor_input_audio;
int analog_only;
int pulse_raw_rate_in;
int pulse_raw_rate_out;
int pulse_digi_rate_in;
@ -405,6 +436,12 @@ typedef struct
int slot1_on;
int slot2_on;
//enable filter options
int use_lpf;
int use_hpf;
int use_pbf;
int use_hpf_d;
//'DSP' Format Output
uint8_t use_dsp_output;
char dsp_out_file[2048];
@ -507,6 +544,7 @@ typedef struct
char slot0light[8];
float aout_gain;
float aout_gainR;
float aout_gainA;
float aout_max_buf[200];
float aout_max_bufR[200];
float *aout_max_buf_p;
@ -630,6 +668,16 @@ typedef struct
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
//new audio filter structs
LPFilter RCFilter;
HPFilter HRCFilter;
PBFilter PBF;
NOTCHFilter NF;
LPFilter RCFilterL;
HPFilter HRCFilterL;
LPFilter RCFilterR;
HPFilter HRCFilterR;
char dpmr_caller_id[20];
char dpmr_target_id[20];
@ -953,7 +1001,11 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state); //float stere
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
void agsm (dsd_opts * opts, dsd_state * state, short * input, int len); //short gain control for analog things
void analog_gain (dsd_opts * opts, dsd_state * state, short * input, int len); //manual gain handling for analong things
//new short stuff
void playSynthesizedVoiceMS (dsd_opts * opts, dsd_state * state); //short mono mix
void playSynthesizedVoiceMSR (dsd_opts * opts, dsd_state * state); //short mono mix R (needed for OSS 48k input/output)
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
@ -1295,12 +1347,24 @@ void eot_cc(dsd_opts * opts, dsd_state * state); //end of TX return to CC
//Generic Tuning Functions
void return_to_cc (dsd_opts * opts, dsd_state * state);
//misc generic audio filtering for analog at 48k/1
//misc audio filtering for analog
long int raw_rms(short *samples, int len, int step);
void analog_deemph_filter(short * input, int len);
void analog_preemph_filter(short * input, int len);
void analog_dc_block_filter(short * input, int len);
void analog_clipping_filter(short * input, int len);
void init_audio_filters(dsd_state * state);
void lpf(dsd_state * state, short * input, int len);
void hpf(dsd_state * state, short * input, int len);
void pbf(dsd_state * state, short * input, int len);
void nf(dsd_state * state, short * input, int len);
void hpf_dL(dsd_state * state, short * input, int len);
void hpf_dR(dsd_state * state, short * input, int len);
//from: https://github.com/NedSimao/FilteringLibrary
void LPFilter_Init(LPFilter *filter, float cutoffFreqHz, float sampleTimeS);
float LPFilter_Update(LPFilter *filter, float v_in);
void HPFilter_Init(HPFilter *filter, float cutoffFreqHz, float sampleTimeS);
float HPFilter_Update(HPFilter *filter, float v_in);
void PBFilter_Init(PBFilter *filter, float HPF_cutoffFreqHz, float LPF_cutoffFreqHz, float sampleTimeS);
float PBFilter_Update(PBFilter *filter, float v_in);
void NOTCHFilter_Init(NOTCHFilter *filter, float centerFreqHz, float notchWidthHz, float sampleTimeS);
float NOTCHFilter_Update(NOTCHFilter *filter, float vin);
//csv imports
int csvGroupImport(dsd_opts * opts, dsd_state * state);

272
src/3.c
View File

@ -321,4 +321,274 @@ uint16_t q_abs_diff(const uint16_t v1, const uint16_t v2)
//
// Wojciech Kaczmarski, SP5WWP
// M17 Project, 29 December 2023
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//audio filter stuff sourced from: https://github.com/NedSimao/FilteringLibrary
//no license / information provided in source code
#define PI 3.141592653
//do we need this for test input sthit?
// #define PLOT_POINTS 100
// #define SAMPLE_TIME_S 0.001
// #define CUTOFFFREQ_HZ 50
// #define sine_freq 40
// #define sine_freq_1 500
// #define HFC 50
// #define LFC 100
void LPFilter_Init(LPFilter *filter, float cutoffFreqHz, float sampleTimeS)
{
float RC=0.0;
RC=1.0/(2*PI*cutoffFreqHz);
filter->coef[0]=sampleTimeS/(sampleTimeS+RC);
filter->coef[1]=RC/(sampleTimeS+RC);
filter->v_out[0]=0.0;
filter->v_out[1]=0.0;
}
float LPFilter_Update(LPFilter *filter, float v_in)
{
filter->v_out[1]=filter->v_out[0];
filter->v_out[0]=(filter->coef[0]*v_in) + (filter->coef[1]*filter->v_out[1]);
return (filter->v_out[0]);
}
/********************************************************************************************************
* HIGH PASS FILTER
********************************************************************************************************/
void HPFilter_Init(HPFilter *filter, float cutoffFreqHz, float sampleTimeS)
{
float RC=0.0;
RC=1.0/(2*PI*cutoffFreqHz);
filter->coef=RC/(sampleTimeS+RC);
filter->v_in[0]=0.0;
filter->v_in[1]=0.0;
filter->v_out[0]=0.0;
filter->v_out[1]=0.0;
}
float HPFilter_Update(HPFilter *filter, float v_in)
{
filter->v_in[1]=filter->v_in[0];
filter->v_in[0]=v_in;
filter->v_out[1]=filter->v_out[0];
filter->v_out[0]=filter->coef * (filter->v_in[0] - filter->v_in[1]+filter->v_out[1]);
return (filter->v_out[0]);
}
/********************************************************************************************************
* BAND PASS FILTER
********************************************************************************************************/
void PBFilter_Init(PBFilter *filter, float HPF_cutoffFreqHz, float LPF_cutoffFreqHz, float sampleTimeS)
{
LPFilter_Init(&filter->lpf, LPF_cutoffFreqHz, sampleTimeS);
HPFilter_Init(&filter->hpf, HPF_cutoffFreqHz, sampleTimeS);
filter->out_in=0.0;
}
float PBFilter_Update(PBFilter *filter, float v_in)
{
filter->out_in=HPFilter_Update(&filter->hpf, v_in);
filter->out_in=LPFilter_Update(&filter->lpf, filter->out_in);
return (filter->out_in);
}
/********************************************************************************************************
* NOTCH FILTER
********************************************************************************************************/
void NOTCHFilter_Init(NOTCHFilter *filter, float centerFreqHz, float notchWidthHz, float sampleTimeS)
{
//filter frequency to angular (rad/s)
float w0_rps=2.0 * PI *centerFreqHz;
float ww_rps=2.0 * PI *notchWidthHz;
//pre warp center frequency
float w0_pw_rps=(2.0/sampleTimeS) * tanf(0.5 * w0_rps * sampleTimeS);
//computing filter coefficients
filter->alpha=4.0 + w0_rps*w0_pw_rps*sampleTimeS*sampleTimeS;
filter->beta=2.0*ww_rps*sampleTimeS;
//clearing input and output buffers
for (uint8_t n=0; n<3; n++)
{
filter->vin[n]=0;
filter->vout[n]=0;
}
}
float NOTCHFilter_Update(NOTCHFilter *filter, float vin)
{
//shifting samples
filter->vin[2]=filter->vin[1];
filter->vin[1]=filter->vin[0];
filter->vout[2]=filter->vout[1];
filter->vout[1]=filter->vout[0];
filter->vin[0]=vin;
//compute new output
filter->vout[0]=(filter->alpha*filter->vin[0] + 2.0 *(filter->alpha -8.0)*filter->vin[1] + filter->alpha*filter->vin[2]
-(2.0f*(filter->alpha-8.0)*filter->vout[1]+(filter->alpha-filter->beta)*filter->vout[2]))/(filter->alpha+filter->beta);
return (filter->vout[0]);
}
void init_audio_filters (dsd_state * state)
{
//still not sure if this is even correct or not, but 48k sounds good now
LPFilter_Init(&state->RCFilter, 960, (float)1/(float)48000);
HPFilter_Init(&state->HRCFilter, 960, (float)1/(float)48000);
//left and right variants for stereo output testing on digital voice samples
LPFilter_Init(&state->RCFilterL, 960, (float)1/(float)16000);
HPFilter_Init(&state->HRCFilterL, 960, (float)1/(float)16000);
LPFilter_Init(&state->RCFilterR, 960, (float)1/(float)16000);
HPFilter_Init(&state->HRCFilterR, 960, (float)1/(float)16000);
//PBFilter_Init(PBFilter *filter, float HPF_cutoffFreqHz, float LPF_cutoffFreqHz, float sampleTimeS);
//NOTCHFilter_Init(NOTCHFilter *filter, float centerFreqHz, float notchWidthHz, float sampleTimeS);
//NOTE: PBFilter_init also inits a LPF and HPF, but on another set of filters, might be worth
//testing just using the PBFilter by itself and see how it does without the hpf used
//passband filter working (seems to be), notch filter unsure which values to use, doesn't have any appreciable affect when used as is
PBFilter_Init(&state->PBF, 8000, 12000, (float)1/(float)1536000); //RTL Sampling at 1536000 S/s.
NOTCHFilter_Init(&state->NF, 1000, 4000, (float)1/(float)1536000);
}
//FUNCTIONS for handing use of above filters
//lpf
void lpf(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = LPFilter_Update(&state->RCFilter, input[i]);
// fprintf (stderr, "\n out: %05d", input[i]);
}
}
//hpf
void hpf(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = HPFilter_Update(&state->HRCFilter, input[i]);
// fprintf (stderr, "\n out: %05d", input[i]);
}
}
//hpf digital left
void hpf_dL(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = HPFilter_Update(&state->HRCFilterL, input[i]);
// fprintf (stderr, "\n out: %05d", input[i]);
}
}
//hpf digital right
void hpf_dR(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = HPFilter_Update(&state->HRCFilterR, input[i]);
// fprintf (stderr, "\n out: %05d", input[i]);
}
}
//nf
void nf(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = NOTCHFilter_Update(&state->NF, input[i]);
// fprintf (stderr, "\n out: %05d", input[i]);
}
}
//pbf
void pbf(dsd_state * state, short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
// fprintf (stderr, "\n in: %05d", input[i]);
input[i] = PBFilter_Update(&state->PBF, input[i]);
}
}
//Generic RMS function derived from RTL_FM (RTL_SDR) RMS code (doesnt' really work correctly outside of RTL)
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; i<len; i+=step) {
s = (long)samples[i];
t += s;
p += s * s;
}
/* correct for dc offset in squares */
dc = (double)(t*step) / (double)len;
err = t * 2 * dc - dc * dc * len;
rms = (long int)sqrt((p-err) / len);
if (rms < 0) rms = 150;
return rms;
}

View File

@ -478,7 +478,7 @@ void processdPMRvoice (dsd_opts * opts, dsd_state * state)
{
processMbeFrame (opts, state, NULL, ambe_fr[i], NULL);
if (opts->floating_point == 0)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);
}

View File

@ -12,6 +12,9 @@
#include "dsd.h"
#include <math.h>
//NOTE: Tones produce ringing sound when put through the hpf_d, may want to look into tweaking it,
//or looking for a way to store is_tone by glancing at ambe_d values and not running hpf_d on them
//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)
@ -721,6 +724,128 @@ void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state)
}
//Mono - Short (SB16LE) - Drop-in replacement for playSyntesizedVoice, but easier to manipulate
void playSynthesizedVoiceMS (dsd_opts * opts, dsd_state * state)
{
int i;
size_t len = state->audio_out_idx;
//debug
// fprintf (stderr, " L LEN: %d", len);
short mono_samp[len];
memset (mono_samp, 0, len*sizeof(short));
if (opts->slot1_on == 0)
goto MS_END;
if (len == 160)
{
for (i = 0; i < len; i++)
mono_samp[i] = state->s_l[i];
}
else if (len == 960)
{
state->audio_out_buf_p -= 960; //rewind first
for (i = 0; i < len; i++)
{
mono_samp[i] = *state->audio_out_buf_p;
state->audio_out_buf_p++;
}
}
if (opts->use_hpf_d == 1)
hpf_dL(state, state->s_l, len);
if (opts->audio_out_type == 0) //Pulse Audio
pa_simple_write(opts->pulse_digi_dev_out, mono_samp, len*2, NULL);
if (opts->audio_out_type == 8) //UDP Audio
udp_socket_blaster (opts, state, len*2, mono_samp);
if (opts->audio_out_type == 1 || opts->audio_out_type == 2 || opts->audio_out_type == 5) //STDOUT or OSS
write (opts->audio_out_fd, mono_samp, len*2);
MS_END:
//run cleanup since we pulled stuff from processAudio
state->audio_out_idx = 0;
//set short temp buffer to baseline
memset (state->s_l, 0, sizeof(state->s_l));
if (state->audio_out_idx2 >= 800000)
{
state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float));
memset (state->audio_out_buf, 0, 100 * sizeof (short));
state->audio_out_idx2 = 0;
}
}
//Mono - Short (SB16LE) - Drop-in replacement for playSyntesizedVoiceR, but easier to manipulate
void playSynthesizedVoiceMSR (dsd_opts * opts, dsd_state * state)
{
int i;
size_t len = state->audio_out_idxR;
//debug
// fprintf (stderr, " R LEN: %d", len);
short mono_samp[len];
memset (mono_samp, 0, len*sizeof(short));
if (opts->slot2_on == 0)
goto MS_ENDR;
if (len == 160)
{
for (i = 0; i < len; i++)
mono_samp[i] = state->s_r[i];
}
else if (len == 960)
{
state->audio_out_buf_pR -= 960; //rewind first
for (i = 0; i < len; i++)
{
mono_samp[i] = *state->audio_out_buf_pR;
state->audio_out_buf_pR++;
}
}
if (opts->use_hpf_d == 1)
hpf_dR(state, mono_samp, len);
if (opts->audio_out_type == 0) //Pulse Audio
pa_simple_write(opts->pulse_digi_dev_out, mono_samp, len*2, NULL);
if (opts->audio_out_type == 8) //UDP Audio
udp_socket_blaster (opts, state, len*2, mono_samp);
if (opts->audio_out_type == 1 || opts->audio_out_type == 2 || opts->audio_out_type == 5) //STDOUT or OSS
write (opts->audio_out_fd, mono_samp, len*2);
MS_ENDR:
//run cleanup since we pulled stuff from processAudioR
state->audio_out_idxR = 0;
//set short temp buffer to baseline
memset (state->s_r, 0, sizeof(state->s_r));
if (state->audio_out_idx2R >= 800000)
{
state->audio_out_float_buf_pR = state->audio_out_float_bufR + 100;
state->audio_out_buf_pR = state->audio_out_bufR + 100;
memset (state->audio_out_float_bufR, 0, 100 * sizeof (float));
memset (state->audio_out_bufR, 0, 100 * sizeof (short));
state->audio_out_idx2R = 0;
}
}
//Stereo Mix - Short (SB16LE) -- When Playing Short FDMA samples when setup for stereo output
void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state)
{
@ -728,7 +853,7 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state)
int i;
int encL;
short stereo_samp1[320]; //8k 2-channel stereo interleave mix
memset (stereo_samp1, 1, sizeof(stereo_samp1));
memset (stereo_samp1, 0, sizeof(stereo_samp1));
//enc checkdown for whether or not to fill the stereo sample or not for playback or writing
encL = 0;
@ -785,6 +910,10 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state)
//likewise, override and unmute if TG hold matches TG
if (state->tg_hold != 0 && state->tg_hold == TGL) encL = 0;
//test hpf
if (opts->use_hpf_d == 1)
hpf_dL(state, state->s_l, 160);
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
{
@ -951,6 +1080,18 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
if (state->tg_hold != 0 && state->tg_hold == TGL) encL = 0;
if (state->tg_hold != 0 && state->tg_hold == TGR) encR = 0;
//test hpf
if (opts->use_hpf_d == 1)
{
hpf_dL(state, state->s_l4[0], 160);
hpf_dL(state, state->s_l4[1], 160);
hpf_dL(state, state->s_l4[2], 160);
hpf_dR(state, state->s_r4[0], 160);
hpf_dR(state, state->s_r4[1], 160);
hpf_dR(state, state->s_r4[2], 160);
}
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
{
@ -1045,7 +1186,7 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
short stereo_samp2[320]; //8k 2-channel stereo interleave mix
short stereo_samp3[320]; //8k 2-channel stereo interleave mix
short stereo_samp4[320];
short empss[160]; //this is used to see if we want to run HPF on an empty set
short empty[320]; //this is used to see if we want to play a single 2v or double 2v or not
memset (stereo_samp1, 0, sizeof(stereo_samp1));
@ -1054,7 +1195,7 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
memset (stereo_samp4, 0, sizeof(stereo_samp4));
memset (empty, 0, sizeof(empty));
memset (empss, 0, sizeof(empss));
//p25p2 enc checkdown for whether or not to fill the stereo sample or not for playback or writing
encL = encR = 1;
@ -1137,6 +1278,24 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
if (state->tg_hold != 0 && state->tg_hold == TGL) encL = 0;
if (state->tg_hold != 0 && state->tg_hold == TGR) encR = 0;
//test hpf
if (opts->use_hpf_d == 1)
{
hpf_dL(state, state->s_l4[0], 160);
hpf_dL(state, state->s_l4[1], 160);
if (memcmp(empss, state->s_l4[2], sizeof(empss)) != 0)
hpf_dL(state, state->s_l4[2], 160);
if (memcmp(empss, state->s_l4[3], sizeof(empss)) != 0)
hpf_dL(state, state->s_l4[3], 160);
hpf_dR(state, state->s_r4[0], 160);
hpf_dR(state, state->s_r4[1], 160);
if (memcmp(empss, state->s_r4[2], sizeof(empss)) != 0)
hpf_dR(state, state->s_r4[2], 160);
if (memcmp(empss, state->s_r4[3], sizeof(empss)) != 0)
hpf_dR(state, state->s_r4[3], 160);
}
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
{
@ -1349,64 +1508,75 @@ void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot)
}
//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.0f, sizeof(empty));
//automatic gain short mono for analog audio and some digital mono (WIP)
void agsm (dsd_opts * opts, dsd_state * state, short * input, int len)
{
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
UNUSED(opts);
// 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);
//NOTE: This seems to be doing better now that I got it worked out properly
//This may produce a mild buzz sound though on the low end
// //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;
float avg = 0.0f; //average of 20 samples
float coeff = 0.0f; //gain coeffiecient
float max = 0.0f; //the highest sample value
float nom = 4800.0f; //nominator value for 48k
float samp[960]; memset (samp, 0.0f, 960*sizeof(float));
// for (i = 0; i < 160; i++)
// {
//assign internal float from short input
for (i = 0; i < len; i++)
samp[i] = (float)input[i];
// samp[i] = samp[i] / df;
for (i = 0; i < len; i++)
{
if ( fabsf (samp[i]) > max)
{
max = fabsf (samp[i]);
}
}
// aavg += fabsf(samp[i]);
for (i = 0; i < len; i++)
avg += (float)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);
avg /= (float)len;
// AGF_END: ; //do nothing
coeff = fabsf (nom / max);
// }
//keep coefficient with tolerable range when silence to prevent crackle/buzz
if (coeff > 3.0f) coeff = 3.0f;
//apply the coefficient to bring the max value to our desired maximum value
for (i = 0; i < 20; i++)
samp[i] *= coeff;
//debug
// fprintf (stderr, "\n M: %f; C: %f; A: %f; ", max, coeff, avg);
// debug
// for (i = 0; i < len; i++)
// {
// fprintf (stderr, " in: %d", input[i]);
// fprintf (stderr, " out: %f", samp[i]);
// }
//return new smaple values post agc
for (i = 0; i < len; i++)
input[i] = (short)samp[i];
state->aout_gainA = coeff; //store for internal use
}
//until analog agc is fixed, going to use a manual gain control on this
void analog_gain (dsd_opts * opts, dsd_state * state, short * input, int len)
{
int i;
UNUSED(state);
float gain = (opts->audio_gainA / 100.0f) * 5.0f; //scale 0x - 5x
for (i = 0; i < len; i++)
input[i] *= gain;
}

View File

@ -195,7 +195,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
int lmin, lmax, lidx;
//assign t_max value based on decoding type expected (all non-auto decodes first)
int t_max; //maximum values allowed for t will depend on decoding type - NXDN will be 10, others will be more
int t_max = 24; //initialize as an actual value to prevent any overflow related issues
if (opts->frame_nxdn48 == 1 || opts->frame_nxdn96 == 1)
{
t_max = 10;
@ -218,6 +218,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
{
t_max = 19; //Phase 2 S-ISCH is only 19
}
else if (opts->analog_only == 1) //shim to make sure this is set to a reasonable value
{
t_max = 24;
}
else t_max = 24; //24 for everything else
int lbuf[48], lbuf2[48]; //if we use t_max in these arrays, and t >= t_max in condition below, then it can overflow those checks in there if t exceeds t_max

View File

@ -583,6 +583,7 @@ initOpts (dsd_opts * opts)
opts->mbe_out_fR = NULL; //second slot on a TDMA system
opts->audio_gain = 0;
opts->audio_gainR = 0;
opts->audio_gainA = 50.0f; //scale of 1 - 100
opts->audio_out = 1;
opts->wav_out_file[0] = 0;
opts->wav_out_fileR[0] = 0;
@ -691,6 +692,7 @@ initOpts (dsd_opts * opts)
opts->dmr_mute_encR = 1;
opts->monitor_input_audio = 0; //enable with -8
opts->analog_only = 0; //only turned on with -fA
opts->inverted_p2 = 0;
opts->p2counter = 0;
@ -766,6 +768,12 @@ initOpts (dsd_opts * opts)
opts->slot1_on = 1;
opts->slot2_on = 1;
//enable filter options
opts->use_lpf = 0;
opts->use_hpf = 1;
opts->use_pbf = 1;
opts->use_hpf_d = 1;
//dsp structured file
opts->dsp_out_file[0] = 0;
opts->use_dsp_output = 0;
@ -899,6 +907,7 @@ initState (dsd_state * state)
sprintf (state->slot2light, "%s", "");
state->aout_gain = 25.0f;
state->aout_gainR = 25.0f;
state->aout_gainA = 0.0f; //use purely as a display or internal value, no user setting
memset (state->aout_max_buf, 0, sizeof (float) * 200);
state->aout_max_buf_p = state->aout_max_buf;
state->aout_max_buf_idx = 0;
@ -1236,7 +1245,7 @@ usage ()
printf (" /dev/dsp for OSS audio (Depreciated: Will require padsp wrapper in Linux) \n");
#endif
printf (" rtl for rtl dongle (Default Values -- see below)\n");
printf (" rtl:dev:freq:gain:ppm:bw:sq:udp for rtl dongle (see below)\n");
printf (" rtl:dev:freq:gain:ppm:bw:sq:vol for rtl dongle (see below)\n");
printf (" tcp for tcp client SDR++/GNURadio Companion/Other (Port 7355)\n");
printf (" tcp:192.168.7.5:7355 for custom address and port \n");
printf (" filename.bin for OP25/FME capture bin files\n");
@ -1283,12 +1292,12 @@ usage ()
// #ifdef AERO_BUILD
printf (" If using /dev/dsp input and output at 48k1, launch two instances of DSD-FME w -V 1 and -V 2 if needed");
// #endif
printf (" (Audio Smoothing is now disabled on all upsampled output by default -- fix crackle/buzz bug)\n");
// printf (" (Audio Smoothing is now disabled on all upsampled output by default -- fix crackle/buzz bug)\n");
printf (" -z Set TDMA Voice Slot Preference when using /dev/dsp audio output (prevent lag and stuttering)\n");
printf (" -y Enable Experimental Pulse Audio Float Audio Output\n");
printf ("\n");
printf ("RTL-SDR options:\n");
printf (" Usage: rtl:dev:freq:gain:ppm:bw:sq:udp\n");
printf (" Usage: rtl:dev:freq:gain:ppm:bw:sq:vol\n");
printf (" NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended\n");
printf (" dev <num> RTL-SDR Device Index Number or 8 Digit Serial Number, no strings! (default 0)\n");
printf (" freq <num> RTL-SDR Frequency (851800000 or 851.8M) \n");
@ -1296,9 +1305,10 @@ usage ()
printf (" ppm <num> RTL-SDR PPM Error (default = 0)\n");
printf (" bw <num> RTL-SDR Bandwidth kHz (default = 12)(4, 6, 8, 12, 16, 24) \n");
printf (" sq <num> RTL-SDR Squelch Level vs RMS Value (Optional)\n");
printf (" udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)\n");
// printf (" udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)\n"); //NOTE: This is still available as an option in the ncurses menu
printf (" vol <num> RTL-SDR Sample 'Volume' Multiplier (default = 1)(1,2,3)\n");
printf (" Example: dsd-fme -fs -i rtl -C cap_plus_channel.csv -T\n");
printf (" Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:24:0:6021\n");
printf (" Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:24:0:2\n");
printf ("\n");
printf ("Encoder options:\n");
printf (" -fZ M17 Stream Voice Encoder\n");
@ -1640,7 +1650,7 @@ main (int argc, char **argv)
initOpts (&opts);
initState (&state);
init_audio_filters(&state); //audio filters
InitAllFecFunction();
// CNXDNConvolution_init(); //seems to function better without initting it
@ -2027,6 +2037,7 @@ main (int argc, char **argv)
case 'g':
sscanf (optarg, "%f", &opts.audio_gain);
opts.audio_gainA = opts.audio_gain; //straight assignment
if (opts.audio_gain < (float) 0 )
{
fprintf (stderr,"Disabling audio out gain setting\n");
@ -2108,6 +2119,7 @@ main (int argc, char **argv)
opts.dmr_mono = 0;
state.rf_mod = 0;
opts.monitor_input_audio = 1;
opts.analog_only = 1;
sprintf (opts.output_name, "Analog Monitor");
fprintf (stderr,"Only Monitoring Passive Analog Signal\n");
}
@ -2178,14 +2190,13 @@ main (int argc, char **argv)
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 12500;
// opts.setmod_bw = 16000;
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding only ProVoice frames.\n");
fprintf (stderr,"EDACS Analog Voice Channels are Experimental.\n");
//rtl specific tweaks
//misc tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
}
else if (optarg[0] == 'h') //standard / net w/o ESK
{
@ -2611,6 +2622,10 @@ main (int argc, char **argv)
opts.m17encoder = 1;
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
//filters disabled by default, use ncurses VBN switches
opts.use_lpf = 0;
opts.use_hpf = 0;
opts.use_pbf = 0;
sprintf (opts.output_name, "M17 Encoder");
}
else if (optarg[0] == 'B') //Captial B to Run the M17 BRT encoder
@ -2901,8 +2916,12 @@ main (int argc, char **argv)
if (curr != NULL) opts.rtl_squelch_level = atoi (curr);
else goto RTLEND;
curr = strtok(NULL, ":"); //rtl udp port "-U"
if (curr != NULL) opts.rtl_udp_port = atoi (curr);
// curr = strtok(NULL, ":"); //rtl udp port "-U"
// if (curr != NULL) opts.rtl_udp_port = atoi (curr);
// else goto RTLEND;
curr = strtok(NULL, ":"); //rtl sample / volume multiplier
if (curr != NULL) opts.rtl_volume_multiplier = atoi (curr);
else goto RTLEND;
RTLEND:
@ -2934,15 +2953,19 @@ main (int argc, char **argv)
}
if (opts.rtl_volume_multiplier > 3 || opts.rtl_volume_multiplier < 0)
opts.rtl_volume_multiplier = 1; //I wonder if you could flip polarity by using -1
fprintf (stderr, "Dev %d ", opts.rtl_dev_index);
fprintf (stderr, "Freq %d ", opts.rtlsdr_center_freq);
fprintf (stderr, "Gain %d ", opts.rtl_gain_value);
fprintf (stderr, "PPM %d ", opts.rtlsdr_ppm_error);
fprintf (stderr, "BW %d ", opts.rtl_bandwidth);
fprintf (stderr, "SQ %d ", opts.rtl_squelch_level);
fprintf (stderr, "UDP %d \n", opts.rtl_udp_port);
// fprintf (stderr, "UDP %d \n", opts.rtl_udp_port);
fprintf (stderr, "VOL %d \n", opts.rtl_volume_multiplier);
opts.audio_in_type = 3;
state.audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
// opts.rtl_volume_multiplier = 2; //TODO: Make this an extra value on the end
rtl_ok = 1;
#endif

View File

@ -134,7 +134,7 @@ void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
if (opts->audio_out == 1 && opts->floating_point == 0)
{
playSynthesizedVoice (opts, state);
playSynthesizedVoiceMS (opts, state);
}
if (opts->floating_point == 1)
{
@ -174,7 +174,7 @@ void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
if (opts->audio_out == 1 && opts->floating_point == 0)
{
playSynthesizedVoice (opts, state);
playSynthesizedVoiceMS (opts, state);
}
if (opts->floating_point == 1)
{
@ -1084,7 +1084,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
if (opts->audio_out == 1 && opts->floating_point == 0 && opts->audio_out_type == 5 && opts->slot1_on == 1) //for OSS 48k 1 channel configs -- relocate later if possible
{
playSynthesizedVoice (opts, state); //it may be more beneficial to move this to each individual decoding type to handle, but ultimately, let's just simpifly mbe handling instead
playSynthesizedVoiceMS (opts, state); //it may be more beneficial to move this to each individual decoding type to handle, but ultimately, let's just simpifly mbe handling instead
}
}
@ -1161,7 +1161,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
}
if (opts->audio_out == 1 && opts->floating_point == 0 && opts->audio_out_type == 5 && opts->slot2_on == 1) //for OSS 48k 1 channel configs -- relocate later if possible
{
playSynthesizedVoiceR (opts, state);
playSynthesizedVoiceMSR (opts, state);
}
}

View File

@ -115,7 +115,7 @@ void soft_mbe (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char amb
PrintAMBEData (opts, state, ambe_d);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoiceFM(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
@ -138,7 +138,7 @@ void soft_mbe (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char amb
PrintAMBEData (opts, state, ambe_d);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoiceFM(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)

View File

@ -728,6 +728,17 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
wscanw(entry_win, "%d", &opts->rtl_udp_port);
noecho();
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " RTL Vol Multiplier (1,2,3) (Default = 1): ");
mvwprintw(entry_win, 3, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &opts->rtl_volume_multiplier);
if (opts->rtl_volume_multiplier > 3 || opts->rtl_volume_multiplier < 0)
opts->rtl_volume_multiplier = 1;
noecho();
entry_win = newwin(8, WIDTH+22, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " RTL RMS Squelch Level (NXDN/dPMR/Analog/Raw only): ");
@ -766,19 +777,20 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
}
entry_win = newwin(17, WIDTH+20, starty+10, startx+10);
entry_win = newwin(18, WIDTH+20, starty+10, startx+10);
box (entry_win, 0, 0);
mvwprintw(entry_win, 2, 2, " Starting RTL Input. Cannot Release/Stop Until Exit.");
mvwprintw(entry_win, 4, 2, " RTL Frequency: %d Hz", opts->rtlsdr_center_freq);
mvwprintw(entry_win, 5, 2, " RTL Device Index Number: %d; SN:%s", opts->rtl_dev_index, serial);
mvwprintw(entry_win, 6, 2, " RTL Device Bandwidth: %d kHz", opts->rtl_bandwidth);
mvwprintw(entry_win, 7, 2, " RTL Device Gain: %d", opts->rtl_gain_value);
mvwprintw(entry_win, 8, 2, " RTL Device UDP Port: %d", opts->rtl_udp_port);
mvwprintw(entry_win, 9, 2, " RTL Device PPM: %d", opts->rtlsdr_ppm_error);
mvwprintw(entry_win, 10, 2, " RTL RMS Squelch: %d", opts->rtl_squelch_level);
mvwprintw(entry_win, 12, 2, " Are You Sure?");
mvwprintw(entry_win, 13, 2, " 1 = Yes, 2 = No ");
mvwprintw(entry_win, 14, 3, " ");
mvwprintw(entry_win, 8, 2, " RTL Volume Multiplier: %d", opts->rtl_volume_multiplier);
mvwprintw(entry_win, 9, 2, " RTL Device UDP Port: %d", opts->rtl_udp_port);
mvwprintw(entry_win, 10, 2, " RTL Device PPM: %d", opts->rtlsdr_ppm_error);
mvwprintw(entry_win, 11, 2, " RTL RMS Squelch: %d", opts->rtl_squelch_level);
mvwprintw(entry_win, 13, 2, " Are You Sure?");
mvwprintw(entry_win, 14, 2, " 1 = Yes, 2 = No ");
mvwprintw(entry_win, 15, 3, " ");
echo();
refresh();
wscanw(entry_win, "%d", &confirm);
@ -2344,7 +2356,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("--Input Output----------------------------------------------------------------\n");
if (opts->audio_in_type == 0)
{
printw ("| Pulse Audio Input: %i kHz; %i Channel; ", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels);
printw ("| Pulse Signal Input: %i kHz; %i Ch; ", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels);
if (opts->use_rigctl == 1)
printw ("RIG: %s:%d; ", opts->tcp_hostname, opts->rigctlportno);
printw ("\n");
@ -2352,7 +2364,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 5)
{
printw ("| OSS Audio Input: %i kHz; 1 Channel;", SAMPLE_RATE_IN/1000);
printw ("| OSS Signal Input: %i kHz; 1 Ch;", SAMPLE_RATE_IN/1000);
if (opts->use_rigctl == 1)
printw ("RIG: %s:%d; ", opts->tcp_hostname, opts->rigctlportno);
printw ("\n");
@ -2365,7 +2377,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 8)
{
printw ("| TCP Audio Input: %s:%d; %d kHz 1 Channel; ", opts->tcp_hostname, opts->tcp_portno, opts->wav_sample_rate/1000);
printw ("| TCP Signal Input: %s:%d; %d kHz; 1 Ch; ", opts->tcp_hostname, opts->tcp_portno, opts->wav_sample_rate/1000);
if (opts->use_rigctl == 1)
printw ("RIG: %s:%d; ", opts->tcp_hostname, opts->rigctlportno);
printw ("\n");
@ -2386,13 +2398,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{
printw ("| RTL: %d;", opts->rtl_dev_index);
if (opts->rtl_gain_value == 0)
printw (" Gain: AGC;");
printw (" G: AGC;");
else
printw (" Gain: %idB;", opts->rtl_gain_value);
printw (" G: %idB;", opts->rtl_gain_value);
printw (" V: %iX;", opts->rtl_volume_multiplier);
printw (" PPM: %i;", opts->rtlsdr_ppm_error);
printw (" SQ: %i;", opts->rtl_squelch_level);
printw (" RMS: %04li;", opts->rtl_rms);
printw (" BW: %i kHz;", opts->rtl_bandwidth);
printw (" BW: %i;", opts->rtl_bandwidth);
printw (" FRQ: %i;", opts->rtlsdr_center_freq);
if (opts->rtl_udp_port != 0) printw ("\n| External RTL Tuning on UDP Port: %i", opts->rtl_udp_port);
printw ("\n");
@ -2400,11 +2413,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_out_type == 0)
{
printw ("| Pulse Audio Output: %i kHz; %i Ch; G: %02.0f%%", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels, state->aout_gain*2);
printw ("| Pulse Digital Output: %i kHz; %i Ch; G: %02.0f%%", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels, state->aout_gain*2);
if (opts->pulse_digi_out_channels == 2) printw (" G: %02.0f%%", state->aout_gainR*2);
if (opts->floating_point == 1) printw (" FLOAT: %02.0f%%;", opts->audio_gain*2);
if (opts->audio_gain == 0) printw (" (+/-) Auto");
if (opts->audio_gain > 0) printw (" (+/-) Manual");
if (opts->audio_gain == 0) printw (" (+|-) Auto");
if (opts->audio_gain > 0) printw (" (+|-) Manual");
if (opts->use_hpf_d == 1) printw (" HPF");
if (opts->call_alert == 1) printw (" *CA!"); //Call Alert
// if (state->audio_smoothing == 1 && opts->floating_point == 0) printw (" Smoothing On;"); //only on short
printw (" \n");
@ -2412,7 +2426,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if ( opts->audio_out_type == 0 && (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) )
{
printw ("| Pulse Audio Output: %i kHz; %i Ch; Analog Monitor RMS: %04ld ", opts->pulse_raw_rate_out/1000, opts->pulse_raw_out_channels, opts->rtl_rms);
printw ("| Pulse Analog Output: %i kHz; %i Ch; G: %02.0f%% (/|*) ", opts->pulse_raw_rate_out/1000, opts->pulse_raw_out_channels, opts->audio_gainA);
if (opts->audio_gainA == 0.0f) printw ("Auto ");
else printw ("Manual ");
if (opts->audio_in_type != 3) printw ("RMS: %04ld; ", opts->rtl_rms);
if (opts->use_lpf == 1) printw ("F: |LP|"); else printw ("F: | |");
if (opts->use_hpf == 1) printw ("HP|"); else printw (" |");
if (opts->use_pbf == 1) printw ("PB|"); else printw (" |");
printw (" \n");
}
@ -2422,6 +2442,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->pulse_digi_out_channels == 2) printw (" G: %02.0f%%", state->aout_gainR*2);
if (opts->audio_gain == 0) printw (" (+/-) Auto");
if (opts->audio_gain > 0) printw (" (+/-) Manual");
if (opts->use_hpf_d == 1) printw (" HPF");
if (opts->call_alert == 1) printw (" *CA!"); //Call Alert
// if (state->audio_smoothing == 1 && opts->floating_point == 0) printw (" Smoothing On;"); //only on short
if ( (opts->audio_out_type == 5 && opts->pulse_digi_rate_out == 48000 && opts->pulse_digi_out_channels == 1) && (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) )
@ -2431,17 +2452,22 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_out_type == 8)
{
printw ("| UDP Audio Output: %s:%d; %d kHz %d Ch; %02.0f%%", opts->udp_hostname, opts->udp_portno, opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels, state->aout_gain*2);
printw ("| UDP Digital Output: %s:%d; %d kHz %d Ch; %02.0f%%", opts->udp_hostname, opts->udp_portno, opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels, state->aout_gain*2);
if (opts->pulse_digi_out_channels == 2) printw (" G: %02.0f%%", state->aout_gainR*2);
if (opts->audio_gain == 0) printw (" (+/-) Auto");
if (opts->audio_gain > 0) printw (" (+/-) Manual");
if (opts->use_hpf_d == 1) printw (" HPF");
if (opts->call_alert == 1) printw (" *CA!"); //Call Alert
if ( (opts->audio_out_type == 5 && opts->pulse_digi_rate_out == 48000 && opts->pulse_digi_out_channels == 1) && (opts->frame_provoice == 1 || opts->monitor_input_audio == 1) )
printw (" - Monitor RMS: %04ld ", opts->rtl_rms);
printw (" \n");
if (opts->udp_sockfdA != 0) //Analog Output on udp port +2
{
printw ("| UDP Audio Output: %s:%d; 48 kHz 1 Ch; Analog Output; ", opts->udp_hostname, opts->udp_portno+2);
printw ("| UDP Analog Output: %s:%d; 48 kHz 1 Ch; ", opts->udp_hostname, opts->udp_portno+2);
if (opts->audio_in_type != 3) printw ("RMS: %04ld; ", opts->rtl_rms);
if (opts->use_lpf == 1) printw ("F: |LP|"); else printw ("F: | |");
if (opts->use_hpf == 1) printw ("HP|"); else printw (" |");
if (opts->use_pbf == 1) printw ("PB|"); else printw (" |");
printw (" \n");
}
}
@ -2621,7 +2647,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->mod_gfsk == 1) printw ("[GFSK]");
printw ( "[%d] \n", (48000*opts->wav_interpolator)/state->samplesPerSymbol);
if (opts->m17encoder == 1) printw ("| Encoding: [%s] ", opts->output_name);
if (opts->m17encoder == 1) printw ("(\\) \n");
if (opts->m17encoder == 1) printw (" Toggle (\\); ");
if (opts->m17encoder == 1) printw (" Mic Gain (/|*): %02.0f%% ", opts->audio_gainA);
if (opts->m17encoder == 1)
{
if (opts->use_lpf == 1) printw ("F: |LP|"); else printw ("F: | |");
if (opts->use_hpf == 1) printw ("HP|"); else printw (" |");
if (opts->use_pbf == 1) printw ("PB|"); else printw (" |");
printw ("\n");
}
printw ("| Decoding: [%s] ", opts->output_name);
if (opts->aggressive_framesync == 0) printw ("CRC/(RAS) ");
//debug -- troubleshoot voice tuning after grant on DMR CC, subsequent grant may not tune because tuner isn't available
@ -3920,6 +3954,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (c == 42) // * key, increment audio_gainA
{
if (opts->audio_gainA < 100)
opts->audio_gainA++;
}
if (c == 47) // / key, decrement audio_gainA
{
if (opts->audio_gainA > 0)
opts->audio_gainA--;
}
if (c == 122) //'z' key, toggle payload to console
{
if (opts->payload == 1) opts->payload = 0;
@ -4544,6 +4590,30 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
}
if (c == 86) // 'V' Key, toggle LPF
{
if (opts->use_lpf == 0) opts->use_lpf = 1;
else opts->use_lpf = 0;
}
if (c == 66) // 'B' Key, toggle HPF
{
if (opts->use_hpf == 0) opts->use_hpf = 1;
else opts->use_hpf = 0;
}
if (c == 78) // 'N' Key, toggle PBF
{
if (opts->use_pbf == 0) opts->use_pbf = 1;
else opts->use_pbf = 0;
}
if (c == 72) // 'H' Key, toggle HPF on digital
{
if (opts->use_hpf_d == 0) opts->use_hpf_d = 1;
else opts->use_hpf_d = 0;
}
if (opts->m17encoder == 1 && c == 92) //'\' key - toggle M17 encoder Encode + TX
{
if (state->m17encoder_tx == 0) state->m17encoder_tx = 1;

View File

@ -17,29 +17,6 @@
#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; i<len; i+=step) {
s = (long)samples[i];
t += s;
p += s * s;
}
/* correct for dc offset in squares */
dc = (double)(t*step) / (double)len;
err = t * 2 * dc - dc * dc * len;
rms = (long int)sqrt((p-err) / len);
if (rms < 0) rms = 150;
return rms;
}
int
getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
{
@ -301,14 +278,30 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
sf_write_sync (opts->wav_out_raw);
}
//test running analog audio through a de-emphasis filter
analog_deemph_filter(state->analog_out, 960);
//and dc_block filter analog_dc_block_filter
analog_dc_block_filter(state->analog_out, 960);
//test running analog audio through a pre-emphasis filter
analog_preemph_filter(state->analog_out, 960);
//test running analog short sample clipping filter
analog_clipping_filter(state->analog_out, 960);
//low pass filter
if (opts->use_lpf == 1)
lpf(state, state->analog_out, 960);
//high pass filter
if (opts->use_hpf == 1)
hpf (state, state->analog_out, 960);
//pass band filter
if (opts->use_pbf == 1)
pbf(state, state->analog_out, 960);
//manual gain control
if (opts->audio_gainA > 0.0f)
analog_gain (opts, state, state->analog_out, 960);
//automatic gain control
else
agsm(opts, state, state->analog_out, 960);
//Running RMS after filtering does remove the analog spike from the RMS value
//but noise floor noise will still produce higher values
// if (opts->audio_in_type != 3 && opts->monitor_input_audio == 1)
// opts->rtl_rms = raw_rms(state->analog_out, 960, 1);
//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) && opts->monitor_input_audio == 1 && state->carrier == 0 ) //added carrier check here in lieu of disabling it above

View File

@ -85,124 +85,21 @@ void openWavOutFile48k (dsd_opts * opts, dsd_state * state)
}
}
//generic rms type function
long int gen_rms(short *samples, int len, int step)
{
int i;
long int rms;
long p, t, s;
double dc, err;
p = t = 0L;
for (i=0; i<len; i+=step) {
s = (long)samples[i];
t += s;
p += s * s;
}
/* correct for dc offset in squares */
dc = (double)(t*step) / (double)len;
err = t * 2 * dc - dc * dc * len;
rms = (long int)sqrt((p-err) / len);
//make sure it doesnt' randomly feed us a large negative value (overflow?)
if (rms < 0) rms = 150; //could also consider returning 0 and making it return the last known good value instead
return rms;
}
//super generic pre-emphasis filter with alpha value of 1 for short sample input / output
static short pstate = 1;
void analog_preemph_filter(short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
//debug
// fprintf (stderr, " I:%d;", input[i]);
input[i] = input[i] - 1 * pstate;
pstate = input[i];
//debug
// fprintf (stderr, " O:%d;;", input[i]);
//increase gain value slightly
input[i] *= 1.5;
//debug
// fprintf (stderr, " O2:%d;;;", input[i]);
}
}
//super generic short sample clipping filter, prevent short values from exceeding tolerable clip value
void analog_clipping_filter(short * input, int len)
{
int i;
for (i = 0; i < len; i++)
{
if (input[i] > 32760)
input[i] = 32760;
else if (input[i] < -32760)
input[i] = -32760;
}
}
//modified from version found in rtl_fm
static short avg = 0;
void analog_deemph_filter(short * input, int len)
{
// static short avg; // cheating...
int i, d;
// int a = (int)round(1.0/((1.0-exp(-1.0/(96000 * 75e-6))))); //48000 is rate out, but doubling it sounds 'beefier'
int a = 8; //result of calc above is 8, so save a cycle on the low end CPUs
// de-emph IIR
// avg = avg * (1 - alpha) + sample * alpha;
for (i = 0; i < len; i++)
{
d = input[i] - avg;
if (d > 0)
avg += (d + a/2) / a;
else
avg += (d - a/2) / a;
input[i] = (short)avg;
}
}
//modified from version found in rtl_fm
static int dc_avg = 0;
void analog_dc_block_filter(short * input, int len)
{
int i, avg;
int64_t sum = 0;
for (i=0; i < len; i++)
sum += input[i];
avg = sum / len;
avg = (avg + dc_avg * 9) / 10;
for (i=0; i < len; i++)
input[i] -= (short)avg;
dc_avg = avg;
}
//listening to and playing back analog audio
void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn)
{
//reset static states for new channel
pstate = 1;
avg = 0;
dc_avg = 0;
int i, result;
int count = 5; //RMS has a 5 count (5 * 180ms) now before cutting off;
short analog1[960];
short analog2[960];
short analog3[960];
short sample = 0;
short sample = 0;
#define DEBUG_ANALOG //enable to digitize analog if 'data' bursts heard
uint8_t d1[192];
uint8_t d2[192];
uint8_t d3[192];
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL);
@ -211,6 +108,10 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
memset (analog2, 0, sizeof(analog2));
memset (analog3, 0, sizeof(analog3));
memset (d1, 0, sizeof(d1));
memset (d2, 0, sizeof(d2));
memset (d3, 0, sizeof(d3));
long int rms = opts->rtl_squelch_level + 1; //one more for the initial loop phase
long int sql = opts->rtl_squelch_level;
@ -239,7 +140,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
analog3[i] = sample;
}
//this rms will only work properly (for now) with squelch enabled in SDR++ or other
rms = gen_rms(analog3, 960, 1);
rms = raw_rms(analog3, 960, 1);
}
//NOTE: The core dumps observed previously were due to SDR++ Remote Server connection dropping due to Internet/Other issues
@ -250,6 +151,10 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
//not be a sample to read in and it hangs on sf_short read until it crashes out, the fix below will prevent issues
//when SDR++ is closed locally, or the TCP connection closes suddenly.
//NOTE: Observed two segfaults on EDACS STM analog when doing radio tests or otherwise holding the radio
//open for extremely long periods of time, could be an issue in digitize where dibit_buf_p is not
//reset for an extended period of time and overflows, may need to reset buffer occassionally here
//TCP Input w/ Simple TCP Error Detection Implemented to prevent hard crash if TCP drops off
if (opts->audio_in_type == 8)
{
@ -293,7 +198,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
}
//this rms will only work properly (for now) with squelch enabled in SDR++
rms = gen_rms(analog3, 960, 1);
rms = raw_rms(analog3, 960, 1);
}
//RTL Input
@ -330,22 +235,71 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
sr += digitize (opts, state, (int)analog1[i]);
}
//test running analog audio through a de-emphasis filter
analog_deemph_filter(analog1, 960);
analog_deemph_filter(analog2, 960);
analog_deemph_filter(analog3, 960);
//and dc_block filter analog_dc_block_filter
analog_dc_block_filter(analog1, 960);
analog_dc_block_filter(analog2, 960);
analog_dc_block_filter(analog3, 960);
//test running analog audio through a pre-emphasis filter
analog_preemph_filter(analog1, 960);
analog_preemph_filter(analog2, 960);
analog_preemph_filter(analog3, 960);
//test running analog short sample clipping filter
analog_clipping_filter(analog1, 960);
analog_clipping_filter(analog2, 960);
analog_clipping_filter(analog3, 960);
#ifdef DEBUG_ANALOG
//save digitized samples to array for looking into those 'data' sounding bursts,
//this format assumes the same sample per symbol rateused in EDACS/PV
for (i = 0; i < 192; i++) //Samples Per Symbol is 5, so incrememnt every 5
{
d1[i] = digitize (opts, state, (int)analog1[i*5]);
d2[i] = digitize (opts, state, (int)analog2[i*5]);
d3[i] = digitize (opts, state, (int)analog3[i*5]);
}
#endif
//Bugfix for buffer overflow from using digitize function, reset buffers
if (state->dibit_buf_p > state->dibit_buf + 900000)
state->dibit_buf_p = state->dibit_buf + 200;
//dmr buffer
if (state->dmr_payload_p > state->dmr_payload_buf + 900000)
state->dmr_payload_p = state->dmr_payload_buf + 200;
// low pass filter
if (opts->use_lpf == 1)
{
lpf (state, analog1, 960);
lpf (state, analog2, 960);
lpf (state, analog3, 960);
}
//high pass filter
if (opts->use_hpf == 1)
{
hpf (state, analog1, 960);
hpf (state, analog2, 960);
hpf (state, analog3, 960);
}
//pass band filter
if (opts->use_pbf == 1)
{
pbf (state, analog1, 960);
pbf (state, analog2, 960);
pbf (state, analog3, 960);
}
//manual gain control
if (opts->audio_gainA > 0.0f)
{
analog_gain (opts, state, analog1, 960);
analog_gain (opts, state, analog2, 960);
analog_gain (opts, state, analog3, 960);
}
//automatic gain control
else
{
agsm (opts, state, analog1, 960);
agsm (opts, state, analog2, 960);
agsm (opts, state, analog3, 960);
}
//NOTE: Ideally, we would run raw_rms for TCP/VS here, but the analog spike on EDACS (STM)
//system gets filtered out, and when they hold the radio open and don't talk,
//it counts against the squelch hit as no audio, so we will just have to use
//the squelch checkbox in SDR++ and similar when using those input methods
// if (opts->audio_in_type != 3)
// rms = raw_rms(analog3, 960, 1);
//reconfigured to use seperate audio out stream that is always 48k short
if (opts->audio_out_type == 0 && opts->slot1_on == 1)
@ -426,6 +380,30 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
fprintf (stderr, "%s", KNRM);
#ifdef PRETTY_COLORS
{} //do nothing
#else
fprintf (stderr, "SQL HIT: %d; ", 5-cnt); //add cnt since user can't see red or green
#endif
#ifdef DEBUG_ANALOG
//debug digitized version of analog out when data bursts may be present
//NOTE: Without a 'framesync' these could be shifted into odd positions
if (opts->payload == 1)
{
fprintf (stderr, "\n A_DUMP: ");
for (i = 0; i < 24; i++)
fprintf (stderr, "%02X", (uint8_t)ConvertBitIntoBytes(&d1[i*8], 8));
fprintf (stderr, "\n ");
for (i = 0; i < 24; i++)
fprintf (stderr, "%02X", (uint8_t)ConvertBitIntoBytes(&d2[i*8], 8));
fprintf (stderr, "\n ");
for (i = 0; i < 24; i++)
fprintf (stderr, "%02X", (uint8_t)ConvertBitIntoBytes(&d3[i*8], 8));
// fprintf (stderr, "\n");
}
#endif
if (count > 0) fprintf (stderr, "\n");
}

View File

@ -359,6 +359,10 @@ void M17processCodec2_1600(dsd_opts * opts, dsd_state * state, uint8_t * payload
codec2_decode(state->codec2_1600, samp1, voice1);
//hpf_d on codec2 sounds better than not on those .rrc samples
if (opts->use_hpf_d == 1)
hpf_dL(state, samp1, nsam);
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
@ -459,6 +463,13 @@ void M17processCodec2_3200(dsd_opts * opts, dsd_state * state, uint8_t * payload
codec2_decode(state->codec2_3200, samp1, voice1);
codec2_decode(state->codec2_3200, samp2, voice2);
//hpf_d on codec2 sounds better than not on those .rrc samples
if (opts->use_hpf_d == 1)
{
hpf_dL(state, samp1, nsam);
hpf_dL(state, samp2, nsam);
}
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
@ -1840,18 +1851,51 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
#endif
}
//read in RMS value for vox function; NOTE: may not work correctly on STDIN and TCP due to blocking when no samples to read
//read in RMS value for vox function; NOTE: will not work correctly SOCAT STDIO TCP due to blocking when no samples to read
if (opts->audio_in_type == 3) opts->rtl_rms = rtl_return_rms();
else opts->rtl_rms = raw_rms(voice1, nsam, 1) / 2; //dividing by two so mic isn't so sensitive on vox
//decimate audio input (default 100% on mic is WAY TOO LOUD for the encoder, fine tune in volume control)
for (i = 0; i < 160; i++)
//low pass filter
if (opts->use_lpf == 1)
{
//NOTE: Use + and - in ncurses to fine tune manually
voice1[i] *= (float)state->aout_gain/ (float)25.0f;
voice2[i] *= (float)state->aout_gain/ (float)25.0f;
lpf (state, voice1, 160);
lpf (state, voice2, 160);
}
//high pass filter
if (opts->use_hpf == 1)
{
hpf (state, voice1, 160);
hpf (state, voice2, 160);
}
//passband filter
if (opts->use_pbf == 1)
{
pbf (state, voice1, 160);
pbf (state, voice2, 160);
}
//manual gain control
if (opts->audio_gainA > 0.0f)
{
analog_gain (opts, state, voice1, 160);
analog_gain (opts, state, voice2, 160);
}
//automatic gain control
else
{
agsm (opts, state, voice1, 160);
agsm (opts, state, voice2, 160);
}
//NOTE: Similar to EDACS analog, if calculating raw rms here after filtering,
//anytime the walkie-talkie is held open but no voice, the center spike is removed,
//and counts against the squelch hits making vox mode inconsistent
// if (opts->audio_in_type != 3)
// opts->rtl_rms = raw_rms(voice1, 160, 1);
//convert out audio input into CODEC2 (3200bps) 8 byte data stream
uint8_t vc1_bytes[8]; memset (vc1_bytes, 0, sizeof(vc1_bytes));
uint8_t vc2_bytes[8]; memset (vc2_bytes, 0, sizeof(vc2_bytes));

View File

@ -93,7 +93,7 @@ void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l));
if (opts->floating_point == 0 )
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);
}

View File

@ -60,7 +60,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -74,7 +74,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -95,7 +95,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -116,7 +116,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -137,7 +137,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -158,7 +158,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -179,7 +179,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -200,7 +200,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -261,7 +261,7 @@ processLDU1 (dsd_opts* opts, dsd_state* state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)

View File

@ -65,7 +65,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -79,7 +79,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -100,7 +100,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -121,7 +121,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -142,7 +142,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -163,7 +163,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -184,7 +184,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoiceFM(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 2)
@ -203,7 +203,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)
@ -264,7 +264,7 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
#endif
process_IMBE (opts, state, &status_count);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 0 && opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
if (opts->floating_point == 1 && opts->pulse_digi_out_channels == 1)

View File

@ -221,12 +221,12 @@ void processProVoice (dsd_opts * opts, dsd_state * state)
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
if (opts->floating_point == 0)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
if (opts->floating_point == 0)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);
@ -399,12 +399,12 @@ void processProVoice (dsd_opts * opts, dsd_state * state)
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr1);
if (opts->floating_point == 0)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);
processMbeFrame (opts, state, NULL, NULL, imbe7100_fr2);
if (opts->floating_point == 0)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if (opts->floating_point == 1)
playSynthesizedVoiceFM(opts, state);

View File

@ -815,6 +815,34 @@ void dongle_init(struct dongle_state *s)
s->demod_target = &demod;
}
void demod_init_analog(struct demod_state *s)
{
s->rate_in = rtl_bandwidth;
s->rate_out = rtl_bandwidth;
s->squelch_level = 0;
s->conseq_squelch = 10;
s->terminate_on_squelch = 0;
s->squelch_hits = 11;
s->downsample_passes = 1; //
s->comp_fir_size = 0;
s->prev_index = 0;
s->post_downsample = 1; //1 -- once this works, default = 4 -- doesn't work on the official rtl-sdr source code either
s->custom_atan = 0;
s->deemph = 1; //
s->rate_out2 = rtl_bandwidth; // -1 flag for disabled -- this enables low_pass_real, seems to work okay
s->mode_demod = &fm_demod;
s->pre_j = s->pre_r = s->now_r = s->now_j = 0;
s->prev_lpr_index = 0;
s->deemph_a = 0; //
s->now_lpr = 0;
s->dc_block = 1; //
s->dc_avg = 0;
pthread_rwlock_init(&s->rw, NULL);
pthread_cond_init(&s->ready, NULL);
pthread_mutex_init(&s->ready_m, NULL);
s->output_target = &output;
}
void demod_init_ro2(struct demod_state *s)
{
s->rate_in = rtl_bandwidth;
@ -1005,6 +1033,8 @@ void open_rtlsdr_stream(dsd_opts *opts)
//init with low pass if decoding P25 or EDACS/Provoice
if (opts->frame_p25p1 == 1 || opts->frame_p25p2 == 1 || opts->frame_provoice == 1)
demod_init_ro2(&demod);
else if (opts->analog_only == 1 || opts->m17encoder == 1)
demod_init_analog(&demod);
else demod_init(&demod);
output_init(&output);
controller_init(&controller);

View File

@ -737,7 +737,7 @@ void ysf_ehr (dsd_opts * opts, dsd_state * state, uint8_t dbuf[180], int start,
writeSynthesizedVoice (opts, state);
if (opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if(opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
@ -1027,7 +1027,7 @@ void processYSF(dsd_opts * opts, dsd_state * state)
if (opts->wav_out_f != NULL)
writeSynthesizedVoice (opts, state);
if (opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if(opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);
@ -1147,7 +1147,7 @@ void processYSF(dsd_opts * opts, dsd_state * state)
writeSynthesizedVoice (opts, state);
if (opts->pulse_digi_out_channels == 1)
playSynthesizedVoice(opts, state);
playSynthesizedVoiceMS(opts, state);
if(opts->pulse_digi_out_channels == 2)
playSynthesizedVoiceSS(opts, state);