| @@ -36,6 +36,9 @@ struct AudioInterface : Module, audio::Port { | |||
| NUM_LIGHTS | |||
| }; | |||
| dsp::RCFilter dcFilters[NUM_AUDIO_INPUTS]; | |||
| bool dcFilterEnabled = false; | |||
| dsp::DoubleRingBuffer<dsp::Frame<NUM_AUDIO_INPUTS>, 32768> engineInputBuffer; | |||
| dsp::DoubleRingBuffer<dsp::Frame<NUM_AUDIO_OUTPUTS>, 32768> engineOutputBuffer; | |||
| @@ -71,6 +74,13 @@ struct AudioInterface : Module, audio::Port { | |||
| maxChannels = std::max(NUM_AUDIO_INPUTS, NUM_AUDIO_OUTPUTS); | |||
| inputSrc.setQuality(6); | |||
| outputSrc.setQuality(6); | |||
| float sampleTime = APP->engine->getSampleTime(); | |||
| for (int i = 0; i < NUM_AUDIO_INPUTS; i++) { | |||
| dcFilters[i].setCutoffFreq(10.f * sampleTime); | |||
| } | |||
| reset(); | |||
| } | |||
| ~AudioInterface() { | |||
| @@ -80,11 +90,20 @@ struct AudioInterface : Module, audio::Port { | |||
| void onReset() override { | |||
| setDriverId(-1); | |||
| if (NUM_AUDIO_INPUTS == 2) | |||
| dcFilterEnabled = true; | |||
| else | |||
| dcFilterEnabled = false; | |||
| } | |||
| void onSampleRateChange(const SampleRateChangeEvent& e) override { | |||
| engineInputBuffer.clear(); | |||
| engineOutputBuffer.clear(); | |||
| for (int i = 0; i < NUM_AUDIO_INPUTS; i++) { | |||
| dcFilters[i].setCutoffFreq(10.f * e.sampleTime); | |||
| } | |||
| } | |||
| void process(const ProcessArgs& args) override { | |||
| @@ -102,6 +121,12 @@ struct AudioInterface : Module, audio::Port { | |||
| else if (i == 1 && NUM_AUDIO_INPUTS == 2) | |||
| v = inputFrame.samples[0]; | |||
| // Apply DC filter | |||
| if (dcFilterEnabled) { | |||
| dcFilters[i].process(v); | |||
| v = dcFilters[i].highpass(); | |||
| } | |||
| // Detect clipping | |||
| if (NUM_AUDIO_INPUTS > 2) { | |||
| if (std::fabs(v) >= 1.f) | |||
| @@ -195,6 +220,8 @@ struct AudioInterface : Module, audio::Port { | |||
| if (isPrimary()) | |||
| json_object_set_new(rootJ, "primary", json_boolean(true)); | |||
| json_object_set_new(rootJ, "dcFilter", json_boolean(dcFilterEnabled)); | |||
| return rootJ; | |||
| } | |||
| @@ -206,6 +233,10 @@ struct AudioInterface : Module, audio::Port { | |||
| json_t* primaryJ = json_object_get(rootJ, "primary"); | |||
| if (primaryJ) | |||
| setPrimary(); | |||
| json_t* dcFilterJ = json_object_get(rootJ, "dcFilter"); | |||
| if (dcFilterJ) | |||
| dcFilterEnabled = json_boolean_value(dcFilterJ); | |||
| } | |||
| /** Must be called when the Engine mutex is unlocked. | |||
| @@ -513,6 +544,19 @@ struct AudioInterfaceWidget : ModuleWidget { | |||
| primaryModuleItem->rightText = CHECKMARK(module->isPrimary()); | |||
| primaryModuleItem->module = module; | |||
| menu->addChild(primaryModuleItem); | |||
| struct DCFilterItem : MenuItem { | |||
| TAudioInterface* module; | |||
| void onAction(const event::Action& e) override { | |||
| module->dcFilterEnabled ^= true; | |||
| } | |||
| }; | |||
| DCFilterItem* dcFilterItem = new DCFilterItem; | |||
| dcFilterItem->text = "DC blocker"; | |||
| dcFilterItem->rightText = CHECKMARK(module->dcFilterEnabled); | |||
| dcFilterItem->module = module; | |||
| menu->addChild(dcFilterItem); | |||
| } | |||
| }; | |||