//====================================================================== // dsp_audio.cpp //====================================================================== #include #include #include "dsp_audio.h" #define RX_RIG_IN 0 #define RX_USB_IN 1 #define RX_ST_IN 2 // sidetone #define TX_MIC_IN 0 #define TX_LINE_IN 0 #define TX_USB_IN 1 #define TX_TEST_IN 2 #define RX_BPF_ONLY 0 #define RX_NOTCH_ON 1 #include #include #include #include #include namespace dsp_audio { // GUItool: begin automatically generated code AudioInputI2S line_in; //xy=148.9999771118164,131 AudioInputUSB usb_in; //xy=148.9999771118164,303 AudioSynthWaveformSine sidetone; //xy=150.9999771118164,214 AudioSynthWaveformSine sine2; //xy=337.9999771118164,482 AudioSynthWaveformSine sine1; //xy=338.9999771118164,428 AudioAnalyzeFFT256 rx_fft; //xy=370.0127944946289,103.02459716796875 AudioAnalyzeRMS rx_rms; //xy=376.9999771118164,20 AudioAnalyzePeak rx_peak; //xy=376.9999771118164,65 AudioEffectFade tx_comp; //xy=400.99999237060547,260.99999809265137 AudioAnalyzeRMS tx_comp_rms; //xy=402.9999771118164,224 AudioMixer4 rx_in_mix; //xy=458.9999771118164,163 AudioFilterFIR rx_fir_filter; //xy=628.0000839233398,135.00000476837158 AudioMixer4 tx_mix; //xy=666.9999771118164,321 AudioFilterBiquad rx_biquad_filter; //xy=765.7827301025391,183.02459716796875 AudioAnalyzeRMS tx_rms; //xy=855.9999771118164,449 AudioAnalyzePeak tx_peak; //xy=857.9999771118164,393 AudioAmplifier tx_line_out_cal; //xy=906.9999771118164,255 AudioAmplifier tx_usb_out_cal; //xy=907.9999771118164,312 AudioMixer4 rx_out_mix; //xy=933.78271484375,119.02459144592285 AudioAmplifier rx_usb_out_cal; //xy=1155,180.99999904632568 AudioAmplifier rx_line_out_cal; //xy=1156.9999771118164,109.00000381469727 AudioAmplifier rx_spkr_out_cal; //xy=1167.0000076293945,50 AudioOutputAnalog spkr_out; //xy=1307.000015258789,53 AudioOutputUSB usb_out; //xy=1332.999984741211,291.0000114440918 AudioOutputI2S line_out; //xy=1374.9999618530273,207.0000057220459 AudioConnection patchCord1(line_in, 0, rx_rms, 0); AudioConnection patchCord2(line_in, 0, rx_peak, 0); AudioConnection patchCord3(line_in, 0, rx_in_mix, 0); AudioConnection patchCord4(line_in, 0, rx_fft, 0); AudioConnection patchCord5(line_in, 1, tx_comp, 0); AudioConnection patchCord6(line_in, 1, tx_comp_rms, 0); AudioConnection patchCord7(usb_in, 0, rx_in_mix, 1); AudioConnection patchCord8(usb_in, 1, tx_mix, 1); AudioConnection patchCord9(sidetone, 0, rx_in_mix, 2); AudioConnection patchCord10(sine2, 0, tx_mix, 3); AudioConnection patchCord11(sine1, 0, tx_mix, 2); AudioConnection patchCord12(tx_comp, 0, tx_mix, 0); AudioConnection patchCord13(rx_in_mix, rx_fir_filter); AudioConnection patchCord14(rx_fir_filter, rx_biquad_filter); AudioConnection patchCord15(rx_fir_filter, 0, rx_out_mix, 0); AudioConnection patchCord16(tx_mix, tx_line_out_cal); AudioConnection patchCord17(tx_mix, tx_usb_out_cal); AudioConnection patchCord18(tx_mix, tx_peak); AudioConnection patchCord19(tx_mix, tx_rms); AudioConnection patchCord20(rx_biquad_filter, 0, rx_out_mix, 1); AudioConnection patchCord21(tx_line_out_cal, 0, line_out, 1); AudioConnection patchCord22(tx_usb_out_cal, 0, usb_out, 1); AudioConnection patchCord23(rx_out_mix, spkr_out_cal); AudioConnection patchCord24(rx_out_mix, rx_line_out_cal); AudioConnection patchCord25(rx_out_mix, rx_usb_out_cal); AudioConnection patchCord26(rx_usb_out_cal, 0, usb_out, 0); AudioConnection patchCord27(rx_line_out_cal, 0, line_out, 0); AudioConnection patchCord28(spkr_out_cal, spkr_out); AudioControlSGTL5000 audioCtrl; //xy=648,517 // GUItool: end automatically generated code class configurator { public: configurator(dsp_audio_cfg& c): data(c) {} dsp_audio_cfg& data; } *cfg = nullptr; }; void dsp_audio::init(dsp_audio_cfg& c) { USBDEBUG("audio initialization started"); if (cfg != nullptr) { delete cfg; } cfg = new configurator(c); audio_ctrl.enable(); audio_ctrl.adcHighPassFilterEnable(); // default audio_ctrl.dacVolume(1.0); // default audio_ctrl.dacVolumeRampDisable(); // not default; just trying to cull out culprits for my high freq hiss audio_ctrl.audioProcessorDisable(); audio_ctrl.autoVolumeDisable(); audio_ctrl.surroundSoundDisable(); audio_ctrl.enhanceBassDisable(); audio_ctrl.eqSelect(FLAT_FREQUENCY); // eventually, use this to smooth out the normal uBITX passband audio_ctrl.muteHeadphone(); // not using the headphone output audio_ctrl.volume(0.0); // not using the headphone output audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN); // required for RX audio audio_ctrl.unmuteLineout(); // required for RX audio audio_ctrl.lineInLevel(cfg.data.rx_rig_in_level, cfg.data.tx_line_in_level); // NOTE: need to see if this persists through input changes (see mic gain...) audio_ctrl.lineOutLevel(cfg.data.rx_line_out_level, cfg.data.tx_rig_out_level); // NOTE: need to see if this persists through input changes (see mic gain...) audio_ctrl.micGain(cfg.data.tx_mic_in_gain); // superfluous, as I have to do this anytime I switch to mic for some reason // configure line input audio_ctrl.lineInLevel(cfg.data.rx_rig_in_level, cfg.data.tx_line_in_level); // configure line output tx_rig_out_cal.gain(cfg.data.tx_rig_out_cal); audio_ctrl.lineOutLevel(cfg.data.rx_line_out_level, cfg.data.tx_rig_out_level); // configure "receive" of USB audio input (debug only) if (cfg.data.rx_usb_in_enable) { rx_in_mix.gain(RX_USB_IN, cfg.data.rx_usb_in_vol * cfg.data.rx_usb_in_cal); } else { rx_in_mix.gain(RX_USB_IN, 0.0); } // configure USB audio output of transmit audio (useful for debug) if (cfg.data.tx_usb_out_enable) { tx_usb_out_cal.gain(cfg.data.tx_usb_out_cal); } else { tx_usb_out_cal.gain(0.0); } // setup the two-tone generator sine1.frequency(700); sine2.frequency(1900); sine1.amplitude(0); sine2.amplitude(0); // no separate filter amp; just need to appropriately set the rx_out_mix values rx_out_mix.gain(RX_BPF_ONLY, 1.0); rx_out_mix.gain(RX_NOTCH_ON, 0.0); // for now, just pass through the compressor tx_comp.disable(); // Hardware should be all setup... now we're going to mute everything // and let the modes take care of enabling/disabling what they should. for (int i = 0; i < 4; i++) { rx_in_mix.gain(i, 0.0); tx_mix.gain(i, 0.0); } audio_equalizer(); USBDEBUG("audio initialization completed"); } void dsp_audio::mute_rx() { rx_in_mix.gain(RX_RIG_IN, 0.0); USBDEBUG("RX audio muted"); } void dsp_audio::unmute_rx() { audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN); rx_in_mix.gain(RX_RIG_IN, cfg.data.rx_rig_in_vol * cfg.data.rx_rig_in_cal); USBDEBUG("RX audio unmuted"); } void dsp_audio::mute_all_tx() { mute_mic_in(); mute_line_in(); mute_usb_in(); mute_twotone_in(); USBDEBUG("all TX audio muted"); } void dsp_audio::mute_mic_in() { tx_mix.gain(TX_LINE_IN, 0.0); USBDEBUG("Mic In audio muted"); } void dsp_audio::unmute_mic_in() { audio_ctrl.inputSelect(AUDIO_INPUT_MIC); audio_ctrl.micGain(cfg.data.tx_mic_in_gain); tx_mix.gain(TX_LINE_IN, cfg.data.tx_mic_in_vol * cfg.data.tx_mic_in_cal); USBDEBUG("Mic In audio unmuted"); } void dsp_audio::mute_line_in() { tx_mix.gain(TX_LINE_IN, 0.0); USBDEBUG("Line In audio muted"); } void dsp_audio::unmute_line_in() { audio_ctrl.inputSelect(AUDIO_INPUT_LINEIN); tx_mix.gain(TX_LINE_IN, cfg.data.tx_line_in_vol * cfg.data.tx_line_in_cal); USBDEBUG("Line In audio unmuted"); } void dsp_audio::mute_usb_in() { tx_mix.gain(TX_USB_IN, 0.0); USBDEBUG("USB In audio muted"); } void dsp_audio::unmuteUSBIn() { tx_mix.gain(TX_USB_IN, cfg.data.tx_usb_in_vol * cfg.data.tx_usb_in_cal); USBDEBUG("USB In audio unmuted"); } void dsp_audio::mute_twotone_in() { tx_mix.gain(TX_TEST_IN, 0.0); tx_mix.gain(TX_TEST_IN + 1, 0.0); sine1.amplitude(0.0); sine2.amplitude(0.0); USBDEBUG("Two Tone audio muted"); } void dsp_audio::unmute_twotone_in() { sine1.amplitude(0.5); sine2.amplitude(0.5); tx_mix.gain(TX_TEST_IN, cfg.data.tx_sine1_vol); tx_mix.gain(TX_TEST_IN + 1, cfg.data.tx_sine2_vol); USBDEBUG("Two Tone audio unmuted"); } void dsp_audio::mute_spkr_out() { rx_spkr_out_cal.gain(0.0); USBDEBUG("Speaker Out audio muted"); } void dsp_audio::unmute_spkr_out() { rx_spkr_out_cal.gain(cfg.data.rx_spkr_out_cal); USBDEBUG("Speaker Out audio unmuted"); } void dsp_audio::mute_line_out() { rx_line_out_cal.gain(0.0); USBDEBUG("Line Out audio muted"); } void dsp_audio::unmute_line_out() { rx_line_out_cal.gain(cfg.data.rx_line_out_cal); USBDEBUG("Line Out audio unmuted"); } void dsp_audio::mute_usb_out() { rx_usb_out_cal.gain(0.0); USBDEBUG("USB Out audio muted"); } void dsp_audio::unmute_usb_out() { rx_usb_out_cal.gain(cfg.data.rx_usb_out_cal); USBDEBUG("USB Out audio unmuted"); } //====================================================================== // bp_filter // // Band Pass Filter methods. //====================================================================== bp_filter::bp_filter(): filter(filterRX), amp(filterAmp) {} bp_filter::bp_filter(AudioFilterFIR& f, AudioAmplifier& a): filter(f), amp(a) {} void bp_filter::init(const bpf_config& cfg) { set_band(cfg.lo_freq, cfg.hi_freq); set_gain(cfg.gain); } void bp_filter::set_band(double f1, double f2) { freq_lo = f1; freq_hi = f2; } void bp_filter::set_freq_lo(double f) { freq_lo = f; } void bp_filter::set_freq_hi(double f) { freq_hi = f; } void bp_filter::set_center_and_width(double c, double w) { freq_lo = c - (0.5 * w); freq_hi = c + (0.5 * w); } void bp_filter::set_center(double c) { double w = freq_hi - freq_lo; set_center_and_width(c, w); } void bp_filter::set_width(double w) { double c = (freq_lo + freq_hi) * 0.5; set_center_and_width(c, w); } void bp_filter::set_gain(double g) { recovery = g; } void bp_filter::enable() { audioFilter(coefficients, NUM_COEFFICIENTS, ID_BANDPASS, W_HAMMING, freq_lo, freq_hi); filter.begin(coefficients, NUM_COEFFICIENTS); amp.gain(recovery); } void bp_filter::disable() { filter.begin(FIR_PASSTHRU, NUM_COEFFICIENTS); amp.gain(1.0); } //====================================================================== speech_comp::speech_comp(comp_config* cfg) : config_(cfg), comp_(compTX), amp_(compAmp), rms_(compRMS) {} void speech_comp::enable() { config_->enabled = true; comp_.begin(1, config_->threshold, config_->ratio); // Need to make configurable amp_.gain(config_->gain); } void speech_comp::disable() { config_->enabled = false; comp_.disable(); amp_.gain(1.0); } // Speech compressor code based on post by 'hyperdyne': https://forum.pjrc.com/threads/36245-Changing-Pitch-of-Voice void speech_comp::update() { float rms_cur; if (config_->enabled && rms_.available()) { rms_cur = rms_.read(); env_ = rms_cur + (alpha_ * (env_ - rms_cur)); comp_.update_pwr(env_); } } //====================================================================== void dsp_audio::audio_equalizer() { static int eqFilter1[5]; audioCtrl.audioPreProcessorEnable(); audioCtrl.eqSelect(PARAMETRIC_EQUALIZER); // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_PARAEQ, 2700, 6, 0.707, 524288, 44100, eqFilter1); // calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter); audioCtrl.eqFilter(0, eqFilter1); // audioCtrl.eqFilter(1, hpFilter); // audioCtrl.eqFilter(2, lpFilter); // audioCtrl.eqFilter(3, hpFilter); // audioCtrl.eqFilter(4, lpFilter); // audioCtrl.eqFilter(5, hpFilter); } //====================================================================== // EOF //======================================================================