mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-09 15:27:22 -05:00
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; commit9bbe4de7fdAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 16:08:16 2024 -0400 EDACS: Digitize Analog For Analysis of 'Data Burst' Like Behavior; commit9249b7a943Author: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 12:28:26 2024 -0400 Simply Mono Short Playback; commit89ad0f17e3Author: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 23 21:12:44 2024 -0400 Add HPF to SS4, SS3, and SS Audio Methods; commite8184c7fbdAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 23 17:13:44 2024 -0400 RTL - Add The Sample / Volume Multiplier as a user configurable option; commitee04d11116Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 23:15:04 2024 -0400 Fix HPF_D so it actually works correctly; commite549b21497Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 20:11:34 2024 -0400 Make Analog Auto Gain Control Mostly Tolerable; commit2f9e0525feAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 18:20:38 2024 -0400 User Toggle HPF on Digital; commitff58d3a6faAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 18:10:15 2024 -0400 User Toggles and Displays for Filters; commitb6fc17c506Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 15:55:09 2024 -0400 More Analog Manual Audio Gain Tweaks; commit076b9fbf04Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 06:26:10 2024 -0400 Add SQL Hit on EDACS if Colors Disabled; commit59fe47ef05Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:23:08 2024 -0400 Disable HPF Test on Digital Voice; commit4a63068ce1Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 23:39:43 2024 -0400 Misc Code Organizing; audio_gainA Tweaks; commit3585e7e594Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 13:18:31 2024 -0400 Test Tweak to RTL Sample Multiplier; commitfa5b25283fAuthor: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 13:18:07 2024 -0400 Adjust Manual Mic Gain on M17 Encoder; Ncurses Display; commitc985fea035Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 12:34:01 2024 -0400 Misc Notes on using raw_rms values during testing; commitb273e5b7beAuthor: 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; commiteadf3fdf23Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 10:12:04 2024 -0400 Analog Gain Has Own Variable; Ncurses Keys; Misc; commit0debcc647eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 08:49:51 2024 -0400 Filtering Misc Cleanup; commit98e10b2627Author: lwvmobile <lwvmobile@gmail.com> Date: Thu Mar 21 00:02:21 2024 -0400 Automatic Gain On Analog WIP; Manual Gain Control; commit89736ae543Author: lwvmobile <lwvmobile@gmail.com> Date: Wed Mar 20 10:22:20 2024 -0400 Passband Filter Testing on Raw Analog / EDACS / M17 Encoder; commit43f6218129Author: lwvmobile <lwvmobile@gmail.com> Date: Wed Mar 20 09:03:02 2024 -0400 Passband and Notch Filter Setup; Debug Output; commit35a1b53867Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 22:35:36 2024 -0400 HPF: Only Use On RTL Input when M17 Encoder Uses It; commitb9949f0d80Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 17:31:59 2024 -0400 Disable LFP on EDACS Analog Out; commit3666740674Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 13:42:07 2024 -0400 Test HPF On Digital Voice Out; commitef13343925Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 12:46:27 2024 -0400 RTL_FM Input for Analog/M17 Encoder; commit2b7de90474Author: 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> commitc8d00846b1Author: 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 commit8d432e8b3eAuthor: 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 commit0440dea1deAuthor: lwvmobile <lwvmobile@gmail.com> Date: Sun Mar 24 02:47:09 2024 -0400 EDACS: Fix Call History For Standard Maybe; commit208f188e55Author: 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 commit36f76a7e21Author: 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. commit4bc73d8c68Author: 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 commit03507055a4Author: 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 commitfbe5fd2093Author: 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 commit413e5f76a2Merge:de9127c388a57dAuthor: 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 commit388a57d8fcAuthor: 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; commit058099f1aaAuthor: 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; commit68aa6b018eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:19:38 2024 -0400 EDACS: Update Docs to Reflect Changes; commitc404f3c48cAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 02:01:09 2024 -0400 EDACS: Ncurses Display Working Mode Tweaks; commitb2d1608eb7Author: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 01:08:28 2024 -0400 EDACS: Toggle Keys A and S for Mode Selection; commita4553a0a0aAuthor: lwvmobile <lwvmobile@gmail.com> Date: Fri Mar 22 00:45:37 2024 -0400 EDACS: Remove Auto Detect Code; Make CLI Switches; commitde9127cfb4Author: 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> commitc85dd60399Author: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 17:38:30 2024 -0400 EDACS: NET/STD LCN > 0 Check; commitbed766a86eAuthor: lwvmobile <lwvmobile@gmail.com> Date: Tue Mar 19 09:34:10 2024 -0400 EDACS: STD/NET Don't Tune Unless CC LCN Set; commit69f532a022Author: 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 inf68367c4f3* 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> commita7de24c47bAuthor: 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. commit10eacd99ccAuthor: 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 commitebe6e8fc65Author: 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) commit8619612b76Author: lwvmobile <lwvmobile@gmail.com> Date: Sat Mar 16 22:42:44 2024 -0400 EDACS: Setup Analog Calls and WAVs on EA and ICALL; commit9ac1573f0bAuthor: 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 commit83ac8feab7. commit0aa01a45efAuthor: 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) commitf68367c4f3Author: 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:
@@ -4,7 +4,7 @@
|
||||
DSD-FME is an evolution of the original DSD project from 'DSD Author' using the base code of [szechyjs](https://github.com/szechyjs/dsd "szechyjs"), some code and ideas from [LouisErigHerve](https://github.com/LouisErigHerve/dsd "LouisErigHerve"), [Boatbod OP25](https://github.com/boatbod/op25 "Boatbod OP25") and
|
||||
[Osmocom OP25](https://gitea.osmocom.org/op25/op25 "Osmocom OP25"), along with other snippets of code, information, and inspirations from other projects including [DSDcc](https://github.com/f4exb/dsdcc "DSDcc"), [SDRTRunk](https://github.com/DSheirer/sdrtrunk "SDRTrunk"), [MMDVMHost](https://github.com/g4klx/MMDVMHost "MMDVMHost"), [LFSR](https://github.com/mattames/LFSR "LFSR"), [OK-DMRlib](https://github.com/OK-DMR/ok-dmrlib "OK-DMRlib"), and [EZPWD-Reed-Solomon](https://github.com/pjkundert/ezpwd-reed-solomon "EZPWD"), Eric Cottrell, SP5WWP and others. Finally, this is all brought together with original code to extend the fuctionality and add new features including NCurses Terminal and Menu system, Pulse Audio, TCP Direct Link Audio, RIGCTL, Trunking Features, LRRP/GPS Mapping, P25 Phase 2, EDACS, YSF, M17, OP25 Capture Bin compatability, etc. DSD-FME is primarily focused with Linux Desktop users in mind, so please understand that this version may not compile, compile easily, or run correctly in other environments.
|
||||
|
||||
This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu, Forts, thewraithe2008, RayAir, Cretu, and others for the many hours of wav samples and information provided by them. Most importantly, HRH17, whose insight, information, samples, and willingness to let me remote into a computer half-way across the globe in order to test trunking features are what make DSD-FME what it has become. I'd also like to thank mrscanner2008 for providing an additional remote where additional NXDN Type-C, 'Idas' Type-D, and XPT decoding and trunking could be sorted out. Thanks to volo-zyko for cleaning up a lot of code. Thank you everybody.
|
||||
This project wouldn't be possible without a few good people providing me plenty of sample audio files to run over and over again. Special thanks to jurek1111, KrisMar, noamlivne, racingfan360, iScottyBotty, LimaZulu, Forts, thewraithe2008, RayAir, Cretu, ilyacodes, and others for the many hours of wav samples and information provided by them. Most importantly, HRH17, whose insight, information, samples, and willingness to let me remote into a computer half-way across the globe in order to test trunking features are what make DSD-FME what it has become. I'd also like to thank mrscanner2008 for providing an additional remote where additional NXDN Type-C, 'Idas' Type-D, and XPT decoding and trunking could be sorted out. Thanks to volo-zyko for cleaning up a lot of code. Thank you everybody.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
-fa Legacy Auto (not recommended)
|
||||
-fi NXDN48
|
||||
-fn NXDN96
|
||||
-fp EDACS/Provoice
|
||||
-fp Provoice
|
||||
-fh EDACS Standard / Network
|
||||
-fH EDACS Standard / Network with ESK
|
||||
-fe EDACS Extended Addresssing
|
||||
-fE EDACS Extended Addressing with ESK
|
||||
-fm dPMR, also may need to use -xd if inverted dPMR.
|
||||
-f1 P25P1
|
||||
-f2 P25P2 (may need to specify wacn/sys/nac manually if traffic channel)
|
||||
@@ -74,7 +78,7 @@ Detailed Setup:
|
||||
|
||||
```
|
||||
RTL-SDR options:
|
||||
Usage: rtl:dev:freq:gain:ppm:bw:sq:udp
|
||||
Usage: rtl:dev:freq:gain:ppm:bw:sq:vol
|
||||
NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended
|
||||
dev <num> RTL-SDR Device Index Number
|
||||
freq <num> RTL-SDR Frequency (851800000 or 851.8M)
|
||||
@@ -82,9 +86,9 @@ RTL-SDR options:
|
||||
ppm <num> RTL-SDR PPM Error (default = 0)
|
||||
bw <num> RTL-SDR Bandwidth kHz (default = 12)(8, 12, 16, 24)
|
||||
sq <num> RTL-SDR Squelch Level vs RMS Value (Optional)
|
||||
udp <num> RTL-SDR Legacy UDP Remote Port (Optional -- External Use Only)
|
||||
Example: dsd-fme-zdev -fs -i rtl -C cap_plus_channel.csv -T
|
||||
Example: dsd-fme-zdev -fp -i rtl:0:851.375M:22:-2:24:0:6021
|
||||
vol <num> RTL-SDR Sample 'Volume' Multiplier (default = 1)(1,2,3)
|
||||
Example: dsd-fme -fs -i rtl -C cap_plus_channel.csv -T
|
||||
Example: dsd-fme -fp -i rtl:0:851.375M:22:-2:24:0:2
|
||||
|
||||
```
|
||||
|
||||
@@ -100,11 +104,11 @@ and in a second terminal tab, same folder, run
|
||||
|
||||
EDACS Trunking (w/ channel map import)
|
||||
|
||||
--EDACS/PV Trunking using RIGCTL and TCP Direct Link Audio inside of SDR++ (Tested and Working on EDACS/EDACS-EA with Provoice, Analog Voice Monitoring and Per Call is Experimental)
|
||||
--EDACS/PV Trunking using RIGCTL and TCP Direct Link Audio inside of SDR++ (see switches above for STD/NET, EA, and ESK modes)
|
||||
|
||||
`dsd-fme -i tcp -fp -C channel_map.csv -G group.csv -T -U 4532 -N 2> log.ans`
|
||||
`dsd-fme -i tcp -fE -C channel_map.csv -G group.csv -T -U 4532 -N 2> log.ans`
|
||||
|
||||
--NXDN48 Trunking (standard band plan) with SDR++ (untested for frequency accuracy)
|
||||
--NXDN48 Trunking (Direct Frequency Assignment) with SDR++ (untested for frequency accuracy)
|
||||
|
||||
`dsd-fme -fi -i tcp -T -U 4532 -N 2> log.ans`
|
||||
|
||||
@@ -176,9 +180,9 @@ M - toggle c4fm/qpsk 8/3 (phase 2 tdma control channel)
|
||||
R - start capturing symbol capture bin (date/time name file)
|
||||
r - stop capturing symbol capture bin
|
||||
spacebar - replay last symbol capture bin (captures must be stopped first)
|
||||
s - stop playing symbol capture bin or wav input file
|
||||
s - stop playing symbol capture bin or wav input file (lower s)
|
||||
P - start per call decoded wav files (Capital P)
|
||||
p - stop per call decoded wav files (Lower p)
|
||||
p - stop per call decoded wav files (lower p)
|
||||
t - toggle trunking (needs either rtl input, or rigctl connection)
|
||||
y - toggle scanner (needs either rtl input, or rigctl connection)
|
||||
1 - Toggle Voice Synthesis in TDMA Slot 1 or FDMA Conventional Voice
|
||||
@@ -202,6 +206,9 @@ l - Hold TG in Slot 2 on TDMA Systems, or clear current hold
|
||||
C - Drop Call and Return to CC during trunking operation
|
||||
L - Manual Cycle Forward Channel Tuned when RIGCTL or using RTL input and channel csv loaded
|
||||
|
||||
S - Toggle between EDACS Standard/Network and Extended Addressing mode (Capital S)
|
||||
A - Toggle EDACS ESK Mask (none vs A0)
|
||||
|
||||
```
|
||||
|
||||
## Sending Audio to a Icecast 2 Server via FFmpeg (Windows)
|
||||
|
||||
@@ -17,9 +17,21 @@
|
||||
dsd-fme -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fs -i rtl:0:450M:44:-2:8 -T -C connect_plus_chan.csv -G group.csv -N 2> log.ans
|
||||
|
||||
#EDACS/EDACS-EA Digital Only
|
||||
#dsd-fme -fp -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fp -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#EDACS Standard Network Analog and Digital
|
||||
#dsd-fme -fh -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fh -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
|
||||
#EDACS Standard Network Analog and Digital (with ESK)
|
||||
#dsd-fme -fH -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fH -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
|
||||
#EDACS Extended Address Analog and Digital
|
||||
#dsd-fme -fe -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fe -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
|
||||
#EDACS Extended Address Analog and Digital (with ESK)
|
||||
#dsd-fme -fE -i tcp:192.168.7.5:7355 -U 4532 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
#dsd-fme -fE -i rtl:0:850M:44:-2:24 -T -C edacs_channel_map.csv -G group.csv -N 2> log.ans
|
||||
|
||||
#NXDN48 Type-C or Type-D Trunking with Channel Map
|
||||
#dsd-fme -fi -i tcp -T -U 4532 -C nxdn_channel_map.csv -N 2> log.ans
|
||||
|
||||
104
include/dsd.h
104
include/dsd.h
@@ -86,6 +86,35 @@
|
||||
|
||||
extern volatile uint8_t exitflag; //fix for issue #136
|
||||
|
||||
//new audio filter stuff from: https://github.com/NedSimao/FilteringLibrary
|
||||
typedef struct {
|
||||
float coef[2];
|
||||
float v_out[2];
|
||||
}LPFilter;
|
||||
|
||||
typedef struct {
|
||||
float coef;
|
||||
float v_out[2];
|
||||
float v_in[2];
|
||||
|
||||
}HPFilter;
|
||||
|
||||
typedef struct {
|
||||
LPFilter lpf;
|
||||
HPFilter hpf;
|
||||
float out_in;
|
||||
}PBFilter;
|
||||
|
||||
typedef struct {
|
||||
float alpha;
|
||||
float beta;
|
||||
|
||||
float vin[3];
|
||||
float vout[3];
|
||||
|
||||
}NOTCHFilter;
|
||||
//end new filters
|
||||
|
||||
//group csv import struct
|
||||
typedef struct
|
||||
{
|
||||
@@ -210,8 +239,8 @@ typedef struct
|
||||
SF_INFO *audio_in_file_info;
|
||||
|
||||
uint32_t rtlsdr_center_freq;
|
||||
int rtlsdr_ppm_error;
|
||||
int audio_in_type;
|
||||
int rtlsdr_ppm_error;
|
||||
int audio_in_type;
|
||||
char audio_out_dev[1024];
|
||||
int audio_out_fd;
|
||||
int audio_out_fdR; //right channel audio for OSS hack
|
||||
@@ -231,6 +260,7 @@ typedef struct
|
||||
FILE *symbol_out_f;
|
||||
float audio_gain;
|
||||
float audio_gainR;
|
||||
float audio_gainA;
|
||||
int audio_out;
|
||||
int dmr_stereo_wav;
|
||||
char wav_out_dir[512];
|
||||
@@ -285,6 +315,7 @@ typedef struct
|
||||
int rtl_started;
|
||||
long int rtl_rms;
|
||||
int monitor_input_audio;
|
||||
int analog_only;
|
||||
int pulse_raw_rate_in;
|
||||
int pulse_raw_rate_out;
|
||||
int pulse_digi_rate_in;
|
||||
@@ -367,7 +398,7 @@ typedef struct
|
||||
char group_in_file[1024];
|
||||
char lcn_in_file[1024];
|
||||
char chan_in_file[1024];
|
||||
char key_in_file[1024];
|
||||
char key_in_file[1024];
|
||||
//end import filenames
|
||||
|
||||
//reverse mute
|
||||
@@ -405,6 +436,12 @@ typedef struct
|
||||
int slot1_on;
|
||||
int slot2_on;
|
||||
|
||||
//enable filter options
|
||||
int use_lpf;
|
||||
int use_hpf;
|
||||
int use_pbf;
|
||||
int use_hpf_d;
|
||||
|
||||
//'DSP' Format Output
|
||||
uint8_t use_dsp_output;
|
||||
char dsp_out_file[2048];
|
||||
@@ -447,14 +484,14 @@ typedef struct
|
||||
//new stereo short sample storage
|
||||
short s_l[160]; //single sample left
|
||||
short s_r[160]; //single sample right
|
||||
short s_l4[4][160]; //quad sample for up to a P25p2 4V
|
||||
short s_r4[4][160]; //quad sample for up to a P25p2 4V
|
||||
short s_l4[18][160]; //quad sample for up to a P25p2 4V
|
||||
short s_r4[18][160]; //quad sample for up to a P25p2 4V
|
||||
//new stereo short sample storage tapped from 48_k internal upsampling
|
||||
short s_lu[160*6]; //single sample left
|
||||
short s_ru[160*6]; //single sample right
|
||||
short s_l4u[4][160*6]; //quad sample for up to a P25p2 4V
|
||||
short s_r4u[4][160*6]; //quad sample for up to a P25p2 4V
|
||||
//end
|
||||
//end
|
||||
int audio_out_idx;
|
||||
int audio_out_idx2;
|
||||
int audio_out_idxR;
|
||||
@@ -507,6 +544,7 @@ typedef struct
|
||||
char slot0light[8];
|
||||
float aout_gain;
|
||||
float aout_gainR;
|
||||
float aout_gainA;
|
||||
float aout_max_buf[200];
|
||||
float aout_max_bufR[200];
|
||||
float *aout_max_buf_p;
|
||||
@@ -616,7 +654,7 @@ typedef struct
|
||||
|
||||
char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify
|
||||
int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet.
|
||||
|
||||
|
||||
//dmr talker alias new/fixed stuff
|
||||
uint8_t dmr_alias_format[2]; //per slot
|
||||
uint8_t dmr_alias_len[2]; //per slot
|
||||
@@ -630,6 +668,16 @@ typedef struct
|
||||
|
||||
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;
|
||||
|
||||
//new audio filter structs
|
||||
LPFilter RCFilter;
|
||||
HPFilter HRCFilter;
|
||||
PBFilter PBF;
|
||||
NOTCHFilter NF;
|
||||
LPFilter RCFilterL;
|
||||
HPFilter HRCFilterL;
|
||||
LPFilter RCFilterR;
|
||||
HPFilter HRCFilterR;
|
||||
|
||||
char dpmr_caller_id[20];
|
||||
char dpmr_target_id[20];
|
||||
|
||||
@@ -664,6 +712,7 @@ typedef struct
|
||||
int p2_vch_chan_num; //vch channel number (0 or 1, not the 0-11 TS)
|
||||
int ess_b[2][96]; //external storage for ESS_B fragments
|
||||
int fourv_counter[2]; //external reference counter for ESS_B fragment collection
|
||||
int voice_counter[2]; //external reference counter for 18V x 2 P25p2 Superframe
|
||||
int p2_is_lcch; //flag to tell us when a frame is lcch and not sacch
|
||||
|
||||
//iden freq storage for frequency calculations
|
||||
@@ -695,13 +744,23 @@ typedef struct
|
||||
|
||||
//edacs
|
||||
int ea_mode;
|
||||
int esk_mode;
|
||||
|
||||
unsigned short esk_mask;
|
||||
unsigned long long int edacs_site_id;
|
||||
int edacs_lcn_count; //running tally of lcn's observed on edacs system
|
||||
int edacs_cc_lcn; //current lcn for the edacs control channel
|
||||
int edacs_vc_lcn; //current lcn for any active vc (not the one we are tuned/tuning to)
|
||||
int edacs_tuned_lcn; //the vc we are currently tuned to...above variable is for updating all in the matrix
|
||||
int edacs_vc_call_type; //the type of call on the given VC - see defines below
|
||||
|
||||
//flags for EDACS call type
|
||||
#define EDACS_IS_VOICE 0x01
|
||||
#define EDACS_IS_DIGITAL 0x02
|
||||
#define EDACS_IS_EMERGENCY 0x04
|
||||
#define EDACS_IS_GROUP 0x08
|
||||
#define EDACS_IS_INDIVIDUAL 0x10
|
||||
#define EDACS_IS_ALL_CALL 0x20
|
||||
#define EDACS_IS_INTERCONNECT 0x40
|
||||
|
||||
//trunking group and lcn freq list
|
||||
long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully
|
||||
@@ -943,10 +1002,15 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state); //float stere
|
||||
void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state); //float stereo mix 4v2 P25p2
|
||||
void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state); //float mono
|
||||
void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot); //float gain control
|
||||
void agsm (dsd_opts * opts, dsd_state * state, short * input, int len); //short gain control for analog things
|
||||
void analog_gain (dsd_opts * opts, dsd_state * state, short * input, int len); //manual gain handling for analong things
|
||||
//new short stuff
|
||||
void playSynthesizedVoiceMS (dsd_opts * opts, dsd_state * state); //short mono mix
|
||||
void playSynthesizedVoiceMSR (dsd_opts * opts, dsd_state * state); //short mono mix R (needed for OSS 48k input/output)
|
||||
void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state); //short stereo mix
|
||||
void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state); //short stereo mix 3v2 DMR
|
||||
void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state); //short stereo mix 4v2 P25p2
|
||||
void playSynthesizedVoiceSS18 (dsd_opts * opts, dsd_state * state); //short stereo mix 18V Superframe
|
||||
void upsampleS (short invalue, short prev, short outbuf[6]); //upsample 8k to 48k short
|
||||
//
|
||||
void openAudioOutDevice (dsd_opts * opts, int speed);
|
||||
@@ -1188,7 +1252,7 @@ bool crc8_ok(uint8_t bits[], unsigned int len);
|
||||
//modified CRC functions for SB/RC
|
||||
uint8_t crc7(uint8_t bits[], unsigned int len);
|
||||
uint8_t crc3(uint8_t bits[], unsigned int len);
|
||||
uint8_t crc4(uint8_t bits[], unsigned int len);
|
||||
uint8_t crc4(uint8_t bits[], unsigned int len);
|
||||
|
||||
//LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/
|
||||
void LFSR(dsd_state * state);
|
||||
@@ -1285,12 +1349,24 @@ void eot_cc(dsd_opts * opts, dsd_state * state); //end of TX return to CC
|
||||
//Generic Tuning Functions
|
||||
void return_to_cc (dsd_opts * opts, dsd_state * state);
|
||||
|
||||
//misc generic audio filtering for analog at 48k/1
|
||||
//misc audio filtering for analog
|
||||
long int raw_rms(short *samples, int len, int step);
|
||||
void analog_deemph_filter(short * input, int len);
|
||||
void analog_preemph_filter(short * input, int len);
|
||||
void analog_dc_block_filter(short * input, int len);
|
||||
void analog_clipping_filter(short * input, int len);
|
||||
void init_audio_filters(dsd_state * state);
|
||||
void lpf(dsd_state * state, short * input, int len);
|
||||
void hpf(dsd_state * state, short * input, int len);
|
||||
void pbf(dsd_state * state, short * input, int len);
|
||||
void nf(dsd_state * state, short * input, int len);
|
||||
void hpf_dL(dsd_state * state, short * input, int len);
|
||||
void hpf_dR(dsd_state * state, short * input, int len);
|
||||
//from: https://github.com/NedSimao/FilteringLibrary
|
||||
void LPFilter_Init(LPFilter *filter, float cutoffFreqHz, float sampleTimeS);
|
||||
float LPFilter_Update(LPFilter *filter, float v_in);
|
||||
void HPFilter_Init(HPFilter *filter, float cutoffFreqHz, float sampleTimeS);
|
||||
float HPFilter_Update(HPFilter *filter, float v_in);
|
||||
void PBFilter_Init(PBFilter *filter, float HPF_cutoffFreqHz, float LPF_cutoffFreqHz, float sampleTimeS);
|
||||
float PBFilter_Update(PBFilter *filter, float v_in);
|
||||
void NOTCHFilter_Init(NOTCHFilter *filter, float centerFreqHz, float notchWidthHz, float sampleTimeS);
|
||||
float NOTCHFilter_Update(NOTCHFilter *filter, float vin);
|
||||
|
||||
//csv imports
|
||||
int csvGroupImport(dsd_opts * opts, dsd_state * state);
|
||||
|
||||
272
src/3.c
272
src/3.c
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
732
src/dsd_audio2.c
732
src/dsd_audio2.c
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
212
src/dsd_main.c
212
src/dsd_main.c
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
1719
src/edacs-fme.c
1719
src/edacs-fme.c
File diff suppressed because it is too large
Load Diff
174
src/m17.c
174
src/m17.c
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
200
src/p25p2_vpdu.c
200
src/p25p2_vpdu.c
@@ -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;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user