You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.3 KiB
120 lines
3.3 KiB
/*
|
|
Calf Box, an open source musical instrument.
|
|
Copyright (C) 2010 Krzysztof Foltman
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef CBOX_ONEPOLE_INT_H
|
|
#define CBOX_ONEPOLE_INT_H
|
|
|
|
#include "dspmath.h"
|
|
|
|
struct cbox_onepole_state
|
|
{
|
|
int32_t x1;
|
|
int32_t y1;
|
|
};
|
|
|
|
struct cbox_onepole_coeffs
|
|
{
|
|
int32_t a0;
|
|
int32_t a1;
|
|
int32_t b1;
|
|
int shift;
|
|
};
|
|
|
|
static inline void cbox_onepole_reset(struct cbox_onepole_state *state)
|
|
{
|
|
state->x1 = state->y1 = 0;
|
|
}
|
|
|
|
static inline void cbox_onepole_set_lowpass(struct cbox_onepole_coeffs *coeffs, float w)
|
|
{
|
|
float x = tan (w);
|
|
float q = 1 / (1 + x);
|
|
float a01 = x*q;
|
|
float b1 = a01 - q;
|
|
int shift = 28;
|
|
float scaler = (1 << shift);
|
|
|
|
coeffs->a1 = coeffs->a0 = (int32_t)(a01 * scaler);
|
|
coeffs->b1 = (int32_t)(b1 * scaler);
|
|
coeffs->shift = shift;
|
|
}
|
|
|
|
static inline void cbox_onepole_set_highpass(struct cbox_onepole_coeffs *coeffs, float w)
|
|
{
|
|
float x = tan (w);
|
|
float q = 1 / (1 + x);
|
|
float a01 = x*q;
|
|
float b1 = a01 - q;
|
|
int shift = 28;
|
|
float scaler = (1 << shift)-1;
|
|
|
|
coeffs->a0 = (int32_t)(a01 * scaler);
|
|
coeffs->a1 = -coeffs->a0;
|
|
coeffs->b1 = (int32_t)(b1 * scaler);
|
|
coeffs->shift = shift;
|
|
}
|
|
|
|
static inline void cbox_onepole_process(struct cbox_onepole_state *state, struct cbox_onepole_coeffs *coeffs, int32_t *buffer)
|
|
{
|
|
int i;
|
|
int64_t a0 = coeffs->a0;
|
|
int64_t a1 = coeffs->a1;
|
|
int64_t b1 = coeffs->b1;
|
|
int shift = coeffs->shift;
|
|
int64_t maxint = ((int64_t)0x7FFFFFF) << shift;
|
|
int32_t round = 1 << (shift - 1);
|
|
|
|
for (i = 0; i < CBOX_BLOCK_SIZE; i++)
|
|
{
|
|
int32_t in = buffer[i];
|
|
int64_t v = a0 * in + a1 * state->x1 - b1 * state->y1 + round;
|
|
int32_t out = (llabs(v) >= maxint) ? (v > 0 ? 0x7FFFFFFF : -0x7FFFFFFF) : (v >> shift);
|
|
|
|
buffer[i] = out;
|
|
state->x1 = in;
|
|
state->y1 = out;
|
|
}
|
|
if (state->y1 > 0 && state->y1 < round)
|
|
state->y1--;
|
|
if (state->y1 < 0 && state->y1 > -round)
|
|
state->y1++;
|
|
}
|
|
|
|
static inline void cbox_onepole_process_to(struct cbox_onepole_state *state, struct cbox_onepole_coeffs *coeffs, int32_t *buffer_in, int32_t *buffer_out)
|
|
{
|
|
int i;
|
|
int64_t a0 = coeffs->a0;
|
|
int64_t a1 = coeffs->a1;
|
|
int64_t b1 = coeffs->b1;
|
|
int shift = coeffs->shift;
|
|
int64_t maxint = ((int64_t)0x7FFFFFF) << shift;
|
|
int64_t round = 1 << (shift - 1);
|
|
|
|
for (i = 0; i < CBOX_BLOCK_SIZE; i++)
|
|
{
|
|
int32_t in = buffer_in[i];
|
|
int64_t v = a0 * in + a1 * state->x1 - b1 * state->y1 + round;
|
|
int32_t out = (llabs(v) >= maxint) ? (v > 0 ? 0x7FFFFFFF : -0x7FFFFFFF) : (v >> shift);
|
|
|
|
buffer_out[i] = out;
|
|
state->x1 = in;
|
|
state->y1 = out;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|