diff --git a/include/dsd.h b/include/dsd.h index e0de6d7..a8a2272 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -889,35 +889,24 @@ typedef struct void processdPMRvoice (dsd_opts * opts, dsd_state * state); void processAudio (dsd_opts * opts, dsd_state * state); void processAudioR (dsd_opts * opts, dsd_state * state); -void openPulseInput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet -void openPulseOutput (dsd_opts * opts); //not sure if we need to just pass opts, or opts and state yet +void openPulseInput (dsd_opts * opts); +void openPulseOutput (dsd_opts * opts); void closePulseInput (dsd_opts * opts); void closePulseOutput (dsd_opts * opts); void writeSynthesizedVoice (dsd_opts * opts, dsd_state * state); void writeSynthesizedVoiceR (dsd_opts * opts, dsd_state * state); -void playSynthesizedVoice (dsd_opts * opts, dsd_state * state); //short mono output -void playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state); //short mono output rigth (obsolete)? +void playSynthesizedVoice (dsd_opts * opts, dsd_state * state); //short mono output slot 1 +void playSynthesizedVoiceR (dsd_opts * opts, dsd_state * state); //short mono output slot 2 //new float stuff void playSynthesizedVoiceFS (dsd_opts * opts, dsd_state * state); //float stereo mix -void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state); //float stereo mix 3v2 DMR...and X2-TDMA +void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state); //float stereo mix 3v2 DMR void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state); //float stereo mix 4v2 P25p2 -// void playSynthesizedVoiceFL (dsd_opts * opts, dsd_state * state); //float left when using stereo configuration void playSynthesizedVoiceFM (dsd_opts * opts, dsd_state * state); //float mono - +//new short stuff void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state); //short stereo mix -void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state); //short stereo mix 3v2 DMR...and X2-TDMA +void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state); //short stereo mix 3v2 DMR void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state); //short stereo mix 4v2 P25p2 - -void upsampleF (float invalue, float prev, float outbuf[6]); -void playSynthesizedVoiceFS3_48k (dsd_opts * opts, dsd_state * state); -void playSynthesizedVoiceFS4_48k (dsd_opts * opts, dsd_state * state); - -void upsampleS (short invalue, short prev, short outbuf[6]); -void playSynthesizedVoiceSS3_48k (dsd_opts * opts, dsd_state * state); -void playSynthesizedVoiceSS4_48k (dsd_opts * opts, dsd_state * state); - -//borrowed from CODEC2 for testing -void fdmdv_8_to_48_float(float out48k[], float in8k[], int n); +void upsampleS (short invalue, short prev, short outbuf[6]); //upsample 8k to 48k short in M17 // void openAudioOutDevice (dsd_opts * opts, int speed); diff --git a/src/dmr_bs.c b/src/dmr_bs.c index 32e049c..649d260 100644 --- a/src/dmr_bs.c +++ b/src/dmr_bs.c @@ -485,12 +485,8 @@ void dmrBS (dsd_opts * opts, dsd_state * state) //NOTE: We want this to play regardless of whether the slot is voice or data, to play silence in one slot and voice in the second, or voices in both if (internalslot == 0 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 8000) playSynthesizedVoiceFS3 (opts, state); //Float Stereo Mix 3v2 - if (internalslot == 0 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 48000) - playSynthesizedVoiceFS3_48k (opts, state); //Float Stereo Mix 3v2 if (internalslot == 0 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000) playSynthesizedVoiceSS3 (opts, state); //Short Stereo Mix 3v2 - if (internalslot == 0 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 48000) - playSynthesizedVoiceSS3_48k (opts, state); //Short Stereo Mix 3v2 if (skipcount > 2) //after 2 consecutive data frames, drop back to getFrameSync and process with dmr_data_sync { @@ -833,12 +829,8 @@ void dmrBSBootstrap (dsd_opts * opts, dsd_state * state) //NOTE: Only play on slot 0, if slot 1, then it'll play after the next TDMA frame in the BS loop instead if (internalslot == 0 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 8000) playSynthesizedVoiceFS3 (opts, state); //Float Stereo Mix 3v2 - if (internalslot == 0 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 48000) - playSynthesizedVoiceFS3_48k (opts, state); //Float Stereo Mix 3v2 if (internalslot == 0 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000) playSynthesizedVoiceSS3 (opts, state); //Short Stereo Mix 3v2 - if (internalslot == 0 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 48000) - playSynthesizedVoiceSS3_48k (opts, state); //Short Stereo Mix 3v2 dmrBS (opts, state); //bootstrap into full TDMA frame for BS mode END: diff --git a/src/dsd_audio2.c b/src/dsd_audio2.c index 199f131..7b75b81 100644 --- a/src/dsd_audio2.c +++ b/src/dsd_audio2.c @@ -11,15 +11,12 @@ #include "dsd.h" -//TODO: Add audio handling for left over types (X2-TDMA, dPMR, Provoice...MBEPlayback?) //TODO: Test All voice decoders with all combos 'short mono, short stereo, float mono, float stereo) -//TODO: Look at upscaling on M17 codec 2 audio for OSS support and backport to 2.1b //TODO: Clean comments and unused code in here -//TODO: Change + and - keys to allow switching to '0' on shorts for auto or manual with values -//CHECKLIST(PULSE): DMR BS(OK) DMR MS (OK) P25p1 (OK) P25p2 (OK) YSF (OK) NXDN (OK) M17 (short only!) pV (OK) dPMR (OK) MBEplayback (OK) X2-TDMA (who cares lol) - -//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) +//CHECKLIST(PULSE): DMR BS(OK) DMR MS (OK) P25p1 (OK) P25p2 (OK) YSF (OK) NXDN (OK) M17 (short only!) pV (OK) dPMR (OK) MBEplayback (OK) X2-TDMA (who cares lol) D-STAR (WIP) +//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) void agf (dsd_opts * opts, dsd_state * state, float samp[160], int slot) { @@ -233,188 +230,6 @@ void playSynthesizedVoiceFS3 (dsd_opts * opts, dsd_state * state) } -//float stereo mix 3v2 DMR with 8k to 48k upsample -void playSynthesizedVoiceFS3_48k (dsd_opts * opts, dsd_state * state) -{ - - //NOTE: The old version UpsampleF had a high pitch ring to it - //new version has an odd 'pattering' or 'crackle' sound or clipping? - - int i, n; - uint8_t encL, encR; - // int j, k; - // float prev; - float stereo_samp1[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp2[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp3[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp4[320*6]; //48k 2-channel stereo interleave mix - float out[6]; - float temp_l[4][160*6]; //temp storage - float temp_r[4][160*6]; //temp storage - float baseline = 0.0f; - - memset (stereo_samp1, baseline, sizeof(stereo_samp1)); - memset (stereo_samp2, baseline, sizeof(stereo_samp2)); - memset (stereo_samp3, baseline, sizeof(stereo_samp3)); - memset (stereo_samp4, baseline, sizeof(stereo_samp4)); - - memset (temp_l, baseline, sizeof(temp_l)); - memset (temp_r, baseline, sizeof(temp_r)); - memset (out, baseline, sizeof(out)); - - //dmr enc checkdown for whether or not to fill the stereo sample or not for playback or writing - encL = encR = 0; - encL = (state->dmr_so >> 6) & 0x1; - encR = (state->dmr_soR >> 6) & 0x1; - - //checkdown to see if we can lift the 'mute' if a key is available - if (encL) - { - if (state->payload_algid == 0) - { - if (state->K != 0 || state->K1 != 0) - { - encL = 0; - } - } - else if (state->payload_algid == 0x21) - { - if (state->R != 0) - { - encL = 0; - } - } - } - - if (encR) - { - if (state->payload_algidR == 0) - { - if (state->K != 0 || state->K1 != 0) - { - encR = 0; - } - } - else if (state->payload_algidR == 0x21) - { - if (state->RR != 0) - { - encR = 0; - } - } - } - - //at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions - if (encL && encR) - goto FS348_END; - - //TODO: Test Upsampling //void upsampleF (float invalue, float prev, float outbuf[6]) - // prev = 0.0f; - // for (j = 0; j < 3; j++) - // { - - // for (i = 0; i < 160; i++) - // { - // upsampleF (state->f_l4[j][i] / ((float) 480*10), prev, out); - // // upsampleF (state->f_l4[j][i], prev, out); - // for (k = 0; k < 6; k++) temp_l[j][i*6+k] = out[k]; - // } - // } - - // prev = 0.0f; //test value - // for (j = 0; j < 3; j++) - // { - - // for (i = 0; i < 160; i++) - // { - // upsampleF (state->f_r4[j][i] / ((float) 480*10), prev, out); - // // upsampleF (state->f_r4[j][i], prev, out); - // for (k = 0; k < 6; k++) temp_r[j][i*6+k] = out[k]; - // } - // } - - n = 160; - fdmdv_8_to_48_float(temp_l[0], state->f_l4[0], n); - fdmdv_8_to_48_float(temp_l[1], state->f_l4[1], n); - fdmdv_8_to_48_float(temp_l[2], state->f_l4[2], n); - fdmdv_8_to_48_float(temp_r[0], state->f_r4[0], n); - fdmdv_8_to_48_float(temp_r[1], state->f_r4[1], n); - fdmdv_8_to_48_float(temp_r[2], state->f_r4[2], n); - - //interleave left and right channels from the temp (float) buffer - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp1[i*2+0] = temp_l[0][i]; - if (!encR) - stereo_samp1[i*2+1] = temp_r[0][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp2[i*2+0] = temp_l[1][i]; - if (!encR) - stereo_samp2[i*2+1] = temp_r[1][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp3[i*2+0] = temp_l[2][i]; - if (!encR) - stereo_samp3[i*2+1] = temp_r[2][i]; - } - - if (opts->audio_out_type == 0) //Pulse Audio - { - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*4*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp2, 320*4*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp3, 320*4*6, NULL); - } - - //No OSS, since we can't use float output, but STDOUT can with play, aplay, etc - - if (opts->audio_out_type == 1) //STDOUT - { - write (opts->audio_out_fd, stereo_samp1, 320*4*6); - write (opts->audio_out_fd, stereo_samp2, 320*4*6); - write (opts->audio_out_fd, stereo_samp3, 320*4*6); - } - - FS348_END: - - memset (state->audio_out_temp_buf, baseline, sizeof(state->audio_out_temp_buf)); - memset (state->audio_out_temp_bufR, baseline, sizeof(state->audio_out_temp_bufR)); - - //set float temp buffer to baseline - memset (state->f_l4, baseline, sizeof(state->f_l4)); - memset (state->f_r4, baseline, sizeof(state->f_r4)); - - //if we don't run processAudio, then I don't think we really need any of the items below active - state->audio_out_idx = 0; - state->audio_out_idxR = 0; - - 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; - } - -} - //float stereo mix 4v2 P25p2 void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state) { @@ -578,193 +393,6 @@ void playSynthesizedVoiceFS4 (dsd_opts * opts, dsd_state * state) } -//float stereo mix 4v2 P25p2 with 8k to 48k upsample -void playSynthesizedVoiceFS4_48k (dsd_opts * opts, dsd_state * state) -{ - - //NOTE: The old version UpsampleF had a high pitch ring to it - //new version has an odd 'pattering' or 'crackle' sound or clipping? - - int i, n, encL, encR; - // int j, k; - // float prev; - float stereo_samp1[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp2[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp3[320*6]; //48k 2-channel stereo interleave mix - float stereo_samp4[320*6]; //48k 2-channel stereo interleave mix - float out[6]; - float temp_l[4][160*6]; //temp storage - float temp_r[4][160*6]; //temp storage - float empty[320*6]; - float baseline = 0.0f; - - memset (stereo_samp1, baseline, sizeof(stereo_samp1)); - memset (stereo_samp2, baseline, sizeof(stereo_samp2)); - memset (stereo_samp3, baseline, sizeof(stereo_samp3)); - memset (stereo_samp4, baseline, sizeof(stereo_samp4)); - - memset (temp_l, baseline, sizeof(temp_l)); - memset (temp_r, baseline, sizeof(temp_r)); - memset (out, baseline, sizeof(out)); - memset (empty, baseline, 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; - } - } - } - - //at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions - if (encL && encR) - goto FS448_END; - - //TODO: Test Upsampling //void upsampleF (float invalue, float prev, float outbuf[6]) - // prev = 0.0f; - // for (j = 0; j < 4; j++) - // { - - // for (i = 0; i < 160; i++) - // { - // upsampleF (state->f_l4[j][i] / ((float) 480*10), prev, out); - // // upsampleF (state->f_l4[j][i], prev, out); - // for (k = 0; k < 6; k++) temp_l[j][i*6+k] = out[k]; - // } - // } - - // prev = 0.0f; //test value - // for (j = 0; j < 4; j++) - // { - - // for (i = 0; i < 160; i++) - // { - // upsampleF (state->f_r4[j][i] / ((float) 480*10), prev, out); - // // upsampleF (state->f_r4[j][i], prev, out); - // for (k = 0; k < 6; k++) temp_r[j][i*6+k] = out[k]; - // } - // } - - n = 160; //not sure why we are using 159 though - fdmdv_8_to_48_float(temp_l[0], state->f_l4[0], n); - fdmdv_8_to_48_float(temp_l[1], state->f_l4[1], n); - fdmdv_8_to_48_float(temp_l[2], state->f_l4[2], n); - fdmdv_8_to_48_float(temp_l[3], state->f_l4[3], n); - fdmdv_8_to_48_float(temp_r[0], state->f_r4[0], n); - fdmdv_8_to_48_float(temp_r[1], state->f_r4[1], n); - fdmdv_8_to_48_float(temp_r[2], state->f_r4[2], n); - fdmdv_8_to_48_float(temp_r[3], state->f_r4[3], n); - - //interleave left and right channels from the temp (float) buffer - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp1[i*2+0] = temp_l[0][i]; - if (!encR) - stereo_samp1[i*2+1] = temp_r[0][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp2[i*2+0] = temp_l[1][i]; - if (!encR) - stereo_samp2[i*2+1] = temp_r[1][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp3[i*2+0] = temp_l[2][i]; - if (!encR) - stereo_samp3[i*2+1] = temp_r[2][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp4[i*2+0] = temp_l[3][i]; - if (!encR) - stereo_samp4[i*2+1] = temp_r[3][i]; - } - - if (opts->audio_out_type == 0) //Pulse Audio - { - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*4*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp2, 320*4*6, NULL); - if (memcmp(empty, stereo_samp3, sizeof(empty)) != 0) - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp3, 320*4*6, NULL); - if (memcmp(empty, stereo_samp4, sizeof(empty)) != 0) - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp4, 320*4*6, NULL); - } - - //No OSS, since we can't use float output, but STDOUT can with play, aplay, etc - - if (opts->audio_out_type == 1) //STDOUT - { - write (opts->audio_out_fd, stereo_samp1, 320*4*6); - write (opts->audio_out_fd, stereo_samp2, 320*4*6); - if (memcmp(empty, stereo_samp3, sizeof(empty)) != 0) - write (opts->audio_out_fd, stereo_samp3, 320*4*6); - if (memcmp(empty, stereo_samp4, sizeof(empty)) != 0) - write (opts->audio_out_fd, stereo_samp4, 320*4*6); - } - - FS448_END: - - memset (state->audio_out_temp_buf, baseline, sizeof(state->audio_out_temp_buf)); - memset (state->audio_out_temp_bufR, baseline, sizeof(state->audio_out_temp_bufR)); - - //set float temp buffer to baseline - memset (state->f_l4, baseline, sizeof(state->f_l4)); - memset (state->f_r4, baseline, sizeof(state->f_r4)); - - //if we don't run processAudio, then I don't think we really need any of the items below active - state->audio_out_idx = 0; - state->audio_out_idxR = 0; - - 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; - } - -} - //float stereo mix -- when using P25p1 and P25p2, we need to send P25p1 to this, also DMR MS/Simplex and YSF void playSynthesizedVoiceFS (dsd_opts * opts, dsd_state * state) { @@ -880,7 +508,7 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state) //dmr enc checkdown for whether or not to fill the stereo sample or not for playback or writing encL = 0; - //TODO: Enc Checkdown + //TODO: Enc Checkdown -- would need to cover more ground than otherwise would like for it to, these should ultimately be passed to each encoding type decoder instead //TODO: add option to bypass enc with a toggle as well @@ -1231,279 +859,4 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state) state->audio_out_idx2R = 0; } -} - -//short stereo mix 3v2 DMR with tapped 8k to 48k upsample -void playSynthesizedVoiceSS3_48k (dsd_opts * opts, dsd_state * state) -{ - - //NOTE: This runs once for every two timeslots, if we are in the BS voice loop - //it doesn't matter if both slots have voice, or if one does, the slot without voice - //will play silence while this runs if no voice present - - int i; - uint8_t encL, encR; - short stereo_samp1[320*6]; //48k 2-channel stereo interleave mix - short stereo_samp2[320*6]; //48k 2-channel stereo interleave mix - short stereo_samp3[320*6]; //48k 2-channel stereo interleave mix - - memset (stereo_samp1, 1, sizeof(stereo_samp1)); - memset (stereo_samp2, 1, sizeof(stereo_samp2)); - memset (stereo_samp3, 1, sizeof(stereo_samp3)); - - //dmr enc checkdown for whether or not to fill the stereo sample or not for playback or writing - encL = encR = 0; - encL = (state->dmr_so >> 6) & 0x1; - encR = (state->dmr_soR >> 6) & 0x1; - - //checkdown to see if we can lift the 'mute' if a key is available - if (encL) - { - if (state->payload_algid == 0) - { - if (state->K != 0 || state->K1 != 0) - { - encL = 0; - } - } - else if (state->payload_algid == 0x21) - { - if (state->R != 0) - { - encL = 0; - } - } - } - - if (encR) - { - if (state->payload_algidR == 0) - { - if (state->K != 0 || state->K1 != 0) - { - encR = 0; - } - } - else if (state->payload_algidR == 0x21) - { - if (state->RR != 0) - { - encR = 0; - } - } - } - - //TODO: add option to bypass enc with a toggle as well - - //interleave left and right channels from the short storage area - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp1[i*2+0] = state->s_l4u[0][i]; - if (!encR) - stereo_samp1[i*2+1] = state->s_r4u[0][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp2[i*2+0] = state->s_l4u[1][i]; - if (!encR) - stereo_samp2[i*2+1] = state->s_r4u[1][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp3[i*2+0] = state->s_l4u[2][i]; - if (!encR) - stereo_samp3[i*2+1] = state->s_r4u[2][i]; - } - - //at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions - if (encL && encR) - goto SS3u_END; - - if (opts->audio_out_type == 0) //Pulse Audio - { - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*2*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp2, 320*2*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp3, 320*2*6, NULL); - } - - - if (opts->audio_out_type == 1 || opts->audio_out_type == 5) //STDOUT or OSS - { - write (opts->audio_out_fd, stereo_samp1, 320*2*6); - write (opts->audio_out_fd, stereo_samp2, 320*2*6); - write (opts->audio_out_fd, stereo_samp3, 320*2*6); - } - - SS3u_END: - - //run cleanup since we pulled stuff from processAudio - state->audio_out_idx = 0; - state->audio_out_idxR = 0; - - //set short temp buffer to baseline - memset (state->s_l4u, 1, sizeof(state->s_l4u)); - memset (state->s_r4u, 1, sizeof(state->s_r4u)); - - 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; - } - -} - -//short stereo mix 4v2 P25p2 with tapped 8k to 48k upsample -void playSynthesizedVoiceSS4_48k (dsd_opts * opts, dsd_state * state) -{ - - int i, encL, encR; - short stereo_samp1[320*6]; //48k 2-channel stereo interleave mix - short stereo_samp2[320*6]; //48k 2-channel stereo interleave mix - short stereo_samp3[320*6]; //48k 2-channel stereo interleave mix - short stereo_samp4[320*6]; //48k 2-channel stereo interleave mix - - memset (stereo_samp1, 1, sizeof(stereo_samp1)); - memset (stereo_samp2, 1, sizeof(stereo_samp2)); - memset (stereo_samp3, 1, sizeof(stereo_samp3)); - memset (stereo_samp4, 1, sizeof(stereo_samp4)); - - float empty[320]; //this is used to see if we want to play a single 2v or double 2v or not - - memset (empty, 1, 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; - } - } - } - - //TODO: add option to bypass enc with a toggle as well - - //interleave left and right channels from the short storage area - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp1[i*2+0] = state->s_l4u[0][i]; - if (!encR) - stereo_samp1[i*2+1] = state->s_r4u[0][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp2[i*2+0] = state->s_l4u[1][i]; - if (!encR) - stereo_samp2[i*2+1] = state->s_r4u[1][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp3[i*2+0] = state->s_l4u[2][i]; - if (!encR) - stereo_samp3[i*2+1] = state->s_r4u[2][i]; - } - - for (i = 0; i < 160*6; i++) - { - if (!encL) - stereo_samp4[i*2+0] = state->s_l4u[3][i]; - if (!encR) - stereo_samp4[i*2+1] = state->s_r4u[3][i]; - } - - //at this point, if both channels are still flagged as enc, then we can skip all playback/writing functions - if (encL && encR) - goto SS4u_END; - - if (opts->audio_out_type == 0) //Pulse Audio - { - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp1, 320*2*6, NULL); - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp2, 320*2*6, NULL); - if (memcmp(empty, stereo_samp3, sizeof(empty)) != 0) - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp3, 320*2*6, NULL); - if (memcmp(empty, stereo_samp4, sizeof(empty)) != 0) - pa_simple_write(opts->pulse_digi_dev_out, stereo_samp4, 320*2*6, NULL); - } - - - if (opts->audio_out_type == 1 || opts->audio_out_type == 5) //STDOUT or OSS - { - write (opts->audio_out_fd, stereo_samp1, 320*2*6); - write (opts->audio_out_fd, stereo_samp2, 320*2*6); - if (memcmp(empty, stereo_samp3, sizeof(empty)) != 0) - write (opts->audio_out_fd, stereo_samp3, 320*2*6); - if (memcmp(empty, stereo_samp4, sizeof(empty)) != 0) - write (opts->audio_out_fd, stereo_samp4, 320*2*6); - } - - SS4u_END: - - //run cleanup since we pulled stuff from processAudio - state->audio_out_idx = 0; - state->audio_out_idxR = 0; - - //set short temp buffer to baseline - memset (state->s_l4u, 1, sizeof(state->s_l4u)); - memset (state->s_r4u, 1, sizeof(state->s_r4u)); - - 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; - } - } \ No newline at end of file diff --git a/src/dsd_main.c b/src/dsd_main.c index 65b1f8a..16b5601 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -2803,7 +2803,6 @@ main (int argc, char **argv) opts.pulse_digi_rate_out = 8000; opts.pulse_digi_out_channels = 1; if (opts.audio_out_type == 0) openPulseOutput(&opts); - if (opts.audio_out_type == 5) openAudioOutDevice (&opts, SAMPLE_RATE_OUT); } //this particular if-elseif-else could be rewritten to be a lot neater and simpler diff --git a/src/dsd_mbe.c b/src/dsd_mbe.c index 8baa25c..019bebb 100644 --- a/src/dsd_mbe.c +++ b/src/dsd_mbe.c @@ -17,8 +17,8 @@ #include "dsd.h" -//NOTE: I attempted to fix the atrocious tab/space alignnment issues that happened in this file, -//it looks fine in VSCodium, but no telling how it will translate when pushed to Github or another editor +//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) { @@ -1084,7 +1084,6 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } 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 - // playSynthesizedVoiceFL (opts, state); //Float Left } @@ -1159,7 +1158,6 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a } memcpy (state->f_r, state->audio_out_temp_bufR, sizeof(state->f_r)); - // playSynthesizedVoiceFR (opts, state); //Float Right } @@ -1175,13 +1173,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a // { // playSynthesizedVoice (opts, state); // } - // playSynthesizedVoiceFL (opts, state); memcpy (state->f_l, state->audio_out_temp_buf, sizeof(state->f_l)); //P25p1 FDMA 8k/1 channel -f1 switch } - // playSynthesizedVoiceFS (opts, state); //Float Stereo Mix -- disable and move this later on - //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)) { diff --git a/src/dsd_upsample.c b/src/dsd_upsample.c index 5d869bd..708819e 100644 --- a/src/dsd_upsample.c +++ b/src/dsd_upsample.c @@ -136,3 +136,23 @@ upsample (dsd_state * state, float invalue) } } + +//produce 6 short samples (48k) for every 1 short sample (8k) +void upsampleS (short invalue, short prev, short outbuf[6]) +{ + + float c, d; + + c = prev; + d = invalue; + + // basic triangle interpolation + outbuf[0] = c = ((invalue * (float) 0.166) + (c * (float) 0.834)); + outbuf[1] = c = ((invalue * (float) 0.332) + (c * (float) 0.668)); + outbuf[2] = c = ((invalue * (float) 0.500) + (c * (float) 0.5)); + outbuf[3] = c = ((invalue * (float) 0.668) + (c * (float) 0.332)); + outbuf[4] = c = ((invalue * (float) 0.834) + (c * (float) 0.166)); + outbuf[5] = c = d; + prev = d; //shift prev to the last d value for the next repitition + +} \ No newline at end of file diff --git a/src/dsd_upsample2.c b/src/dsd_upsample2.c deleted file mode 100644 index 9aabd7b..0000000 --- a/src/dsd_upsample2.c +++ /dev/null @@ -1,259 +0,0 @@ -#include "dsd.h" - -static const float fdmdv_os_filter48[48]= { - -3.55606818e-04, - -8.98615286e-04, - -1.40119781e-03, - -1.71713852e-03, - -1.56471179e-03, - -6.28128960e-04, - 1.24522223e-03, - 3.83138676e-03, - 6.41309478e-03, - 7.85893186e-03, - 6.93514929e-03, - 2.79361991e-03, - -4.51051400e-03, - -1.36671853e-02, - -2.21034939e-02, - -2.64084653e-02, - -2.31425052e-02, - -9.84218694e-03, - 1.40648474e-02, - 4.67316298e-02, - 8.39615986e-02, - 1.19925275e-01, - 1.48381174e-01, - 1.64097819e-01, - 1.64097819e-01, - 1.48381174e-01, - 1.19925275e-01, - 8.39615986e-02, - 4.67316298e-02, - 1.40648474e-02, - -9.84218694e-03, - -2.31425052e-02, - -2.64084653e-02, - -2.21034939e-02, - -1.36671853e-02, - -4.51051400e-03, - 2.79361991e-03, - 6.93514929e-03, - 7.85893186e-03, - 6.41309478e-03, - 3.83138676e-03, - 1.24522223e-03, - -6.28128960e-04, - -1.56471179e-03, - -1.71713852e-03, - -1.40119781e-03, - -8.98615286e-04, - -3.55606818e-04 -}; - - -//from CODEC2 -//float filter /* Generate using fir1(47,1/2) in Octave */ -static const float fdmdv_os_filter[48]= { - -0.0008215855034550382, - -0.0007833023901802921, - 0.001075563790768233, - 0.001199092367787555, - -0.001765309502928316, - -0.002055372115328064, - 0.002986877604154257, - 0.003462567920638414, - -0.004856570111126334, - -0.005563143845031497, - 0.007533613299748122, - 0.008563932468880897, - -0.01126857129039911, - -0.01280782411693687, - 0.01651443896361847, - 0.01894875110322284, - -0.02421604439474981, - -0.02845107338464062, - 0.03672973563400258, - 0.04542046150312214, - -0.06189165826716491, - -0.08721876380763803, - 0.1496157094199961, - 0.4497962274137046, - 0.4497962274137046, - 0.1496157094199961, - -0.08721876380763803, - -0.0618916582671649, - 0.04542046150312216, - 0.03672973563400257, - -0.02845107338464062, - -0.02421604439474984, - 0.01894875110322284, - 0.01651443896361848, - -0.01280782411693687, - -0.0112685712903991, - 0.008563932468880899, - 0.007533613299748123, - -0.005563143845031501, - -0.004856570111126346, - 0.003462567920638419, - 0.002986877604154259, - -0.002055372115328063, - -0.001765309502928318, - 0.001199092367787557, - 0.001075563790768233, - -0.0007833023901802925, - -0.0008215855034550383 -}; - -//produce 6 float samples (48k) for every 1 float sample (8k) -void upsampleF (float invalue, float prev, float outbuf[6]) -{ - - float c, d; - - c = prev; //may ned up needing storage for the prev value to prevent the high pitch 'ring' sound - d = invalue; - - // basic triangle interpolation - outbuf[0] = c = ((invalue * (float) 0.166) + (c * (float) 0.834)); - outbuf[1] = c = ((invalue * (float) 0.332) + (c * (float) 0.668)); - outbuf[2] = c = ((invalue * (float) 0.500) + (c * (float) 0.5)); - outbuf[3] = c = ((invalue * (float) 0.668) + (c * (float) 0.332)); - outbuf[4] = c = ((invalue * (float) 0.834) + (c * (float) 0.166)); - outbuf[5] = c = d; - prev = d; //shift prev to the last d value for the next repitition - - // fdmdv_os_filter48 - -} - -//produce 6 short samples (48k) for every 1 short sample (8k) -void upsampleS (short invalue, short prev, short outbuf[6]) -{ - - float c, d; - - c = prev; - d = invalue; - - // basic triangle interpolation - outbuf[0] = c = ((invalue * (float) 0.166) + (c * (float) 0.834)); - outbuf[1] = c = ((invalue * (float) 0.332) + (c * (float) 0.668)); - outbuf[2] = c = ((invalue * (float) 0.500) + (c * (float) 0.5)); - outbuf[3] = c = ((invalue * (float) 0.668) + (c * (float) 0.332)); - outbuf[4] = c = ((invalue * (float) 0.834) + (c * (float) 0.166)); - outbuf[5] = c = d; - prev = d; //shift prev to the last d value for the next repitition - -} - -// void fdmdv_8_to_48_short(short out48k[], short in8k[], int n) -// { -// int i,j,k,l; -// float acc; - -// //FDMDV_OS_TAPS_48K = 48 -// //FDMDV_OS_48 = 6 -// //unsure of what the n value would be, could be number of samples to process? - -// for(i=0; ifloating_point == 1 && opts->pulse_digi_rate_out == 8000) //this should be a real TS value %2 and non-inverted frames, so 0-9, need a way to get real TS number each go around playSynthesizedVoiceFS4 (opts, state); - if (sacch == 0 && ts_counter & 1 && opts->floating_point == 1 && opts->pulse_digi_rate_out == 48000) //this should be a real TS value %2 and non-inverted frames, so 0-9, need a way to get real TS number each go around - playSynthesizedVoiceFS4_48k (opts, state); - if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 8000) //this should be a real TS value %2 and non-inverted frames, so 0-9, need a way to get real TS number each go around playSynthesizedVoiceSS4 (opts, state); - if (sacch == 0 && ts_counter & 1 && opts->floating_point == 0 && opts->pulse_digi_rate_out == 48000) //this should be a real TS value %2 and non-inverted frames, so 0-9, need a way to get real TS number each go around - playSynthesizedVoiceSS4_48k (opts, state); - //flip slots after each TS processed if (state->currentslot == 0) {