From 9bc72014b8c193c2e0b105aee86c55f051699db3 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Thu, 25 May 2023 13:59:17 -0400 Subject: [PATCH] gh-63: Also adds two pole output for Bob. --- libsignaletic/include/libsignaletic.h | 45 +++++++++++++++++---------- libsignaletic/src/libsignaletic.c | 41 +++++++++++++----------- 2 files changed, 50 insertions(+), 36 deletions(-) diff --git a/libsignaletic/include/libsignaletic.h b/libsignaletic/include/libsignaletic.h index 8b13545..4b275ef 100644 --- a/libsignaletic/include/libsignaletic.h +++ b/libsignaletic/include/libsignaletic.h @@ -1634,6 +1634,28 @@ struct sig_dsp_Filter_Inputs { }; +struct sig_dsp_FourPoleFilter_Outputs { + /** + * @brief The four pole 24 dB output from the filter. + */ + float_array_ptr main; + + /** + * @brief A two pole 12 dB output from the second stage of the filter. + */ + float_array_ptr twoPole; +}; + +void sig_dsp_FourPoleFilter_Outputs_newAudioBlocks( + struct sig_Allocator* allocator, + struct sig_AudioSettings* audioSettings, + struct sig_dsp_FourPoleFilter_Outputs* outputs); + +void sig_dsp_FourPoleFilter_Outputs_destroyAudioBlocks( + struct sig_Allocator* allocator, + struct sig_dsp_FourPoleFilter_Outputs* outputs); + + /** * @brief Miller Pucket's 24dB Moog-style ladder low pass filter. * Imitates a Moog resonant filter by Runge-Kutte numerical integration @@ -1664,7 +1686,7 @@ struct sig_dsp_BobLPF { struct sig_dsp_Signal signal; struct sig_dsp_Filter_Inputs inputs; // TODO: Add outputs for the other filter poles. - struct sig_dsp_Signal_SingleMonoOutput outputs; + struct sig_dsp_FourPoleFilter_Outputs outputs; float state[4]; float deriv1[4]; @@ -1690,32 +1712,21 @@ void sig_dsp_BobLPF_destroy(struct sig_Allocator* allocator, struct sig_dsp_BobLPF* self); + struct sig_dsp_LadderLPF_Parameters { /** * @brief The passband gain of the filter (best between 0.0-0.5), - * helps to offset the drop in low frequencies when resonance is high. + * higher values will amplify the lower frequencies when resonance is high. */ float passbandGain; /** - * @brief Gain prior to the filter, allowing for greater saturation levels. + * @brief Input gain applied prior to the filter, + * allowing for greater saturation levels (best between 0.0-4.0) */ float overdrive; }; -struct sig_dsp_LadderLPF_Outputs { - float_array_ptr main; - float_array_ptr twoPole; -}; - -void sig_dsp_LadderLPF_Outputs_newAudioBlocks( - struct sig_Allocator* allocator, - struct sig_AudioSettings* audioSettings, - struct sig_dsp_LadderLPF_Outputs* outputs); - -void sig_dsp_LadderLPF_Outputs_destroyAudioBlocks( - struct sig_Allocator* allocator, - struct sig_dsp_LadderLPF_Outputs* outputs); /** * @brief Valimaki and Huovilainen's Moog-style Ladder Filter * Ported from Infrasonic Audio LLC's adaptation of @@ -1732,7 +1743,7 @@ struct sig_dsp_LadderLPF { struct sig_dsp_Filter_Inputs inputs; struct sig_dsp_LadderLPF_Parameters parameters; // TODO: Add outputs for the other filter poles. - struct sig_dsp_LadderLPF_Outputs outputs; + struct sig_dsp_FourPoleFilter_Outputs outputs; uint8_t interpolation; float interpolationRecip; diff --git a/libsignaletic/src/libsignaletic.c b/libsignaletic/src/libsignaletic.c index ba47963..6af34e6 100644 --- a/libsignaletic/src/libsignaletic.c +++ b/libsignaletic/src/libsignaletic.c @@ -2213,12 +2213,28 @@ void sig_dsp_TwoOpFM_destroy(struct sig_Allocator* allocator, +void sig_dsp_FourPoleFilter_Outputs_newAudioBlocks( + struct sig_Allocator* allocator, + struct sig_AudioSettings* audioSettings, + struct sig_dsp_FourPoleFilter_Outputs* outputs) { + outputs->main = sig_AudioBlock_newSilent(allocator, audioSettings); + outputs->twoPole = sig_AudioBlock_newSilent(allocator, audioSettings); +} + +void sig_dsp_FourPoleFilter_Outputs_destroyAudioBlocks( + struct sig_Allocator* allocator, + struct sig_dsp_FourPoleFilter_Outputs* outputs) { + sig_AudioBlock_destroy(allocator, outputs->main); + sig_AudioBlock_destroy(allocator, outputs->twoPole); +} + + struct sig_dsp_BobLPF* sig_dsp_BobLPF_new(struct sig_Allocator* allocator, struct sig_SignalContext* context) { struct sig_dsp_BobLPF* self = sig_MALLOC(allocator, struct sig_dsp_BobLPF); sig_dsp_BobLPF_init(self, context); - sig_dsp_Signal_SingleMonoOutput_newAudioBlocks(allocator, + sig_dsp_FourPoleFilter_Outputs_newAudioBlocks(allocator, context->audioSettings, &self->outputs); return self; @@ -2327,6 +2343,7 @@ void sig_dsp_BobLPF_generate(void* signal) { for (size_t i = 0; i < self->signal.audioSettings->blockSize; i++) { float input = FLOAT_ARRAY(self->inputs.source)[i]; + // TODO: Should we account for oversampling here? float cutoff = sig_TWOPI * FLOAT_ARRAY(self->inputs.frequency)[i]; float resonance = FLOAT_ARRAY(self->inputs.resonance)[i]; resonance = resonance < 0.0f ? 0.0f : resonance; @@ -2336,38 +2353,24 @@ void sig_dsp_BobLPF_generate(void* signal) { } FLOAT_ARRAY(self->outputs.main)[i] = self->state[3]; + FLOAT_ARRAY(self->outputs.twoPole)[i] = self->state[1]; } } void sig_dsp_BobLPF_destroy(struct sig_Allocator* allocator, struct sig_dsp_BobLPF* self) { - sig_dsp_Signal_SingleMonoOutput_destroyAudioBlocks(allocator, + sig_dsp_FourPoleFilter_Outputs_destroyAudioBlocks(allocator, &self->outputs); sig_dsp_Signal_destroy(allocator, self); } -void sig_dsp_LadderLPF_Outputs_newAudioBlocks( - struct sig_Allocator* allocator, - struct sig_AudioSettings* audioSettings, - struct sig_dsp_LadderLPF_Outputs* outputs) { - outputs->main = sig_AudioBlock_newSilent(allocator, audioSettings); - outputs->twoPole = sig_AudioBlock_newSilent(allocator, audioSettings); -} - -void sig_dsp_LadderLPF_Outputs_destroyAudioBlocks( - struct sig_Allocator* allocator, - struct sig_dsp_LadderLPF_Outputs* outputs) { - sig_AudioBlock_destroy(allocator, outputs->main); - sig_AudioBlock_destroy(allocator, outputs->twoPole); -} - struct sig_dsp_LadderLPF* sig_dsp_LadderLPF_new( struct sig_Allocator* allocator, struct sig_SignalContext* context) { struct sig_dsp_LadderLPF* self = sig_MALLOC(allocator, struct sig_dsp_LadderLPF); sig_dsp_LadderLPF_init(self, context); - sig_dsp_LadderLPF_Outputs_newAudioBlocks(allocator, + sig_dsp_FourPoleFilter_Outputs_newAudioBlocks(allocator, context->audioSettings, &self->outputs); return self; @@ -2470,7 +2473,7 @@ void sig_dsp_LadderLPF_generate(void* signal) { void sig_dsp_LadderLPF_destroy(struct sig_Allocator* allocator, struct sig_dsp_LadderLPF* self) { - sig_dsp_LadderLPF_Outputs_destroyAudioBlocks(allocator, + sig_dsp_FourPoleFilter_Outputs_destroyAudioBlocks(allocator, &self->outputs); sig_dsp_Signal_destroy(allocator, self); }