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
elapsedMillis cpu_mem_millis;
#endif
//uint32_t overload = 0;
uint32_t cpumax = 0;
uint32_t peak_dexed = 0;
float peak_dexed_value = 0.0;
uint32_t peak_r = 0;
@ -773,8 +773,9 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
break;
case 107: // CC 107: delay volume
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));
master_mixer_l.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_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();
break;
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].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)
@ -1462,40 +1468,39 @@ uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https:/
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);
#if defined(USE_REVERB)
#if defined(USE_REVERB)
const uint8_t num_fx = 4;
#else
#else
const uint8_t num_fx = 3;
#endif
#endif
float new_level[num_fx];
new_level[CHORUS] = master_mixer_level[CHORUS] / 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[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];
#endif
master_mixer_r.gain(DEXED, new_level[DEXED]);
master_mixer_l.gain(DEXED, new_level[DEXED]);
master_mixer_r.gain(CHORUS, new_level[CHORUS]);
master_mixer_l.gain(CHORUS, new_level[CHORUS]);
master_mixer_r.gain(DELAY, new_level[DELAY]);
master_mixer_l.gain(DELAY, new_level[DELAY]);
#if defined(USE_REVERB)
master_mixer_r.gain(REVERB, new_level[REVERB]);
master_mixer_l.gain(REVERB, new_level[REVERB]);
#endif
#ifdef DEBUG
#endif
master_mixer_r.gain(DEXED, new_level[DEXED]);
master_mixer_l.gain(DEXED, new_level[DEXED]);
master_mixer_r.gain(CHORUS, new_level[CHORUS]);
master_mixer_l.gain(CHORUS, new_level[CHORUS]);
master_mixer_r.gain(DELAY, new_level[DELAY]);
master_mixer_l.gain(DELAY, new_level[DELAY]);
#if defined(USE_REVERB)
master_mixer_r.gain(REVERB, new_level[REVERB]);
master_mixer_l.gain(REVERB, new_level[REVERB]);
#endif
#ifdef DEBUG
Serial.print(F("Volumes for master_mixer(type="));
Serial.print(type, DEC);
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(F(" DELAY="));
Serial.print(new_level[DELAY], 2);
#if defined(USE_REVERB)
#if defined(USE_REVERB)
Serial.print(F(" REVERB="));
Serial.print(new_level[REVERB], 2);
#endif
#endif
Serial.println();
#endif
}
*/
#endif
}
/******************************************************************************
DEBUG HELPER
@ -1534,11 +1538,20 @@ void show_cpu_and_mem_usage(void)
sum_overload += MicroDexed[instance_id]->overload;
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(AudioProcessorUsage(), 2);
Serial.print(F("%|CPUMAX:"));
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(F("|MEMMAX:"));
Serial.print(AudioMemoryUsageMax(), DEC);

@ -57,6 +57,7 @@ extern void strip_extension(char* s, char *target);
extern void eeprom_write(void);
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 void set_master_mixer_gain(uint8_t type, float level);
#ifdef DISPLAY_LCD_SPI
extern void change_disp_sd(bool d);
#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));
master_mixer_l.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_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);
@ -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));
master_mixer_l.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_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);
@ -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));
master_mixer_l.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_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);

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

@ -51,16 +51,19 @@ void AudioEffectMonoStereo::update(void)
if (in && mod && out[0] && out[1])
{
float pan = mapfloat(mod->data[0], -1.0, 1.0, 0.0, 1.0);
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(in->data, in_f, AUDIO_BLOCK_SAMPLES);
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);
for (uint8_t i = 0; i < 2; i++)
{
arm_scale_f32 (in_f, f[i], out_f[i], AUDIO_BLOCK_SAMPLES);
arm_float_to_q15 (out_f[i], out[i]->data, AUDIO_BLOCK_SAMPLES);
}
// right
for (uint8_t n = 0; n < AUDIO_BLOCK_SAMPLES; n++)
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);
// left
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)
{

@ -47,6 +47,8 @@ class AudioEffectMonoStereo : public AudioStream
audio_block_t *out[2];
float in_f[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);
};

@ -64,14 +64,13 @@ inline static T max(const T& a, const T& b) {
#define QER(n,b) ( ((float)n)/(1<<b) )
#define FRAC_NUM float
//#define SIN_FUNC sinf
#define SIN_FUNC arm_sin_f32 // very fast but not as accurate
//#define COS_FUNC cosf
#define COS_FUNC arm_cos_f32 // very fast but not as accurate
#define SIN_FUNC sinf
// #define SIN_FUNC arm_sin_f32 // very fast but not as accurate
#define COS_FUNC cosf
// #define COS_FUNC arm_cos_f32 // very fast but not as accurate
#define LOG_FUNC logf
#define EXP_FUNC expf
#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

Loading…
Cancel
Save