digibox/digibox/dsp_audio.cpp

369 lines
12 KiB
C++

//======================================================================
// dsp_audio.cpp
//======================================================================
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#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 <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
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
//======================================================================