mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
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
1226 lines
41 KiB
C
1226 lines
41 KiB
C
/*
|
|
* Copyright (C) 2010 DSD Author
|
|
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "dsd.h"
|
|
|
|
//NOTE: This set of functions will be reorganized and simplified (hopefully) or at least
|
|
//a more logical flow will be established to jive with the new audio handling
|
|
|
|
void keyring(dsd_opts * opts, dsd_state * state)
|
|
{
|
|
UNUSED(opts);
|
|
|
|
if (state->currentslot == 0)
|
|
state->R = state->rkey_array[state->payload_keyid];
|
|
|
|
if (state->currentslot == 1)
|
|
state->RR = state->rkey_array[state->payload_keyidR];
|
|
}
|
|
|
|
void RC4(int drop, uint8_t keylength, uint8_t messagelength, uint8_t key[], uint8_t cipher[], uint8_t plain[])
|
|
{
|
|
int i, j, count;
|
|
uint8_t t, b;
|
|
|
|
//init Sbox
|
|
uint8_t S[256];
|
|
for(int i = 0; i < 256; i++) S[i] = i;
|
|
|
|
//Key Scheduling
|
|
j = 0;
|
|
for(i = 0; i < 256; i++)
|
|
{
|
|
j = (j + S[i] + key[i % keylength]) % 256;
|
|
t = S[i];
|
|
S[i] = S[j];
|
|
S[j] = t;
|
|
}
|
|
|
|
//Drop Bytes and Cipher Byte XOR
|
|
i = j = 0;
|
|
for(count = 0; count < (messagelength + drop); count++)
|
|
{
|
|
i = (i + 1) % 256;
|
|
j = (j + S[i]) % 256;
|
|
t = S[i];
|
|
S[i] = S[j];
|
|
S[j] = t;
|
|
b = S[(S[i] + S[j]) % 256];
|
|
|
|
//return mbe payload byte here
|
|
if (count >= drop)
|
|
plain[count - drop] = b^cipher[count - drop];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int Pr[256] = {
|
|
0x0000, 0x1F00, 0xE300, 0xFC00, 0x2503, 0x3A03, 0xC603, 0xD903,
|
|
0x4A05, 0x5505, 0xA905, 0xB605, 0x6F06, 0x7006, 0x8C06, 0x9306,
|
|
0x2618, 0x3918, 0xC518, 0xDA18, 0x031B, 0x1C1B, 0xE01B, 0xFF1B,
|
|
0x6C1D, 0x731D, 0x8F1D, 0x901D, 0x491E, 0x561E, 0xAA1E, 0xB51E, //31
|
|
0x4B28, 0x5428, 0xA828, 0xB728, 0x6E2B, 0x712B, 0x8D2B, 0x922B,
|
|
0x012D, 0x1E2D, 0xE22D, 0xFD2D, 0x242E, 0x3B2E, 0xC72E, 0xD82E,
|
|
0x6D30, 0x7230, 0x8E30, 0x9130, 0x4833, 0x5733, 0xAB33, 0xB433,
|
|
0x2735, 0x3835, 0xC435, 0xDB35, 0x0236, 0x1D36, 0xE136, 0xFE36, //63
|
|
0x2B49, 0x3449, 0xC849, 0xD749, 0x0E4A, 0x114A, 0xED4A, 0xF24A,
|
|
0x614C, 0xAE4C, 0x824C, 0x9D4C, 0x444F, 0x5B4F, 0xA74F, 0xB84F,
|
|
0x0D51, 0x1251, 0xEE51, 0xF151, 0x2852, 0x3752, 0xCB52, 0xD452,
|
|
0x4754, 0x5854, 0xA454, 0xBB54, 0x6257, 0x7D57, 0x8157, 0x9E57, //95
|
|
0x6061, 0x7F61, 0x8361, 0x9C61, 0x4562, 0x5A62, 0xA662, 0xB962,
|
|
0x2A64, 0x3564, 0xC964, 0xD664, 0x0F67, 0x1067, 0xEC67, 0xF367,
|
|
0x4679, 0x5979, 0xA579, 0xBA79, 0x637A, 0x7C7A, 0x807A, 0x9F7A,
|
|
0x0C7C, 0x137C, 0xEF7C, 0xF07C, 0x297F, 0x367F, 0xCA7F, 0xD57F, //127
|
|
0x4D89, 0x5289, 0xAE89, 0xB189, 0x688A, 0x778A, 0x8B8A, 0x948A,
|
|
0x078C, 0x188C, 0xE48C, 0xFB8C, 0x228F, 0x3D8F, 0xC18F, 0xDE8F,
|
|
0x6B91, 0x7491, 0x8891, 0x9791, 0x4E92, 0x5192, 0xAD92, 0xB292,
|
|
0x2194, 0x3E94, 0xC294, 0xDD94, 0x0497, 0x1B97, 0xE797, 0xF897, //159
|
|
0x06A1, 0x19A1, 0xE5A1, 0xFAA1, 0x23A2, 0x3CA2, 0xC0A2, 0xDFA2,
|
|
0x4CA4, 0x53A4, 0xAFA4, 0xB0A4, 0x69A7, 0x76A7, 0x8AA7, 0x95A7,
|
|
0x20B9, 0x3FB9, 0xC3B9, 0xDCB9, 0x05BA, 0x1ABA, 0xE6BA, 0xF9BA,
|
|
0x6ABC, 0x75BC, 0x89BC, 0x96BC, 0x4FBF, 0x50BF, 0xACBF, 0xB3BF, //191
|
|
0x66C0, 0x79C0, 0x85C0, 0x9AC0, 0x43C3, 0x5CC3, 0xA0C3, 0xBFC3,
|
|
0x2CC5, 0x33C5, 0xCFC5, 0xD0C5, 0x09C6, 0x16C6, 0xEAC6, 0xF5C6,
|
|
0x84D0, 0x85DF, 0x8AD3, 0x8BDC, 0xB6D5, 0xB7DA, 0xB8D6, 0xB9D9,
|
|
0xD0DA, 0xD1D5, 0xDED9, 0xDFD6, 0xE2DF, 0xE3D0, 0xECDC, 0xEDD3, //223
|
|
0x2DE8, 0x32E8, 0xCEE8, 0xD1E8, 0x08EB, 0x17EB, 0xEBEB, 0xF4EB,
|
|
0x67ED, 0x78ED, 0x84ED, 0x9BED, 0x42EE, 0x5DEE, 0xA1EE, 0xBEEE,
|
|
0x0BF0, 0x14F0, 0xE8F0, 0xF7F0, 0x2EF3, 0x31F3, 0xCDF3, 0xD2F3,
|
|
0x41F5, 0x5EF5, 0xA2F5, 0xBDF5, 0x64F6, 0x7BF6, 0x87F6, 0x98F6 //255
|
|
};
|
|
|
|
void playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
|
|
{
|
|
|
|
int i;
|
|
char imbe_d[88];
|
|
char ambe_d[49];
|
|
|
|
for (i = state->optind; i < argc; i++)
|
|
{
|
|
sprintf (opts->mbe_in_file, "%s", argv[i]);
|
|
openMbeInFile (opts, state);
|
|
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
|
|
fprintf (stderr, "playing %s\n", opts->mbe_in_file);
|
|
while (feof (opts->mbe_in_f) == 0)
|
|
{
|
|
if (state->mbe_file_type == 0)
|
|
{
|
|
readImbe4400Data (opts, state, imbe_d);
|
|
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
if (opts->audio_out == 1 && opts->floating_point == 0)
|
|
{
|
|
processAudio(opts, state);
|
|
}
|
|
if (opts->wav_out_f != NULL)
|
|
{
|
|
writeSynthesizedVoice (opts, state);
|
|
}
|
|
|
|
if (opts->audio_out == 1 && opts->floating_point == 0)
|
|
{
|
|
playSynthesizedVoiceMS (opts, state);
|
|
}
|
|
if (opts->floating_point == 1)
|
|
{
|
|
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l));
|
|
playSynthesizedVoiceFM (opts, state);
|
|
}
|
|
}
|
|
else if (state->mbe_file_type > 0) //ambe files
|
|
{
|
|
readAmbe2450Data (opts, state, ambe_d);
|
|
int x;
|
|
unsigned long long int k;
|
|
if (state->K != 0) //apply Pr key
|
|
{
|
|
k = Pr[state->K];
|
|
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
|
for (short int j = 0; j < 48; j++) //49
|
|
{
|
|
x = ( ((k << j) & 0x800000000000) >> 47 );
|
|
ambe_d[j] ^= x;
|
|
}
|
|
}
|
|
|
|
//ambe+2
|
|
if (state->mbe_file_type == 1) mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
//dstar ambe
|
|
if (state->mbe_file_type == 2) mbe_processAmbe2400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
|
|
if (opts->audio_out == 1 && opts->floating_point == 0)
|
|
{
|
|
processAudio(opts, state);
|
|
}
|
|
if (opts->wav_out_f != NULL)
|
|
{
|
|
writeSynthesizedVoice (opts, state);
|
|
}
|
|
|
|
if (opts->audio_out == 1 && opts->floating_point == 0)
|
|
{
|
|
playSynthesizedVoiceMS (opts, state);
|
|
}
|
|
if (opts->floating_point == 1)
|
|
{
|
|
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l));
|
|
playSynthesizedVoiceFM (opts, state);
|
|
}
|
|
}
|
|
if (exitflag == 1)
|
|
{
|
|
cleanupAndExit (opts, state);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24])
|
|
{
|
|
|
|
int i;
|
|
char imbe_d[88];
|
|
char ambe_d[49];
|
|
unsigned long long int k;
|
|
int x;
|
|
|
|
//these conditions should ensure no clashing with the BP/HBP/Scrambler key loading machanisms already coded in
|
|
if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->keyloader == 1)
|
|
keyring (opts, state);
|
|
|
|
if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->keyloader == 1)
|
|
keyring (opts, state);
|
|
|
|
//24-bit TG to 16-bit hash
|
|
uint32_t hash = 0;
|
|
uint8_t hash_bits[24];
|
|
memset (hash_bits, 0, sizeof(hash_bits));
|
|
|
|
int preempt = 0; //TDMA dual voice slot preemption(when using OSS output)
|
|
|
|
|
|
for (i = 0; i < 88; i++)
|
|
{
|
|
imbe_d[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < 49; i++)
|
|
{
|
|
ambe_d[i] = 0;
|
|
}
|
|
|
|
//set playback mode for this frame
|
|
char mode[8];
|
|
sprintf (mode, "%s", "");
|
|
|
|
//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 (mode, "%s", "B");
|
|
|
|
int groupNumber = 0;
|
|
|
|
if (state->currentslot == 0) groupNumber = state->lasttg;
|
|
else groupNumber = state->lasttgR;
|
|
|
|
for (i = 0; i < state->group_tally; i++)
|
|
{
|
|
if (state->group_array[i].groupNumber == groupNumber)
|
|
{
|
|
strcpy (mode, state->group_array[i].groupMode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//set flag to not play audio this time, but won't prevent writing to wav files -- disabled for now
|
|
// if (strcmp(mode, "B") == 0) opts->audio_out = 0; //causes a buzzing now (probably due to not running processAudio before the SS3 or SS4)
|
|
|
|
//end set playback mode for this frame
|
|
|
|
if ((state->synctype == 0) || (state->synctype == 1))
|
|
{
|
|
// 0 +P25p1
|
|
// 1 -P25p1
|
|
state->errs = mbe_eccImbe7200x4400C0 (imbe_fr);
|
|
state->errs2 = state->errs;
|
|
mbe_demodulateImbe7200x4400Data (imbe_fr);
|
|
state->errs2 += mbe_eccImbe7200x4400Data (imbe_fr, imbe_d);
|
|
|
|
//P25p1 RC4 Handling
|
|
if (state->payload_algid == 0xAA && state->R != 0)
|
|
{
|
|
uint8_t cipher[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t plain[11] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
|
|
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
|
|
0x00, 0x00, 0x00}; // <- MI cont.
|
|
|
|
//easier to manually load up rather than make a loop
|
|
rckey[0] = ((state->R & 0xFF00000000) >> 32);
|
|
rckey[1] = ((state->R & 0xFF000000) >> 24);
|
|
rckey[2] = ((state->R & 0xFF0000) >> 16);
|
|
rckey[3] = ((state->R & 0xFF00) >> 8);
|
|
rckey[4] = ((state->R & 0xFF) >> 0);
|
|
|
|
// load valid MI from state->payload_miP
|
|
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
|
|
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
|
|
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
|
|
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
|
|
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
|
|
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
|
|
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
|
|
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
|
|
|
|
// if (state->p25vc == 0)
|
|
// {
|
|
// fprintf (stderr, "%s", KYEL);
|
|
// fprintf (stderr, "\n RC4K ");
|
|
// for (short o = 0; o < 13; o++)
|
|
// {
|
|
// fprintf (stderr, "%02X", rckey[o]);
|
|
// }
|
|
// fprintf (stderr, "%s", KNRM);
|
|
// }
|
|
|
|
//load imbe_d into imbe_cipher octets
|
|
int z = 0;
|
|
for (i = 0; i < 11; i++)
|
|
{
|
|
cipher[i] = 0;
|
|
plain[i] = 0;
|
|
for (short int j = 0; j < 8; j++)
|
|
{
|
|
cipher[i] = cipher[i] << 1;
|
|
cipher[i] = cipher[i] + imbe_d[z];
|
|
imbe_d[z] = 0;
|
|
z++;
|
|
}
|
|
}
|
|
|
|
RC4(state->dropL, 13, 11, rckey, cipher, plain);
|
|
state->dropL += 11;
|
|
|
|
z = 0;
|
|
for (short p = 0; p < 11; p++)
|
|
{
|
|
for (short o = 0; o < 8; o++)
|
|
{
|
|
imbe_d[z] = (plain[p] & 0x80) >> 7;
|
|
plain[p] = plain[p] << 1;
|
|
z++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
|
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
|
|
//mbe_processImbe7200x4400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_fr, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
if (opts->payload == 1)
|
|
{
|
|
PrintIMBEData (opts, state, imbe_d);
|
|
}
|
|
|
|
//increment vc counter by one.
|
|
state->p25vc++;
|
|
|
|
if (opts->mbe_out_f != NULL && state->dmr_encL == 0) //only save if this bit not set
|
|
{
|
|
saveImbe4400Data (opts, state, imbe_d);
|
|
}
|
|
}
|
|
else if ((state->synctype == 14) || (state->synctype == 15)) //pV Sync
|
|
{
|
|
|
|
state->errs = mbe_eccImbe7100x4400C0 (imbe7100_fr);
|
|
state->errs2 = state->errs;
|
|
mbe_demodulateImbe7100x4400Data (imbe7100_fr);
|
|
state->errs2 += mbe_eccImbe7100x4400Data (imbe7100_fr, imbe_d);
|
|
|
|
if (opts->payload == 1)
|
|
{
|
|
PrintIMBEData (opts, state, imbe_d);
|
|
}
|
|
|
|
mbe_convertImbe7100to7200(imbe_d);
|
|
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
|
imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
|
|
if (opts->mbe_out_f != NULL)
|
|
{
|
|
saveImbe4400Data (opts, state, imbe_d);
|
|
}
|
|
}
|
|
else if ((state->synctype == 6) || (state->synctype == 7))
|
|
{
|
|
mbe_processAmbe3600x2400Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
if (opts->payload == 1)
|
|
{
|
|
PrintAMBEData (opts, state, ambe_d);
|
|
}
|
|
if (opts->mbe_out_f != NULL)
|
|
{
|
|
saveAmbe2450Data (opts, state, ambe_d);
|
|
}
|
|
}
|
|
else if ((state->synctype == 28) || (state->synctype == 29)) //was 8 and 9
|
|
{
|
|
|
|
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
|
state->errs2 = state->errs;
|
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
|
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
|
|
|
if ( (state->nxdn_cipher_type == 0x01 && state->R > 0) ||
|
|
(state->M == 1 && state->R > 0) )
|
|
{
|
|
|
|
if (state->payload_miN == 0)
|
|
{
|
|
state->payload_miN = state->R;
|
|
}
|
|
|
|
char ambe_temp[49];
|
|
for (short int i = 0; i < 49; i++)
|
|
{
|
|
ambe_temp[i] = ambe_d[i];
|
|
ambe_d[i] = 0;
|
|
}
|
|
LFSRN(ambe_temp, ambe_d, state);
|
|
|
|
}
|
|
|
|
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
|
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
|
|
if (opts->payload == 1)
|
|
{
|
|
PrintAMBEData (opts, state, ambe_d);
|
|
}
|
|
|
|
if (opts->mbe_out_f != NULL && (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) )
|
|
{
|
|
saveAmbe2450Data (opts, state, ambe_d);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//stereo slots and slot 0 (left slot)
|
|
if (state->currentslot == 0) //&& opts->dmr_stereo == 1
|
|
{
|
|
|
|
state->errs = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
|
state->errs2 = state->errs;
|
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
|
state->errs2 += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
|
|
|
//EXPERIMENTAL!!
|
|
//load basic privacy key number from array by the tg value (if not forced)
|
|
//currently only Moto BP and Hytera 10 Char BP
|
|
if (state->M == 0 && state->payload_algid == 0)
|
|
{
|
|
//see if we need to hash a value larger than 16-bits
|
|
hash = state->lasttg & 0xFFFFFF;
|
|
// fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttg, hash);
|
|
if (hash > 0xFFFF) //if greater than 16-bits
|
|
{
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
hash_bits[i] = ((hash << i) & 0x800000) >> 23; //load into array for CRC16
|
|
}
|
|
hash = ComputeCrcCCITT16d (hash_bits, 24);
|
|
hash = hash & 0xFFFF; //make sure its no larger than 16-bits
|
|
// fprintf (stderr, "Hash: %d ", hash);
|
|
}
|
|
if (state->rkey_array[hash] != 0)
|
|
{
|
|
state->K = state->rkey_array[hash] & 0xFF; //doesn't exceed 255
|
|
state->K1 = state->H = state->rkey_array[hash] & 0xFFFFFFFFFF; //doesn't exceed 40-bit limit
|
|
opts->dmr_mute_encL = 0;
|
|
// fprintf (stderr, "Key: %X ", state->rkey_array[hash]);
|
|
}
|
|
// else opts->dmr_mute_encL = 1; //may cause issues for manual key entry (non-csv)
|
|
}
|
|
|
|
if ( (state->K > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x10) ||
|
|
(state->K > 0 && state->M == 1) )
|
|
{
|
|
k = Pr[state->K];
|
|
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
|
for (short int j = 0; j < 48; j++) //49
|
|
{
|
|
x = ( ((k << j) & 0x800000000000) >> 47 );
|
|
ambe_d[j] ^= x;
|
|
}
|
|
}
|
|
|
|
if ( (state->K1 > 0 && state->dmr_so & 0x40 && state->payload_keyid == 0 && state->dmr_fid == 0x68) ||
|
|
(state->K1 > 0 && state->M == 1) )
|
|
{
|
|
|
|
int pos = 0;
|
|
|
|
unsigned long long int k1 = state->K1;
|
|
unsigned long long int k2 = state->K2;
|
|
unsigned long long int k3 = state->K3;
|
|
unsigned long long int k4 = state->K4;
|
|
|
|
int T_Key[256] = {0};
|
|
int pN[882] = {0};
|
|
|
|
int len = 0;
|
|
|
|
if (k2 == 0)
|
|
{
|
|
len = 39;
|
|
k1 = k1 << 24;
|
|
}
|
|
if (k2 != 0)
|
|
{
|
|
len = 127;
|
|
}
|
|
if (k4 != 0)
|
|
{
|
|
len = 255;
|
|
}
|
|
|
|
for (i = 0; i < 64; i++)
|
|
{
|
|
T_Key[i] = ( ((k1 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+64] = ( ((k2 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+128] = ( ((k3 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+192] = ( ((k4 << i) & 0x8000000000000000) >> 63 );
|
|
}
|
|
|
|
for (i = 0; i < 882; i++)
|
|
{
|
|
pN[i] = T_Key[pos];
|
|
pos++;
|
|
if (pos > len)
|
|
{
|
|
pos = 0;
|
|
}
|
|
}
|
|
|
|
//sanity check
|
|
if (state->DMRvcL > 17) //18
|
|
{
|
|
state->DMRvcL = 17; //18
|
|
}
|
|
|
|
pos = state->DMRvcL * 49;
|
|
for(i = 0; i < 49; i++)
|
|
{
|
|
ambe_d[i] ^= pN[pos];
|
|
pos++;
|
|
}
|
|
state->DMRvcL++;
|
|
}
|
|
|
|
//DMR RC4, Slot 1
|
|
if (state->currentslot == 0 && state->payload_algid == 0x21 && state->R != 0)
|
|
{
|
|
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
|
|
0x00, 0x00, 0x00, 0x00}; // <- MI
|
|
|
|
//easier to manually load up rather than make a loop
|
|
rckey[0] = ((state->R & 0xFF00000000) >> 32);
|
|
rckey[1] = ((state->R & 0xFF000000) >> 24);
|
|
rckey[2] = ((state->R & 0xFF0000) >> 16);
|
|
rckey[3] = ((state->R & 0xFF00) >> 8);
|
|
rckey[4] = ((state->R & 0xFF) >> 0);
|
|
rckey[5] = ((state->payload_mi & 0xFF000000) >> 24);
|
|
rckey[6] = ((state->payload_mi & 0xFF0000) >> 16);
|
|
rckey[7] = ((state->payload_mi & 0xFF00) >> 8);
|
|
rckey[8] = ((state->payload_mi & 0xFF) >> 0);
|
|
|
|
// if (opts->payload == 1)
|
|
// {
|
|
// fprintf (stderr, "%s", KYEL);
|
|
// fprintf (stderr, " RC4K ");
|
|
// for (short o = 0; o < 9; o++)
|
|
// {
|
|
// fprintf (stderr, "%02X", rckey[o]);
|
|
// }
|
|
// fprintf (stderr, "%s", KNRM);
|
|
// fprintf (stderr, "\n");
|
|
// }
|
|
|
|
short k = 0;
|
|
for (short o = 0; o < 7; o++)
|
|
{
|
|
short b = 0;
|
|
for (short p = 0; p < 8; p++)
|
|
{
|
|
b = b << 1;
|
|
b = b + ambe_d[k];
|
|
k++;
|
|
if (k == 49)
|
|
{
|
|
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
|
|
break;
|
|
}
|
|
}
|
|
cipher[o] = b;
|
|
}
|
|
|
|
//only run keystream application if errs < 3 -- this is a fix to the pop sound
|
|
//that may occur on some systems that preempt VC6 voice for a RC opportuninity (TXI)
|
|
//this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play
|
|
//due to the error, but the keystream application makes it random 'pfft pop' sound instead
|
|
if (state->errs < 3)
|
|
RC4(state->dropL, 9, 7, rckey, cipher, plain);
|
|
else memcpy (plain, cipher, sizeof(plain));
|
|
|
|
state->dropL += 7;
|
|
|
|
short z = 0;
|
|
for (short p = 0; p <= 6; p++)
|
|
{
|
|
//convert bytes back to bits and load into ambe_d array.
|
|
short b = 0; //reset b to use again
|
|
for (short o = 0; o < 8; o++)
|
|
{
|
|
b = (( (plain[p] << o) & 0x80) >> 7);
|
|
ambe_d[z] = b;
|
|
z++;
|
|
if (z == 49)
|
|
{
|
|
ambe_d[48] = ( (plain[p] << o) & 0x80);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//P25p2 RC4 Handling, VCH 0
|
|
if (state->currentslot == 0 && state->payload_algid == 0xAA && state->R != 0 && ((state->synctype == 35) || (state->synctype == 36)))
|
|
{
|
|
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
|
|
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
|
|
0x00, 0x00, 0x00}; // <- MI cont.
|
|
|
|
//easier to manually load up rather than make a loop
|
|
rckey[0] = ((state->R & 0xFF00000000) >> 32);
|
|
rckey[1] = ((state->R & 0xFF000000) >> 24);
|
|
rckey[2] = ((state->R & 0xFF0000) >> 16);
|
|
rckey[3] = ((state->R & 0xFF00) >> 8);
|
|
rckey[4] = ((state->R & 0xFF) >> 0);
|
|
|
|
// load valid MI from state->payload_miP
|
|
rckey[5] = ((state->payload_miP & 0xFF00000000000000) >> 56);
|
|
rckey[6] = ((state->payload_miP & 0xFF000000000000) >> 48);
|
|
rckey[7] = ((state->payload_miP & 0xFF0000000000) >> 40);
|
|
rckey[8] = ((state->payload_miP & 0xFF00000000) >> 32);
|
|
rckey[9] = ((state->payload_miP & 0xFF000000) >> 24);
|
|
rckey[10] = ((state->payload_miP & 0xFF0000) >> 16);
|
|
rckey[11] = ((state->payload_miP & 0xFF00) >> 8);
|
|
rckey[12] = ((state->payload_miP & 0xFF) >> 0);
|
|
|
|
// if (opts->payload == 1)
|
|
// {
|
|
// fprintf (stderr, "%s", KYEL);
|
|
// fprintf (stderr, " RC4K ");
|
|
// for (short o = 0; o < 13; o++)
|
|
// {
|
|
// fprintf (stderr, "%02X", rckey[o]);
|
|
// }
|
|
// fprintf (stderr, "%s", KNRM);
|
|
// fprintf (stderr, "\n");
|
|
// }
|
|
|
|
short k = 0;
|
|
for (short o = 0; o < 7; o++)
|
|
{
|
|
short b = 0;
|
|
for (short p = 0; p < 8; p++)
|
|
{
|
|
b = b << 1;
|
|
b = b + ambe_d[k];
|
|
k++;
|
|
if (k == 49)
|
|
{
|
|
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
|
|
break;
|
|
}
|
|
}
|
|
cipher[o] = b;
|
|
}
|
|
|
|
RC4(state->dropL, 13, 7, rckey, cipher, plain);
|
|
state->dropL += 7;
|
|
|
|
short z = 0;
|
|
for (short p = 0; p <= 6; p++)
|
|
{
|
|
//convert bytes back to bits and load into ambe_d array.
|
|
short b = 0; //reset b to use again
|
|
for (short o = 0; o < 8; o++)
|
|
{
|
|
b = (( (plain[p] << o) & 0x80) >> 7);
|
|
ambe_d[z] = b;
|
|
z++;
|
|
if (z == 49)
|
|
{
|
|
ambe_d[48] = ( (plain[p] << o) & 0x80);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str,
|
|
ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
|
|
|
|
//old method for this step below
|
|
//mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
if (opts->payload == 1) // && state->R == 0 this is why slot 1 didn't primt abme, probably had it set during testing
|
|
{
|
|
PrintAMBEData (opts, state, ambe_d);
|
|
}
|
|
|
|
//restore MBE file save, slot 1 -- consider saving even if enc
|
|
if (opts->mbe_out_f != NULL && (state->dmr_encL == 0 || opts->dmr_mute_encL == 0) )
|
|
{
|
|
saveAmbe2450Data (opts, state, ambe_d);
|
|
}
|
|
|
|
}
|
|
//stereo slots and slot 1 (right slot)
|
|
if (state->currentslot == 1) //&& opts->dmr_stereo == 1
|
|
{
|
|
|
|
state->errsR = mbe_eccAmbe3600x2450C0 (ambe_fr);
|
|
state->errs2R = state->errsR;
|
|
mbe_demodulateAmbe3600x2450Data (ambe_fr);
|
|
state->errs2R += mbe_eccAmbe3600x2450Data (ambe_fr, ambe_d);
|
|
|
|
//EXPERIMENTAL!!
|
|
//load basic privacy key number from array by the tg value (if not forced)
|
|
//currently only Moto BP and Hytera 10 Char BP
|
|
if (state->M == 0 && state->payload_algidR == 0)
|
|
{
|
|
//see if we need to hash a value larger than 16-bits
|
|
hash = state->lasttgR & 0xFFFFFF;
|
|
// fprintf (stderr, "TG: %lld Hash: %ld ", state->lasttgR, hash);
|
|
if (hash > 0xFFFF) //if greater than 16-bits
|
|
{
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
hash_bits[i] = ((hash << i) & 0x800000) >> 23; //load into array for CRC16
|
|
}
|
|
hash = ComputeCrcCCITT16d (hash_bits, 24);
|
|
hash = hash & 0xFFFF; //make sure its no larger than 16-bits
|
|
// fprintf (stderr, "Hash: %d ", hash);
|
|
}
|
|
if (state->rkey_array[hash] != 0)
|
|
{
|
|
state->K = state->rkey_array[hash] & 0xFF; //doesn't exceed 255
|
|
state->K1 = state->H = state->rkey_array[hash] & 0xFFFFFFFFFF; //doesn't exceed 40-bit limit
|
|
opts->dmr_mute_encR = 0;
|
|
// fprintf (stderr, "Key: %X ", state->rkey_array[hash]);
|
|
}
|
|
// else opts->dmr_mute_encR = 1; //may cause issues for manual key entry (non-csv)
|
|
}
|
|
|
|
if ( (state->K > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x10) ||
|
|
(state->K > 0 && state->M == 1) )
|
|
{
|
|
k = Pr[state->K];
|
|
k = ( ((k & 0xFF0F) << 32 ) + (k << 16) + k );
|
|
for (short int j = 0; j < 48; j++)
|
|
{
|
|
x = ( ((k << j) & 0x800000000000) >> 47 );
|
|
ambe_d[j] ^= x;
|
|
}
|
|
}
|
|
|
|
if ( (state->K1 > 0 && state->dmr_soR & 0x40 && state->payload_keyidR == 0 && state->dmr_fidR == 0x68) ||
|
|
(state->K1 > 0 && state->M == 1))
|
|
{
|
|
|
|
int pos = 0;
|
|
|
|
unsigned long long int k1 = state->K1;
|
|
unsigned long long int k2 = state->K2;
|
|
unsigned long long int k3 = state->K3;
|
|
unsigned long long int k4 = state->K4;
|
|
|
|
int T_Key[256] = {0};
|
|
int pN[882] = {0};
|
|
|
|
int len = 0;
|
|
|
|
if (k2 == 0)
|
|
{
|
|
len = 39;
|
|
k1 = k1 << 24;
|
|
}
|
|
if (k2 != 0)
|
|
{
|
|
len = 127;
|
|
}
|
|
if (k4 != 0)
|
|
{
|
|
len = 255;
|
|
}
|
|
|
|
for (i = 0; i < 64; i++)
|
|
{
|
|
T_Key[i] = ( ((k1 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+64] = ( ((k2 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+128] = ( ((k3 << i) & 0x8000000000000000) >> 63 );
|
|
T_Key[i+192] = ( ((k4 << i) & 0x8000000000000000) >> 63 );
|
|
}
|
|
|
|
for (i = 0; i < 882; i++)
|
|
{
|
|
pN[i] = T_Key[pos];
|
|
pos++;
|
|
if (pos > len)
|
|
{
|
|
pos = 0;
|
|
}
|
|
}
|
|
|
|
//sanity check
|
|
if (state->DMRvcR > 17) //18
|
|
{
|
|
state->DMRvcR = 17; //18
|
|
}
|
|
|
|
pos = state->DMRvcR * 49;
|
|
for(i = 0; i < 49; i++)
|
|
{
|
|
ambe_d[i] ^= pN[pos];
|
|
pos++;
|
|
}
|
|
state->DMRvcR++;
|
|
}
|
|
|
|
//DMR RC4, Slot 2
|
|
if (state->currentslot == 1 && state->payload_algidR == 0x21 && state->RR != 0)
|
|
{
|
|
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t rckey[9] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
|
|
0x00, 0x00, 0x00, 0x00}; // <- MI
|
|
|
|
//easier to manually load up rather than make a loop
|
|
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
|
|
rckey[1] = ((state->RR & 0xFF000000) >> 24);
|
|
rckey[2] = ((state->RR & 0xFF0000) >> 16);
|
|
rckey[3] = ((state->RR & 0xFF00) >> 8);
|
|
rckey[4] = ((state->RR & 0xFF) >> 0);
|
|
rckey[5] = ((state->payload_miR & 0xFF000000) >> 24);
|
|
rckey[6] = ((state->payload_miR & 0xFF0000) >> 16);
|
|
rckey[7] = ((state->payload_miR & 0xFF00) >> 8);
|
|
rckey[8] = ((state->payload_miR & 0xFF) >> 0);
|
|
|
|
// if (opts->payload == 1)
|
|
// {
|
|
// fprintf (stderr, "%s", KYEL);
|
|
// fprintf (stderr, " RC4K ");
|
|
// for (short o = 0; o < 9; o++)
|
|
// {
|
|
// fprintf (stderr, "%02X", rckey[o]);
|
|
// }
|
|
// fprintf (stderr, "%s", KNRM);
|
|
// fprintf (stderr, "\n");
|
|
// }
|
|
|
|
short k = 0;
|
|
for (short o = 0; o < 7; o++)
|
|
{
|
|
short b = 0;
|
|
for (short p = 0; p < 8; p++)
|
|
{
|
|
b = b << 1;
|
|
b = b + ambe_d[k];
|
|
k++;
|
|
if (k == 49)
|
|
{
|
|
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
|
|
break;
|
|
}
|
|
}
|
|
cipher[o] = b;
|
|
}
|
|
|
|
//only run keystream application if errs < 3 -- this is a fix to the pop sound
|
|
//that may occur on some systems that preempt VC6 voice for a RC opportuninity (TXI)
|
|
//this occurs because we are supposed to either have a a 'repeat' frame, or 'silent' frame play
|
|
//due to the error, but the keystream application makes it random 'pfft pop' sound instead
|
|
if (state->errsR < 3)
|
|
RC4(state->dropR, 9, 7, rckey, cipher, plain);
|
|
else memcpy (plain, cipher, sizeof(plain));
|
|
state->dropR += 7;
|
|
|
|
short z = 0;
|
|
for (short p = 0; p <= 6; p++)
|
|
{
|
|
//convert bytes back to bits and load into ambe_d array.
|
|
short b = 0; //reset b to use again
|
|
for (short o = 0; o < 8; o++)
|
|
{
|
|
b = (( (plain[p] << o) & 0x80) >> 7);
|
|
ambe_d[z] = b;
|
|
z++;
|
|
if (z == 49)
|
|
{
|
|
ambe_d[48] = ( (plain[p] << o) & 0x80);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//P25p2 RC4 Handling, VCH 1
|
|
if (state->currentslot == 1 && state->payload_algidR == 0xAA && state->RR != 0 && ((state->synctype == 35) || (state->synctype == 36)))
|
|
{
|
|
uint8_t cipher[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t plain[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
uint8_t rckey[13] = {0x00, 0x00, 0x00, 0x00, 0x00, // <- RC4 Key
|
|
0x00, 0x00, 0x00, 0x00, 0x00, // <- MI
|
|
0x00, 0x00, 0x00}; // <- MI cont.
|
|
|
|
//easier to manually load up rather than make a loop
|
|
rckey[0] = ((state->RR & 0xFF00000000) >> 32);
|
|
rckey[1] = ((state->RR & 0xFF000000) >> 24);
|
|
rckey[2] = ((state->RR & 0xFF0000) >> 16);
|
|
rckey[3] = ((state->RR & 0xFF00) >> 8);
|
|
rckey[4] = ((state->RR & 0xFF) >> 0);
|
|
|
|
//state->payload_miN for VCH1/slot 2
|
|
rckey[5] = ((state->payload_miN & 0xFF00000000000000) >> 56);
|
|
rckey[6] = ((state->payload_miN & 0xFF000000000000) >> 48);
|
|
rckey[7] = ((state->payload_miN & 0xFF0000000000) >> 40);
|
|
rckey[8] = ((state->payload_miN & 0xFF00000000) >> 32);
|
|
rckey[9] = ((state->payload_miN & 0xFF000000) >> 24);
|
|
rckey[10] = ((state->payload_miN & 0xFF0000) >> 16);
|
|
rckey[11] = ((state->payload_miN & 0xFF00) >> 8);
|
|
rckey[12] = ((state->payload_miN & 0xFF) >> 0);
|
|
|
|
// if (opts->payload == 1)
|
|
// {
|
|
// fprintf (stderr, "%s", KYEL);
|
|
// fprintf (stderr, " RC4K ");
|
|
// for (short o = 0; o < 13; o++)
|
|
// {
|
|
// fprintf (stderr, "%02X", rckey[o]);
|
|
// }
|
|
// fprintf (stderr, "%s", KNRM);
|
|
// fprintf (stderr, "\n");
|
|
// }
|
|
|
|
short k = 0;
|
|
for (short o = 0; o < 7; o++)
|
|
{
|
|
short b = 0;
|
|
for (short p = 0; p < 8; p++)
|
|
{
|
|
b = b << 1;
|
|
b = b + ambe_d[k];
|
|
k++;
|
|
if (k == 49)
|
|
{
|
|
cipher[6] = ((b << 3) & 0x80); //set 7th octet/bit 49 accordingly
|
|
break;
|
|
}
|
|
}
|
|
cipher[o] = b;
|
|
}
|
|
|
|
RC4(state->dropR, 13, 7, rckey, cipher, plain);
|
|
state->dropR += 7;
|
|
|
|
short z = 0;
|
|
for (short p = 0; p <= 6; p++)
|
|
{
|
|
//convert bytes back to bits and load into ambe_d array.
|
|
short b = 0; //reset b to use again
|
|
for (short o = 0; o < 8; o++)
|
|
{
|
|
b = (( (plain[p] << o) & 0x80) >> 7);
|
|
ambe_d[z] = b;
|
|
z++;
|
|
if (z == 49)
|
|
{
|
|
ambe_d[48] = ( (plain[p] << o) & 0x80);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mbe_processAmbe2450Dataf (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR,
|
|
ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
|
|
|
|
//old method for this step below
|
|
//mbe_processAmbe3600x2450Framef (state->audio_out_temp_bufR, &state->errsR, &state->errs2R, state->err_strR, ambe_fr, ambe_d, state->cur_mp2, state->prev_mp2, state->prev_mp_enhanced2, opts->uvquality);
|
|
if (opts->payload == 1)
|
|
{
|
|
PrintAMBEData (opts, state, ambe_d);
|
|
}
|
|
|
|
//restore MBE file save, slot 2 -- consider saving even if enc
|
|
if (opts->mbe_out_fR != NULL && (state->dmr_encR == 0 || opts->dmr_mute_encR == 0) )
|
|
{
|
|
saveAmbe2450DataR (opts, state, ambe_d);
|
|
}
|
|
}
|
|
|
|
//X2-TDMA? Not sure what still makes it this far to run under Framef
|
|
// if (opts->dmr_stereo == 0)
|
|
// {
|
|
// mbe_processAmbe3600x2450Framef (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_fr, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
|
|
// if (opts->payload == 1)
|
|
// {
|
|
// PrintAMBEData (opts, state, ambe_d);
|
|
// }
|
|
// //only save MBE files if not enc or unmuted, THIS does not seem to work for some reason
|
|
// if (opts->mbe_out_f != NULL && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) )
|
|
// {
|
|
// saveAmbe2450Data (opts, state, ambe_d);
|
|
// }
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
//quick enc check to determine whether or not to play enc traffic
|
|
int enc_bit = 0;
|
|
//end enc check
|
|
|
|
if ( (opts->dmr_mono == 1 || opts->dmr_stereo == 1) && state->currentslot == 0) //all mono traffic routed through 'left'
|
|
{
|
|
enc_bit = (state->dmr_so >> 6) & 0x1;
|
|
if (enc_bit == 1)
|
|
{
|
|
state->dmr_encL = 1;
|
|
}
|
|
|
|
//checkdown for P25 1 and 2
|
|
else if (state->payload_algid != 0 && state->payload_algid != 0x80)
|
|
{
|
|
state->dmr_encL = 1;
|
|
}
|
|
else state->dmr_encL = 0;
|
|
|
|
//check for available R key
|
|
if (state->R != 0) state->dmr_encL = 0;
|
|
|
|
//second checkdown for P25p2 WACN, SYSID, and CC set
|
|
if (state->synctype == 35 || state->synctype == 36)
|
|
{
|
|
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
|
|
{
|
|
state->dmr_encL = 1;
|
|
}
|
|
}
|
|
|
|
//reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method)
|
|
if (opts->reverse_mute == 1)
|
|
{
|
|
if (state->dmr_encL == 0)
|
|
{
|
|
state->dmr_encL = 1;
|
|
opts->unmute_encrypted_p25 = 0;
|
|
opts->dmr_mute_encL = 1;
|
|
}
|
|
else
|
|
{
|
|
state->dmr_encL = 0;
|
|
opts->unmute_encrypted_p25 = 1;
|
|
opts->dmr_mute_encL = 0;
|
|
}
|
|
}
|
|
//end reverse mute test
|
|
|
|
//OSS 48k/1 Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
|
|
if (opts->slot_preference == 1 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstR == 16 || state->dmrburstR == 21) )
|
|
{
|
|
opts->audio_out = 0;
|
|
preempt = 1;
|
|
if (opts->payload == 0 && opts->slot1_on == 1)
|
|
fprintf (stderr, " *MUTED*");
|
|
else if (opts->payload == 0 && opts->slot1_on == 0)
|
|
fprintf (stderr, " *OFF*");
|
|
}
|
|
|
|
state->debug_audio_errors += state->errs2;
|
|
|
|
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
|
{
|
|
if ( opts->floating_point == 0 ) //opts->audio_out == 1 && //needed to remove for AERO OSS so we could still save wav files during dual voices
|
|
{
|
|
#ifdef AERO_BUILD
|
|
if(opts->audio_out == 1 && opts->slot1_on == 1) //add conditional check here, otherwise some lag occurs on dual voices with OSS48k/1 input due to buffered audio
|
|
#endif
|
|
processAudio(opts, state);
|
|
}
|
|
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
|
|
{
|
|
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
|
|
}
|
|
}
|
|
|
|
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); //these are for mono or FDMA where we don't need to buffer and wait for a stereo mix
|
|
|
|
}
|
|
|
|
if (opts->dmr_stereo == 1 && state->currentslot == 1)
|
|
{
|
|
enc_bit = (state->dmr_soR >> 6) & 0x1;
|
|
if (enc_bit == 0x1)
|
|
{
|
|
state->dmr_encR = 1;
|
|
}
|
|
|
|
//checkdown for P25 1 and 2
|
|
else if (state->payload_algidR != 0 && state->payload_algidR != 0x80)
|
|
{
|
|
state->dmr_encR = 1;
|
|
}
|
|
else state->dmr_encR = 0;
|
|
|
|
//check for available RR key
|
|
if (state->RR != 0) state->dmr_encR = 0;
|
|
|
|
//second checkdown for P25p2 WACN, SYSID, and CC set
|
|
if (state->synctype == 35 || state->synctype == 36)
|
|
{
|
|
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
|
|
{
|
|
state->dmr_encR = 1;
|
|
}
|
|
}
|
|
|
|
//reverse mute testing, only mute unencrypted traffic (slave piggyback dsd+ method)
|
|
if (opts->reverse_mute == 1)
|
|
{
|
|
if (state->dmr_encR == 0)
|
|
{
|
|
state->dmr_encR = 1;
|
|
opts->unmute_encrypted_p25 = 0;
|
|
opts->dmr_mute_encR = 1;
|
|
}
|
|
else
|
|
{
|
|
state->dmr_encR = 0;
|
|
opts->unmute_encrypted_p25 = 1;
|
|
opts->dmr_mute_encR = 0;
|
|
}
|
|
}
|
|
//end reverse mute test
|
|
|
|
//OSS 48k/1 Specific Voice Preemption if dual voices on TDMA and one slot has preference over the other
|
|
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && (state->dmrburstL == 16 || state->dmrburstL == 21) )
|
|
{
|
|
opts->audio_out = 0;
|
|
preempt = 1;
|
|
if (opts->payload == 0 && opts->slot2_on == 1)
|
|
fprintf (stderr, " *MUTED*");
|
|
else if (opts->payload == 0 && opts->slot2_on == 0)
|
|
fprintf (stderr, " *OFF*");
|
|
}
|
|
|
|
state->debug_audio_errorsR += state->errs2R;
|
|
|
|
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
|
{
|
|
if ( opts->floating_point == 0) //opts->audio_out == 1 && //needed to remove for AERO OSS so we could still save wav files during dual voices
|
|
{
|
|
#ifdef AERO_BUILD
|
|
if(opts->audio_out == 1 && opts->slot2_on == 1) //add conditional check here, otherwise some lag occurs on dual voices with OSS48k/1 input due to buffered audio
|
|
#endif
|
|
processAudioR(opts, state);
|
|
}
|
|
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
|
|
{
|
|
playSynthesizedVoiceMSR (opts, state);
|
|
}
|
|
}
|
|
|
|
memcpy (state->f_r, state->audio_out_temp_bufR, sizeof(state->f_r));
|
|
|
|
}
|
|
|
|
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
|
if (opts->dmr_mono == 0 && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0) )
|
|
{
|
|
state->debug_audio_errors += state->errs2;
|
|
if (opts->audio_out == 1 && opts->floating_point == 0 ) //&& opts->pulse_digi_rate_out == 8000
|
|
{
|
|
processAudio(opts, state);
|
|
}
|
|
// if (opts->audio_out == 1)
|
|
// {
|
|
// playSynthesizedVoice (opts, state);
|
|
// }
|
|
|
|
memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); //P25p1 FDMA 8k/1 channel -f1 switch
|
|
}
|
|
|
|
//if using anything but DMR Stereo, borrowing state->dmr_encL to signal enc or clear for other types
|
|
if (opts->wav_out_f != NULL && opts->dmr_stereo == 0 && (opts->unmute_encrypted_p25 == 1 || state->dmr_encL == 0))
|
|
{
|
|
writeSynthesizedVoice (opts, state);
|
|
}
|
|
|
|
//per call can only be used when ncurses terminal is active since we use its call history matrix for when to record
|
|
if (opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 0) //opts->use_ncurses_terminal == 1 &&
|
|
{
|
|
if (state->dmr_encL == 0 || opts->dmr_mute_encL == 0)
|
|
{
|
|
//write wav to per call on left channel Slot 1
|
|
writeSynthesizedVoice (opts, state);
|
|
}
|
|
}
|
|
|
|
//per call can only be used when ncurses terminal is active since we use its call history matrix for when to record
|
|
if (opts->dmr_stereo_wav == 1 && opts->dmr_stereo == 1 && state->currentslot == 1) //opts->use_ncurses_terminal == 1 &&
|
|
{
|
|
if (state->dmr_encR == 0 || opts->dmr_mute_encR == 0)
|
|
{
|
|
//write wav to per call on right channel Slot 2
|
|
writeSynthesizedVoiceR (opts, state);
|
|
}
|
|
}
|
|
|
|
if (preempt == 1)
|
|
{
|
|
opts->audio_out = 1;
|
|
preempt = 0;
|
|
}
|
|
|
|
//reset audio out flag for next repitition --disabled for now
|
|
// if (strcmp(mode, "B") == 0) opts->audio_out = 1;
|
|
|
|
//restore flag for null output type
|
|
if (opts->audio_out_type == 9) opts->audio_out = 0;
|
|
}
|