Squashed commit of the following:

commit 833e0173f24b12a12ff80f9a35fb43107d355cc3
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 22:51:02 2024 -0400

    Fix Slot Preference Depending on Build;

commit 716577ab09c0cee68bca3bcdcbaaa7cfa3be4f97
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 22:27:24 2024 -0400

    M17 - Voice Playback Only If Enabled; Misc;

commit c0f9818cf38ce7f127370f19ec4afa2457cef19a
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 17:39:34 2024 -0400

    Add DMR/P25p2 Stereo Channel Patch;

commit 1a0baf0a17ccf8cc0eb0a01a809269354480d1d1
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 17:37:46 2024 -0400

    Add DMR Cap+ Faster Rest Patch;

commit 9f5b52aa8f20bfe3eab5413f2c3fa41003d53b3c
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 17:36:24 2024 -0400

    Disable EDACS Analog Debug;

commit 7dd0de67b602f0acd111200f838fbb1a0541a8bf
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 17:36:04 2024 -0400

    Squashed commit of the following:

    commit 95d46fb35d6cb6fb0a9825084f4c2accf8edad4a
    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 1f37837664e16760b5cbf5653fc4d829ee6cce83
    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;

commit 3b9f9f5a3befb295da284379262323fad7d69c7a
Author: lwvmobile <lwvmobile@gmail.com>
Date:   Tue Mar 26 17:33:34 2024 -0400

    Squashed commit of the following:

    commit a5c5be3b955a82cc72f1486ff87d7c1b4893295f
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Tue Mar 26 17:28:35 2024 -0400

        EDACS: Standard display rewrite, parsing/RE fixes, tune i-calls and all-calls (#246)

        * EDACS EA: Fix reversed TDMA/data calls

        * EDACS: deduplicate ncurses printing logic

        * EDACS: pass call state via new state struct field

        * EDACS: RE some differences from Standard spec

        * EDACS: show state for data calls

        * EDACS: tune individual calls on Standard

        * EDACS: tune all-calls on Standard

        * EDACS: properly identify emergency on channel updates

        * EDACS: fix build break

        * EDACS: fix conditions for refreshing the display source

        * EDACS EA: Identify calls as voice for display

        * EDACS: voice channel update emergency refactor

        * EDACS: Show interconnect calls in call log

        * EDACS EA: show unknown data channel assignments in log

        * EDACS: check LCN is not 0 before assigning it

        * EDACS: C operator precedence is dumb

        * Initialize edacs_vc_call_type

        * use j and not i in call_matrix for call history;

        ---------

        Co-authored-by: lwvmobile <lwvmobile@gmail.com>

    commit c8d00846b1
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sun Mar 24 17:48:46 2024 -0400

        EDACS: Display cached call source on Standard, tune group calls on assignment (#241)

        * Trim trailing whitespace

        * EDACS: Display cached call source on Standard

        The logic in `edacs-fme.c` didn't work, in retrospect, because it would have depended on getting back-to-back messages for the same call. In practice, that is unlikely even on an idle system as system state gets displayed.

        Instead, cache on the display end, for a "better" user experience.

        * EDACS: Pad channel freq to "000.000000 MHz"

        * EDACS: Process/tune group calls on assignment

    commit 8d432e8b3e
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sun Mar 24 12:29:22 2024 -0400

        EDACS: ESK fixes, RE of standard channel assignments, cleanups (#238)

        * EDACS: Make i-calls very obvious on standard

        * EDACS: abstract target for Interconnect Channel Assignment

        * EDACS: little shortcut example updates

        * EDACS: Apply ESK to both FR1 and FR4

        * EDACS: Group channel assignment by mode

        * EDACS: Merge MT-A 0/1 and 2/3 cases

    commit 0440dea1de
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Sun Mar 24 02:47:09 2024 -0400

        EDACS: Fix Call History For Standard Maybe;

    commit 208f188e55
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 23 21:35:42 2024 -0400

        EDACS: Speculative RE of MT-A value 0, pretty colours (#231)

        * EDACS: fix log formatting

        * EDACS: Speculative RE of MT-A value 0

        * EDACS: CC message pretty colours

        * EDACS: little formatting

        * EDACS: eh make interconnect magenta

    commit 36f76a7e21
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 23 17:35:45 2024 -0400

        EDACS: Fix copy/paste error (#230)

        I went through by hand and I'm confident this is the last of the `get_lcn_status_string()` errors.

    commit 4bc73d8c68
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 23 17:24:32 2024 -0400

        EDACS: Rewrite Standard/Networked parsing per TIA/EIA TSB 69.3 (#229)

        * EDACS EA: refactor log messages for consistency

        * EDACS: Log LCN status values

        * EDACS EA: channel assignment vs update

        * EDACS: Implement TIA/EIA TSB 69.3

        * EDACS: clean up Site ID message

        * EDACS: Actually process call for Channel Update

        * EDACS: Update display for Standard calls

        * EDACS: Format of Voice Group Channel Assignment

        * EDACS Standard: Log LCN status values

        * EDACS: Rebase and fix some issues

        * EDACS: Fix copy/paste error

    commit 03507055a4
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 23 16:05:09 2024 -0400

        EDACS: add EA messages / start mass Standard refactor (#226)

        * EDACS EA: refactor log messages for consistency

        * EDACS EA: channel assignment command (unknown data)

        * EDACS EA: status/message command

        * EDACS Standard: Refactor variable declarations

        * EDACS Standard: log raw payloads for debugging

        * EDACS: Fix typing

        * EDACS EA: update status/message CC command

        * EDACS: Log LCN status values

        * EDACS: String format

        * EDACS EA: channel assignment vs update

        * EDACS: fix syntax error

        * EDACS: change string for reserved LCN status

    commit fbe5fd2093
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Fri Mar 22 15:26:50 2024 -0400

        EDACS EA: emergency calls, MT1 fixes, logging improvements (#221)

        * EDACS EA: Fix i-call MT1 after ESK changes

        * EDACS EA: Fix all-call ncurses display

        * EDACS EA: Make detailed log slightly more readable

        * EDACS EA: Improve colours in logs

        * EDACS EA: Space in logs for consistency

        * EDACS EA: Fix MT1 for analog group voice after ESK change

        * EDACS EA: add parsing for emergency calls

    commit 413e5f76a2
    Merge: de9127c 388a57d
    Author: lwvmobile <59371473+lwvmobile@users.noreply.github.com>
    Date:   Fri Mar 22 06:59:31 2024 -0400

        Merge pull request #220 from lwvmobile/edacs_manual_modes

        Edacs manual modes

    commit 388a57d8fc
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 05:28:11 2024 -0400

        EDACS: Re-enable the -9 switch to maintain user compatability; Fix Missing Bracket on non color mode;

    commit 058099f1aa
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 03:24:57 2024 -0400

        EDACS: Tweak Mode Toggle Display; Add Frame Dump on No Mode Set;

    commit 68aa6b018e
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 02:19:38 2024 -0400

        EDACS: Update Docs to Reflect Changes;

    commit c404f3c48c
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 02:01:09 2024 -0400

        EDACS: Ncurses Display Working Mode Tweaks;

    commit b2d1608eb7
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 01:08:28 2024 -0400

        EDACS: Toggle Keys A and S for Mode Selection;

    commit a4553a0a0a
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Fri Mar 22 00:45:37 2024 -0400

        EDACS: Remove Auto Detect Code; Make CLI Switches;

    commit de9127cfb4
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Thu Mar 21 21:02:53 2024 -0400

        EDACS: support for EA system all-calls (#214)

        * Refactor debug printing a bit

        * Clean up group call logic

        * Minor changes to debug printing

        * EDACS EA: support for system all-calls

        * EDACS: split out MT1 for TDMA call since we can't decode it anyway

        * Refactor identifying call mode (digital/analog)

        * Maintain consistent indentation for all MT1

        * EDACS: Fix Compiler Error.

        Had an extra right bracket on line 383

        ---------

        Co-authored-by: lwvmobile <59371473+lwvmobile@users.noreply.github.com>

    commit c85dd60399
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Tue Mar 19 17:38:30 2024 -0400

        EDACS: NET/STD LCN > 0 Check;

    commit bed766a86e
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Tue Mar 19 09:34:10 2024 -0400

        EDACS: STD/NET Don't Tune Unless CC LCN Set;

    commit 69f532a022
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Mon Mar 18 11:41:58 2024 -0400

        EDACS: EA I-Call decoding improvements (#205)

        * EDACS: formatting nit

        * EDACS: add name to credits

        * EDACS: Handle initial grant vs grant update for i-call

        * EDACS: consistency for group vs i-call

        * EDACS: file naming for i-call recordings

        * EDACS: EA refactor when MT1 is 0x1F

        * EDACS: check we know CC LCN before leaving it

        * EDACS: fix breaking change for Standard

        Revert mistake in f68367c4f3

        * Fix patent number

        * EDACS: Fix Compiler Error 1;

        Fix Rogue Copy Paste

        * EDACS: Add MT1, MT2, and FR1 and FR4 Dumps on Payload;

        ---------

        Co-authored-by: lwvmobile <59371473+lwvmobile@users.noreply.github.com>

    commit a7de24c47b
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Mon Mar 18 07:47:34 2024 -0400

        EDACS: fixes and improvements to EA analog and i-call parsing (#204)

        * Fix MT1 math given esk_mask value is 0xA0

        * EDACS: Clean up formatting for I-Calls

        * EDACS: typo, fix the TGID for group calls

        Fix copy-pasta

        * EDACS: Fix MT2 for I-Calls

        Incorrectly copied decimal values as hex - obviously MT2 is only 4 bits so it cannot be greater than 15.

        * EDACS: check LCN is > 0 before trying to tune

        An EA CC sometimes includes commands that parse as LCN 0 - but otherwise valid - analog call voice grants for TG 1. Since LCN 0 is not valid, ensure that we don't try to tune to them while we try to figure out what they're about.

        * EDACS: Process "login" message on CC

        Log "login" messages sent on the CC. Verified behaviour against UniTrunker.

    commit 10eacd99cc
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sun Mar 17 18:56:41 2024 -0400

        EDACS: Clean up formatting for I-Calls (#203)

        * Fix MT1 math given esk_mask value is 0xA0

        * EDACS: Clean up formatting for I-Calls

    commit ebe6e8fc65
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sun Mar 17 18:02:12 2024 -0400

        Fix MT1 math given esk_mask value is 0xA0 (#202)

    commit 8619612b76
    Author: lwvmobile <lwvmobile@gmail.com>
    Date:   Sat Mar 16 22:42:44 2024 -0400

        EDACS: Setup Analog Calls and WAVs on EA and ICALL;

    commit 9ac1573f0b
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 16 17:17:14 2024 -0400

        EDACS: Add MT1 value / logging for analog group calls (#198)

        * Add MT1 value / logging for analog group calls

        * Respect user preference for tuning to group calls

        * Revert "Respect user preference for tuning to group calls"

        This reverts commit 83ac8feab7.

    commit 0aa01a45ef
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 16 17:16:52 2024 -0400

        EDACS: Respect user preference for tuning to group calls (#201)

    commit f68367c4f3
    Author: ilyacodes <33097525+ilyacodes@users.noreply.github.com>
    Date:   Sat Mar 16 17:16:20 2024 -0400

        EDACS: Add parsing for individual calls (#200)

        * EDACS: Add parsing for individual calls

        This change adds parsing for I-Calls on EA systems. Both analog and ProVoice modes are parsed and processed. See related issue for discussion.

        * Respect user preference for tuning to private calls

        * EDACS: Respect user preference for tuning to private calls

        * EDACS: Handle i-call target in ProVoice logging

        * EDACS: Show i-calls distinctly from group calls
This commit is contained in:
lwvmobile
2024-03-26 22:59:05 -04:00
parent f05ddf8fcd
commit ab844202bc
28 changed files with 3526 additions and 947 deletions

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

@@ -423,6 +423,10 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//check the p_clear logic and report status
if (clear && csbk_fid == 255) fprintf (stderr, " Slot %d No Encrypted Call Trunking; Slot %d Free; Return to CC; ", pslot, oslot);
else if (!clear && csbk_fid == 255) fprintf (stderr, " Slot %d No Encrypted Call Trunking; Slot %d Busy; Remain on VC;", pslot, oslot);
else if (clear && csbk_fid == 254) fprintf (stderr, " Cap+ Rest LSN Change: %d; Slot %d Free; Slot %d Free; Go To Rest LSN;", state->dmr_rest_channel, pslot, oslot); //disabled
else if (!clear && csbk_fid == 254) fprintf (stderr, " Cap+ Rest LSN Change: %d; Slot %d Free; Slot %d Busy; Remain on LSN;", state->dmr_rest_channel, pslot, oslot); //disabled
else if (clear && csbk_fid == 253) fprintf (stderr, " Cap+ Rest LSN Change: %d; No CSBK Channel Activity; Go To Rest LSN;", state->dmr_rest_channel);
else if (!clear && csbk_fid == 253) fprintf (stderr, " Cap+ Rest LSN Change: %d; CSBK Channel Activity; Remain on LSN;", state->dmr_rest_channel); //this should never happen in code
else if (!clear) fprintf (stderr, " Slot %d Clear; Slot %d Busy; Remain on VC;", pslot, oslot);
else if (clear == 1) fprintf (stderr, " Slot %d Clear; Slot %d Idle; Return to CC;", pslot, oslot);
else if (clear == 2 || clear == 3) fprintf (stderr, " Slot %d Clear; Slot %d Free; Return to CC;", pslot, oslot);
@@ -441,14 +445,14 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//display/le/buzzer bug fix when p_clear activated (unsure why this was disabled)
//clear only the current slot initially, then clear both if tuning to a different freq
if (state->currentslot == 0)
if (state->currentslot == 0 && csbk_fid != 253) //don't reset on Cap+ since we aren't testing based on the current TS
{
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
}
if (state->currentslot == 1)
if (state->currentslot == 1 && csbk_fid != 253)
{
state->payload_miR = 0;
state->payload_algidR = 0;
@@ -1206,6 +1210,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//tg and channel info for trunking purposes
uint16_t t_tg[24];
char cap_active[20]; //local string to concantenate to active channel stuff
uint8_t empty[24]; //used to evaluate whether or not all channels are idle or not with memcmp after loading
//sanity check
if (block_num > 6)
@@ -1218,6 +1223,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
memset (t_tg, 0, sizeof(t_tg));
memset (ch, 0, sizeof(ch));
memset (pch, 0, sizeof(pch));
memset (empty, 0, sizeof(empty));
//treating FL as a form of LCSS
if (fl == 2 || fl == 3) //initial or single block (fl2 or fl3)
@@ -1234,6 +1240,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
state->cap_plus_block_num[ts]++;
}
//move assignment until later when evaluating for a p_clear condition
if (rest_channel != state->dmr_rest_channel)
{
state->dmr_rest_channel = rest_channel;
@@ -1242,7 +1249,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//assign to cc freq to follow during no sync
if (state->trunk_chan_map[rest_channel] != 0)
{
state->p25_cc_freq = state->trunk_chan_map[rest_channel];
// state->p25_cc_freq = state->trunk_chan_map[rest_channel];
//set to always tuned
opts->p25_is_tuned = 1;
}
@@ -1412,15 +1419,15 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
tg = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[ts][(group_tally*8)+(x*16)+56], 16); //don't change this AGAIN!, this is correct!
if (tg != 0) fprintf (stderr, "%5d; ", tg);
else fprintf (stderr, " P||D; ");
//flag as available for tuning if data calls enabled
if (opts->trunk_tune_data_calls == 1) t_tg[i] = tg; //ch[i] = 1;
//flag as available for tuning if private calls enabled
if (opts->trunk_tune_private_calls == 1) t_tg[i] = tg; //ch[i] = 1;
if (tg != 0) x++;
//add active channel to display string
//NOTE: Consider only adding this if user toggled or else
//lots of short data bursts blink in and out
if (1 == 1) //opts->trunk_tune_data_calls
if (1 == 1) //opts->trunk_tune_private_calls
{
sprintf (cap_active, "LSN:%d PC:%d; ", i+1, tg);
strcat (state->active_channel[i+1], cap_active);
@@ -1515,6 +1522,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
state->last_vc_sync_time = time(NULL);
j = 11; //break loop
}
@@ -1550,6 +1558,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
// else fprintf (stderr, "\n DONT RTL LSN/TG to tune to: %d - %d", j+1, t_tg[j]); //debug
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1;
state->last_vc_sync_time = time(NULL);
j = 11; //break loop
#endif
}
@@ -1577,6 +1586,25 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
}
memset (state->cap_plus_csbk_bits[ts], 0, sizeof(state->cap_plus_csbk_bits[ts]));
state->cap_plus_block_num[ts] = 0;
//check here to see if we can go to the current rest lsn, if not already on it
int busy = memcmp (empty, t_tg, sizeof(empty));
//testing (don't keep setting on quick data call LSN flip flops but same frequency for rest channel, other misc conditions)
// if (!busy && rest_channel != state->dmr_rest_channel && opts->p25_trunk == 1 && state->p25_cc_freq != state->trunk_chan_map[rest_channel])
if (!busy && opts->p25_trunk == 1 && state->p25_cc_freq != state->trunk_chan_map[rest_channel])
{
//assign now, ideally, this should always trigger a positive p_clear when needed
// state->dmr_rest_channel = rest_channel;
//update frequency
if (state->trunk_chan_map[rest_channel] != 0)
state->p25_cc_freq = state->trunk_chan_map[rest_channel];
//Craft a fake CSBK pdu send it to run as a p_clear to go to rest channel if its available (no calls currently)
uint8_t dummy[12]; uint8_t* dbits; memset (dummy, 0, sizeof(dummy)); dummy[0] = 46; dummy[1] = 253;
dmr_cspdu (opts, state, dbits, dummy, 1, 0);
}
} //if (fl == 1 || fl == 3)
} //opcode == 0x3E

View File

@@ -354,15 +354,18 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
}
if (restchannel != state->dmr_rest_channel && restchannel != -1)
//only assign this value here if not trunking
// if (opts->p25_trunk == 0) //may be safe to always do this now with code changes, will want to test at some point (tg hold w/ dual voice / slco may optimally need this set)
{
state->dmr_rest_channel = restchannel;
//assign to cc freq
if (state->trunk_chan_map[restchannel] != 0)
if (restchannel != state->dmr_rest_channel && restchannel != -1)
{
state->p25_cc_freq = state->trunk_chan_map[restchannel];
}
state->dmr_rest_channel = restchannel;
//assign to cc freq
// if (state->trunk_chan_map[restchannel] != 0)
// {
// state->p25_cc_freq = state->trunk_chan_map[restchannel];
// }
}
}
if (type == 1) fprintf (stderr, "%s \n", KGRN);
@@ -1004,21 +1007,35 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
else if (slco == 0xF)
{
fprintf (stderr, " SLCO Capacity Plus Site: %d - Rest LSN: %d - RS: %02X", capsite, restchannel, cap_reserved);
//assign to cc freq if available
if (state->trunk_chan_map[restchannel] != 0)
{
state->p25_cc_freq = state->trunk_chan_map[restchannel];
}
//extra handling for TG hold while trunking enabled
if (state->tg_hold != 0 && opts->p25_trunk == 1)
if (state->tg_hold != 0 && opts->p25_trunk == 1) //logic seems to be fixed now for new rest lsn logic and other considerations
{
//if both slots are voice,
if (state->dmrburstL == 16 && state->dmrburstR == 16)
//debug
// fprintf (stderr, " TG HOLD Both Slots Busy Check; ");
//if both slots have some cobination of vlc, pi, voice, or tlc
int busy = 0;
if ( (state->dmrburstL == 16 || state->dmrburstL == 0 || state->dmrburstL == 1 || state->dmrburstL == 2) &&
(state->dmrburstR == 16 || state->dmrburstR == 0 || state->dmrburstR == 1 || state->dmrburstR == 2)) busy = 1;
if (busy)
{
//debug
// fprintf (stderr, " Busy; ");
//but nether is the TG on hold
if ( (state->tg_hold != state->lasttg) && (state->tg_hold != state->lasttgR) )
{
//debug
// fprintf (stderr, " Neither Slot is TG on Hold; ");
//assign to cc freq if available -- move to right before needed for new logic on rest lsn
if (state->trunk_chan_map[restchannel] != 0)
{
state->p25_cc_freq = state->trunk_chan_map[restchannel];
}
//tune to the current rest channel so we can observe its channel status csbks for the TG on hold
if (state->p25_cc_freq != 0)
{

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++)
{
@@ -906,8 +1035,8 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
//CHEAT: Using the slot on/off, use that to set encL or encR back on
//as a simple way to turn off voice synthesis in a particular slot
//its not really 'disabled', we just aren't playing it
if (opts->slot1_on == 0) encL = 1;
if (opts->slot2_on == 0) encR = 1;
// if (opts->slot1_on == 0) encL = 1;
// if (opts->slot2_on == 0) encR = 1;
//WIP: Mute if on B list (or not W list)
char modeL[8];
@@ -944,42 +1073,182 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
if (strcmp(modeL, "B") == 0) encL = 1;
if (strcmp(modeR, "B") == 0) encR = 1;
//check to see if we need to enable slot and toggle slot preference here
//this method will always favor slot 2 (this is a patch anyways, so....meh)
// if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
//check to see if we need to enable slot and toggle slot preference here
//if both groups allowed, then give no preference to either one (not sure this is needed now)
// if ( (strcmp(modeL, "A") == 0) && (strcmp(modeR, "A") == 0) )
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
// else if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// else if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
// else //if any other condition, then give no preference to either one
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
//if TG Hold in place, mute anything but that TG #132
if (state->tg_hold != 0 && state->tg_hold != TGL) encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR) encR = 1;
//likewise, override and unmute if TG hold matches TG
if (state->tg_hold != 0 && state->tg_hold == TGL) encL = 0;
if (state->tg_hold != 0 && state->tg_hold == TGR) encR = 0;
if (state->tg_hold != 0 && state->tg_hold != TGL)
encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR)
encR = 1;
//interleave left and right channels from the short storage area
for (i = 0; i < 160; i++)
//likewise, override and unmute if TG hold matches TG (and turn on slot and set preference)
if (state->tg_hold != 0 && state->tg_hold == TGL)
{
if (!encL)
stereo_samp1[i*2+0] = state->s_l4[0][i];
if (!encR)
stereo_samp1[i*2+1] = state->s_r4[0][i];
encL = 0;
opts->slot1_on = 1;
opts->slot_preference = 0;
}
else if (state->tg_hold != 0 && state->tg_hold == TGR)
{
encR = 0;
opts->slot2_on = 1;
opts->slot_preference = 1;
}
else //otherwise, reset slot preference to either or (both slots enabled)
{
opts->slot_preference = 2;
}
for (i = 0; i < 160; i++)
//test hpf
if (opts->use_hpf_d == 1)
{
if (!encL)
stereo_samp2[i*2+0] = state->s_l4[1][i];
if (!encR)
stereo_samp2[i*2+1] = state->s_r4[1][i];
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);
}
for (i = 0; i < 160; i++)
//convert the left or right channel to both channels if single voice under certain conditions, if defined to do so
#define DMR_STEREO_OUTPUT
#ifdef DMR_STEREO_OUTPUT
if (encL) memset (state->s_l4, 0, sizeof(state->s_l4));
if (encR) memset (state->s_r4, 0, sizeof(state->s_r4));
//this is for playing single voice over both channels, or when to keep them seperated
if (opts->slot1_on == 0 && opts->slot2_on == 1 && encR == 0) //slot 1 is hard off and slot 2 is on
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (opts->slot1_on == 1 && opts->slot2_on == 0 && encL == 0) //slot 2 is hard off and slot 1 is on
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 0 && state->dmrburstL == 16 && encL == 0) //slot 1 is preferred, and voice in slot 1
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 1 && state->dmrburstR == 16 && encR == 0) //slot 2 is preferred, and voice in slot 2
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (state->dmrburstL == 16 && state->dmrburstR != 16 && encL == 0) //voice in left, no voice in right
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (state->dmrburstR == 16 && state->dmrburstL != 16 && encR == 0) //voice in right, no voice in left
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
//else if voice in both, and both slots on, and no preference on slot, then regular stereo interleave (left and right channels)
//if both slots are the same now, then let's decimate the audio to keep the audio level consistent
// if (memcmp (state->s_l4, state->s_r4, sizeof(state->s_l4)) == 0)
// {
// for (int j = 0; j < 3; j++)
// {
// for (i = 0; i < 160; i++)
// {
// state->s_l4[j][i] *= 0.85;
// state->s_r4[j][i] *= 0.85;
// }
// }
// }
#endif
//check this last
if (opts->slot1_on == 0 && opts->slot2_on == 0) //both slots are hard off, disable playback
{
if (!encL)
stereo_samp3[i*2+0] = state->s_l4[2][i];
if (!encR)
stereo_samp3[i*2+1] = state->s_r4[2][i];
encL = 1;
encR = 1;
}
//at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions
if (encL && encR)
goto SS3_END;
//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++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp1[i*2+0] = state->s_l4[0][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp1[i*2+1] = state->s_r4[0][i];
}
for (i = 0; i < 160; i++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp2[i*2+0] = state->s_l4[1][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp2[i*2+1] = state->s_r4[1][i];
}
for (i = 0; i < 160; i++)
{
#ifdef DMR_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_samp3[i*2+0] = state->s_l4[2][i];
#ifdef DMR_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_samp3[i*2+1] = state->s_r4[2][i];
}
if (opts->audio_out_type == 0) //Pulse Audio
{
pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*2, NULL);
@@ -1045,7 +1314,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 +1323,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 +1406,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++)
{
@@ -1238,6 +1525,284 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
}
//short stereo mix 18v superframe
void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state)
{
//NOTE: This will run once every superframe during a sacch field
//exact implementation to be determined
int i, j;
uint8_t encL, encR;
short stereo_sf[18][320]; //8k 2-channel stereo interleave mix for full superframe
// memset (stereo_sf, 1, 18*sizeof(short)); //I don't think 18*sizeof(short) was large enough, should probably be 18*320*sizeof(short)
memset (stereo_sf, 0, sizeof(stereo_sf));
short empty[320];
memset (empty, 0, sizeof(empty));
//p25p2 enc checkdown for whether or not to fill the stereo sample or not for playback or writing
encL = encR = 1;
if (state->payload_algid == 0 || state->payload_algid == 0x80)
encL = 0;
if (state->payload_algidR == 0 || state->payload_algidR == 0x80)
encR = 0;
//checkdown to see if we can lift the 'mute' if a key is available
if (encL)
{
if (state->payload_algid == 0xAA)
{
if (state->R != 0)
{
encL = 0;
}
}
}
if (encR)
{
if (state->payload_algidR == 0xAA)
{
if (state->RR != 0)
{
encR = 0;
}
}
}
//WIP: Mute if on B list (or not W list)
char modeL[8];
sprintf (modeL, "%s", "");
char modeR[8];
sprintf (modeR, "%s", "");
int TGL = state->lasttg;
int TGR = state->lasttgR;
//if we are using allow/whitelist mode, then write 'B' to mode for block
//comparison below will look for an 'A' to write to mode if it is allowed
if (opts->trunk_use_allow_list == 1)
{
sprintf (modeL, "%s", "B");
sprintf (modeR, "%s", "B");
}
for (i = 0; i < state->group_tally; i++)
{
if (state->group_array[i].groupNumber == TGL)
{
strcpy (modeL, state->group_array[i].groupMode);
// break; //need to keep going to check other potential slot group
}
if (state->group_array[i].groupNumber == TGR)
{
strcpy (modeR, state->group_array[i].groupMode);
// break; //need to keep going to check other potential slot group
}
}
//flag either left or right as 'enc' to mute if B
if (strcmp(modeL, "B") == 0) encL = 1;
if (strcmp(modeR, "B") == 0) encR = 1;
//check to see if we need to enable slot and toggle slot preference here
//this method will always favor slot 2 (this is a patch anyways, so....meh)
// if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
//check to see if we need to enable slot and toggle slot preference here
//if both groups allowed, then give no preference to either one (not sure this is needed now)
// if ( (strcmp(modeL, "A") == 0) && (strcmp(modeR, "A") == 0) )
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
// else if (strcmp(modeL, "A") == 0)
// {
// opts->slot1_on = 1;
// opts->slot_preference = 0;
// }
// else if (strcmp(modeR, "A") == 0)
// {
// opts->slot2_on = 1;
// opts->slot_preference = 1;
// }
// else //if any other condition, then give no preference to either one
// {
// opts->slot1_on = 1;
// opts->slot2_on = 1;
// opts->slot_preference = 2;
// }
//if TG Hold in place, mute anything but that TG #132
if (state->tg_hold != 0 && state->tg_hold != TGL)
encL = 1;
if (state->tg_hold != 0 && state->tg_hold != TGR)
encR = 1;
//likewise, override and unmute if TG hold matches TG (and turn on slot and set preference)
if (state->tg_hold != 0 && state->tg_hold == TGL)
{
encL = 0;
opts->slot1_on = 1;
opts->slot_preference = 0;
}
else if (state->tg_hold != 0 && state->tg_hold == TGR)
{
encR = 0;
opts->slot2_on = 1;
opts->slot_preference = 1;
}
else //otherwise, reset slot preference to either or (both slots enabled)
{
opts->slot_preference = 2;
}
//run hpf_d filter, if enabled
if (opts->use_hpf_d == 1)
{
for (j = 0; j < 18; j++)
{
hpf_dL(state, state->s_l4[j], 160);
hpf_dR(state, state->s_r4[j], 160);
}
}
//convert the left or right channel to both channels if single voice under certain conditions, if defined to do so
#define P2_STEREO_OUTPUT
#ifdef P2_STEREO_OUTPUT
if (encL) memset (state->s_l4, 0, sizeof(state->s_l4));
if (encR) memset (state->s_r4, 0, sizeof(state->s_r4));
//this is for playing single voice over both channels, or when to keep them seperated
if (opts->slot1_on == 0 && opts->slot2_on == 1 && encR == 0) //slot 1 is hard off and slot 2 is on
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (opts->slot1_on == 1 && opts->slot2_on == 0 && encL == 0) //slot 2 is hard off and slot 1 is on
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 0 && state->dmrburstL == 21 && encL == 0) //slot 1 is preferred, and voice in slot 1
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (opts->slot_preference == 1 && state->dmrburstR == 21 && encR == 0) //slot 2 is preferred, and voice in slot 2
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
else if (state->dmrburstL == 21 && state->dmrburstR != 21 && encL == 0) //voice in left, no voice in right
memcpy (state->s_r4, state->s_l4, sizeof(state->s_r4)); //copy left to right
else if (state->dmrburstR == 21 && state->dmrburstL != 21 && encR == 0) //voice in right, no voice in left
memcpy (state->s_l4, state->s_r4, sizeof(state->s_l4)); //copy right to left
//else if voice in both, and both slots on, and no preference on slot, then regular stereo interleave (left and right channels)
//if both slots are the same now, then let's decimate the audio to keep the audio level consistent
// if (memcmp (state->s_l4, state->s_r4, sizeof(state->s_l4)) == 0)
// {
// for (j = 0; j < 18; j++)
// {
// for (i = 0; i < 160; i++)
// {
// state->s_l4[j][i] *= 0.85;
// state->s_r4[j][i] *= 0.85;
// }
// }
// }
#endif
//check this last
if (opts->slot1_on == 0 && opts->slot2_on == 0) //both slots are hard off, disable playback
{
encL = 1;
encR = 1;
}
//at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions
if (encL && encR)
goto SS18_END;
//interleave left and right channels from the short storage area
for (j = 0; j < 18; j++)
{
for (i = 0; i < 160; i++)
{
#ifdef P2_STEREO_OUTPUT
#else
if (!encL)
#endif
stereo_sf[j][i*2+0] = state->s_l4[j][i];
#ifdef P2_STEREO_OUTPUT
#else
if (!encR)
#endif
stereo_sf[j][i*2+1] = state->s_r4[j][i];
}
}
if (opts->audio_out_type == 0) //Pulse Audio
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
pa_simple_write(opts->pulse_digi_dev_out, stereo_sf[j], 320*2, NULL);
}
}
if (opts->audio_out_type == 8) //UDP Audio
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
udp_socket_blaster (opts, state, 320*2, stereo_sf[j]);
}
}
if (opts->audio_out_type == 1 || opts->audio_out_type == 2) //STDOUT or OSS 8k/2channel
{
for (j = 0; j < 18; j++)
{
if (memcmp(empty, stereo_sf[j], sizeof(empty)) != 0) //may not work as intended because its stereo and one will have something in it most likely
write (opts->audio_out_fd, stereo_sf[j], 320*2);
}
}
SS18_END:
//run cleanup since we pulled stuff from processAudio
state->audio_out_idx = 0;
state->audio_out_idxR = 0;
//set float temp buffer to baseline
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
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;
}
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;
}
}
//largely borrowed from Boatbod OP25 (simplified single tone ID version)
void soft_tonef (float samp[160], int n, int ID, int AD)
{
@@ -1349,64 +1914,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

@@ -382,6 +382,8 @@ noCarrier (dsd_opts * opts, dsd_state * state)
}
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
//values displayed in ncurses terminal
// state->p25_vc_freq[0] = 0;
@@ -583,6 +585,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 +694,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;
@@ -760,12 +764,21 @@ initOpts (dsd_opts * opts)
//slot preference is used during OSS audio playback to
//prefer one tdma voice slot over another when both are playing back
//this is a fix to OSS 48k/1 output
#ifdef AERO_BUILD
opts->slot_preference = 0; //default prefer slot 1 -- state->currentslot = 0;
#else
opts->slot_preference = 2; //use 2 since integrating the Stereo Channel Patch;
#endif
//hardset slots to synthesize
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 +912,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;
@@ -956,6 +970,8 @@ initState (dsd_state * state)
}
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
state->K = 0;
state->R = 0;
@@ -1047,8 +1063,8 @@ initState (dsd_state * state)
//edacs - may need to make these user configurable instead for stability on non-ea systems
state->ea_mode = -1; //init on -1, 0 is standard, 1 is ea
state->esk_mode = -1; //same as above, but with esk or not
state->esk_mask = 0x0; //toggles from 0x0 to 0xA0 if esk mode enabled
state->edacs_vc_call_type = 0;
state->esk_mask = 0x0; //esk mask value
state->edacs_site_id = 0;
state->edacs_lcn_count = 0;
state->edacs_cc_lcn = 0;
@@ -1236,7 +1252,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 +1299,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 +1312,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");
@@ -1333,7 +1350,11 @@ usage ()
printf (" -fz Decode only M17*\n");
printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n");
printf (" -fn Decode only NXDN96* (12.5 kHz)\n");
printf (" -fp Decode only EDACS/ProVoice*\n");
printf (" -fp Decode only ProVoice*\n");
printf (" -fh Decode only EDACS Standard/ProVoice*\n");
printf (" -fH Decode only EDACS Standard/ProVoice with ESK 0xA0*\n");
printf (" -fe Decode only EDACS EA/ProVoice*\n");
printf (" -fE Decode only EDACS EA/ProVoice with ESK 0xA0*\n");
printf (" -fm Decode only dPMR*\n");
printf (" -l Disable DMR, dPMR, and NXDN input filtering\n");
printf (" -u <num> Unvoiced speech quality (default=3)\n");
@@ -1416,7 +1437,7 @@ usage ()
printf (" P25 - 12000; NXDN48 - 7000; NXDN96: 12000; DMR - 7000-12000; EDACS/PV - 12000-24000;\n"); //redo this, or check work, or whatever
printf (" May vary based on system stregnth, etc.\n");
printf (" -t <secs> Set Trunking or Scan Speed VC/sync loss hangtime in seconds. (default = 1 second)\n");
printf (" -9 Force Enable EDACS Standard or Networked Mode if Auto Detection Fails \n");
// printf (" -9 Force Enable EDACS Standard or Networked Mode if Auto Detection Fails \n");
printf ("\n");
printf (" Trunking Example TCP: dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans\n");
printf (" Trunking Example RTL: dsd-fme -fs -i rtl:0:450M:26:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans\n");
@@ -1636,7 +1657,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
@@ -1684,9 +1705,10 @@ main (int argc, char **argv)
fprintf (stderr, "TG Hold set to %d \n", state.tg_hold);
break;
case '9': //This is a temporary fix for RR issue until a permanent fix can be found
case '9': //Leaving Enabled to maintain backwards compatability
state.ea_mode = 0;
fprintf (stderr,"Force Enabling EDACS Standard/Networked Mode Mode\n");
state.esk_mask = 0;
fprintf (stderr,"Force Enabling EDACS Standard/Networked Mode Mode without ESK.\n");
break;
//experimental audio monitoring
@@ -2022,6 +2044,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");
@@ -2103,6 +2126,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");
}
@@ -2173,11 +2197,150 @@ 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");
//misc tweaks
opts.rtl_bandwidth = 24;
}
else if (optarg[0] == 'h') //standard / net w/o ESK
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_p25p2 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 1;
state.ea_mode = 0;
state.esk_mask = 0;
opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 12500;
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding EDACS STD/NET and ProVoice frames.\n");
fprintf (stderr,"EDACS Analog Voice Channels are Experimental.\n");
//rtl specific tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
}
else if (optarg[0] == 'H') //standard / net w/ ESK
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_p25p2 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 1;
state.ea_mode = 0;
state.esk_mask = 0xA0;
opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 12500;
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding EDACS STD/NET w/ ESK and ProVoice frames.\n");
fprintf (stderr,"EDACS Analog Voice Channels are Experimental.\n");
//rtl specific tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
}
else if (optarg[0] == 'e') //extended addressing w/o ESK
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_p25p2 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 1;
state.ea_mode = 1;
state.esk_mask = 0;
opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 12500;
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding EDACS Extended Addressing and ProVoice frames.\n");
fprintf (stderr,"EDACS Analog Voice Channels are Experimental.\n");
//rtl specific tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
}
else if (optarg[0] == 'E') //extended addressing w/ ESK
{
opts.frame_dstar = 0;
opts.frame_x2tdma = 0;
opts.frame_p25p1 = 0;
opts.frame_p25p2 = 0;
opts.frame_nxdn48 = 0;
opts.frame_nxdn96 = 0;
opts.frame_dmr = 0;
opts.frame_dpmr = 0;
opts.frame_provoice = 1;
state.ea_mode = 1;
state.esk_mask = 0xA0;
opts.frame_ysf = 0;
opts.frame_m17 = 0;
state.samplesPerSymbol = 5;
state.symbolCenter = 2;
opts.mod_c4fm = 0;
opts.mod_qpsk = 0;
opts.mod_gfsk = 1;
state.rf_mod = 2;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
opts.dmr_stereo = 0;
opts.dmr_mono = 0;
state.dmr_stereo = 0;
// opts.setmod_bw = 12500;
sprintf (opts.output_name, "EDACS/PV");
fprintf (stderr,"Setting symbol rate to 9600 / second\n");
fprintf (stderr,"Decoding EDACS Extended Addressing w/ ESK and ProVoice frames.\n");
fprintf (stderr,"EDACS Analog Voice Channels are Experimental.\n");
//rtl specific tweaks
opts.rtl_bandwidth = 24;
// opts.rtl_gain_value = 36;
@@ -2466,6 +2629,11 @@ 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;
opts.dmr_stereo = 0;
sprintf (opts.output_name, "M17 Encoder");
}
else if (optarg[0] == 'B') //Captial B to Run the M17 BRT encoder
@@ -2756,8 +2924,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:
@@ -2789,15 +2961,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)

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

174
src/m17.c
View File

@@ -359,37 +359,46 @@ void M17processCodec2_1600(dsd_opts * opts, dsd_state * state, uint8_t * payload
codec2_decode(state->codec2_1600, samp1, voice1);
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
}
//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 == 8 && state->m17_enc == 0) //UDP Audio
if (opts->slot1_on == 1) //playback if enabled
{
udp_socket_blaster (opts, state, nsam*2, samp1);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0) //OSS 48k/1
{
//upsample to 48k and then play
prev = samp1[0];
for (i = 0; i < 160; i++)
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
{
upsampleS (samp1[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
}
if (opts->audio_out_type == 8 && state->m17_enc == 0) //UDP Audio
{
udp_socket_blaster (opts, state, nsam*2, samp1);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0) //OSS 48k/1
{
//upsample to 48k and then play
prev = samp1[0];
for (i = 0; i < 160; i++)
{
upsampleS (samp1[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
if (opts->audio_out_type == 1 && state->m17_enc == 0) //STDOUT
{
write (opts->audio_out_fd, samp1, nsam*2);
}
}
if (opts->audio_out_type == 1 && state->m17_enc == 0) //STDOUT
{
write (opts->audio_out_fd, samp1, nsam*2);
}
if (opts->audio_out_type == 2 && state->m17_enc == 0) //OSS 8k/1
{
write (opts->audio_out_fd, samp1, nsam*2);
}
if (opts->audio_out_type == 2 && state->m17_enc == 0) //OSS 8k/1
{
write (opts->audio_out_fd, samp1, nsam*2);
}
//WIP: Wav file saving -- still need a way to open/close/label wav files similar to call history
@@ -459,47 +468,59 @@ 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);
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
//hpf_d on codec2 sounds better than not on those .rrc samples
if (opts->use_hpf_d == 1)
{
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
pa_simple_write(opts->pulse_digi_dev_out, samp2, nsam*2, NULL);
hpf_dL(state, samp1, nsam);
hpf_dL(state, samp2, nsam);
}
if (opts->audio_out_type == 8 && state->m17_enc == 0) //UDP Audio
if (opts->slot1_on == 1) //playback if enabled
{
udp_socket_blaster (opts, state, nsam*2, samp1);
udp_socket_blaster (opts, state, nsam*2, samp2);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0) //OSS 48k/1
{
//upsample to 48k and then play
prev = samp1[0];
for (i = 0; i < 160; i++)
if (opts->audio_out_type == 0 && state->m17_enc == 0) //Pulse Audio
{
upsampleS (samp1[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
pa_simple_write(opts->pulse_digi_dev_out, samp1, nsam*2, NULL);
pa_simple_write(opts->pulse_digi_dev_out, samp2, nsam*2, NULL);
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
prev = samp2[0];
for (i = 0; i < 160; i++)
if (opts->audio_out_type == 8 && state->m17_enc == 0) //UDP Audio
{
upsampleS (samp2[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
udp_socket_blaster (opts, state, nsam*2, samp1);
udp_socket_blaster (opts, state, nsam*2, samp2);
}
if (opts->audio_out_type == 5 && state->m17_enc == 0) //OSS 48k/1
{
//upsample to 48k and then play
prev = samp1[0];
for (i = 0; i < 160; i++)
{
upsampleS (samp1[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
prev = samp2[0];
for (i = 0; i < 160; i++)
{
upsampleS (samp2[i], prev, out);
for (j = 0; j < 6; j++) upsamp[(i*6)+j] = out[j];
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
}
write (opts->audio_out_fd, upsamp, nsam*2*6);
}
if (opts->audio_out_type == 1 && state->m17_enc == 0) //STDOUT
{
write (opts->audio_out_fd, samp1, nsam*2);
write (opts->audio_out_fd, samp2, nsam*2);
}
if (opts->audio_out_type == 1 && state->m17_enc == 0) //STDOUT
{
write (opts->audio_out_fd, samp1, nsam*2);
write (opts->audio_out_fd, samp2, nsam*2);
}
if (opts->audio_out_type == 2 && state->m17_enc == 0) //OSS 8k/1
{
write (opts->audio_out_fd, samp1, nsam*2);
write (opts->audio_out_fd, samp2, nsam*2);
}
if (opts->audio_out_type == 2 && state->m17_enc == 0) //OSS 8k/1
{
write (opts->audio_out_fd, samp1, nsam*2);
write (opts->audio_out_fd, samp2, nsam*2);
}
//WIP: Wav file saving -- still need a way to open/close/label wav files similar to call history
@@ -1840,18 +1861,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

@@ -77,6 +77,13 @@ static uint32_t crc32mbf(uint8_t * buf, int len)
void processMPDU(dsd_opts * opts, dsd_state * state)
{
//p25p2 18v reset counters and buffers
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
opts->slot_preference = 2;
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces

View File

@@ -11,6 +11,14 @@
void processTSBK(dsd_opts * opts, dsd_state * state)
{
//p25p2 18v reset counters and buffers
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
opts->slot_preference = 2;
//reset some strings when returning from a call in case they didn't get zipped already
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces

View File

@@ -490,18 +490,27 @@ void process_4V (dsd_opts * opts, dsd_state * state)
// else state->dmrburstR = 21;
// }
// #endif
//unsure of the best location for these counter resets
if (state->voice_counter[0] >= 18)
state->voice_counter[0] = 0;
if (state->voice_counter[1] >= 18)
state->voice_counter[1] = 0;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
if(state->currentslot == 0)
{
memcpy(state->f_l4[0], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[0], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[0], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[0], state->s_ru, sizeof(state->s_ru));
}
@@ -509,13 +518,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[1], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[1], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[1], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[1], state->s_ru, sizeof(state->s_ru));
}
@@ -523,13 +534,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[2], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[2], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[2], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[2], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[2], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[2], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[2], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[2], state->s_ru, sizeof(state->s_ru));
}
@@ -537,13 +550,15 @@ void process_4V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[3], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[3], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[3], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[3], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[3], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[3], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[3], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[3], state->s_ru, sizeof(state->s_ru));
}
@@ -773,17 +788,26 @@ void process_2V (dsd_opts * opts, dsd_state * state)
// }
// #endif
//unsure of the best location for these counter resets
if (state->voice_counter[0] >= 18)
state->voice_counter[0] = 0;
if (state->voice_counter[1] >= 18)
state->voice_counter[1] = 0;
processMbeFrame (opts, state, NULL, ambe_fr1, NULL);
if(state->currentslot == 0)
{
memcpy(state->f_l4[0], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[0], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[0], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[0], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[0], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[0], state->s_ru, sizeof(state->s_ru));
}
@@ -791,17 +815,19 @@ void process_2V (dsd_opts * opts, dsd_state * state)
if(state->currentslot == 0)
{
memcpy(state->f_l4[1], state->audio_out_temp_buf, sizeof(state->audio_out_temp_buf));
memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
// memcpy(state->s_l4[1], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4[(state->voice_counter[0]++)%18], state->s_l, sizeof(state->s_l));
memcpy(state->s_l4u[1], state->s_lu, sizeof(state->s_lu));
}
else
{
memcpy(state->f_r4[1], state->audio_out_temp_bufR, sizeof(state->audio_out_temp_bufR));
memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
// memcpy(state->s_r4[1], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4[(state->voice_counter[1]++)%18], state->s_r, sizeof(state->s_r));
memcpy(state->s_r4u[1], state->s_ru, sizeof(state->s_ru));
}
// if (state->currentslot == 0) state->voice_counter[0] = 0; if (state->currentslot == 1) state->voice_counter[1] = 0;
process_ESS(opts, state);
//reset drop bytes after a 2V
@@ -908,10 +934,20 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine
//clear out stale voice samples left in the buffer and reset counter value
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
memset(state->s_l4, 0, sizeof(state->s_l4));
memset(state->s_r4, 0, sizeof(state->s_r4));
}
else if (duid_decoded == 13 && ((time(NULL) - state->last_active_time) > 2) && opts->p25_is_tuned == 0) //should we use && opts->p25_is_tuned == 1?
{
memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine
//clear out stale voice samples left in the buffer and reset counter value
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
memset(state->s_l4, 0, sizeof(state->s_l4));
memset(state->s_r4, 0, sizeof(state->s_r4));
}
if (duid_decoded == 0)
@@ -998,6 +1034,8 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
state->p2_is_lcch = 0;
state->fourv_counter[0] = 0;
state->fourv_counter[1] = 0;
state->voice_counter[0] = 0;
state->voice_counter[1] = 0;
goto END;
}
@@ -1017,8 +1055,22 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state)
if (sacch == 0 && ts_counter & 1 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 8000)
playSynthesizedVoiceFS4 (opts, state);
if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000)
playSynthesizedVoiceSS4 (opts, state);
// if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000)
// playSynthesizedVoiceSS4 (opts, state);
// fprintf (stderr, " VCH0: %d;", state->voice_counter[0]); //debug
// fprintf (stderr, " VCH1: %d;", state->voice_counter[1]); //debug
//this works, but may still have an element of 'dual voice stutter' which was my initial complaint, but shouldn't 'lag' during trunking operations (hopefully)
if ( (state->voice_counter[0] >= 18 || state->voice_counter[1] >= 18 ) && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000 && ts_counter & 1)
{
//debug test, see what each counter is at during playback on dual voice
// fprintf (stderr, " VC1: %02d; VC2: %02d;", state->voice_counter[0], state->voice_counter[1] );
playSynthesizedVoiceSS18 (opts, state);
state->voice_counter[0] = 0; //reset
state->voice_counter[1] = 0; //reset
}
//debug: fix burst indicator for ncurses if marginal signal
// if (voice)

View File

@@ -154,16 +154,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -254,16 +254,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -390,16 +390,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -515,16 +515,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -646,16 +646,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -752,16 +752,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channel & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channel & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -922,16 +922,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -1124,16 +1124,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -1265,16 +1265,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (tunable_chan & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (tunable_chan & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}
}
@@ -1394,16 +1394,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
//shim fix to stutter/lag by only enabling slot on the target/channel we tuned to
//this will only occur in realtime tuning, not not required .bin or .wav playback
if (channelt & 1) //VCH1
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else //VCH0
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
// if (channelt & 1) //VCH1
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else //VCH0
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
}

View File

@@ -122,6 +122,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
@@ -171,6 +172,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well
@@ -230,6 +232,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0;
@@ -258,6 +261,7 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0;
@@ -370,19 +374,19 @@ void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180]
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
if (state->currentslot == 1)
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
}
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 1)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces
@@ -512,6 +516,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
@@ -552,6 +557,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20;
@@ -608,6 +614,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well
@@ -636,6 +643,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well
@@ -737,6 +745,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->payload_keyid = 0;
state->dmrburstL = 24;
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->lastsrc = 0;
state->lasttg = 0;
@@ -747,6 +756,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
state->payload_keyidR = 0;
state->dmrburstR = 24;
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->lastsrcR = 0;
state->lasttgR = 0;
@@ -756,19 +766,19 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
if (state->currentslot == 0)
{
opts->slot1_on = 0;
opts->slot2_on = 1;
}
else
{
opts->slot1_on = 1;
opts->slot2_on = 0;
}
}
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 0)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces

View File

@@ -27,12 +27,19 @@ void processProVoice (dsd_opts * opts, dsd_state * state)
fprintf (stderr," VOICE");
//print group and source values if EA trunked
//print group/target and source values if EA trunked
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && state->ea_mode == 1)
{
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Site: %lld Group: %d Source: %d LCN: %d ",
state->edacs_site_id, state->lasttg, state->lastsrc, state->edacs_tuned_lcn);
if (state->lasttg > 100000) {
// I-Call
fprintf (stderr, " Site: %lld Target: %d Source: %d LCN: %d ",
state->edacs_site_id, state->lasttg - 100000, state->lastsrc, state->edacs_tuned_lcn);
} else {
// Group call
fprintf (stderr, " Site: %lld Group: %d Source: %d LCN: %d ",
state->edacs_site_id, state->lasttg, state->lastsrc, state->edacs_tuned_lcn);
}
fprintf (stderr, "%s", KNRM);
}
//print afs value if standard/networked trunked
@@ -214,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);
@@ -392,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);