From 48c256a2ef723007e586a91f458c0103e995c6aa Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Tue, 28 Apr 2020 22:07:34 +0200 Subject: [PATCH] Add ability to change response curve of volume CV and volume pot --- stereo_mix/makefile | 1 + stereo_mix/processor.cc | 39 ++++++++++++++++----------- stereo_mix/processor.h | 9 +++++-- stereo_mix/resources/lookup_tables.py | 19 ++++++++++--- stereo_mix/resources/resources.py | 2 +- stereo_mix/stereo_mix.cc | 2 +- stereo_mix/ui.cc | 2 +- 7 files changed, 50 insertions(+), 24 deletions(-) diff --git a/stereo_mix/makefile b/stereo_mix/makefile index 5cd351c..42a8280 100644 --- a/stereo_mix/makefile +++ b/stereo_mix/makefile @@ -32,6 +32,7 @@ FAMILY = f0xx #APPLICATION = true #BOOTLOADER = midi2cv_bootloader OPTIMIZE = TRUE +OPTIMIZE_FLAG = 1 # Preferred upload command UPLOAD_COMMAND = upload_jtag diff --git a/stereo_mix/processor.cc b/stereo_mix/processor.cc index 4e19891..b671c2d 100644 --- a/stereo_mix/processor.cc +++ b/stereo_mix/processor.cc @@ -1,10 +1,12 @@ #include "processor.h" #include "stmlib/stmlib.h" +#include "stmlib/utils/dsp.h" #include using namespace stereo_mix; +using namespace stmlib; -const int kVolumeFilterValue = 4095; +const int kVolumeFilterValue = 65535; void Processor::Process(int16_t cvs[], uint16_t* outs) { @@ -16,28 +18,33 @@ void Processor::Process(int16_t cvs[], uint16_t* outs) int16_t pan_cv = cvs[0] >> (16 - 12); int16_t vol_cv = cvs[1] >> (16 - 12); int32_t pan = pan_pot + pan_cv; - int32_t vol = vol_pot + vol_cv; - CONSTRAIN(pan, 0, (1 << 12) - 1); - CONSTRAIN(vol, 0, (1 << 12) - 1); + int32_t lin = volume_offset + (cvs[1] * 2); + CONSTRAIN(lin, 0, 65535); + lin *= !mute; + linear_vol = lin; - if (mute) { - vol = 0; - } + uint16_t vol_pot_exp = lut_linear_to_exp[vol_pot]; + uint16_t vol_pot_log = 65535 - lut_linear_to_exp[LUT_LINEAR_TO_EXP_SIZE - 1 - vol_pot]; - if (vol > previous_vol + kVolumeFilterValue) { - vol = previous_vol + kVolumeFilterValue; - } else if (vol < previous_vol - kVolumeFilterValue) { - vol = previous_vol - kVolumeFilterValue; - } + vol_pot = Mix(vol_pot_exp, vol_pot_log, log_exp_mix_pot); - CONSTRAIN(pan, 0, (1 << 12) - 1); - CONSTRAIN(vol, 0, (1 << 12) - 1); + uint16_t vol_cv_absu16 = abs(vol_cv) << 1; + uint16_t vol_cv_exp = lut_linear_to_exp[vol_cv_absu16]; + uint16_t vol_cv_log = 65535 - lut_linear_to_exp[LUT_LINEAR_TO_EXP_SIZE - 1 - vol_cv_absu16]; + uint16_t vol_cv_pre = Mix(vol_cv_exp, vol_cv_log, log_exp_mix_cv); + int32_t vol = vol_pot; + vol += vol_cv > 0 ? vol_cv_pre : -vol_cv_pre; + + vol *= !mute; + + CONSTRAIN(pan, 0, (1 << 16) - 1); + CONSTRAIN(vol, 0, (1 << 16) - 1); previous_vol = vol; // leds.set_intensity(i, vol >> 4); - value_l = (lut_left_sin_pan[pan] * lut_linear_to_exp[vol]) >> 16; - value_r = (lut_right_cos_pan[pan] * lut_linear_to_exp[vol]) >> 16; + value_l = (lut_left_sin_pan[pan] * vol) >> 16; + value_r = (lut_right_cos_pan[pan] * vol) >> 16; outs[0] = value_r; outs[1] = value_l; diff --git a/stereo_mix/processor.h b/stereo_mix/processor.h index 65da964..efd0c60 100644 --- a/stereo_mix/processor.h +++ b/stereo_mix/processor.h @@ -22,13 +22,18 @@ class Processor { mute = m; } - uint16_t previous_volume() { - return previous_vol; + uint16_t linear_volume() { + return linear_vol; } private: uint16_t volume_offset = 0; int16_t pan_offset = 0; uint16_t previous_vol; + uint16_t linear_vol; + + uint16_t log_exp_mix_cv = 32767; // -> linear + uint16_t log_exp_mix_pot = 0; + bool mute = false; }; diff --git a/stereo_mix/resources/lookup_tables.py b/stereo_mix/resources/lookup_tables.py index 599caf9..649a82b 100644 --- a/stereo_mix/resources/lookup_tables.py +++ b/stereo_mix/resources/lookup_tables.py @@ -1,4 +1,7 @@ import numpy as np +import matplotlib +import matplotlib.pyplot as plt + lookup_tables_u16 = [] lookup_tables_u8 = [] @@ -7,11 +10,22 @@ OUTPUT_RESOLUTION = 2 ** 16 - 1 # linear to exponential conversion -values = np.linspace(0, 1, num=ADC_RESOLUTION) -values = np.power(values, 2) * OUTPUT_RESOLUTION +space = np.linspace(0, 1, num=ADC_RESOLUTION) +values = np.power(space, 2) * OUTPUT_RESOLUTION lookup_tables_u16.append(('linear_to_exp', values)) +fig, ax = plt.subplots() +ax.plot(space, values) +other_values = OUTPUT_RESOLUTION - np.flip(values) +ax.plot(space, OUTPUT_RESOLUTION - (np.flip(values))) +ax.plot(space, values / 2 + other_values / 2) + +ax.set(xlabel='space', ylabel='values') +ax.grid() + +#plt.show() + # Left pan Lookup table @@ -34,4 +48,3 @@ max_out = 511 input_vals = np.linspace(0, max_in, num=max_in + 1) gamma_correction = ((input_vals / max_in) ** gamma) * max_out + 0.5 lookup_tables_u16.append(('led_gamma', np.floor(gamma_correction))) - diff --git a/stereo_mix/resources/resources.py b/stereo_mix/resources/resources.py index b77eb32..41775e9 100755 --- a/stereo_mix/resources/resources.py +++ b/stereo_mix/resources/resources.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.5 +#!/usr/bin/python # # Copyright 2016 Emilie Gillet. # diff --git a/stereo_mix/stereo_mix.cc b/stereo_mix/stereo_mix.cc index 999a283..c84e995 100644 --- a/stereo_mix/stereo_mix.cc +++ b/stereo_mix/stereo_mix.cc @@ -145,7 +145,7 @@ void Init(void) HAL_NVIC_EnableIRQ(TIM6_IRQn); htim6.Init.Prescaler = 64; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; - htim6.Init.Period = 96; //128; //256; //512; + htim6.Init.Period = 96; // 512 without optimize htim6.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim6.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim6); diff --git a/stereo_mix/ui.cc b/stereo_mix/ui.cc index b0d7a81..294c0b1 100644 --- a/stereo_mix/ui.cc +++ b/stereo_mix/ui.cc @@ -113,7 +113,7 @@ void UI::TaskDrawLeds() leds->set_blinking(i, pan_pots[i] - 32767 < 0); } else { // show volume if not muted - leds->set_intensity(i, processors[i].previous_volume() >> (4)); + leds->set_intensity(i, processors[i].linear_volume() >> (8)); leds->set_blinking(i, false); } }