//====================================================================== // 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 #include #include "audio.h" #include "tx_audio_proc.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 #include #include #include #include // 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; */ //====================================================================== short _internal_coefficients[NUM_COEFFICIENTS]; BPFilter::BPFilter(double f1, double f2, bool use_center=false, short int window, short int coeff): _window(window), _coeff(coeff) { if (window == -1) { _window = W_HAMMING; } if (coeff == -1) { _coeff = NUM_COEFFICIENTS; } if (use_center) { // treat f1 as center frequency, f2 as filter width _freq_lo = f1 - (0.5 * f2); _freq_hi = f1 + (0.5 * f2); } else { _freq_lo = f1; _freq_hi = f2; } } void BPFilter::init(AudioFilterFIR* filter, short* coefficients) { if (filter == NULL) { _filter = &filterRX; } else { _filter = filter; } if (coefficients == NULL) { _coefficients = _internal_coefficients; } else { _coefficients = coefficients; } //audioFilter(coefficients, NUM_COEFFICIENTS, ID_BANDPASS, _window, _freq_lo, _freq_hi); //filter->begin(coefficients, NUM_COEFFICIENTS); } void BPFilter::setFreqLo(double f) { _freq_lo = f; } void BPFilter::setFreqHi(double f) { _freq_hi = f; } void BPFilter::setBand(double f1, double f2) { _freq_lo = f1; _freq_hi = f2; } void BPFilter::setCenter(double c) { double w = _freq_hi - _freq_lo; setCenterAndWidth(c, w); } void BPFilter::setWidth(double w) { double c = (_freq_lo + _freq_hi) * 0.5; setCenterAndWidth(c, w); } void BPFilter::setCenterAndWidth(double c, double w) { _freq_lo = c - (0.5 * w); _freq_hi = c + (0.5 * w); } void BPFilter::enable() { audioFilter(_coefficients, NUM_COEFFICIENTS, ID_BANDPASS, _window, _freq_lo, _freq_hi); _filter->begin(_coefficients, NUM_COEFFICIENTS); } void BPFilter::disable() { _filter->begin(FIR_PASSTHRU, NUM_COEFFICIENTS); } //====================================================================== SpeechCompressor speechCompressor(compTX, compAmp, compRMS); //====================================================================== /* // array based on mode right now BPFilter *rxFilter[NUM_RIG_MODES][NUM_RX_FILTERS]; //====================================================================== void audioSetupFilters() { rxFilter[RIG_MODE_SSB][FILTER_WIDE] = new BPFilter( 300.0, 3100.0); rxFilter[RIG_MODE_SSB][FILTER_NORMAL] = new BPFilter( 500.0, 2900.0); rxFilter[RIG_MODE_SSB][FILTER_NARROW] = new BPFilter( 700.0, 2500.0); // Need to make the NARROW filter center frequency configurable. rxFilter[RIG_MODE_DIGI][FILTER_WIDE] = new BPFilter( 300.0, 3100.0); rxFilter[RIG_MODE_DIGI][FILTER_NORMAL] = new BPFilter( 500.0, 2900.0); rxFilter[RIG_MODE_DIGI][FILTER_NARROW] = new BPFilter(1500.0, 500.0, true); // Need to use the sidetone frequency for the NORMAL and NARROW filters. rxFilter[RIG_MODE_CW][FILTER_WIDE] = new BPFilter( 300.0, 1300.0); rxFilter[RIG_MODE_CW][FILTER_NORMAL] = new BPFilter( 700.0, 500.0, true); rxFilter[RIG_MODE_CW][FILTER_NARROW] = new BPFilter( 700.0, 250.0, true); } //====================================================================== SpeechCompressor speechCompressor(compTX, compAmp, compRMS); //====================================================================== // audioInit() // Setup the audio subsystem. void audioInit() { audioCtrl.enable(); 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(rigConfig.rxRigInLevel, rigConfig.txLineInLevel); // NOTE: need to see if this persists through input changes (see mic gain...) audioCtrl.lineOutLevel(rigConfig.rxLineOutLevel, rigConfig.txRigOutLevel); // NOTE: need to see if this persists through input changes (see mic gain...) audioCtrl.micGain(rigConfig.txMicInGain); // superfluous, as I have to do this anytime I switch to mic for some reason //audioCtrl.dacVolumeRamp(); // if this seems too slow, might try dacVolumeRampLinear(). //audioCtrl.dacVolume(1.0, 0.0); // we're going to mute TX audio via the DAC unless we're transmitting updateRxRigIn(); updateRxSpkrOut(); updateRxLineOut(); updateRxUSBOut(); // Note - these really just need to be init functions; keep things muted while setting them up. updateTxMicIn(); updateTxLineIn(); updateTxUSBIn(); updateTxTwoToneIn(); updateTxRigOut(); audioSelectRxInput(RX_RIG_IN); audioSelectTxInput(TX_MIC_IN); // superfluous I think //audioCtrl.adcHighPassFilterDisable(); //audioCtrl.audioPreProcessorEnable(); // 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); speechCompressor.enable(); } //====================================================================== //====================================================================== void audioCalibrate(AudioConfig* c, char cmd, char subcmd, char parm, float value, bool set_value=true) { switch(cmd) { case 'r': case 'R': // RX audio parameters switch(subcmd) { case 'r': case 'R': // Rig input switch(parm) { case 'l': case 'L': // level if (set_value) { c->rxRigInLevel = int(value); updateRxRigIn(); } USBSERIAL.print("rxRigInLevel: "); USBSERIAL.println(c->rxRigInLevel); break; case 'v': case 'V': // volume if (set_value) { c->rxRigInVol = value; updateRxRigIn(); } USBSERIAL.print("rxRigInVol: "); USBSERIAL.println(c->rxRigInVol); break; case 'c': case 'C': // calibration if (set_value) { c->rxRigInCal = value; updateRxRigIn(); } USBSERIAL.print("rxRigInCal: "); USBSERIAL.println(c->rxRigInCal); break; } break; case 's': case 'S': // Speaker output switch(parm) { case 'c': case 'C': // calibration if (set_value) { c->rxSpkrOutCal = value; updateRxSpkrOut(); } USBSERIAL.print("rxSpkrOutCal: "); USBSERIAL.println(c->rxSpkrOutCal); break; } break; case 'l': case 'L': // Line output switch(parm) { case 'l': case 'L': // level if (set_value) { c->rxLineOutLevel = int(value); updateRxLineOut(); } USBSERIAL.print("rxLineOutLevel: "); USBSERIAL.println(c->rxLineOutLevel); break; case 'c': case 'C': // calibration if (set_value) { c->rxLineOutCal = value; updateRxLineOut(); } USBSERIAL.print("rxLineOutCal: "); USBSERIAL.println(c->rxLineOutCal); break; } break; case 'u': case 'U': // USB output switch(parm) { case 'c': case 'C': // calibration if (set_value) { c->rxUSBOutCal = value; updateRxUSBOut(); } USBSERIAL.print("rxUSBOutCal: "); USBSERIAL.println(c->rxUSBOutCal); break; } break; } break; case 't': case 'T': //TX audio parameters switch(subcmd) { case 'm': case 'M': // Mic input switch(parm) { case 'g': case 'G': // mic gain if (set_value) { c->txMicInGain = int(value); updateTxMicIn(); } USBSERIAL.print("txMicInGain: "); USBSERIAL.println(c->txMicInGain); break; case 'v': case 'V': // volume if (set_value) { c->txMicInVol = value; updateTxMicIn(); } USBSERIAL.print("txMicInVol: "); USBSERIAL.println(c->txMicInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txMicInCal = value; updateTxMicIn(); } USBSERIAL.print("txMicInCal: "); USBSERIAL.println(c->txMicInCal); break; } break; case 'l': case 'L': // Line input switch(parm) { case 'l': case 'L': // level if (set_value) { c->txLineInLevel = int(value); updateTxLineIn(); } USBSERIAL.print("txLineInLevel: "); USBSERIAL.println(c->txLineInLevel); break; case 'v': case 'V': // volume if (set_value) { c->txLineInVol = value; updateTxLineIn(); } USBSERIAL.print("txLineInVol: "); USBSERIAL.println(c->txLineInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txLineInCal = value; updateTxLineIn(); } USBSERIAL.print("txLineInCal: "); USBSERIAL.println(c->txLineInCal); break; } break; case 'u': case 'U': // USB input switch(parm) { case 'v': case 'V': // volume if (set_value) { c->txUSBInVol = value; updateTxUSBIn(); } USBSERIAL.print("txUSBInVol: "); USBSERIAL.println(c->txUSBInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txUSBInCal = value; updateTxUSBIn(); } USBSERIAL.print("txUSBInCal: "); USBSERIAL.println(c->txUSBInCal); break; } break; case 'r': case 'R': // Rig output switch(parm) { case 'l': case 'L': // level if (set_value) { c->txRigOutLevel = int(value); updateTxRigOut(); } USBSERIAL.print("txRigOutLevel: "); USBSERIAL.println(c->txRigOutLevel); break; case 'c': case 'C': // calibration if (set_value) { c->txRigOutCal = value; updateTxRigOut(); } USBSERIAL.print("txRigOutCal: "); USBSERIAL.println(c->txRigOutCal); break; } break; } break; } } int lpFilter[5]; int hpFilter[5]; void audioSSBFilter() { // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_LOPASS, 3300, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter); audioCtrl.eqFilter(0, lpFilter); audioCtrl.eqFilter(1, hpFilter); audioCtrl.eqFilter(2, lpFilter); audioCtrl.eqFilter(3, hpFilter); audioCtrl.eqFilter(4, lpFilter); audioCtrl.eqFilter(5, hpFilter); } void audioCWFilter() { // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_LOPASS, 1300, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter); audioCtrl.eqFilter(0, lpFilter); audioCtrl.eqFilter(1, hpFilter); audioCtrl.eqFilter(2, lpFilter); audioCtrl.eqFilter(3, hpFilter); audioCtrl.eqFilter(4, lpFilter); audioCtrl.eqFilter(5, hpFilter); } //====================================================================== // audioDigiFilter() // Create a very wide filter for digital modes... wider than the uBITX // needs, but just want to make sure we leave the full audio bandwidth // open for digimodes, while ensuring we've cut down any extraneous // noise outside the normal band. //====================================================================== void audioDigiFilter() { // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_LOPASS, 5000, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 0, 0.707, 524288, 44100, hpFilter); audioCtrl.eqFilter(0, lpFilter); audioCtrl.eqFilter(1, hpFilter); audioCtrl.eqFilter(2, lpFilter); audioCtrl.eqFilter(3, hpFilter); audioCtrl.eqFilter(4, lpFilter); audioCtrl.eqFilter(5, hpFilter); } */ 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 //======================================================================