diff --git a/src/app/Toolbar.cpp b/src/app/Toolbar.cpp index 756b8b5e..99f00d73 100644 --- a/src/app/Toolbar.cpp +++ b/src/app/Toolbar.cpp @@ -18,6 +18,8 @@ extern void vst2_idle_detect_mode_get (int *_mode); extern void vst2_refresh_rate_set (float _hz); extern float vst2_refresh_rate_get (void); 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 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 { void onAction(EventAction &e) override { @@ -437,6 +448,11 @@ struct SettingsButton : TooltipIconButton { vsyncItem->rightText = CHECKMARK( (0 != lglw_swap_interval_get(global_ui->window.lglw)) ); 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(); saveItem->text = "Save Settings (+Favourites)"; menu->addChild(saveItem); diff --git a/src/settings.cpp b/src/settings.cpp index 1bb8ad61..1f72d873 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -25,6 +25,8 @@ extern void vst2_idle_detect_mode_fx_set (int _mode); extern int vst2_idle_detect_mode_fx_get (void); extern void vst2_idle_detect_mode_instr_set (int _mode); 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 namespace rack { @@ -168,6 +170,10 @@ static json_t *settingsToJson() { json_t *sampleRateJ = json_real(engineGetSampleRate()); 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 json_t *lastPathJ = json_string(global_ui->app.gRackWidget->lastPath.c_str()); json_object_set_new(rootJ, "lastPath", lastPathJ); @@ -414,6 +420,13 @@ static void settingsFromJson(json_t *rootJ, bool bWindowSizeOnly) { if (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 diff --git a/src/vst2_main.cpp b/src/vst2_main.cpp index 1b517dcb..edf8cefe 100644 --- a/src/vst2_main.cpp +++ b/src/vst2_main.cpp @@ -1,7 +1,7 @@ #ifdef USE_VST2 /// 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"); /// you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ /// created: 25Jun2018 /// changed: 26Jun2018, 27Jun2018, 29Jun2018, 01Jul2018, 02Jul2018, 06Jul2018, 13Jul2018 /// 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; 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; sBool b_editor_open; @@ -1034,6 +1036,15 @@ public: #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) { setGlobals(); vst2_set_shared_plugin_tls_globals(); @@ -1503,7 +1514,28 @@ void VSTPluginProcessReplacingFloat32(VSTPlugin *vstPlugin, 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 else { @@ -2147,6 +2179,8 @@ VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback, idle_output_sec_threshold = 120.0f / 1000.0f; // idle after 120ms of silence idle_output_framecount = 0u; + b_fix_denorm = false; + last_program_chunk_str = NULL; b_open = false; @@ -2281,6 +2315,14 @@ void vst2_idle_detect_mode_get(int *_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