369 lines
12 KiB
C++
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
|
|
//======================================================================
|