parent
81492cc5ac
commit
52e646ace1
@ -0,0 +1,159 @@ |
|||||||
|
/* Audio Library for Teensy 3.X
|
||||||
|
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com |
||||||
|
* Copyright (c) 2018, Paul Geisler |
||||||
|
* |
||||||
|
* Development of this audio library was funded by PJRC.COM, LLC by sales of |
||||||
|
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop |
||||||
|
* open source software by purchasing Teensy or other PJRC products. |
||||||
|
* |
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
* of this software and associated documentation files (the "Software"), to deal |
||||||
|
* in the Software without restriction, including without limitation the rights |
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
* copies of the Software, and to permit persons to whom the Software is |
||||||
|
* furnished to do so, subject to the following conditions: |
||||||
|
* |
||||||
|
* The above copyright notice, development funding notice, and this permission |
||||||
|
* notice shall be included in all copies or substantial portions of the Software. |
||||||
|
* |
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||||
|
* THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "filter_variable_f32.h" |
||||||
|
#include <AudioStream_F32.h> |
||||||
|
#include <math.h> |
||||||
|
|
||||||
|
#if defined(KINETISK) |
||||||
|
|
||||||
|
__inline__ float clamp(float x, float m) |
||||||
|
{ |
||||||
|
return min(m,max(-m,x)); |
||||||
|
} |
||||||
|
|
||||||
|
void AudioFilterStateVariable_F32::update_variable(const float *in, |
||||||
|
const float *ctl, float *lp, float *bp, float *hp) |
||||||
|
{ |
||||||
|
const float *end = in + AUDIO_BLOCK_SAMPLES; |
||||||
|
float input, inputprev; |
||||||
|
float lowpass, bandpass, highpass; |
||||||
|
float lowpasstmp, bandpasstmp, highpasstmp; |
||||||
|
float fcenter, fmult, damp, octavemult; |
||||||
|
|
||||||
|
fcenter = setting_fcenter; |
||||||
|
octavemult = setting_octavemult; |
||||||
|
damp = setting_damp; |
||||||
|
inputprev = state_inputprev; |
||||||
|
lowpass = state_lowpass; |
||||||
|
bandpass = state_bandpass; |
||||||
|
int i=0; |
||||||
|
// compute fmult using control input, fcenter and octavemult
|
||||||
|
// fmult is linearly interpolated across AUDIO_BLOCK_SAMPLES.
|
||||||
|
// as an exp2f call is not feasable for every single sample,
|
||||||
|
// it consumes too much CPU cycles on Teensy 3.5 to allow for multiple filters.
|
||||||
|
float fmult0=clamp(ctl ? exp2f(octavemult * ctl[0 ])*fcenter : fcenter, 0.8f); |
||||||
|
float fmult1=clamp(ctl ? exp2f(octavemult * ctl[AUDIO_BLOCK_SAMPLES-1])*fcenter : fcenter, 0.8f); |
||||||
|
do { |
||||||
|
float t=((float)i++)/AUDIO_BLOCK_SAMPLES; |
||||||
|
fmult=(1.f-t)*fmult0 + t*fmult1; |
||||||
|
|
||||||
|
input = *in++; |
||||||
|
lowpass = lowpass + fmult * bandpass; |
||||||
|
highpass = (input + inputprev)/2.f - lowpass - damp * bandpass; |
||||||
|
inputprev = input; |
||||||
|
bandpass = bandpass + (fmult * highpass); |
||||||
|
lowpasstmp = lowpass; |
||||||
|
bandpasstmp = bandpass; |
||||||
|
highpasstmp = highpass; |
||||||
|
lowpass = lowpass + fmult * bandpass; |
||||||
|
highpass = input - lowpass - damp * bandpass; |
||||||
|
bandpass = bandpass + fmult * highpass; |
||||||
|
|
||||||
|
lowpass= clamp(lowpass ,setting_limit); |
||||||
|
bandpass=clamp(bandpass,setting_limit); |
||||||
|
highpass=clamp(highpass,setting_limit); |
||||||
|
|
||||||
|
lowpasstmp = (lowpass+lowpasstmp) /2.f; |
||||||
|
bandpasstmp = (bandpass+bandpasstmp)/2.f; |
||||||
|
highpasstmp = (highpass+highpasstmp)/2.f; |
||||||
|
|
||||||
|
*lp++ = lowpasstmp; |
||||||
|
*bp++ = bandpasstmp; |
||||||
|
*hp++ = highpasstmp; |
||||||
|
} while (in < end); |
||||||
|
|
||||||
|
state_inputprev = inputprev; |
||||||
|
state_lowpass = lowpass; |
||||||
|
state_bandpass = bandpass; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void AudioFilterStateVariable_F32::update(void) |
||||||
|
{ |
||||||
|
audio_block_f32_t *input_block=NULL, *control_block=NULL; |
||||||
|
audio_block_f32_t *lowpass_block=NULL, *bandpass_block=NULL, *highpass_block=NULL; |
||||||
|
|
||||||
|
input_block = receiveReadOnly_f32(0); |
||||||
|
control_block = receiveReadOnly_f32(1); |
||||||
|
if (!input_block) { |
||||||
|
if (control_block) AudioStream_F32::release(control_block); |
||||||
|
return; |
||||||
|
} |
||||||
|
lowpass_block = allocate_f32(); |
||||||
|
if (!lowpass_block) { |
||||||
|
AudioStream_F32::release(input_block); |
||||||
|
if (control_block) AudioStream_F32::release(control_block); |
||||||
|
return; |
||||||
|
} |
||||||
|
bandpass_block = allocate_f32(); |
||||||
|
if (!bandpass_block) { |
||||||
|
AudioStream_F32::release(input_block); |
||||||
|
AudioStream_F32::release(lowpass_block); |
||||||
|
if (control_block) AudioStream_F32::release(control_block); |
||||||
|
return; |
||||||
|
} |
||||||
|
highpass_block = allocate_f32(); |
||||||
|
if (!highpass_block) { |
||||||
|
AudioStream_F32::release(input_block); |
||||||
|
AudioStream_F32::release(lowpass_block); |
||||||
|
AudioStream_F32::release(bandpass_block); |
||||||
|
if (control_block) release(control_block); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
update_variable(input_block->data, |
||||||
|
control_block ? control_block->data : NULL,
|
||||||
|
lowpass_block->data, |
||||||
|
bandpass_block->data, |
||||||
|
highpass_block->data); |
||||||
|
AudioStream_F32::release(control_block); |
||||||
|
|
||||||
|
AudioStream_F32::release(input_block); |
||||||
|
AudioStream_F32::transmit(lowpass_block, 0); |
||||||
|
AudioStream_F32::release(lowpass_block); |
||||||
|
AudioStream_F32::transmit(bandpass_block, 1); |
||||||
|
AudioStream_F32::release(bandpass_block); |
||||||
|
AudioStream_F32::transmit(highpass_block, 2); |
||||||
|
AudioStream_F32::release(highpass_block); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
#elif defined(KINETISL) |
||||||
|
|
||||||
|
void AudioFilterStateVariable_F32::update(void) |
||||||
|
{ |
||||||
|
audio_block_f32_t *block; |
||||||
|
|
||||||
|
block = receiveReadOnly_f32(0); |
||||||
|
if (block) release(block); |
||||||
|
block = receiveReadOnly_f32(1); |
||||||
|
if (block) release(block); |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,85 @@ |
|||||||
|
/* Audio Library for Teensy 3.X
|
||||||
|
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com |
||||||
|
* |
||||||
|
* Development of this audio library was funded by PJRC.COM, LLC by sales of |
||||||
|
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop |
||||||
|
* open source software by purchasing Teensy or other PJRC products. |
||||||
|
* |
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
* of this software and associated documentation files (the "Software"), to deal |
||||||
|
* in the Software without restriction, including without limitation the rights |
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
* copies of the Software, and to permit persons to whom the Software is |
||||||
|
* furnished to do so, subject to the following conditions: |
||||||
|
* |
||||||
|
* The above copyright notice, development funding notice, and this permission |
||||||
|
* notice shall be included in all copies or substantial portions of the Software. |
||||||
|
* |
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||||
|
* THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef filter_variable_f32_h_ |
||||||
|
#define filter_variable_f32_h_ |
||||||
|
|
||||||
|
#include "Arduino.h" |
||||||
|
#include "AudioStream_F32.h" |
||||||
|
|
||||||
|
class AudioFilterStateVariable_F32: public AudioStream_F32 |
||||||
|
{ |
||||||
|
public: |
||||||
|
AudioFilterStateVariable_F32() : AudioStream_F32(2, inputQueueArray) { |
||||||
|
frequency(1000); |
||||||
|
octaveControl(1.0); // default values
|
||||||
|
resonance(0.707); |
||||||
|
limit(5.f); |
||||||
|
state_inputprev = 0; |
||||||
|
state_lowpass = 0; |
||||||
|
state_bandpass = 0; |
||||||
|
} |
||||||
|
void frequency(float freq) { |
||||||
|
if (freq < 20.0) freq = 20.0; |
||||||
|
else if (freq > AUDIO_SAMPLE_RATE_EXACT/2.5) freq = AUDIO_SAMPLE_RATE_EXACT/2.5; |
||||||
|
setting_fcenter = (freq * (3.141592654/(AUDIO_SAMPLE_RATE_EXACT*2.0))); |
||||||
|
} |
||||||
|
void resonance(float q) { |
||||||
|
if (q < 0.5) q = 0.5; |
||||||
|
else if (q > 5.0) q = 5.0; |
||||||
|
// TODO: allow lower Q when frequency is lower
|
||||||
|
setting_damp = (1.0 / q); |
||||||
|
} |
||||||
|
void octaveControl(float n) { |
||||||
|
// filter's corner frequency is Fcenter * 2^(control * N)
|
||||||
|
// where "control" ranges from -1.0 to +1.0
|
||||||
|
// and "N" allows the frequency to change from 0 to 7 octaves
|
||||||
|
if (n < 0.0) n = 0.0; |
||||||
|
else if (n > 6.9999) n = 6.9999; |
||||||
|
setting_octavemult = n; |
||||||
|
} |
||||||
|
|
||||||
|
void limit(float l) |
||||||
|
{ |
||||||
|
if(l<0.f) l=0.f; |
||||||
|
setting_limit=l; |
||||||
|
} |
||||||
|
|
||||||
|
virtual void update(void); |
||||||
|
private: |
||||||
|
void update_variable(const float *in, const float *ctl, |
||||||
|
float *lp, float *bp, float *hp); |
||||||
|
float setting_fcenter; |
||||||
|
float setting_octavemult; |
||||||
|
float setting_damp; |
||||||
|
float setting_limit; |
||||||
|
float state_inputprev; |
||||||
|
float state_lowpass; |
||||||
|
float state_bandpass; |
||||||
|
audio_block_f32_t *inputQueueArray[2]; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue