Reverse stereo and preamp.
This commit is contained in:
parent
db52d728a3
commit
5fd063a9af
|
@ -47,12 +47,13 @@ static const default_configuration default_config = {
|
||||||
.set_configuration = { SET_CONFIGURATION, sizeof(default_config) },
|
.set_configuration = { SET_CONFIGURATION, sizeof(default_config) },
|
||||||
.filters = {
|
.filters = {
|
||||||
.filter = { FILTER_CONFIGURATION, sizeof(default_config.filters) },
|
.filter = { FILTER_CONFIGURATION, sizeof(default_config.filters) },
|
||||||
.f1 = { PEAKING, 38, -19, 0.9 },
|
.f1 = { PEAKING, {0}, 38, -19, 0.9 },
|
||||||
.f2 = { LOWSHELF, 2900, 2, 0.7 },
|
.f2 = { LOWSHELF, {0}, 2900, 2, 0.7 },
|
||||||
.f3 = { PEAKING, 430, 3, 3.5 },
|
.f3 = { PEAKING, {0}, 430, 3, 3.5 },
|
||||||
.f4 = { HIGHSHELF, 8400, 2, 0.7 },
|
.f4 = { HIGHSHELF, {0}, 8400, 2, 0.7 },
|
||||||
.f5 = { PEAKING, 4800, 3, 5 }
|
.f5 = { PEAKING, {0}, 4800, 3, 5 }
|
||||||
}
|
},
|
||||||
|
.preprocessing = { .header = { PREPROCESSING_CONFIGURATION, sizeof(default_config.preprocessing) }, -0.1f, false, {0} }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grab the last 4k page of flash for our configuration strutures.
|
// Grab the last 4k page of flash for our configuration strutures.
|
||||||
|
@ -96,6 +97,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;
|
||||||
|
@ -105,6 +108,8 @@ 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;
|
||||||
|
@ -155,15 +160,25 @@ void apply_filter_configuration(filter_configuration_tlv *filters) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate_configuration(tlv_header *config) {
|
bool validate_configuration(tlv_header *config) {
|
||||||
if (config->type != SET_CONFIGURATION) {
|
uint8_t *ptr = NULL;
|
||||||
printf("Unexpcected Config type: %d\n", config->type);
|
switch (config->type)
|
||||||
return false;
|
{
|
||||||
|
case SET_CONFIGURATION:
|
||||||
|
ptr = (uint8_t *) config->value;
|
||||||
|
break;
|
||||||
|
case FLASH_HEADER: {
|
||||||
|
ptr = (uint8_t *) ((flash_header_tlv*) config)->tlvs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
printf("Unexpected Config type: %d\n", config->type);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
uint8_t *ptr = (uint8_t *)config->value;
|
|
||||||
const uint8_t *end = (uint8_t *)config + config->length;
|
const uint8_t *end = (uint8_t *)config + config->length;
|
||||||
while (ptr < end) {
|
while (ptr < end) {
|
||||||
tlv_header* tlv = (tlv_header*) ptr;
|
tlv_header* tlv = (tlv_header*) ptr;
|
||||||
if (tlv->length < 4) {
|
if (tlv->length < 4) {
|
||||||
|
printf("Bad length... %d\n", tlv->length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (tlv->type) {
|
switch (tlv->type) {
|
||||||
|
@ -172,6 +187,14 @@ bool validate_configuration(tlv_header *config) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PREPROCESSING_CONFIGURATION: {
|
||||||
|
preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv;
|
||||||
|
//printf("Preproc %0.2f %d\n", preprocessing_config->preamp, preprocessing_config->reverse_stereo);
|
||||||
|
if (tlv->length != sizeof(preprocessing_configuration_tlv)) {
|
||||||
|
printf("Preprocessing size missmatch: %u != %zu\n", tlv->length, sizeof(preprocessing_configuration_tlv));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;}
|
||||||
default:
|
default:
|
||||||
// Unknown TLVs are not invalid, just ignored.
|
// Unknown TLVs are not invalid, just ignored.
|
||||||
break;
|
break;
|
||||||
|
@ -193,17 +216,23 @@ bool apply_configuration(tlv_header *config) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
printf("Unexpcected Config type: %d\n", config->type);
|
printf("Unexpected Config type: %d\n", config->type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *end = (uint8_t *)config + config->length;
|
const uint8_t *end = (uint8_t *)config + config->length;
|
||||||
while (ptr < end) {
|
while ((ptr + 4) < end) {
|
||||||
tlv_header* tlv = (tlv_header*) ptr;
|
tlv_header* tlv = (tlv_header*) ptr;
|
||||||
switch (tlv->type) {
|
switch (tlv->type) {
|
||||||
case FILTER_CONFIGURATION:
|
case FILTER_CONFIGURATION:
|
||||||
apply_filter_configuration((filter_configuration_tlv*) tlv);
|
apply_filter_configuration((filter_configuration_tlv*) tlv);
|
||||||
break;
|
break;
|
||||||
|
case PREPROCESSING_CONFIGURATION: {
|
||||||
|
preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv;
|
||||||
|
preprocessing.preamp = fix16_from_dbl(1.0 + preprocessing_config->preamp);
|
||||||
|
preprocessing.reverse_stereo = preprocessing_config->reverse_stereo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +277,8 @@ bool process_cmd(tlv_header* cmd) {
|
||||||
switch (cmd->type) {
|
switch (cmd->type) {
|
||||||
case SET_CONFIGURATION:
|
case SET_CONFIGURATION:
|
||||||
if (validate_configuration(cmd)) {
|
if (validate_configuration(cmd)) {
|
||||||
inactive_working_configuration = inactive_working_configuration ? 0 : 1;
|
inactive_working_configuration = (inactive_working_configuration ? 0 : 1);
|
||||||
|
((tlv_header*) working_configuration[inactive_working_configuration])->length = 0;
|
||||||
reload_config = true;
|
reload_config = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +307,7 @@ void config_out_packet(struct usb_endpoint *ep) {
|
||||||
|
|
||||||
const uint16_t transfer_length = ((tlv_header*) working_configuration[inactive_working_configuration])->length;
|
const uint16_t transfer_length = ((tlv_header*) working_configuration[inactive_working_configuration])->length;
|
||||||
//printf("config_length %d %d\n", transfer_length, write_offset);
|
//printf("config_length %d %d\n", transfer_length, write_offset);
|
||||||
if (write_offset >= transfer_length) {
|
if (transfer_length && write_offset >= transfer_length) {
|
||||||
// Command complete, fill the result buffer
|
// Command complete, fill the result buffer
|
||||||
tlv_header* result = ((tlv_header*) result_buffer);
|
tlv_header* result = ((tlv_header*) result_buffer);
|
||||||
write_offset = 0;
|
write_offset = 0;
|
||||||
|
|
|
@ -32,8 +32,8 @@ struct usb_endpoint;
|
||||||
|
|
||||||
#define INIT_FILTER3(T) { \
|
#define INIT_FILTER3(T) { \
|
||||||
filter3 *args = (filter3 *)ptr; \
|
filter3 *args = (filter3 *)ptr; \
|
||||||
bqf_##T##_config(SAMPLING_FREQ, args->f0, args->dBgain, args->Q, &bqf_filters_left[filter_stages]); \
|
bqf_##T##_config(SAMPLING_FREQ, args->f0, args->db_gain, args->Q, &bqf_filters_left[filter_stages]); \
|
||||||
bqf_##T##_config(SAMPLING_FREQ, args->f0, args->dBgain, args->Q, &bqf_filters_right[filter_stages]); \
|
bqf_##T##_config(SAMPLING_FREQ, args->f0, args->db_gain, args->Q, &bqf_filters_right[filter_stages]); \
|
||||||
ptr += sizeof(filter3); \
|
ptr += sizeof(filter3); \
|
||||||
break; \
|
break; \
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,15 +49,17 @@ typedef struct __attribute__((__packed__)) _tlv_header {
|
||||||
} tlv_header;
|
} tlv_header;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) _filter2 {
|
typedef struct __attribute__((__packed__)) _filter2 {
|
||||||
uint32_t type;
|
uint8_t type;
|
||||||
|
uint8_t reserved[3];
|
||||||
double f0;
|
double f0;
|
||||||
double Q;
|
double Q;
|
||||||
} filter2;
|
} filter2;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) _filter3 {
|
typedef struct __attribute__((__packed__)) _filter3 {
|
||||||
uint32_t type;
|
uint8_t type;
|
||||||
|
uint8_t reserved[3];
|
||||||
double f0;
|
double f0;
|
||||||
double dBgain;
|
double db_gain;
|
||||||
double Q;
|
double Q;
|
||||||
} filter3;
|
} filter3;
|
||||||
|
|
||||||
|
@ -80,6 +82,13 @@ typedef struct __attribute__((__packed__)) _flash_header_tlv {
|
||||||
const uint8_t tlvs[];
|
const uint8_t tlvs[];
|
||||||
} flash_header_tlv;
|
} flash_header_tlv;
|
||||||
|
|
||||||
|
typedef struct __attribute__((__packed__)) _preprocessing_configuration_tlv {
|
||||||
|
tlv_header header;
|
||||||
|
double preamp;
|
||||||
|
uint8_t reverse_stereo;
|
||||||
|
uint8_t reserved[3];
|
||||||
|
} preprocessing_configuration_tlv;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) _filter_configuration_tlv {
|
typedef struct __attribute__((__packed__)) _filter_configuration_tlv {
|
||||||
tlv_header header;
|
tlv_header header;
|
||||||
const uint8_t filters[];
|
const uint8_t filters[];
|
||||||
|
@ -101,6 +110,7 @@ typedef struct __attribute__((__packed__)) _default_configuration {
|
||||||
filter3 f4;
|
filter3 f4;
|
||||||
filter3 f5;
|
filter3 f5;
|
||||||
} filters;
|
} filters;
|
||||||
|
preprocessing_configuration_tlv preprocessing;
|
||||||
} default_configuration;
|
} default_configuration;
|
||||||
|
|
||||||
#endif // __CONFIGURATION_TYPES_H__
|
#endif // __CONFIGURATION_TYPES_H__
|
|
@ -64,6 +64,11 @@ static struct {
|
||||||
.freq = 48000,
|
.freq = 48000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
preprocessing_config preprocessing = {
|
||||||
|
.preamp = fix16_one,
|
||||||
|
.reverse_stereo = false
|
||||||
|
};
|
||||||
|
|
||||||
static char spi_serial_number[17] = "";
|
static char spi_serial_number[17] = "";
|
||||||
|
|
||||||
enum vendor_cmds {
|
enum vendor_cmds {
|
||||||
|
@ -103,8 +108,16 @@ static void _as_audio_packet(struct usb_endpoint *ep) {
|
||||||
int32_t *out = (int32_t *) userbuf;
|
int32_t *out = (int32_t *) userbuf;
|
||||||
int samples = usb_buffer->data_len / 2;
|
int samples = usb_buffer->data_len / 2;
|
||||||
|
|
||||||
for (int i = 0; i < samples; i++)
|
if (preprocessing.reverse_stereo) {
|
||||||
out[i] = in[i];
|
for (int i = 0; i < samples; i+=2) {
|
||||||
|
out[i] = in[i+1];
|
||||||
|
out[i+1] = in[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < samples; i++)
|
||||||
|
out[i] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
multicore_fifo_push_blocking(CORE0_READY);
|
multicore_fifo_push_blocking(CORE0_READY);
|
||||||
multicore_fifo_push_blocking(samples);
|
multicore_fifo_push_blocking(samples);
|
||||||
|
@ -112,7 +125,7 @@ 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_from_int((int16_t) out[i]);
|
fix16_t x_f16 = fix16_mul(fix16_from_int((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]);
|
||||||
|
@ -168,7 +181,7 @@ void core1_entry() {
|
||||||
|
|
||||||
for (int j = 0; j < filter_stages; j++) {
|
for (int j = 0; j < filter_stages; j++) {
|
||||||
for (int i = 1; i < limit; i += 2) {
|
for (int i = 1; i < limit; i += 2) {
|
||||||
fix16_t x_f16 = fix16_from_int((int16_t) out[i]);
|
fix16_t x_f16 = fix16_mul(fix16_from_int((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]);
|
||||||
|
@ -198,6 +211,11 @@ void setup() {
|
||||||
sleep_ms(100);
|
sleep_ms(100);
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
|
for (int i=0; i<MAX_FILTER_STAGES; i++) {
|
||||||
|
bqf_memreset(&bqf_filters_mem_left[i]);
|
||||||
|
bqf_memreset(&bqf_filters_mem_right[i]);
|
||||||
|
}
|
||||||
|
|
||||||
pico_get_unique_board_id_string(spi_serial_number, 17);
|
pico_get_unique_board_id_string(spi_serial_number, 17);
|
||||||
descriptor_strings[2] = spi_serial_number;
|
descriptor_strings[2] = spi_serial_number;
|
||||||
userbuf = malloc(sizeof(uint8_t) * RINGBUF_LEN_IN_BYTES);
|
userbuf = malloc(sizeof(uint8_t) * RINGBUF_LEN_IN_BYTES);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "ringbuf.h"
|
#include "ringbuf.h"
|
||||||
#include "i2s.h"
|
#include "i2s.h"
|
||||||
|
#include "fix16.h"
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* USB-related definitions begin here.
|
* USB-related definitions begin here.
|
||||||
|
@ -74,6 +75,13 @@ typedef struct _audio_device_config {
|
||||||
struct usb_endpoint_descriptor ep4;
|
struct usb_endpoint_descriptor ep4;
|
||||||
} audio_device_config;
|
} audio_device_config;
|
||||||
|
|
||||||
|
typedef struct _preprocessing_config {
|
||||||
|
fix16_t preamp;
|
||||||
|
int reverse_stereo;
|
||||||
|
} preprocessing_config;
|
||||||
|
|
||||||
|
extern preprocessing_config preprocessing;
|
||||||
|
|
||||||
static char *descriptor_strings[] = {
|
static char *descriptor_strings[] = {
|
||||||
"Ploopy Corporation",
|
"Ploopy Corporation",
|
||||||
"Ploopy Headphones",
|
"Ploopy Headphones",
|
||||||
|
|
Loading…
Reference in New Issue