@@ -18,6 +18,8 @@ extern void vst2_idle_detect_mode_get (int *_mode); | |||||
extern void vst2_refresh_rate_set (float _hz); | extern void vst2_refresh_rate_set (float _hz); | ||||
extern float vst2_refresh_rate_get (void); | extern float vst2_refresh_rate_get (void); | ||||
extern void vst2_window_size_set (int _width, int _height); | extern void vst2_window_size_set (int _width, int _height); | ||||
extern int vst2_fix_denorm_get (void); | |||||
extern void vst2_fix_denorm_set (int _bEnable); | |||||
#endif // RACK_HOST | #endif // RACK_HOST | ||||
namespace rack { | namespace rack { | ||||
@@ -385,6 +387,15 @@ struct SettingsVsyncItem : MenuItem { | |||||
} | } | ||||
}; | }; | ||||
struct SettingsFixDenormItem : MenuItem { | |||||
void onAction(EventAction &e) override { | |||||
#ifdef RACK_HOST | |||||
vst2_fix_denorm_set(!vst2_fix_denorm_get()); | |||||
#endif // RACK_HOST | |||||
} | |||||
}; | |||||
struct SettingsSaveItem : MenuItem { | struct SettingsSaveItem : MenuItem { | ||||
void onAction(EventAction &e) override { | void onAction(EventAction &e) override { | ||||
@@ -437,6 +448,11 @@ struct SettingsButton : TooltipIconButton { | |||||
vsyncItem->rightText = CHECKMARK( (0 != lglw_swap_interval_get(global_ui->window.lglw)) ); | vsyncItem->rightText = CHECKMARK( (0 != lglw_swap_interval_get(global_ui->window.lglw)) ); | ||||
menu->addChild(vsyncItem); | menu->addChild(vsyncItem); | ||||
SettingsFixDenormItem *fixDenormItem = new SettingsFixDenormItem(); | |||||
fixDenormItem->text = "Fix denorm. floats and clip to [-4, 4]"; | |||||
fixDenormItem->rightText = CHECKMARK( (0 != vst2_fix_denorm_get()) ); | |||||
menu->addChild(fixDenormItem); | |||||
SettingsSaveItem *saveItem = new SettingsSaveItem(); | SettingsSaveItem *saveItem = new SettingsSaveItem(); | ||||
saveItem->text = "Save Settings (+Favourites)"; | saveItem->text = "Save Settings (+Favourites)"; | ||||
menu->addChild(saveItem); | menu->addChild(saveItem); | ||||
@@ -25,6 +25,8 @@ extern void vst2_idle_detect_mode_fx_set (int _mode); | |||||
extern int vst2_idle_detect_mode_fx_get (void); | extern int vst2_idle_detect_mode_fx_get (void); | ||||
extern void vst2_idle_detect_mode_instr_set (int _mode); | extern void vst2_idle_detect_mode_instr_set (int _mode); | ||||
extern int vst2_idle_detect_mode_instr_get (void); | extern int vst2_idle_detect_mode_instr_get (void); | ||||
extern int vst2_fix_denorm_get (void); | |||||
extern void vst2_fix_denorm_set (int _bEnable); | |||||
#endif // RACK_HOST | #endif // RACK_HOST | ||||
namespace rack { | namespace rack { | ||||
@@ -168,6 +170,10 @@ static json_t *settingsToJson() { | |||||
json_t *sampleRateJ = json_real(engineGetSampleRate()); | json_t *sampleRateJ = json_real(engineGetSampleRate()); | ||||
json_object_set_new(rootJ, "sampleRate", sampleRateJ); | json_object_set_new(rootJ, "sampleRate", sampleRateJ); | ||||
// fixDenorm | |||||
json_t *fixDenormJ = json_boolean(vst2_fix_denorm_get()); | |||||
json_object_set_new(rootJ, "fixDenorm", fixDenormJ); | |||||
// lastPath | // lastPath | ||||
json_t *lastPathJ = json_string(global_ui->app.gRackWidget->lastPath.c_str()); | json_t *lastPathJ = json_string(global_ui->app.gRackWidget->lastPath.c_str()); | ||||
json_object_set_new(rootJ, "lastPath", lastPathJ); | json_object_set_new(rootJ, "lastPath", lastPathJ); | ||||
@@ -414,6 +420,13 @@ static void settingsFromJson(json_t *rootJ, bool bWindowSizeOnly) { | |||||
if (idleJ) { | if (idleJ) { | ||||
vst2_idle_detect_mode_fx_set(int(json_number_value(idleJ))); | vst2_idle_detect_mode_fx_set(int(json_number_value(idleJ))); | ||||
} | } | ||||
} | |||||
// fixDenorm | |||||
json_t *fixDenormJ = json_object_get(rootJ, "fixDenorm"); | |||||
if (fixDenormJ) | |||||
{ | |||||
vst2_fix_denorm_set(json_is_true(fixDenormJ)); | |||||
} | } | ||||
#endif // RACK_HOST | #endif // RACK_HOST | ||||
@@ -1,7 +1,7 @@ | |||||
#ifdef USE_VST2 | #ifdef USE_VST2 | ||||
/// vst2_main.cpp | /// vst2_main.cpp | ||||
/// | /// | ||||
/// (c) 2018 bsp. very loosely based on pongasoft's "hello, world" example plugin. | |||||
/// (c) 2018-2019 bsp. very loosely based on pongasoft's "hello, world" example plugin. | |||||
/// | /// | ||||
/// Licensed under the Apache License, Version 2.0 (the "License"); | /// Licensed under the Apache License, Version 2.0 (the "License"); | ||||
/// you may not use this file except in compliance with the License. | /// you may not use this file except in compliance with the License. | ||||
@@ -18,7 +18,7 @@ | |||||
/// created: 25Jun2018 | /// created: 25Jun2018 | ||||
/// changed: 26Jun2018, 27Jun2018, 29Jun2018, 01Jul2018, 02Jul2018, 06Jul2018, 13Jul2018 | /// changed: 26Jun2018, 27Jun2018, 29Jun2018, 01Jul2018, 02Jul2018, 06Jul2018, 13Jul2018 | ||||
/// 26Jul2018, 04Aug2018, 05Aug2018, 06Aug2018, 07Aug2018, 09Aug2018, 11Aug2018 | /// 26Jul2018, 04Aug2018, 05Aug2018, 06Aug2018, 07Aug2018, 09Aug2018, 11Aug2018 | ||||
/// 18Aug2018, 19Aug2018, 05Sep2018, 06Sep2018, 10Oct2018, 26Oct2018 | |||||
/// 18Aug2018, 19Aug2018, 05Sep2018, 06Sep2018, 10Oct2018, 26Oct2018, 10Mar2019 | |||||
/// | /// | ||||
/// | /// | ||||
@@ -497,6 +497,8 @@ public: | |||||
sUI idle_output_framecount; | sUI idle_output_framecount; | ||||
bool b_idle; | bool b_idle; | ||||
sBool b_fix_denorm; // true=fix denormalized floats + clip to -4..4. fixes broken audio in FLStudio and Reason. | |||||
ERect editor_rect; | ERect editor_rect; | ||||
sBool b_editor_open; | sBool b_editor_open; | ||||
@@ -1034,6 +1036,15 @@ public: | |||||
#endif // VST2_EFFECT | #endif // VST2_EFFECT | ||||
} | } | ||||
void setEnableFixDenorm(int32_t _bEnable) { | |||||
b_fix_denorm = (0 != _bEnable); | |||||
Dprintf("vst2_main:setEnableFixDenorm(%d)\n", b_fix_denorm); | |||||
} | |||||
int32_t getEnableFixDenorm(void) { | |||||
return int32_t(b_fix_denorm); | |||||
} | |||||
sUI getProgramChunk(uint8_t**_addr) { | sUI getProgramChunk(uint8_t**_addr) { | ||||
setGlobals(); | setGlobals(); | ||||
vst2_set_shared_plugin_tls_globals(); | vst2_set_shared_plugin_tls_globals(); | ||||
@@ -1503,7 +1514,28 @@ void VSTPluginProcessReplacingFloat32(VSTPlugin *vstPlugin, | |||||
wrapper->idle_output_framecount = 0u; | wrapper->idle_output_framecount = 0u; | ||||
} | } | ||||
} // if idle detect | |||||
// Fix denormalized floats (which can lead to silent audio in FLStudio and Reason) | |||||
if(wrapper->b_fix_denorm) | |||||
{ | |||||
for(chIdx = 0u; chIdx < NUM_OUTPUTS; chIdx++) | |||||
{ | |||||
float *d = _outputs[chIdx]; | |||||
for(int32_t frameIdx = 0; frameIdx < sampleFrames; frameIdx++) | |||||
{ | |||||
sF32 t = d[frameIdx]; | |||||
t = t + 100.0f; | |||||
t = t - 100.0f; | |||||
if(t >= 4.0f) | |||||
t = 4.0f; | |||||
else if(t < -4.0f) | |||||
t = -4.0f; | |||||
d[frameIdx] = t; | |||||
} | |||||
} | |||||
} | } | ||||
} // if !wrapper->b_idle | } // if !wrapper->b_idle | ||||
else | else | ||||
{ | { | ||||
@@ -2147,6 +2179,8 @@ VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback, | |||||
idle_output_sec_threshold = 120.0f / 1000.0f; // idle after 120ms of silence | idle_output_sec_threshold = 120.0f / 1000.0f; // idle after 120ms of silence | ||||
idle_output_framecount = 0u; | idle_output_framecount = 0u; | ||||
b_fix_denorm = false; | |||||
last_program_chunk_str = NULL; | last_program_chunk_str = NULL; | ||||
b_open = false; | b_open = false; | ||||
@@ -2281,6 +2315,14 @@ void vst2_idle_detect_mode_get(int *_mode) { | |||||
*_mode = int(rack::global->vst2.wrapper->idle_detect_mode); | *_mode = int(rack::global->vst2.wrapper->idle_detect_mode); | ||||
} | } | ||||
int vst2_fix_denorm_get(void) { | |||||
return rack::global->vst2.wrapper->getEnableFixDenorm(); | |||||
} | |||||
void vst2_fix_denorm_set(int _bEnable) { | |||||
rack::global->vst2.wrapper->setEnableFixDenorm(_bEnable); | |||||
} | |||||
/** | /** | ||||
* Implementation of the main entry point of the plugin | * Implementation of the main entry point of the plugin | ||||