q3.28 changes
This commit is contained in:
parent
009dd2e698
commit
481219341d
|
@ -73,12 +73,12 @@ void bqf_lowpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficient
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,12 +123,12 @@ void bqf_highpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficien
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,12 +168,12 @@ void bqf_bandpass_skirt_config(double fs, double f0, double Q, bqf_coeff_t *coef
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,12 +213,12 @@ void bqf_bandpass_peak_config(double fs, double f0, double Q, bqf_coeff_t *coeff
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,12 +257,12 @@ void bqf_notch_config(double fs, double f0, double Q, bqf_coeff_t *coefficients)
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -300,12 +300,12 @@ void bqf_allpass_config(double fs, double f0, double Q, bqf_coeff_t *coefficient
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,12 +353,12 @@ void bqf_peaking_config(double fs, double f0, double dBgain, double Q,
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -406,12 +406,12 @@ void bqf_lowshelf_config(double fs, double f0, double dBgain, double Q,
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -459,16 +459,16 @@ void bqf_highshelf_config(double fs, double f0, double dBgain, double Q,
|
||||||
a2 = a2 / a0;
|
a2 = a2 / a0;
|
||||||
a0 = 1.0;
|
a0 = 1.0;
|
||||||
|
|
||||||
coefficients->b0 = fix16_from_dbl(b0);
|
coefficients->b0 = fix3_28_from_dbl(b0);
|
||||||
coefficients->b1 = fix16_from_dbl(b1);
|
coefficients->b1 = fix3_28_from_dbl(b1);
|
||||||
coefficients->b2 = fix16_from_dbl(b2);
|
coefficients->b2 = fix3_28_from_dbl(b2);
|
||||||
coefficients->a0 = fix16_from_dbl(a0);
|
coefficients->a0 = fix3_28_from_dbl(a0);
|
||||||
coefficients->a1 = fix16_from_dbl(a1);
|
coefficients->a1 = fix3_28_from_dbl(a1);
|
||||||
coefficients->a2 = fix16_from_dbl(a2);
|
coefficients->a2 = fix3_28_from_dbl(a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fix16_t bqf_transform(fix16_t x, bqf_coeff_t *coefficients, bqf_mem_t *memory) {
|
fix3_28_t bqf_transform(fix3_28_t x, bqf_coeff_t *coefficients, bqf_mem_t *memory) {
|
||||||
fix16_t y = fix16_mul(coefficients->b0, x) -
|
fix3_28_t y = fix16_mul(coefficients->b0, x) -
|
||||||
fix16_mul(coefficients->a1, memory->y_1) +
|
fix16_mul(coefficients->a1, memory->y_1) +
|
||||||
fix16_mul(coefficients->b1, memory->x_1) -
|
fix16_mul(coefficients->b1, memory->x_1) -
|
||||||
fix16_mul(coefficients->a2, memory->y_2) +
|
fix16_mul(coefficients->a2, memory->y_2) +
|
||||||
|
|
|
@ -26,19 +26,19 @@
|
||||||
#include "fix16.h"
|
#include "fix16.h"
|
||||||
|
|
||||||
typedef struct _bqf_coeff_t {
|
typedef struct _bqf_coeff_t {
|
||||||
fix16_t a0;
|
fix3_28_t a0;
|
||||||
fix16_t a1;
|
fix3_28_t a1;
|
||||||
fix16_t a2;
|
fix3_28_t a2;
|
||||||
fix16_t b0;
|
fix3_28_t b0;
|
||||||
fix16_t b1;
|
fix3_28_t b1;
|
||||||
fix16_t b2;
|
fix3_28_t b2;
|
||||||
} bqf_coeff_t;
|
} bqf_coeff_t;
|
||||||
|
|
||||||
typedef struct _bqf_mem_t {
|
typedef struct _bqf_mem_t {
|
||||||
fix16_t x_1;
|
fix3_28_t x_1;
|
||||||
fix16_t x_2;
|
fix3_28_t x_2;
|
||||||
fix16_t y_1;
|
fix3_28_t y_1;
|
||||||
fix16_t y_2;
|
fix3_28_t y_2;
|
||||||
} bqf_mem_t;
|
} bqf_mem_t;
|
||||||
|
|
||||||
// In reality we do not have enough CPU resource to run 8 filtering
|
// In reality we do not have enough CPU resource to run 8 filtering
|
||||||
|
@ -65,7 +65,7 @@ void bqf_peaking_config(double, double, double, double, bqf_coeff_t *);
|
||||||
void bqf_lowshelf_config(double, double, double, double, bqf_coeff_t *);
|
void bqf_lowshelf_config(double, double, double, double, bqf_coeff_t *);
|
||||||
void bqf_highshelf_config(double, double, double, double, bqf_coeff_t *);
|
void bqf_highshelf_config(double, double, double, double, bqf_coeff_t *);
|
||||||
|
|
||||||
fix16_t bqf_transform(fix16_t, bqf_coeff_t *, bqf_mem_t *);
|
fix3_28_t bqf_transform(fix3_28_t, bqf_coeff_t *, bqf_mem_t *);
|
||||||
void bqf_memreset(bqf_mem_t *);
|
void bqf_memreset(bqf_mem_t *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -179,12 +179,12 @@ void apply_filter_configuration(filter_configuration_tlv *filters) {
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i];
|
for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i];
|
||||||
if (checksum != bqf_filter_checksum[filter_stages]) {
|
if (checksum != bqf_filter_checksum[filter_stages]) {
|
||||||
bqf_filters_left[filter_stages].a0 = fix16_from_dbl(1.0);
|
bqf_filters_left[filter_stages].a0 = fix3_28_from_dbl(1.0);
|
||||||
bqf_filters_left[filter_stages].a1 = fix16_from_dbl(args->a1/args->a0);
|
bqf_filters_left[filter_stages].a1 = fix3_28_from_dbl(args->a1/args->a0);
|
||||||
bqf_filters_left[filter_stages].a2 = fix16_from_dbl(args->a2/args->a0);
|
bqf_filters_left[filter_stages].a2 = fix3_28_from_dbl(args->a2/args->a0);
|
||||||
bqf_filters_left[filter_stages].b0 = fix16_from_dbl(args->b0/args->a0);
|
bqf_filters_left[filter_stages].b0 = fix3_28_from_dbl(args->b0/args->a0);
|
||||||
bqf_filters_left[filter_stages].b1 = fix16_from_dbl(args->b1/args->a0);
|
bqf_filters_left[filter_stages].b1 = fix3_28_from_dbl(args->b1/args->a0);
|
||||||
bqf_filters_left[filter_stages].b2 = fix16_from_dbl(args->b2/args->a0);
|
bqf_filters_left[filter_stages].b2 = fix3_28_from_dbl(args->b2/args->a0);
|
||||||
memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t));
|
memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t));
|
||||||
bqf_filter_checksum[filter_stages] = checksum;
|
bqf_filter_checksum[filter_stages] = checksum;
|
||||||
}
|
}
|
||||||
|
@ -198,8 +198,8 @@ void apply_filter_configuration(filter_configuration_tlv *filters) {
|
||||||
if (type_changed) {
|
if (type_changed) {
|
||||||
// The memory structure stores the last 2 input samples, we can replay them into
|
// The memory structure stores the last 2 input samples, we can replay them into
|
||||||
// the new filter rather than starting again from scratch.
|
// the new filter rather than starting again from scratch.
|
||||||
fix16_t left[2] = { bqf_filters_mem_left[filter_stages].x_2, bqf_filters_mem_left[filter_stages].x_1 };
|
fix3_28_t left[2] = { bqf_filters_mem_left[filter_stages].x_2, bqf_filters_mem_left[filter_stages].x_1 };
|
||||||
fix16_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 };
|
fix3_28_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 };
|
||||||
|
|
||||||
bqf_memreset(&bqf_filters_mem_left[filter_stages]);
|
bqf_memreset(&bqf_filters_mem_left[filter_stages]);
|
||||||
bqf_memreset(&bqf_filters_mem_right[filter_stages]);
|
bqf_memreset(&bqf_filters_mem_right[filter_stages]);
|
||||||
|
@ -305,7 +305,7 @@ bool apply_configuration(tlv_header *config) {
|
||||||
#ifndef TEST_TARGET
|
#ifndef TEST_TARGET
|
||||||
case PREPROCESSING_CONFIGURATION: {
|
case PREPROCESSING_CONFIGURATION: {
|
||||||
preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv;
|
preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv;
|
||||||
preprocessing.preamp = fix16_from_dbl(1.0 + preprocessing_config->preamp);
|
preprocessing.preamp = fix3_28_from_dbl(1.0 + preprocessing_config->preamp);
|
||||||
preprocessing.reverse_stereo = preprocessing_config->reverse_stereo;
|
preprocessing.reverse_stereo = preprocessing_config->reverse_stereo;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -546,4 +546,4 @@ void apply_config_changes() {
|
||||||
apply_configuration((tlv_header*) working_configuration[active_configuration]);
|
apply_configuration((tlv_header*) working_configuration[active_configuration]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,17 +60,36 @@ fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) {
|
||||||
return inArg0 * inArg1;
|
return inArg0 * inArg1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fix16_t fix16_from_s16sample(int16_t a) {
|
|
||||||
return a * fix16_lsb;
|
/// @brief Produces a fixed point number from a 16-bit signed integer, normalized to ]-1,1[.
|
||||||
|
/// @param a Signed 16-bit integer.
|
||||||
|
/// @return A fixed point number in Q3.28 format, with input normalized to ]-1,1[.
|
||||||
|
fix3_28_t norm_fix3_28_from_s16sample(int16_t a) {
|
||||||
|
/* So, we're using a Q3.28 fixed point system here, and we want the incoming
|
||||||
|
audio signal to be represented as a number between -1 and 1. To do this,
|
||||||
|
we need the 16-bit value to map to the 28-bit right-of-decimal field in
|
||||||
|
our fixed point number. 28-16 = 12, so we shift the incoming value by
|
||||||
|
that much to covert it to the desired Q3.28 format and do the normalization
|
||||||
|
all in one go.
|
||||||
|
*/
|
||||||
|
return (fix3_28_t)a << 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t fix16_to_s16sample(fix16_t a) {
|
/// @brief Convert fixed point samples into signed integer. Used to convert
|
||||||
|
/// calculated sample to one that the DAC can understand.
|
||||||
|
/// @param a
|
||||||
|
/// @return Signed 16-bit integer.
|
||||||
|
int16_t norm_fix3_28_to_s16sample(fix3_28_t a) {
|
||||||
// Handle rounding up front, adding one can cause an overflow/underflow
|
// Handle rounding up front, adding one can cause an overflow/underflow
|
||||||
|
|
||||||
|
// It's not clear exactly how this works, so we'll disable it for now.
|
||||||
|
/*
|
||||||
if (a < 0) {
|
if (a < 0) {
|
||||||
a -= (fix16_lsb >> 1);
|
a -= (fix16_lsb >> 1);
|
||||||
} else {
|
} else {
|
||||||
a += (fix16_lsb >> 1);
|
a += (fix16_lsb >> 1);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Saturate the value if an overflow has occurred
|
// Saturate the value if an overflow has occurred
|
||||||
uint32_t upper = (a >> 30);
|
uint32_t upper = (a >> 30);
|
||||||
|
@ -85,25 +104,31 @@ int16_t fix16_to_s16sample(fix16_t a) {
|
||||||
return SHRT_MAX;
|
return SHRT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (a >> 15);
|
/* When we converted the USB audio sample to a fixed point number, we applied
|
||||||
|
a normalization, or a gain of 1/65536. To convert it back, we can undo that
|
||||||
|
by shifting it back by the same amount we shifted it in the first place. */
|
||||||
|
return (a >> 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
fix16_t fix16_from_dbl(double a) {
|
|
||||||
|
fix3_28_t fix3_28_from_dbl(double a) {
|
||||||
double temp = a * fix16_one;
|
double temp = a * fix16_one;
|
||||||
temp += (double)((temp >= 0) ? 0.5f : -0.5f);
|
temp += (double)((temp >= 0) ? 0.5f : -0.5f);
|
||||||
return (fix16_t)temp;
|
return (fix3_28_t)temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
double fix16_to_dbl(fix16_t a) {
|
/// @brief Multiplies two fixed point numbers in Q3.28 format together.
|
||||||
return (double)a / fix16_one;
|
/// @param inArg0 Q3.28 format fixed point number.
|
||||||
}
|
/// @param inArg1 Q3.28 format fixed point number.
|
||||||
|
/// @return A Q3.28 fixed point number that represents the truncated result of inArg0 x inArg1.
|
||||||
// We work in 64bits then shift the result to get
|
fix3_28_t fix16_mul(fix3_28_t inArg0, fix3_28_t inArg1) {
|
||||||
// the bit representing 1 back into the correct position.
|
|
||||||
// i.e. 1*1 == 1, so 20000000^2 >> 25 = 20000000
|
|
||||||
fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) {
|
|
||||||
const int64_t product = (int64_t)inArg0 * inArg1;
|
const int64_t product = (int64_t)inArg0 * inArg1;
|
||||||
fix16_t result = product >> 25;
|
|
||||||
|
/* Since we're expecting 2 Q3.28 numbers, the multiplication result should be a Q7.56 number.
|
||||||
|
To bring this number back to the right order of magnitude, we need to shift
|
||||||
|
it to the right by 28. */
|
||||||
|
fix3_28_t result = product >> 28;
|
||||||
|
|
||||||
// Handle rounding where we are choppping off low order bits
|
// Handle rounding where we are choppping off low order bits
|
||||||
// Disabled for now, too much load. We get crackling when adjusting
|
// Disabled for now, too much load. We get crackling when adjusting
|
||||||
// the volume.
|
// the volume.
|
||||||
|
|
|
@ -32,24 +32,29 @@ typedef double fix16_t;
|
||||||
static const fix16_t fix16_zero = 0;
|
static const fix16_t fix16_zero = 0;
|
||||||
static const fix16_t fix16_one = 1;
|
static const fix16_t fix16_one = 1;
|
||||||
#else
|
#else
|
||||||
// We normalize all values into the range -32..32 with 1 extra bit for overflows
|
|
||||||
// and one bit for the sign. We allow fixed point values to overflow, but they
|
/// @brief Fixed point math type, in format Q3.28. One sign bit, 3 bits for left-of-decimal
|
||||||
// are clipped at the point they are written back to a s16sample.
|
///and 28 for right-of-decimal. This arrangment works because we normalize the incoming USB
|
||||||
//
|
///audio data to ]-1,1[ before operating on it, to push as much of the precision in the signal
|
||||||
// The reason for normalizing the samples is because the filter coefficients are
|
///to the right of the decimal as possible.
|
||||||
// small (usually well within in the range -32..32), by normalizing everything the coefficients
|
typedef int32_t fix3_28_t;
|
||||||
// get lots of additional bits of precision.
|
|
||||||
typedef int32_t fix16_t;
|
/// @brief Represents the number 1 in Q3.28. There are 3 bits and a sign bit to the left of the
|
||||||
static const fix16_t fix16_lsb = 0x8000;
|
///decimal, so 1.0000 would be represented as 0b 0001 followed by 28 zeros.
|
||||||
static const fix16_t fix16_one = 0x002000000;
|
static const fix3_28_t fix16_one = 0x10000000;
|
||||||
static const fix16_t fix16_zero = 0x00000000;
|
|
||||||
|
/// @brief Represents zero in fixed point world.
|
||||||
|
static const fix3_28_t fix16_zero = 0x00000000;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fix16_t fix16_from_s16sample(int16_t);
|
|
||||||
int16_t fix16_to_s16sample(fix16_t);
|
|
||||||
fix16_t fix16_from_dbl(double);
|
|
||||||
double fix16_to_dbl(fix16_t);
|
|
||||||
|
|
||||||
fix16_t fix16_mul(fix16_t, fix16_t);
|
fix3_28_t norm_fix3_28_from_s16sample(int16_t);
|
||||||
|
|
||||||
|
int16_t norm_fix3_28_to_s16sample(fix3_28_t);
|
||||||
|
|
||||||
|
fix3_28_t fix3_28_from_dbl(double);
|
||||||
|
|
||||||
|
fix3_28_t fix16_mul(fix3_28_t, fix3_28_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -143,12 +143,12 @@ static void _as_audio_packet(struct usb_endpoint *ep) {
|
||||||
for (int j = 0; j < filter_stages; j++) {
|
for (int j = 0; j < filter_stages; j++) {
|
||||||
// Left channel filter
|
// Left channel filter
|
||||||
for (int i = 0; i < samples; i += 2) {
|
for (int i = 0; i < samples; i += 2) {
|
||||||
fix16_t x_f16 = fix16_mul(fix16_from_s16sample((int16_t) out[i]), preprocessing.preamp);
|
fix3_28_t x_f16 = fix16_mul(norm_fix3_28_from_s16sample((int16_t) out[i]), preprocessing.preamp);
|
||||||
|
|
||||||
x_f16 = bqf_transform(x_f16, &bqf_filters_left[j],
|
x_f16 = bqf_transform(x_f16, &bqf_filters_left[j],
|
||||||
&bqf_filters_mem_left[j]);
|
&bqf_filters_mem_left[j]);
|
||||||
|
|
||||||
out[i] = (int32_t) fix16_to_s16sample(x_f16);
|
out[i] = (int32_t) norm_fix3_28_to_s16sample(x_f16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +189,12 @@ void core1_entry() {
|
||||||
|
|
||||||
for (int j = 0; j < filter_stages; j++) {
|
for (int j = 0; j < filter_stages; j++) {
|
||||||
for (int i = 1; i < samples; i += 2) {
|
for (int i = 1; i < samples; i += 2) {
|
||||||
fix16_t x_f16 = fix16_mul(fix16_from_s16sample((int16_t) out[i]), preprocessing.preamp);
|
fix3_28_t x_f16 = fix16_mul(norm_fix3_28_from_s16sample((int16_t) out[i]), preprocessing.preamp);
|
||||||
|
|
||||||
x_f16 = bqf_transform(x_f16, &bqf_filters_right[j],
|
x_f16 = bqf_transform(x_f16, &bqf_filters_right[j],
|
||||||
&bqf_filters_mem_right[j]);
|
&bqf_filters_mem_right[j]);
|
||||||
|
|
||||||
out[i] = (int16_t) fix16_to_s16sample(x_f16);
|
out[i] = (int16_t) norm_fix3_28_to_s16sample(x_f16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,8 +773,8 @@ static bool do_set_current(struct usb_setup_packet *setup) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tf_send_control_in_ack(__unused struct usb_endpoint *endpoint, __unused struct usb_transfer *transfer) {
|
static void _tf_send_control_in_ack(__unused struct usb_endpoint *endpoint, __unused struct usb_transfer *transfer) {
|
||||||
assert(endpoint == &usb_control_in);
|
//assert(endpoint == &usb_control_in);
|
||||||
assert(transfer == &_control_in_transfer);
|
//assert(transfer == &_control_in_transfer);
|
||||||
usb_debug("_tf_setup_control_ack\n");
|
usb_debug("_tf_setup_control_ack\n");
|
||||||
static struct usb_transfer _control_out_transfer;
|
static struct usb_transfer _control_out_transfer;
|
||||||
usb_start_empty_transfer(usb_get_control_out_endpoint(), &_control_out_transfer, 0);
|
usb_start_empty_transfer(usb_get_control_out_endpoint(), &_control_out_transfer, 0);
|
||||||
|
|
|
@ -109,7 +109,7 @@ typedef struct _audio_device_config {
|
||||||
} audio_device_config;
|
} audio_device_config;
|
||||||
|
|
||||||
typedef struct _preprocessing_config {
|
typedef struct _preprocessing_config {
|
||||||
fix16_t preamp;
|
fix3_28_t preamp;
|
||||||
int reverse_stereo;
|
int reverse_stereo;
|
||||||
} preprocessing_config;
|
} preprocessing_config;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue