Created
May 3, 2018 10:49
-
-
Save cstroie/1ffc7c938f4ed58f2edcf4b0e8fe575c to your computer and use it in GitHub Desktop.
Chebyshev 2025-2225Hz PBF (http://www.micromodeler.com/dsp/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************* SOURCE LICENSE ********************************* | |
Copyright (c) 2018 MicroModeler. | |
A non-exclusive, nontransferable, perpetual, royalty-free license is granted to the Licensee to | |
use the following Information for academic, non-profit, or government-sponsored research purposes. | |
Use of the following Information under this License is restricted to NON-COMMERCIAL PURPOSES ONLY. | |
Commercial use of the following Information requires a separately executed written license agreement. | |
This Information is distributed WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
******************************* END OF LICENSE *********************************/ | |
// A commercial license for MicroModeler DSP can be obtained at http://www.micromodeler.com/launch.jsp | |
#include "pbf.h" | |
#include <stdlib.h> // For malloc/free | |
#include <string.h> // For memset | |
signed char filter1_coefficients[10] = | |
{ | |
// Scaled for a 8x8:16 Direct form 2 IIR filter with: | |
// Output shift = 7 | |
// Input shift = 2 | |
// Central shift = 6 | |
// Input has a maximum value of 1, scaled by 2^7 | |
// Output has a maximum value of 2.340986885943709, scaled by 2^5 | |
34, -68, 34, 32, -60,// b0 Q9(0.0666), b1 Q9(-0.133), b2 Q9(0.0666), a1 Q6(0.500), a2 Q6(-0.943) | |
32, 64, 32, 14, -60// b0 Q9(0.0625), b1 Q9(0.125), b2 Q9(0.0625), a1 Q6(0.219), a2 Q6(-0.941) | |
}; | |
filter1Type *filter1_create( void ) | |
{ | |
filter1Type *result = (filter1Type *)malloc( sizeof( filter1Type ) ); // Allocate memory for the object | |
filter1_init( result ); // Initialize it | |
return result; // Return the result | |
} | |
void filter1_destroy( filter1Type *pObject ) | |
{ | |
free( pObject ); | |
} | |
void filter1_init( filter1Type * pThis ) | |
{ | |
filter1_reset( pThis ); | |
} | |
void filter1_reset( filter1Type * pThis ) | |
{ | |
memset( &pThis->state, 0, sizeof( pThis->state ) ); // Reset state to 0 | |
pThis->output = 0; // Reset output | |
} | |
int filter1_filterBlock( filter1Type * pThis, signed char * pInput, signed char * pOutput, unsigned int count ) | |
{ | |
filter1_executionState executionState; // The executionState structure holds call data, minimizing stack reads and writes | |
if( ! count ) return 0; // If there are no input samples, return immediately | |
executionState.pInput = pInput; // Pointers to the input and output buffers that each call to filterBiquad() will use | |
executionState.pOutput = pOutput; // - pInput and pOutput can be equal, allowing reuse of the same memory. | |
executionState.count = count; // The number of samples to be processed | |
executionState.pState = pThis->state; // Pointer to the biquad's internal state and coefficients. | |
executionState.pCoefficients = filter1_coefficients; // Each call to filterBiquad() will advance pState and pCoefficients to the next biquad | |
// The 1st call to filter1_filterBiquad() reads from the caller supplied input buffer and writes to the output buffer. | |
// The remaining calls to filterBiquad() recycle the same output buffer, so that multiple intermediate buffers are not required. | |
filter1_filterBiquad_2_6_7( &executionState ); // Run biquad #0 | |
executionState.pInput = executionState.pOutput; // The remaining biquads will now re-use the same output buffer. | |
filter1_filterBiquad_3_6_7( &executionState ); // Run biquad #1 | |
// At this point, the caller-supplied output buffer will contain the filtered samples and the input buffer will contain the unmodified input samples. | |
return count; // Return the number of samples processed, the same as the number of input samples | |
} | |
void filter1_filterBiquad_2_6_7( filter1_executionState * pExecState ) | |
{ | |
// Read state variables | |
signed char w0, x0; | |
signed char w1 = pExecState->pState[0]; | |
signed char w2 = pExecState->pState[1]; | |
// Read coefficients into work registers | |
signed char b0 = *(pExecState->pCoefficients++); | |
signed char b1 = *(pExecState->pCoefficients++); | |
signed char b2 = *(pExecState->pCoefficients++); | |
signed char a1 = *(pExecState->pCoefficients++); | |
signed char a2 = *(pExecState->pCoefficients++); | |
// Read source and target pointers | |
signed char *pInput = pExecState->pInput; | |
signed char *pOutput = pExecState->pOutput; | |
short count = pExecState->count; | |
short accumulator; | |
// Loop for all samples in the input buffer | |
while( count-- ) | |
{ | |
// Read input sample | |
x0 = *(pInput++); | |
// Run feedback part of filter | |
accumulator = (short)w2 * a2; | |
accumulator += (short)w1 * a1; | |
accumulator += (short)x0 << 2; | |
w0 = accumulator >> 6; | |
// Run feedforward part of filter | |
accumulator = (short)w0 * b0; | |
accumulator += (short)w1 * b1; | |
accumulator += (short)w2 * b2; | |
w2 = w1; // Shuffle history buffer | |
w1 = w0; | |
// Write output | |
*(pOutput++) = accumulator >> 7; | |
} | |
// Write state variables | |
*(pExecState->pState++) = w1; | |
*(pExecState->pState++) = w2; | |
} | |
void filter1_filterBiquad_3_6_7( filter1_executionState * pExecState ) | |
{ | |
// Read state variables | |
signed char w0, x0; | |
signed char w1 = pExecState->pState[0]; | |
signed char w2 = pExecState->pState[1]; | |
// Read coefficients into work registers | |
signed char b0 = *(pExecState->pCoefficients++); | |
signed char b1 = *(pExecState->pCoefficients++); | |
signed char b2 = *(pExecState->pCoefficients++); | |
signed char a1 = *(pExecState->pCoefficients++); | |
signed char a2 = *(pExecState->pCoefficients++); | |
// Read source and target pointers | |
signed char *pInput = pExecState->pInput; | |
signed char *pOutput = pExecState->pOutput; | |
short count = pExecState->count; | |
short accumulator; | |
// Loop for all samples in the input buffer | |
while( count-- ) | |
{ | |
// Read input sample | |
x0 = *(pInput++); | |
// Run feedback part of filter | |
accumulator = (short)w2 * a2; | |
accumulator += (short)w1 * a1; | |
accumulator += (short)x0 << 3; | |
w0 = accumulator >> 6; | |
// Run feedforward part of filter | |
accumulator = (short)w0 * b0; | |
accumulator += (short)w1 * b1; | |
accumulator += (short)w2 * b2; | |
w2 = w1; // Shuffle history buffer | |
w1 = w0; | |
// Write output | |
*(pOutput++) = accumulator >> 7; | |
} | |
// Write state variables | |
*(pExecState->pState++) = w1; | |
*(pExecState->pState++) = w2; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************* SOURCE LICENSE ********************************* | |
Copyright (c) 2018 MicroModeler. | |
A non-exclusive, nontransferable, perpetual, royalty-free license is granted to the Licensee to | |
use the following Information for academic, non-profit, or government-sponsored research purposes. | |
Use of the following Information under this License is restricted to NON-COMMERCIAL PURPOSES ONLY. | |
Commercial use of the following Information requires a separately executed written license agreement. | |
This Information is distributed WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
******************************* END OF LICENSE *********************************/ | |
// A commercial license for MicroModeler DSP can be obtained at http://www.micromodeler.com/launch.jsp | |
// Begin header file, pbf.h | |
#ifndef FILTER1_H_ // Include guards | |
#define FILTER1_H_ | |
static const int filter1_numStages = 2; | |
static const int filter1_coefficientLength = 10; | |
extern signed char filter1_coefficients[10]; | |
typedef struct | |
{ | |
signed char state[8]; | |
signed char output; | |
} filter1Type; | |
typedef struct | |
{ | |
signed char *pInput; | |
signed char *pOutput; | |
signed char *pState; | |
signed char *pCoefficients; | |
short count; | |
} filter1_executionState; | |
filter1Type *filter1_create( void ); | |
void filter1_destroy( filter1Type *pObject ); | |
void filter1_init( filter1Type * pThis ); | |
void filter1_reset( filter1Type * pThis ); | |
#define filter1_writeInput( pThis, input ) \ | |
filter1_filterBlock( pThis, &input, &pThis->output, 1 ); | |
#define filter1_readOutput( pThis ) \ | |
pThis->output | |
int filter1_filterBlock( filter1Type * pThis, signed char * pInput, signed char * pOutput, unsigned int count ); | |
#define filter1_outputToFloat( output ) \ | |
(( (1.0f/16) * (output) )) | |
#define filter1_inputFromFloat( input ) \ | |
((signed char)(128f * (input))) | |
void filter1_filterBiquad_2_6_7( filter1_executionState * pExecState ); | |
void filter1_filterBiquad_3_6_7( filter1_executionState * pExecState ); | |
#endif // FILTER1_H_ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment