From 84306c0922cc0014b329ee2115c746e1a77e1ca8 Mon Sep 17 00:00:00 2001 From: PloopyCo Date: Thu, 14 Sep 2023 05:06:57 -0400 Subject: [PATCH] Adjusted Oratory's default EQ: - Less bass. Excursion limits happen at 30-50Hz first, so reducing response in this range makes it a little less likely this will be a problem. Plus, I like it. - A little more response above 12kHz. Updated config version to 4. Added a parameter for post EQ gain. Applied once after EQ is calculated. --- firmware/code/configuration_manager.c | 24 +++++++++++++++++++----- firmware/code/configuration_types.h | 8 ++++++-- firmware/code/run.c | 13 ++++++++++++- firmware/code/run.h | 2 ++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/firmware/code/configuration_manager.c b/firmware/code/configuration_manager.c index e17728a..969a075 100644 --- a/firmware/code/configuration_manager.c +++ b/firmware/code/configuration_manager.c @@ -54,7 +54,7 @@ static const default_configuration default_config = { .filter = { FILTER_CONFIGURATION, sizeof(default_config.filters) }, .f1 = { PEAKING, {0}, 38.5, -21.0, 1.4 }, .f2 = { PEAKING, {0}, 60, -6.7, 0.5 }, - .f3 = { LOWSHELF, {0}, 105, 5.5, 0.71 }, + .f3 = { LOWSHELF, {0}, 105, 2.0, 0.71 }, .f4 = { PEAKING, {0}, 280, -3.5, 1.1 }, .f5 = { PEAKING, {0}, 350, -1.6, 6.0 }, .f6 = { PEAKING, {0}, 425, 7.8, 1.3 }, @@ -66,9 +66,15 @@ static const default_configuration default_config = { .f12 = { PEAKING, {0}, 3430, -12.2, 2.0 }, .f13 = { PEAKING, {0}, 4800, 4.0, 2.0 }, .f14 = { PEAKING, {0}, 6200, -15.0, 3.0 }, - .f15 = { HIGHSHELF, {0}, 12000, -6.0, 0.71 } + .f15 = { HIGHSHELF, {0}, 12000, -3.0, 0.71 } }, - .preprocessing = { .header = { PREPROCESSING_CONFIGURATION, sizeof(default_config.preprocessing) }, -0.08f, true, {0} } + .preprocessing = { + .header = { PREPROCESSING_CONFIGURATION, sizeof(default_config.preprocessing) }, + -0.376265f, // pre-EQ gain of -4.1dB + 0.4125f, // post-EQ gain, set to ~3dB (1.4x, less the 1 that is added when config is applied) + true, + {0} + } }; // Grab the last 4k page of flash for our configuration strutures. @@ -316,6 +322,7 @@ bool apply_configuration(tlv_header *config) { case PREPROCESSING_CONFIGURATION: { preprocessing_configuration_tlv* preprocessing_config = (preprocessing_configuration_tlv*) tlv; preprocessing.preamp = fix3_28_from_flt(1.0f + preprocessing_config->preamp); + preprocessing.postEQGain = fix3_28_from_flt(1.0f + preprocessing_config->postEQGain); preprocessing.reverse_stereo = preprocessing_config->reverse_stereo; break; } @@ -351,11 +358,13 @@ void load_config() { #ifndef TEST_TARGET bool __no_inline_not_in_flash_func(save_configuration)() { + + + const uint8_t active_configuration = inactive_working_configuration ? 0 : 1; tlv_header* config = (tlv_header*) working_configuration[active_configuration]; - if (validate_configuration(config)) { - power_down_dac(); + if (validate_configuration(config)) { const size_t config_length = config->length - ((size_t)config->value - (size_t)config); // Write data to flash @@ -367,6 +376,10 @@ bool __no_inline_not_in_flash_func(save_configuration)() { flash_header->version = CONFIG_VERSION; memcpy((void*)(flash_header->tlvs), config->value, config_length); + /* Turn the DAC off so we don't make a huge noise when disrupting + real time audio operation. */ + power_down_dac(); + uint32_t ints = save_and_disable_interrupts(); flash_range_erase(USER_CONFIGURATION_OFFSET, FLASH_SECTOR_SIZE); flash_range_program(USER_CONFIGURATION_OFFSET, flash_buffer, CFG_BUFFER_SIZE); @@ -376,6 +389,7 @@ bool __no_inline_not_in_flash_func(save_configuration)() { return true; } + return false; } diff --git a/firmware/code/configuration_types.h b/firmware/code/configuration_types.h index 051edd4..db8a70b 100644 --- a/firmware/code/configuration_types.h +++ b/firmware/code/configuration_types.h @@ -17,8 +17,8 @@ #include #define FLASH_MAGIC 0x2E8AFEDD -#define CONFIG_VERSION 3 -#define MINIMUM_CONFIG_VERSION 3 +#define CONFIG_VERSION 4 +#define MINIMUM_CONFIG_VERSION 4 enum structure_types { // Commands/Responses, these are container TLVs. The Value will be a set of TLV structures. @@ -98,9 +98,13 @@ typedef struct __attribute__((__packed__)) _flash_header_tlv { const uint8_t tlvs[0]; } flash_header_tlv; +/// @brief Holds values relating to processing surrounding the EQ calculation. typedef struct __attribute__((__packed__)) _preprocessing_configuration_tlv { tlv_header header; + /// @brief Gain applied to input signal before EQ chain. Use to avoid clipping due to overflow in the biquad filters of the EQ. float preamp; + /// @brief Gain applied to the output of the EQ chain. Used to set output volume. + float postEQGain; uint8_t reverse_stereo; uint8_t reserved[3]; } preprocessing_configuration_tlv; diff --git a/firmware/code/run.c b/firmware/code/run.c index 0acc1a8..1d764ea 100644 --- a/firmware/code/run.c +++ b/firmware/code/run.c @@ -56,6 +56,7 @@ audio_state_config audio_state = { preprocessing_config preprocessing = { .preamp = fix16_one, + .postEQGain = fix16_one, .reverse_stereo = false }; @@ -148,6 +149,10 @@ static void __no_inline_not_in_flash_func(_as_audio_packet)(struct usb_endpoint x_f16 = bqf_transform(x_f16, &bqf_filters_left[j], &bqf_filters_mem_left[j]); } + + /* Apply post-EQ gain. */ + x_f16 = fix16_mul( x_f16, preprocessing.postEQGain); + out[i] = (int32_t) norm_fix3_28_to_s16sample(x_f16); } @@ -186,12 +191,18 @@ void __no_inline_not_in_flash_func(core1_entry)() { const uint32_t samples = multicore_fifo_pop_blocking(); + /* Right channel EQ. */ for (int i = 1; i < samples; i += 2) { + /* Apply EQ pre-filter gain to avoid clipping. */ fix3_28_t x_f16 = fix16_mul(norm_fix3_28_from_s16sample((int16_t) out[i]), preprocessing.preamp); + /* Apply the biquad filters one by one. */ for (int j = 0; j < filter_stages; j++) { x_f16 = bqf_transform(x_f16, &bqf_filters_right[j], &bqf_filters_mem_right[j]); } + /* Apply post-EQ gain. */ + x_f16 = fix16_mul( x_f16, preprocessing.postEQGain); + out[i] = (int32_t) norm_fix3_28_to_s16sample(x_f16); } @@ -957,7 +968,7 @@ void power_down_dac() { i2c_write_blocking(i2c0, PCM_I2C_ADDR, buf, 2, false); } -void power_up_dac() { +void power_up_dac() { uint8_t buf[2]; buf[0] = 64; // register addr buf[1] = 0xE0; // DAC normal mode diff --git a/firmware/code/run.h b/firmware/code/run.h index 6cfcd48..2ccd6e3 100644 --- a/firmware/code/run.h +++ b/firmware/code/run.h @@ -110,6 +110,8 @@ typedef struct _audio_device_config { typedef struct _preprocessing_config { fix3_28_t preamp; + /// @brief Apply this gain after applying EQ, to set output volume without causing overflow in the EQ calculations. + fix3_28_t postEQGain; int reverse_stereo; } preprocessing_config;