Allow the user to create fully custom filters.
This commit is contained in:
parent
66943e9c84
commit
6c627d22fd
|
@ -103,10 +103,8 @@ bool validate_filter_configuration(filter_configuration_tlv *filters)
|
||||||
case BANDPASSPEAK:
|
case BANDPASSPEAK:
|
||||||
case NOTCH:
|
case NOTCH:
|
||||||
case ALLPASS: {
|
case ALLPASS: {
|
||||||
//filter2 *args = (filter2 *)ptr;
|
|
||||||
//printf("Found Filter %d: %0.2f %0.2f\n", args->type, args->f0, args->Q);
|
|
||||||
if (remaining < sizeof(filter2)) {
|
if (remaining < sizeof(filter2)) {
|
||||||
printf("Error! Not enough data left for filter2 (%d)..\n", remaining);
|
printf("Error! Not enough data left for filter2 (%d)\n", remaining);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ptr += sizeof(filter2);
|
ptr += sizeof(filter2);
|
||||||
|
@ -115,15 +113,27 @@ bool validate_filter_configuration(filter_configuration_tlv *filters)
|
||||||
case PEAKING:
|
case PEAKING:
|
||||||
case LOWSHELF:
|
case LOWSHELF:
|
||||||
case HIGHSHELF: {
|
case HIGHSHELF: {
|
||||||
//filter3 *args = (filter3 *)ptr;
|
|
||||||
//printf("Found Filter %d: %0.2f %0.2f %0.2f\n", args->type, args->f0, args->db_gain, args->Q);
|
|
||||||
if (remaining < sizeof(filter3)) {
|
if (remaining < sizeof(filter3)) {
|
||||||
printf("Error! Not enough data left for filter3 (%d)..\n", remaining);
|
printf("Error! Not enough data left for filter3 (%d)\n", remaining);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ptr += sizeof(filter3);
|
ptr += sizeof(filter3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CUSTOMIIR: {
|
||||||
|
filter6 *args = (filter6 *)ptr;
|
||||||
|
if (remaining < sizeof(filter6)) {
|
||||||
|
printf("Error! Not enough data left for filter6 (%d)\n", remaining);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (args->a0 == 0.0) {
|
||||||
|
printf("Error! The a0 co-efficient of an IIR filter must not be 0.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ptr += sizeof(filter6);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unknown filter type\n");
|
printf("Unknown filter type\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -164,26 +174,42 @@ void apply_filter_configuration(filter_configuration_tlv *filters) {
|
||||||
case PEAKING: INIT_FILTER3(peaking);
|
case PEAKING: INIT_FILTER3(peaking);
|
||||||
case LOWSHELF: INIT_FILTER3(lowshelf);
|
case LOWSHELF: INIT_FILTER3(lowshelf);
|
||||||
case HIGHSHELF: INIT_FILTER3(highshelf);
|
case HIGHSHELF: INIT_FILTER3(highshelf);
|
||||||
|
case CUSTOMIIR: {
|
||||||
|
filter6 *args = (filter6 *)ptr;
|
||||||
|
uint32_t checksum = 0;
|
||||||
|
for (int i = 0; i < sizeof(filter6) / 4; i++) checksum ^= ((uint32_t*) args)[i];
|
||||||
|
if (checksum != bqf_filter_checksum[filter_stages]) {
|
||||||
|
bqf_filters_left[filter_stages].a0 = fix16_from_dbl(1.0);
|
||||||
|
bqf_filters_left[filter_stages].a1 = fix16_from_dbl(args->a1/args->a0);
|
||||||
|
bqf_filters_left[filter_stages].a2 = fix16_from_dbl(args->a2/args->a0);
|
||||||
|
bqf_filters_left[filter_stages].b0 = fix16_from_dbl(args->b0/args->a0);
|
||||||
|
bqf_filters_left[filter_stages].b1 = fix16_from_dbl(args->b1/args->a0);
|
||||||
|
bqf_filters_left[filter_stages].b2 = fix16_from_dbl(args->b2/args->a0);
|
||||||
|
memcpy(&bqf_filters_right[filter_stages], &bqf_filters_left[filter_stages], sizeof(bqf_coeff_t));
|
||||||
|
bqf_filter_checksum[filter_stages] = checksum;
|
||||||
|
}
|
||||||
|
ptr += sizeof(filter6);
|
||||||
|
type_changed = true; // Always flush our memory
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
filter_stages++;
|
|
||||||
}
|
|
||||||
|
|
||||||
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[0].x_2, bqf_filters_mem_left[0].x_1 };
|
fix16_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[0].x_2, bqf_filters_mem_right[0].x_1 };
|
fix16_t right[2] = { bqf_filters_mem_right[filter_stages].x_2, bqf_filters_mem_right[filter_stages].x_1 };
|
||||||
for (int i=0; i<filter_stages; i++) {
|
|
||||||
bqf_memreset(&bqf_filters_mem_left[i]);
|
|
||||||
bqf_memreset(&bqf_filters_mem_right[i]);
|
|
||||||
|
|
||||||
left[0] = bqf_transform(left[0], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
|
bqf_memreset(&bqf_filters_mem_left[filter_stages]);
|
||||||
left[1] = bqf_transform(left[1], &bqf_filters_left[i], &bqf_filters_mem_left[i]);
|
bqf_memreset(&bqf_filters_mem_right[filter_stages]);
|
||||||
right[0] = bqf_transform(right[0], &bqf_filters_right[i], &bqf_filters_mem_right[i]);
|
|
||||||
right[1] = bqf_transform(right[1], &bqf_filters_right[i], &bqf_filters_mem_right[i]);
|
left[0] = bqf_transform(left[0], &bqf_filters_left[filter_stages], &bqf_filters_mem_left[filter_stages]);
|
||||||
|
left[1] = bqf_transform(left[1], &bqf_filters_left[filter_stages], &bqf_filters_mem_left[filter_stages]);
|
||||||
|
right[0] = bqf_transform(right[0], &bqf_filters_right[filter_stages], &bqf_filters_mem_right[filter_stages]);
|
||||||
|
right[1] = bqf_transform(right[1], &bqf_filters_right[filter_stages], &bqf_filters_mem_right[filter_stages]);
|
||||||
}
|
}
|
||||||
|
filter_stages++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define FLASH_MAGIC 0x2E8AFEDD
|
#define FLASH_MAGIC 0x2E8AFEDD
|
||||||
#define CONFIG_VERSION 1
|
#define CONFIG_VERSION 2
|
||||||
#define MINIMUM_CONFIG_VERSION 1
|
#define MINIMUM_CONFIG_VERSION 1
|
||||||
|
|
||||||
enum structure_types {
|
enum structure_types {
|
||||||
|
@ -65,6 +65,17 @@ typedef struct __attribute__((__packed__)) _filter3 {
|
||||||
double Q;
|
double Q;
|
||||||
} filter3;
|
} filter3;
|
||||||
|
|
||||||
|
typedef struct __attribute__((__packed__)) _filter6 {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t reserved[3];
|
||||||
|
double a0;
|
||||||
|
double a1;
|
||||||
|
double a2;
|
||||||
|
double b0;
|
||||||
|
double b1;
|
||||||
|
double b2;
|
||||||
|
} filter6;
|
||||||
|
|
||||||
enum filter_type {
|
enum filter_type {
|
||||||
LOWPASS = 0,
|
LOWPASS = 0,
|
||||||
HIGHPASS,
|
HIGHPASS,
|
||||||
|
@ -74,7 +85,8 @@ enum filter_type {
|
||||||
ALLPASS,
|
ALLPASS,
|
||||||
PEAKING,
|
PEAKING,
|
||||||
LOWSHELF,
|
LOWSHELF,
|
||||||
HIGHSHELF
|
HIGHSHELF,
|
||||||
|
CUSTOMIIR
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) _flash_header_tlv {
|
typedef struct __attribute__((__packed__)) _flash_header_tlv {
|
||||||
|
|
Loading…
Reference in New Issue