Optimized mono2stereo effect.

Enabled set_master_mixer_gain() again.
Disabled sin/cos function optimization.
pull/32/head
Holger Wirtz 5 years ago
parent 1651855403
commit 81ca62604c
  1. 75
      MicroDexed.ino
  2. 16
      UI.hpp
  3. 4
      config.h
  4. 21
      effect_mono_stereo.cpp
  5. 2
      effect_mono_stereo.h
  6. 11
      synth.h

@ -216,7 +216,7 @@ uint8_t active_voices[NUM_DEXED];
#ifdef SHOW_CPU_LOAD_MSEC #ifdef SHOW_CPU_LOAD_MSEC
elapsedMillis cpu_mem_millis; elapsedMillis cpu_mem_millis;
#endif #endif
//uint32_t overload = 0; uint32_t cpumax = 0;
uint32_t peak_dexed = 0; uint32_t peak_dexed = 0;
float peak_dexed_value = 0.0; float peak_dexed_value = 0.0;
uint32_t peak_r = 0; uint32_t peak_r = 0;
@ -773,8 +773,9 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
break; break;
case 107: // CC 107: delay volume case 107: // CC 107: delay volume
configuration.dexed[instance_id].delay_send = map(inValue, 0, 0x7f, DELAY_SEND_MIN, DELAY_SEND_MAX); configuration.dexed[instance_id].delay_send = map(inValue, 0, 0x7f, DELAY_SEND_MIN, DELAY_SEND_MAX);
master_mixer_r.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); set_master_mixer_gain(DELAY, configuration.delay_level / 100.0);
master_mixer_l.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); //master_mixer_r.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0));
//master_mixer_l.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0));
eeprom_write(); eeprom_write();
break; break;
case 120: case 120:
@ -1365,6 +1366,11 @@ void check_configuration(void)
configuration.dexed[instance_id].portamento_time = constrain(configuration.dexed[instance_id].portamento_time, PORTAMENTO_TIME_MIN, PORTAMENTO_TIME_MAX); configuration.dexed[instance_id].portamento_time = constrain(configuration.dexed[instance_id].portamento_time, PORTAMENTO_TIME_MIN, PORTAMENTO_TIME_MAX);
configuration.dexed[instance_id].op_enabled = constrain(configuration.dexed[instance_id].op_enabled, OP_ENABLED_MIN, OP_ENABLED_MAX); configuration.dexed[instance_id].op_enabled = constrain(configuration.dexed[instance_id].op_enabled, OP_ENABLED_MIN, OP_ENABLED_MAX);
} }
set_master_mixer_gain(CHORUS, configuration.chorus_level / 100.0);
set_master_mixer_gain(DELAY, configuration.delay_level / 100.0);
#if defined(USE_REVERB)
set_master_mixer_gain(REVERB, configuration.reverb_level / 100.0);
#endif
} }
void init_configuration(void) void init_configuration(void)
@ -1462,40 +1468,39 @@ uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https:/
return (crc); return (crc);
} }
/* void set_master_mixer_gain(uint8_t type, float level)
void set_master_mixer_gain(uint8_t type, float level) {
{
master_mixer_level[type] = constrain(level, 0.0, 1.0); master_mixer_level[type] = constrain(level, 0.0, 1.0);
#if defined(USE_REVERB) #if defined(USE_REVERB)
const uint8_t num_fx = 4; const uint8_t num_fx = 4;
#else #else
const uint8_t num_fx = 3; const uint8_t num_fx = 3;
#endif #endif
float new_level[num_fx]; float new_level[num_fx];
new_level[CHORUS] = master_mixer_level[CHORUS] / float(num_fx); new_level[CHORUS] = master_mixer_level[CHORUS] / float(num_fx);
new_level[DELAY] = master_mixer_level[DELAY] / float(num_fx); new_level[DELAY] = master_mixer_level[DELAY] / float(num_fx);
#if defined(USE_REVERB) #if defined(USE_REVERB)
new_level[REVERB] = master_mixer_level[REVERB] / float(num_fx); new_level[REVERB] = master_mixer_level[REVERB] / float(num_fx);
new_level[DEXED] = 1.0 - new_level[CHORUS] - new_level[DELAY] - new_level[REVERB]; new_level[DEXED] = 1.0 - new_level[CHORUS] - new_level[DELAY] - new_level[REVERB];
#else #else
new_level[DEXED] = 1.0 - new_level[CHORUS] - new_level[DELAY]; new_level[DEXED] = 1.0 - new_level[CHORUS] - new_level[DELAY];
#endif #endif
master_mixer_r.gain(DEXED, new_level[DEXED]); master_mixer_r.gain(DEXED, new_level[DEXED]);
master_mixer_l.gain(DEXED, new_level[DEXED]); master_mixer_l.gain(DEXED, new_level[DEXED]);
master_mixer_r.gain(CHORUS, new_level[CHORUS]); master_mixer_r.gain(CHORUS, new_level[CHORUS]);
master_mixer_l.gain(CHORUS, new_level[CHORUS]); master_mixer_l.gain(CHORUS, new_level[CHORUS]);
master_mixer_r.gain(DELAY, new_level[DELAY]); master_mixer_r.gain(DELAY, new_level[DELAY]);
master_mixer_l.gain(DELAY, new_level[DELAY]); master_mixer_l.gain(DELAY, new_level[DELAY]);
#if defined(USE_REVERB) #if defined(USE_REVERB)
master_mixer_r.gain(REVERB, new_level[REVERB]); master_mixer_r.gain(REVERB, new_level[REVERB]);
master_mixer_l.gain(REVERB, new_level[REVERB]); master_mixer_l.gain(REVERB, new_level[REVERB]);
#endif #endif
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Volumes for master_mixer(type=")); Serial.print(F("Volumes for master_mixer(type="));
Serial.print(type, DEC); Serial.print(type, DEC);
Serial.print(F(",level=")); Serial.print(F(",level="));
@ -1506,15 +1511,14 @@ uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https:/
Serial.print(new_level[CHORUS], 2); Serial.print(new_level[CHORUS], 2);
Serial.print(F(" DELAY=")); Serial.print(F(" DELAY="));
Serial.print(new_level[DELAY], 2); Serial.print(new_level[DELAY], 2);
#if defined(USE_REVERB) #if defined(USE_REVERB)
Serial.print(F(" REVERB=")); Serial.print(F(" REVERB="));
Serial.print(new_level[REVERB], 2); Serial.print(new_level[REVERB], 2);
#endif #endif
Serial.println(); Serial.println();
#endif #endif
} }
*/
/****************************************************************************** /******************************************************************************
DEBUG HELPER DEBUG HELPER
@ -1534,11 +1538,20 @@ void show_cpu_and_mem_usage(void)
sum_overload += MicroDexed[instance_id]->overload; sum_overload += MicroDexed[instance_id]->overload;
MicroDexed[instance_id]->render_time_max = 0; MicroDexed[instance_id]->render_time_max = 0;
} }
if (AudioProcessorUsageMax() > 99.9)
{
cpumax++;
Serial.print(F("*"));
}
else
Serial.print(F(""));
Serial.print(F("CPU:")); Serial.print(F("CPU:"));
Serial.print(AudioProcessorUsage(), 2); Serial.print(AudioProcessorUsage(), 2);
Serial.print(F("%|CPUMAX:")); Serial.print(F("%|CPUMAX:"));
Serial.print(AudioProcessorUsageMax(), 2); Serial.print(AudioProcessorUsageMax(), 2);
Serial.print(F("%|MEM:")); Serial.print(F("%|CPUMAXCNT:"));
Serial.print(cpumax,DEC);
Serial.print(F("|MEM:"));
Serial.print(AudioMemoryUsage(), DEC); Serial.print(AudioMemoryUsage(), DEC);
Serial.print(F("|MEMMAX:")); Serial.print(F("|MEMMAX:"));
Serial.print(AudioMemoryUsageMax(), DEC); Serial.print(AudioMemoryUsageMax(), DEC);

@ -57,6 +57,7 @@ extern void strip_extension(char* s, char *target);
extern void eeprom_write(void); extern void eeprom_write(void);
extern bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id); extern bool get_voice_names_from_bank(uint8_t b, uint8_t instance_id);
extern bool load_sysex(uint8_t b, uint8_t v); extern bool load_sysex(uint8_t b, uint8_t v);
extern void set_master_mixer_gain(uint8_t type, float level);
#ifdef DISPLAY_LCD_SPI #ifdef DISPLAY_LCD_SPI
extern void change_disp_sd(bool d); extern void change_disp_sd(bool d);
#endif #endif
@ -1160,8 +1161,9 @@ void UI_func_reverb_level(uint8_t param)
} }
} }
master_mixer_r.gain(REVERB, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); set_master_mixer_gain(REVERB, configuration.reverb_level / 100.0);
master_mixer_l.gain(REVERB, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); //master_mixer_r.gain(REVERB, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0));
//master_mixer_l.gain(REVERB, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0));
} }
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
@ -1429,8 +1431,9 @@ void UI_func_chorus_level(uint8_t param)
} }
} }
master_mixer_r.gain(CHORUS, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); set_master_mixer_gain(CHORUS, configuration.chorus_level / 100.0);
master_mixer_l.gain(CHORUS, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); //master_mixer_r.gain(CHORUS, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0));
//master_mixer_l.gain(CHORUS, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0));
} }
lcd.setCursor(0, 1); lcd.setCursor(0, 1);
@ -1637,8 +1640,9 @@ void UI_func_delay_level(uint8_t param)
} }
} }
master_mixer_r.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); set_master_mixer_gain(DELAY, configuration.delay_level / 100.0);
master_mixer_l.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); //master_mixer_r.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0));
//master_mixer_l.gain(DELAY, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0));
} }
lcd.setCursor(0, 1); lcd.setCursor(0, 1);

@ -229,9 +229,9 @@ enum { DEXED, REVERB, DELAY, CHORUS };
// Teensy-3.6 settings // Teensy-3.6 settings
#define MIDI_DEVICE_USB_HOST 1 #define MIDI_DEVICE_USB_HOST 1
#if defined(USE_REVERB) #if defined(USE_REVERB)
#define MAX_NOTES 14 #define MAX_NOTES 12
#else #else
#define MAX_NOTES 16 #define MAX_NOTES 14
#endif #endif
#endif #endif

@ -51,16 +51,19 @@ void AudioEffectMonoStereo::update(void)
if (in && mod && out[0] && out[1]) if (in && mod && out[0] && out[1])
{ {
float pan = mapfloat(mod->data[0], -1.0, 1.0, 0.0, 1.0); arm_q15_to_float(in->data, in_f, AUDIO_BLOCK_SAMPLES);
const float f[2] = { _pseudo_log * arm_sin_f32(pan * PI / 2), _pseudo_log * arm_cos_f32(pan * PI / 2) }; // Pan [L0.0 ... M0.5 ... 1.0R] arm_q15_to_float(mod->data, pan_f, AUDIO_BLOCK_SAMPLES);
arm_offset_f32(pan_f, 1.0, pan_f_tmp, AUDIO_BLOCK_SAMPLES);
arm_scale_f32(pan_f_tmp, PI / 4.0, pan_f, AUDIO_BLOCK_SAMPLES); // PI/4
arm_q15_to_float (in->data, in_f, AUDIO_BLOCK_SAMPLES); // right
for (uint8_t n = 0; n < AUDIO_BLOCK_SAMPLES; n++)
for (uint8_t i = 0; i < 2; i++) out_f[0][n] = in_f[n] * _pseudo_log * arm_sin_f32(pan_f[n]);
{ arm_float_to_q15 (out_f[0], out[0]->data, AUDIO_BLOCK_SAMPLES);
arm_scale_f32 (in_f, f[i], out_f[i], AUDIO_BLOCK_SAMPLES); // left
arm_float_to_q15 (out_f[i], out[i]->data, AUDIO_BLOCK_SAMPLES); for (uint8_t n = 0; n < AUDIO_BLOCK_SAMPLES; n++)
} out_f[1][n] = in_f[n] * _pseudo_log * arm_cos_f32(pan_f[n]);
arm_float_to_q15 (out_f[1], out[1]->data, AUDIO_BLOCK_SAMPLES);
if (in) if (in)
{ {

@ -47,6 +47,8 @@ class AudioEffectMonoStereo : public AudioStream
audio_block_t *out[2]; audio_block_t *out[2];
float in_f[AUDIO_BLOCK_SAMPLES]; float in_f[AUDIO_BLOCK_SAMPLES];
float out_f[2][AUDIO_BLOCK_SAMPLES]; float out_f[2][AUDIO_BLOCK_SAMPLES];
float pan_f[AUDIO_BLOCK_SAMPLES];
float pan_f_tmp[AUDIO_BLOCK_SAMPLES];
const float _pseudo_log = 1048575 / (float)(1 << 20); const float _pseudo_log = 1048575 / (float)(1 << 20);
}; };

@ -64,14 +64,13 @@ inline static T max(const T& a, const T& b) {
#define QER(n,b) ( ((float)n)/(1<<b) ) #define QER(n,b) ( ((float)n)/(1<<b) )
#define FRAC_NUM float #define FRAC_NUM float
//#define SIN_FUNC sinf #define SIN_FUNC sinf
#define SIN_FUNC arm_sin_f32 // very fast but not as accurate // #define SIN_FUNC arm_sin_f32 // very fast but not as accurate
//#define COS_FUNC cosf #define COS_FUNC cosf
#define COS_FUNC arm_cos_f32 // very fast but not as accurate // #define COS_FUNC arm_cos_f32 // very fast but not as accurate
#define LOG_FUNC logf #define LOG_FUNC logf
#define EXP_FUNC expf #define EXP_FUNC expf
#define SQRT_FUNC sqrtf #define SQRT_FUNC sqrtf
#define ARM_SQRT_FUNC arm_sqrt_f32 // fast but not as accurate // #define ARM_SQRT_FUNC arm_sqrt_f32 // fast but not as accurate
#endif // __SYNTH_H #endif // __SYNTH_H

Loading…
Cancel
Save