mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-15 10:17:20 -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:
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;
|
||||
}
|
||||
Reference in New Issue
Block a user