ubitx-v5d-xcvr/ubitx_iop/audio.ino

371 lines
12 KiB
C++

//======================================================================
// audio.ino
//
// NOTE: Let's change the name of this file to Rigconfig.cc. Will need
// to ensure that "Arduino-isms" are resolved if it's converted to .cc
// from .ino, however.
//======================================================================
#include <dynamicFilters.h>
#include <effect_compressor_fb.h>
#include "audio.h"
//short firActive[NUM_COEFFICIENTS];
#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
//extern RigConfig rigConfig;
/*
#define DEFAULT_RX_INPUT RIG
#define DEFAULT_RX_OUTPUT SPKR
#define DEFAULT_TX_INPUT MIC
#define DEFAULT_TX_OUTPUT RIG
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S inLine; //xy=134,131
AudioInputUSB inUSB; //xy=134,303
AudioSynthWaveformSine sideTone; //xy=136,214
AudioSynthWaveformSine sine2; //xy=323,482
AudioSynthWaveformSine sine1; //xy=324,428
AudioAnalyzeRMS rmsRX; //xy=362,20
AudioAnalyzePeak peakRX; //xy=362,65
AudioEffectCompressor compTX; //xy=383,256
AudioAnalyzeRMS compRMS; //xy=388,224
AudioMixer4 mixRX; //xy=444,163
AudioAmplifier compAmp; //xy=514,257
AudioFilterFIR filterRX; //xy=577,161
AudioMixer4 mixTX; //xy=652,321
AudioAmplifier filterAmp; //xy=700,160
AudioAnalyzeRMS rmsTX; //xy=841,449
AudioAnalyzePeak peakTX; //xy=843,393
AudioAmplifier calRxUSB; //xy=873,172
AudioAmplifier calRxSpkr; //xy=877,62
AudioAmplifier calRxLine; //xy=880,119
AudioAmplifier calTxLine; //xy=892,255
AudioAmplifier calTxUSB; //xy=893,312
AudioOutputAnalog outSpkr; //xy=1053,62
AudioOutputUSB outUSB; //xy=1066,307
AudioOutputI2S outLine; //xy=1070,192
AudioConnection patchCord1(inLine, 0, rmsRX, 0);
AudioConnection patchCord2(inLine, 0, peakRX, 0);
AudioConnection patchCord3(inLine, 0, mixRX, 0);
AudioConnection patchCord4(inLine, 1, compTX, 0);
AudioConnection patchCord5(inLine, 1, compRMS, 0);
AudioConnection patchCord6(inUSB, 0, mixRX, 1);
AudioConnection patchCord7(inUSB, 1, mixTX, 1);
AudioConnection patchCord8(sideTone, 0, mixRX, 2);
AudioConnection patchCord9(sine2, 0, mixTX, 3);
AudioConnection patchCord10(sine1, 0, mixTX, 2);
AudioConnection patchCord11(compTX, compAmp);
AudioConnection patchCord12(mixRX, filterRX);
AudioConnection patchCord13(compAmp, 0, mixTX, 0);
AudioConnection patchCord14(filterRX, filterAmp);
AudioConnection patchCord15(mixTX, calTxLine);
AudioConnection patchCord16(mixTX, calTxUSB);
AudioConnection patchCord17(mixTX, peakTX);
AudioConnection patchCord18(mixTX, rmsTX);
AudioConnection patchCord19(filterAmp, calRxSpkr);
AudioConnection patchCord20(filterAmp, calRxLine);
AudioConnection patchCord21(filterAmp, calRxUSB);
AudioConnection patchCord22(calRxUSB, 0, outUSB, 0);
AudioConnection patchCord23(calRxSpkr, outSpkr);
AudioConnection patchCord24(calRxLine, 0, outLine, 0);
AudioConnection patchCord25(calTxLine, 0, outLine, 1);
AudioConnection patchCord26(calTxUSB, 0, outUSB, 1);
AudioControlSGTL5000 audioCtrl; //xy=648,517
// GUItool: end automatically generated code
void RigAudio::init() const {
USBDEBUG("audio initialization started");
audioCtrl.enable();
audioCtrl.adcHighPassFilterEnable(); // default
audioCtrl.dacVolume(1.0); // default
audioCtrl.dacVolumeRampDisable(); // not default; just trying to cull out culprits for my high freq hiss
audioCtrl.audioProcessorDisable();
audioCtrl.autoVolumeDisable();
audioCtrl.surroundSoundDisable();
audioCtrl.enhanceBassDisable();
audioCtrl.eqSelect(FLAT_FREQUENCY); // eventually, use this to smooth out the normal uBITX passband
audioCtrl.muteHeadphone(); // not using the headphone output
audioCtrl.volume(0.0); // not using the headphone output
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); // required for RX audio
audioCtrl.unmuteLineout(); // required for RX audio
audioCtrl.lineInLevel(_config.rxRigInLevel, _config.txLineInLevel); // NOTE: need to see if this persists through input changes (see mic gain...)
audioCtrl.lineOutLevel(_config.rxLineOutLevel, _config.txRigOutLevel); // NOTE: need to see if this persists through input changes (see mic gain...)
audioCtrl.micGain(_config.txMicInGain); // superfluous, as I have to do this anytime I switch to mic for some reason
// configure line input
audioCtrl.lineInLevel(_config.rxRigInLevel, _config.txLineInLevel);
// configure line output
calTxLine.gain(_config.txRigOutCal);
audioCtrl.lineOutLevel(_config.rxLineOutLevel, _config.txRigOutLevel);
// configure "receive" of USB audio input (debug only)
if (_config.rxUSBInEnable) {
mixRX.gain(RX_USB_IN, _config.rxUSBInVol * _config.rxUSBInCal);
} else {
mixRX.gain(RX_USB_IN, 0.0);
}
// configure USB audio output of transmit audio (useful for debug)
if (_config.txUSBOutEnable) {
calTxUSB.gain(_config.txUSBOutCal);
} else {
calTxUSB.gain(0.0);
}
// setup the two-tone generator
sine1.frequency(700);
sine2.frequency(1900);
sine1.amplitude(0);
sine2.amplitude(0);
//audioFilter(firActive, NUM_COEFFICIENTS, ID_BANDPASS, W_HAMMING, 300.0, 3100.0); // 2.8 kHz filter
//filterRX.begin(firActive, NUM_COEFFICIENTS);
filterAmp.gain(1.0);
// for now, just pass through the compressor
compTX.disable();
compAmp.gain(1.0);
// 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++) {
mixRX.gain(i, 0.0);
mixTX.gain(i, 0.0);
}
audioEqualizer();
USBDEBUG("audio initialization completed");
}
void RigAudio::muteRx() const {
mixRX.gain(RX_RIG_IN, 0.0);
USBDEBUG("RX audio muted");
}
void RigAudio::unmuteRx() const {
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
mixRX.gain(RX_RIG_IN, _config.rxRigInVol * _config.rxRigInCal);
USBDEBUG("RX audio unmuted");
}
void RigAudio::muteAllTx() const {
muteMicIn();
muteLineIn();
muteUSBIn();
muteTTIn();
USBDEBUG("all TX audio muted");
}
void RigAudio::muteMicIn() const {
mixTX.gain(TX_LINE_IN, 0.0);
USBDEBUG("Mic In audio muted");
}
void RigAudio::unmuteMicIn() const {
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
audioCtrl.micGain(_config.txMicInGain);
mixTX.gain(TX_LINE_IN, _config.txMicInVol * _config.txMicInCal);
USBDEBUG("Mic In audio unmuted");
}
void RigAudio::muteLineIn() const {
mixTX.gain(TX_LINE_IN, 0.0);
USBDEBUG("Line In audio muted");
}
void RigAudio::unmuteLineIn() const {
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
mixTX.gain(TX_LINE_IN, _config.txLineInVol * _config.txLineInCal);
USBDEBUG("Line In audio unmuted");
}
void RigAudio::muteUSBIn() const {
mixTX.gain(TX_USB_IN, 0.0);
USBDEBUG("USB In audio muted");
}
void RigAudio::unmuteUSBIn() const {
mixTX.gain(TX_USB_IN, _config.txUSBInVol * _config.txUSBInCal);
USBDEBUG("USB In audio unmuted");
}
void RigAudio::muteTTIn() const {
mixTX.gain(TX_TEST_IN, 0.0);
mixTX.gain(TX_TEST_IN + 1, 0.0);
sine1.amplitude(0.0);
sine2.amplitude(0.0);
USBDEBUG("Two Tone audio muted");
}
void RigAudio::unmuteTTIn() const {
sine1.amplitude(0.5);
sine2.amplitude(0.5);
mixTX.gain(TX_TEST_IN, _config.txSine1Vol);
mixTX.gain(TX_TEST_IN + 1, _config.txSine2Vol);
USBDEBUG("Two Tone audio unmuted");
}
void RigAudio::muteSpkrOut() const {
calRxSpkr.gain(0.0);
USBDEBUG("Speaker Out audio muted");
}
void RigAudio::unmuteSpkrOut() const {
calRxSpkr.gain(_config.rxSpkrOutCal);
USBDEBUG("Speaker Out audio unmuted");
}
void RigAudio::muteLineOut() const {
calRxLine.gain(0.0);
USBDEBUG("Line Out audio muted");
}
void RigAudio::unmuteLineOut() const {
calRxLine.gain(_config.rxLineOutCal);
USBDEBUG("Line Out audio unmuted");
}
void RigAudio::muteUSBOut() const {
calRxUSB.gain(0.0);
USBDEBUG("USB Out audio muted");
}
void RigAudio::unmuteUSBOut() const {
calRxUSB.gain(_config.rxUSBOutCal);
USBDEBUG("USB Out audio unmuted");
}
/*
RxInput audioRxInput;
RxOutput audioRxOutput;
TxInput audioTxInput;
TxOutput audioTxOutput;
*/
//======================================================================
// 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_);
}
}
//======================================================================
int eqFilter1[5];
void audioEqualizer()
{
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
//======================================================================