├── .gitignore ├── Builds ├── MacOSX │ ├── DSP Testbench.entitlements │ ├── DSP Testbench.xcodeproj │ │ └── project.pbxproj │ ├── Info-App.plist │ └── RecentFilesMenuTemplate.nib └── VisualStudio2022 │ ├── DSP Testbench.sln │ ├── DSP Testbench_App.vcxproj │ ├── DSP Testbench_App.vcxproj.filters │ ├── cpp.hint │ └── resources.rc ├── DSP Testbench.jucer ├── JuceLibraryCode ├── AppConfig.h ├── BinaryData.cpp ├── BinaryData.h ├── JuceHeader.h ├── ReadMe.txt ├── include_juce_audio_basics.cpp ├── include_juce_audio_basics.mm ├── include_juce_audio_devices.cpp ├── include_juce_audio_devices.mm ├── include_juce_audio_formats.cpp ├── include_juce_audio_formats.mm ├── include_juce_audio_processors.cpp ├── include_juce_audio_processors.mm ├── include_juce_audio_processors_ara.cpp ├── include_juce_audio_processors_lv2_libs.cpp ├── include_juce_audio_utils.cpp ├── include_juce_audio_utils.mm ├── include_juce_core.cpp ├── include_juce_core.mm ├── include_juce_core_CompilationTime.cpp ├── include_juce_data_structures.cpp ├── include_juce_data_structures.mm ├── include_juce_dsp.cpp ├── include_juce_dsp.mm ├── include_juce_events.cpp ├── include_juce_events.mm ├── include_juce_graphics.cpp ├── include_juce_graphics.mm ├── include_juce_graphics_Harfbuzz.cpp ├── include_juce_graphics_Sheenbidi.c ├── include_juce_gui_basics.cpp ├── include_juce_gui_basics.mm ├── include_juce_gui_extra.cpp ├── include_juce_gui_extra.mm ├── include_juce_opengl.cpp └── include_juce_opengl.mm ├── LICENSE ├── README.md ├── Resources ├── about.svg ├── audio_settings.svg ├── configure.svg ├── dashboard_gauge.svg ├── expand.svg ├── mute.svg ├── pause.svg ├── phase_invert.svg ├── play.svg └── screenshot.svg ├── Source ├── GUI │ ├── AboutComponent.cpp │ ├── AboutComponent.h │ ├── AnalyserComponent.cpp │ ├── AnalyserComponent.h │ ├── BenchmarkComponent.cpp │ ├── BenchmarkComponent.h │ ├── FftScope.h │ ├── Goniometer.cpp │ ├── Goniometer.h │ ├── LookAndFeel.cpp │ ├── LookAndFeel.h │ ├── MainComponent.cpp │ ├── MainComponent.h │ ├── MenuBarComponent.cpp │ ├── MenuBarComponent.h │ ├── MeteringComponents.cpp │ ├── MeteringComponents.h │ ├── MonitoringComponent.cpp │ ├── MonitoringComponent.h │ ├── Oscilloscope.cpp │ ├── Oscilloscope.h │ ├── ProcessorComponent.cpp │ ├── ProcessorComponent.h │ ├── SourceComponent.cpp │ └── SourceComponent.h ├── Main.cpp ├── Main.h └── Processing │ ├── AudioDataTransfer.h │ ├── AudioScopeProcessor.h │ ├── FastApproximations.h │ ├── FftProcessor.h │ ├── MeteringProcessors.cpp │ ├── MeteringProcessors.h │ ├── NoiseGenerators.h │ ├── PolyBLEP.h │ ├── ProcessorExamples.cpp │ ├── ProcessorExamples.h │ ├── ProcessorHarness.cpp │ ├── ProcessorHarness.h │ └── PulseFunctions.h └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################################ 2 | # JUCE standard .gitignore 3 | ################################################################################################ 4 | ._* 5 | *.mode1v3 6 | *.pbxuser 7 | *.perspectivev3 8 | *.user 9 | *.ncb 10 | *.suo 11 | *.ilk 12 | *.pch 13 | *.pdb 14 | *.dep 15 | *.idb 16 | *.manifest 17 | *.manifest.res 18 | *.o 19 | *.d 20 | *.sdf 21 | *.opensdf 22 | *.VC.db 23 | *.VC.opendb 24 | xcuserdata 25 | *.xccheckout 26 | *.xcscmblueprint 27 | *.xcscheme 28 | contents.xcworkspacedata 29 | .DS_Store 30 | .svn 31 | .deps 32 | .dirstamp 33 | profile 34 | **/MacOSX/build 35 | **/iOS/build 36 | **/IDEWorkspaceChecks.plist 37 | **/Linux/build 38 | **/LinuxMakefile/build 39 | **/VisualStudio[0-9]*/Win32 40 | **/VisualStudio[0-9]*/x64 41 | **/Builds/x64 42 | **/.vs 43 | **/CodeBlocks/bin 44 | **/CodeBlocks/obj 45 | **/CodeBlocks/*.depend 46 | **/CodeBlocks/*.layout 47 | **/Builds/Android/.gradle 48 | **/Builds/Android/.idea 49 | **/Builds/Android/build 50 | **/Builds/Android/**/*.iml 51 | **/Builds/Android/local.properties 52 | **/Builds/Android/app/build 53 | **/Builds/Android/app/.externalNativeBuild 54 | **/Builds/Android/app/.cxx 55 | **/Builds/Android/lib/build 56 | **/Builds/Android/lib/.externalNativeBuild 57 | **/Builds/CLion/cmake-build-* 58 | **/Builds/CLion/.idea 59 | **/Builds/MacOSX/**/Index 60 | **/Builds/MacOSX/**/Intermediates.noindex 61 | **/doxygen/doc 62 | **/doxygen/build 63 | **/.idea 64 | extras/Projucer/JUCECompileEngine.dylib 65 | 66 | .idea 67 | **/cmake-build* 68 | 69 | .vscode 70 | /build -------------------------------------------------------------------------------- /Builds/MacOSX/DSP Testbench.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Builds/MacOSX/Info-App.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CFBundleExecutable 7 | ${EXECUTABLE_NAME} 8 | CFBundleIconFile 9 | 10 | CFBundleIdentifier 11 | com.yourcompany.DSPTestbench 12 | CFBundleName 13 | DSP Testbench 14 | CFBundleDisplayName 15 | DSP Testbench 16 | CFBundlePackageType 17 | APPL 18 | CFBundleSignature 19 | ???? 20 | CFBundleShortVersionString 21 | 1.1.0 22 | CFBundleVersion 23 | 1.1.0 24 | NSHumanReadableCopyright 25 | 26 | NSHighResolutionCapable 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Builds/MacOSX/RecentFilesMenuTemplate.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndrewJJ/DSP-Testbench/124080107531336827cfbe153c92a8d5676d2bc3/Builds/MacOSX/RecentFilesMenuTemplate.nib -------------------------------------------------------------------------------- /Builds/VisualStudio2022/DSP Testbench.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio Version 17 4 | 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSP Testbench - App", "DSP Testbench_App.vcxproj", "{E94EA53F-B63F-A591-817A-2D8CDB81386C}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|x64 = Debug|x64 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {E94EA53F-B63F-A591-817A-2D8CDB81386C}.Debug|x64.ActiveCfg = Debug|x64 14 | {E94EA53F-B63F-A591-817A-2D8CDB81386C}.Debug|x64.Build.0 = Debug|x64 15 | {E94EA53F-B63F-A591-817A-2D8CDB81386C}.Release|x64.ActiveCfg = Release|x64 16 | {E94EA53F-B63F-A591-817A-2D8CDB81386C}.Release|x64.Build.0 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /Builds/VisualStudio2022/cpp.hint: -------------------------------------------------------------------------------- 1 | // Hint files help the Visual Studio IDE interpret Visual C++ identifiers 2 | // such as names of functions and macros. 3 | // For more information see https://go.microsoft.com/fwlink/?linkid=865984 4 | #define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className) JUCE_DECLARE_NON_COPYABLE(className) JUCE_LEAK_DETECTOR(className) 5 | -------------------------------------------------------------------------------- /Builds/VisualStudio2022/resources.rc: -------------------------------------------------------------------------------- 1 | #pragma code_page(65001) 2 | 3 | #ifdef JUCE_USER_DEFINED_RC_FILE 4 | #include JUCE_USER_DEFINED_RC_FILE 5 | #else 6 | 7 | #undef WIN32_LEAN_AND_MEAN 8 | #define WIN32_LEAN_AND_MEAN 9 | #include 10 | 11 | VS_VERSION_INFO VERSIONINFO 12 | FILEVERSION 1,1,0,0 13 | BEGIN 14 | BLOCK "StringFileInfo" 15 | BEGIN 16 | BLOCK "040904E4" 17 | BEGIN 18 | VALUE "FileDescription", "DSP Testbench\0" 19 | VALUE "FileVersion", "1.1.0\0" 20 | VALUE "ProductName", "DSP Testbench\0" 21 | VALUE "ProductVersion", "1.1.0\0" 22 | END 23 | END 24 | 25 | BLOCK "VarFileInfo" 26 | BEGIN 27 | VALUE "Translation", 0x409, 1252 28 | END 29 | END 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /DSP Testbench.jucer: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 29 | 31 | 33 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 60 | 62 | 64 | 66 | 68 | 69 | 70 | 72 | 74 | 76 | 77 | 79 | 81 | 83 | 84 | 86 | 88 | 90 | 92 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /JuceLibraryCode/AppConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | There's a section below where you can add your own custom code safely, and the 7 | Projucer will preserve the contents of that block, but the best way to change 8 | any of these definitions is by using the Projucer's project settings. 9 | 10 | Any commented-out settings will assume their default values. 11 | 12 | */ 13 | 14 | #pragma once 15 | 16 | //============================================================================== 17 | // [BEGIN_USER_CODE_SECTION] 18 | 19 | // (You can add your own code in this section, and the Projucer will not overwrite it) 20 | 21 | #ifndef GUI_BASE_SIZE 22 | #define GUI_BASE_SIZE 30.0 23 | #endif 24 | 25 | #ifndef GUI_BASE_SIZE_I 26 | #define GUI_BASE_SIZE_I static_cast (GUI_BASE_SIZE) 27 | #endif 28 | 29 | #ifndef GUI_BASE_SIZE_F 30 | #define GUI_BASE_SIZE_F static_cast (GUI_BASE_SIZE) 31 | #endif 32 | 33 | #ifndef GUI_BASE_SIZE_PX 34 | #define GUI_BASE_SIZE_PX Grid::Px (GUI_BASE_SIZE_I) 35 | #endif 36 | 37 | #ifndef GUI_SIZE 38 | #define GUI_SIZE(N) GUI_BASE_SIZE * (N) // Note that the brackets around the N are needed so that any calculations within the argument are performed correctly 39 | #endif 40 | 41 | #ifndef GUI_SIZE_I 42 | #define GUI_SIZE_I(N) static_cast (GUI_SIZE(N)) 43 | #endif 44 | 45 | #ifndef GUI_SIZE_F 46 | #define GUI_SIZE_F(N) static_cast (GUI_SIZE(N)) 47 | #endif 48 | 49 | #ifndef GUI_SIZE_PX 50 | #define GUI_SIZE_PX(N) Grid::Px (GUI_SIZE_I(N)) 51 | #endif 52 | 53 | #ifndef GUI_BASE_GAP 54 | #define GUI_BASE_GAP 5.0 55 | #endif 56 | 57 | #ifndef GUI_BASE_GAP_I 58 | #define GUI_BASE_GAP_I static_cast (GUI_BASE_GAP) 59 | #endif 60 | 61 | #ifndef GUI_BASE_GAP_F 62 | #define GUI_BASE_GAP_F static_cast (GUI_BASE_GAP) 63 | #endif 64 | 65 | #ifndef GUI_BASE_GAP_PX 66 | #define GUI_BASE_GAP_PX Grid::Px (GUI_BASE_GAP_I) 67 | #endif 68 | 69 | #ifndef GUI_GAP 70 | #define GUI_GAP(N) GUI_BASE_GAP * (N) // Note that the brackets around the N are needed so that any calculations within the argument are performed correctly 71 | #endif 72 | 73 | #ifndef GUI_GAP_I 74 | #define GUI_GAP_I(N) static_cast (GUI_GAP(N)) 75 | #endif 76 | 77 | #ifndef GUI_GAP_F 78 | #define GUI_GAP_F(N) static_cast (GUI_GAP(N)) 79 | #endif 80 | 81 | #ifndef GUI_GAP_PX 82 | #define GUI_GAP_PX(N) Grid::Px (GUI_GAP_I(N)) 83 | #endif 84 | 85 | 86 | // [END_USER_CODE_SECTION] 87 | 88 | #define JUCE_PROJUCER_VERSION 0x80006 89 | 90 | //============================================================================== 91 | #define JUCE_MODULE_AVAILABLE_juce_audio_basics 1 92 | #define JUCE_MODULE_AVAILABLE_juce_audio_devices 1 93 | #define JUCE_MODULE_AVAILABLE_juce_audio_formats 1 94 | #define JUCE_MODULE_AVAILABLE_juce_audio_processors 1 95 | #define JUCE_MODULE_AVAILABLE_juce_audio_utils 1 96 | #define JUCE_MODULE_AVAILABLE_juce_core 1 97 | #define JUCE_MODULE_AVAILABLE_juce_data_structures 1 98 | #define JUCE_MODULE_AVAILABLE_juce_dsp 1 99 | #define JUCE_MODULE_AVAILABLE_juce_events 1 100 | #define JUCE_MODULE_AVAILABLE_juce_graphics 1 101 | #define JUCE_MODULE_AVAILABLE_juce_gui_basics 1 102 | #define JUCE_MODULE_AVAILABLE_juce_gui_extra 1 103 | #define JUCE_MODULE_AVAILABLE_juce_opengl 1 104 | 105 | #define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1 106 | 107 | //============================================================================== 108 | // juce_audio_devices flags: 109 | 110 | #ifndef JUCE_USE_WINRT_MIDI 111 | //#define JUCE_USE_WINRT_MIDI 0 112 | #endif 113 | 114 | #ifndef JUCE_ASIO 115 | #define JUCE_ASIO 1 116 | #endif 117 | 118 | #ifndef JUCE_WASAPI 119 | //#define JUCE_WASAPI 1 120 | #endif 121 | 122 | #ifndef JUCE_DIRECTSOUND 123 | //#define JUCE_DIRECTSOUND 1 124 | #endif 125 | 126 | #ifndef JUCE_ALSA 127 | //#define JUCE_ALSA 1 128 | #endif 129 | 130 | #ifndef JUCE_JACK 131 | //#define JUCE_JACK 0 132 | #endif 133 | 134 | #ifndef JUCE_BELA 135 | //#define JUCE_BELA 0 136 | #endif 137 | 138 | #ifndef JUCE_USE_ANDROID_OBOE 139 | //#define JUCE_USE_ANDROID_OBOE 1 140 | #endif 141 | 142 | #ifndef JUCE_USE_OBOE_STABILIZED_CALLBACK 143 | //#define JUCE_USE_OBOE_STABILIZED_CALLBACK 0 144 | #endif 145 | 146 | #ifndef JUCE_USE_ANDROID_OPENSLES 147 | //#define JUCE_USE_ANDROID_OPENSLES 0 148 | #endif 149 | 150 | #ifndef JUCE_DISABLE_AUDIO_MIXING_WITH_OTHER_APPS 151 | //#define JUCE_DISABLE_AUDIO_MIXING_WITH_OTHER_APPS 0 152 | #endif 153 | 154 | //============================================================================== 155 | // juce_audio_formats flags: 156 | 157 | #ifndef JUCE_USE_FLAC 158 | //#define JUCE_USE_FLAC 1 159 | #endif 160 | 161 | #ifndef JUCE_USE_OGGVORBIS 162 | //#define JUCE_USE_OGGVORBIS 1 163 | #endif 164 | 165 | #ifndef JUCE_USE_MP3AUDIOFORMAT 166 | //#define JUCE_USE_MP3AUDIOFORMAT 0 167 | #endif 168 | 169 | #ifndef JUCE_USE_LAME_AUDIO_FORMAT 170 | //#define JUCE_USE_LAME_AUDIO_FORMAT 0 171 | #endif 172 | 173 | #ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT 174 | //#define JUCE_USE_WINDOWS_MEDIA_FORMAT 1 175 | #endif 176 | 177 | //============================================================================== 178 | // juce_audio_processors flags: 179 | 180 | #ifndef JUCE_PLUGINHOST_VST 181 | //#define JUCE_PLUGINHOST_VST 0 182 | #endif 183 | 184 | #ifndef JUCE_PLUGINHOST_VST3 185 | //#define JUCE_PLUGINHOST_VST3 0 186 | #endif 187 | 188 | #ifndef JUCE_PLUGINHOST_AU 189 | //#define JUCE_PLUGINHOST_AU 0 190 | #endif 191 | 192 | #ifndef JUCE_PLUGINHOST_LADSPA 193 | //#define JUCE_PLUGINHOST_LADSPA 0 194 | #endif 195 | 196 | #ifndef JUCE_PLUGINHOST_LV2 197 | //#define JUCE_PLUGINHOST_LV2 0 198 | #endif 199 | 200 | #ifndef JUCE_PLUGINHOST_ARA 201 | //#define JUCE_PLUGINHOST_ARA 0 202 | #endif 203 | 204 | #ifndef JUCE_CUSTOM_VST3_SDK 205 | //#define JUCE_CUSTOM_VST3_SDK 0 206 | #endif 207 | 208 | //============================================================================== 209 | // juce_audio_utils flags: 210 | 211 | #ifndef JUCE_USE_CDREADER 212 | //#define JUCE_USE_CDREADER 0 213 | #endif 214 | 215 | #ifndef JUCE_USE_CDBURNER 216 | //#define JUCE_USE_CDBURNER 0 217 | #endif 218 | 219 | //============================================================================== 220 | // juce_core flags: 221 | 222 | #ifndef JUCE_FORCE_DEBUG 223 | //#define JUCE_FORCE_DEBUG 0 224 | #endif 225 | 226 | #ifndef JUCE_LOG_ASSERTIONS 227 | //#define JUCE_LOG_ASSERTIONS 0 228 | #endif 229 | 230 | #ifndef JUCE_CHECK_MEMORY_LEAKS 231 | //#define JUCE_CHECK_MEMORY_LEAKS 1 232 | #endif 233 | 234 | #ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 235 | //#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 0 236 | #endif 237 | 238 | #ifndef JUCE_INCLUDE_ZLIB_CODE 239 | //#define JUCE_INCLUDE_ZLIB_CODE 1 240 | #endif 241 | 242 | #ifndef JUCE_USE_CURL 243 | //#define JUCE_USE_CURL 1 244 | #endif 245 | 246 | #ifndef JUCE_LOAD_CURL_SYMBOLS_LAZILY 247 | //#define JUCE_LOAD_CURL_SYMBOLS_LAZILY 0 248 | #endif 249 | 250 | #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS 251 | //#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 0 252 | #endif 253 | 254 | #ifndef JUCE_ALLOW_STATIC_NULL_VARIABLES 255 | //#define JUCE_ALLOW_STATIC_NULL_VARIABLES 0 256 | #endif 257 | 258 | #ifndef JUCE_STRICT_REFCOUNTEDPOINTER 259 | //#define JUCE_STRICT_REFCOUNTEDPOINTER 0 260 | #endif 261 | 262 | #ifndef JUCE_ENABLE_ALLOCATION_HOOKS 263 | //#define JUCE_ENABLE_ALLOCATION_HOOKS 0 264 | #endif 265 | 266 | //============================================================================== 267 | // juce_dsp flags: 268 | 269 | #ifndef JUCE_ASSERTION_FIRFILTER 270 | //#define JUCE_ASSERTION_FIRFILTER 1 271 | #endif 272 | 273 | #ifndef JUCE_DSP_USE_INTEL_MKL 274 | //#define JUCE_DSP_USE_INTEL_MKL 0 275 | #endif 276 | 277 | #ifndef JUCE_DSP_USE_SHARED_FFTW 278 | //#define JUCE_DSP_USE_SHARED_FFTW 0 279 | #endif 280 | 281 | #ifndef JUCE_DSP_USE_STATIC_FFTW 282 | //#define JUCE_DSP_USE_STATIC_FFTW 0 283 | #endif 284 | 285 | #ifndef JUCE_DSP_ENABLE_SNAP_TO_ZERO 286 | //#define JUCE_DSP_ENABLE_SNAP_TO_ZERO 1 287 | #endif 288 | 289 | //============================================================================== 290 | // juce_events flags: 291 | 292 | #ifndef JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 293 | //#define JUCE_EXECUTE_APP_SUSPEND_ON_BACKGROUND_TASK 0 294 | #endif 295 | 296 | //============================================================================== 297 | // juce_graphics flags: 298 | 299 | #ifndef JUCE_USE_COREIMAGE_LOADER 300 | //#define JUCE_USE_COREIMAGE_LOADER 1 301 | #endif 302 | 303 | #ifndef JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING 304 | //#define JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING 0 305 | #endif 306 | 307 | //============================================================================== 308 | // juce_gui_basics flags: 309 | 310 | #ifndef JUCE_ENABLE_REPAINT_DEBUGGING 311 | //#define JUCE_ENABLE_REPAINT_DEBUGGING 0 312 | #endif 313 | 314 | #ifndef JUCE_USE_XRANDR 315 | //#define JUCE_USE_XRANDR 1 316 | #endif 317 | 318 | #ifndef JUCE_USE_XINERAMA 319 | //#define JUCE_USE_XINERAMA 1 320 | #endif 321 | 322 | #ifndef JUCE_USE_XSHM 323 | //#define JUCE_USE_XSHM 1 324 | #endif 325 | 326 | #ifndef JUCE_USE_XRENDER 327 | //#define JUCE_USE_XRENDER 0 328 | #endif 329 | 330 | #ifndef JUCE_USE_XCURSOR 331 | //#define JUCE_USE_XCURSOR 1 332 | #endif 333 | 334 | #ifndef JUCE_WIN_PER_MONITOR_DPI_AWARE 335 | //#define JUCE_WIN_PER_MONITOR_DPI_AWARE 1 336 | #endif 337 | 338 | //============================================================================== 339 | // juce_gui_extra flags: 340 | 341 | #ifndef JUCE_WEB_BROWSER 342 | //#define JUCE_WEB_BROWSER 1 343 | #endif 344 | 345 | #ifndef JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING 346 | //#define JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING 0 347 | #endif 348 | 349 | #ifndef JUCE_USE_WIN_WEBVIEW2 350 | //#define JUCE_USE_WIN_WEBVIEW2 0 351 | #endif 352 | 353 | #ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR 354 | //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR 0 355 | #endif 356 | 357 | //============================================================================== 358 | #ifndef JUCE_STANDALONE_APPLICATION 359 | #if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone) 360 | #define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone 361 | #else 362 | #define JUCE_STANDALONE_APPLICATION 1 363 | #endif 364 | #endif 365 | -------------------------------------------------------------------------------- /JuceLibraryCode/BinaryData.h: -------------------------------------------------------------------------------- 1 | /* ========================================================================================= 2 | 3 | This is an auto-generated file: Any edits you make may be overwritten! 4 | 5 | */ 6 | 7 | #pragma once 8 | 9 | namespace BinaryData 10 | { 11 | extern const char* about_svg; 12 | const int about_svgSize = 1108; 13 | 14 | extern const char* audio_settings_svg; 15 | const int audio_settings_svgSize = 2610; 16 | 17 | extern const char* configure_svg; 18 | const int configure_svgSize = 1998; 19 | 20 | extern const char* dashboard_gauge_svg; 21 | const int dashboard_gauge_svgSize = 1781; 22 | 23 | extern const char* expand_svg; 24 | const int expand_svgSize = 1044; 25 | 26 | extern const char* mute_svg; 27 | const int mute_svgSize = 1263; 28 | 29 | extern const char* pause_svg; 30 | const int pause_svgSize = 811; 31 | 32 | extern const char* play_svg; 33 | const int play_svgSize = 797; 34 | 35 | extern const char* phase_invert_svg; 36 | const int phase_invert_svgSize = 1297; 37 | 38 | extern const char* screenshot_svg; 39 | const int screenshot_svgSize = 2475; 40 | 41 | // Number of elements in the namedResourceList and originalFileNames arrays. 42 | const int namedResourceListSize = 10; 43 | 44 | // Points to the start of a list of resource names. 45 | extern const char* namedResourceList[]; 46 | 47 | // Points to the start of a list of resource filenames. 48 | extern const char* originalFilenames[]; 49 | 50 | // If you provide the name of one of the binary resource variables above, this function will 51 | // return the corresponding data and its size (or a null pointer if the name isn't found). 52 | const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes); 53 | 54 | // If you provide the name of one of the binary resource variables above, this function will 55 | // return the corresponding original, non-mangled filename (or a null pointer if the name isn't found). 56 | const char* getNamedResourceOriginalFilename (const char* resourceNameUTF8); 57 | } 58 | -------------------------------------------------------------------------------- /JuceLibraryCode/JuceHeader.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | This is the header file that your files should include in order to get all the 7 | JUCE library headers. You should avoid including the JUCE headers directly in 8 | your own source files, because that wouldn't pick up the correct configuration 9 | options for your app. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include "AppConfig.h" 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "BinaryData.h" 32 | 33 | #if defined (JUCE_PROJUCER_VERSION) && JUCE_PROJUCER_VERSION < JUCE_VERSION 34 | /** If you've hit this error then the version of the Projucer that was used to generate this project is 35 | older than the version of the JUCE modules being included. To fix this error, re-save your project 36 | using the latest version of the Projucer or, if you aren't using the Projucer to manage your project, 37 | remove the JUCE_PROJUCER_VERSION define. 38 | */ 39 | #error "This project was last saved using an outdated version of the Projucer! Re-save this project with the latest version to fix this error." 40 | #endif 41 | 42 | #if ! DONT_SET_USING_JUCE_NAMESPACE 43 | // If your code uses a lot of JUCE classes, then this will obviously save you 44 | // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE. 45 | using namespace juce; 46 | #endif 47 | 48 | #if ! JUCE_DONT_DECLARE_PROJECTINFO 49 | namespace ProjectInfo 50 | { 51 | const char* const projectName = "DSP Testbench"; 52 | const char* const companyName = ""; 53 | const char* const versionString = "1.1.0"; 54 | const int versionNumber = 0x10100; 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /JuceLibraryCode/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 2 | Important Note!! 3 | ================ 4 | 5 | The purpose of this folder is to contain files that are auto-generated by the Projucer, 6 | and ALL files in this folder will be mercilessly DELETED and completely re-written whenever 7 | the Projucer saves your project. 8 | 9 | Therefore, it's a bad idea to make any manual changes to the files in here, or to 10 | put any of your own files in here if you don't want to lose them. (Of course you may choose 11 | to add the folder's contents to your version-control system so that you can re-merge your own 12 | modifications after the Projucer has saved its changes). 13 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_basics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_basics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_devices.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_devices.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_formats.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_formats.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_processors.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_processors.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_processors_ara.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_audio_utils.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_core.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_core.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_core_CompilationTime.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_data_structures.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_data_structures.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_dsp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_dsp.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_events.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_events.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_graphics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_graphics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_graphics_Harfbuzz.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_graphics_Sheenbidi.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_gui_basics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_gui_basics.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_gui_extra.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_gui_extra.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_opengl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /JuceLibraryCode/include_juce_opengl.mm: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | IMPORTANT! This file is auto-generated each time you save your 4 | project - if you alter its contents, your changes may be overwritten! 5 | 6 | */ 7 | 8 | #include "AppConfig.h" 9 | #include 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Andrew J 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSP Testbench 2 | 3 | DSP Testbench is designed to help developers using the [JUCE framework](https://juce.com) to analyse their DSP by providing a test harness for code inheriting from `juce::dsp::ProcessorBase`. The harness provides signal sources, routing, analysis and monitoring functions. 4 | 5 | ![Screenshot](./screenshot.png) 6 | 7 | ## Features 8 | 9 | ### Title Bar Controls 10 | 11 | Besides the usual window sizing buttons, the title bar hosts the following controls: 12 | 13 | - CPU meter 14 | - Snapshot 15 | - Performance benchmarks 16 | - Audio device settings 17 | - About (you already know what this does :) ) 18 | 19 | Most of the application settings are automatically saved and restored each time you restart the app. 20 | 21 | ### Signal Sources 22 | 23 | Two individual signal source modules generate synthesised signals, play back audio files, or pass through from an audio interface. The synthesis tab provides periodic waveforms with sweepable frequencies, as well as impulse & step functions and noise generators. Each source can be muted, inverted or gain trimmed, and the periodic waveforms can be synchronised between the two source modules. 24 | 25 | The triangle, square and saw oscillators are implemented with a PolyBLEP implementation to reduce aliasing, however it will still be visible in the analyser at higher frequencies. 26 | 27 | Note that white and pink noise show up as a circle on the phase scope because we generate different samples on each channel. The other oscillators generate the same samples on each channel. 28 | 29 | ### Processor Control 30 | 31 | Each of the two processor modules are used to host and control your DSP code. Either or both signal sources can be routed to each processor; and the output can be inverted, or muted. 32 | 33 | One use case is to verify that code optimisations do not alter the output. You can achieve this by hosting different versions of your DSP code in either module, routing the same audio to both, and inverting the output of one processor to ensure perfect cancellation. 34 | 35 | ### Analysis 36 | 37 | The analyser provides the following: 38 | 39 | - FFT scope with logarithmic frequency scale (0 to -80dB amplitude scale) 40 | - Oscilloscope 41 | - Phase scope 42 | - Level meter with VU (narrow) and peak (wide) meters for each channel 43 | - Clip indicators (click to popup clip stats window with reset button) 44 | - Pause button to freeze the display (audio is not paused) 45 | - Expand button 46 | - Advanced settings for scopes 47 | 48 | The oscilloscope can be zoomed using the mouse wheel (hold shift to zoom amplitude instead of time) and you can pan by clicking and dragging. Double click anywhere on the oscilloscope to reset scale 49 | 50 | ### Monitoring 51 | 52 | The monitoring section has a gain control and mute button to control the output level of the application. An optional output limiter is also provided to prevent digital overs (this is applied after the processors so does not affect their behaviour). 53 | 54 | ### Snapshot 55 | 56 | The snapshot functionality allows you to pass 4096 samples through the processor then pause the analysis and audio so you can forensically examine the resulting output. Normal operation can be resumed by toggling the snapshot button again. When a snapshot is triggered, the audio device is stopped and restarted and all modules are reset so that the same 4096 samples will be generated and processed every single time. The only exception to this is if the wave file player has its' right hand button disabled, in which case playback will be from the current position. 57 | 58 | ### Performance Benchmarks 59 | 60 | The benchmark functionality starts your processor(s) on another thread and pumps audio through, gathering statistics on how much time has been spent running your routines. A single block of audio is repeated from source A (using live audio input will not work). 61 | 62 | ## Developer Notes 63 | 64 | To make use of DSP Testbench, you need to include your own code, wrap it appropriately and build the project. 65 | 66 | - Navigate to the `Source\Processing` folder and take a look at `ProcessorExamples.h/.cpp` 67 | - This shows how to inherit from ProcessorHarness and shows examples of how to override the necessary pure virtual functions 68 | - Create a local branch of the repository before proceeding 69 | - Copy (or create) your own code into the project folder 70 | - Make sure you add these files to the Projucer project also 71 | - Either extend `ProcessorExamples.h/cpp` or create your own wrapper class and include it in `MainComponent.cpp` 72 | - Instantiate your processor harness in the `MainContentComponent` constructor 73 | - If optimising code, then use two separate wrappers and instantiate them separately 74 | - Build, run and test! 75 | 76 | ## Credits & Attributions 77 | 78 | ASIO Interface Technology by Steinberg Media Technologies GmbH 79 | 80 | This software makes use of certain code libraries, those portions of code are copyright as per below: 81 | 82 | - JUCE 8 - copyright © 2025 Raw Material Software 83 | - Application code - copyright © 2021 Oblique Audio 84 | - Fast maths approximations - copyright © 2011 Paul Mineiro 85 | - rand31pmc white noise generator - copyright © 2005 Robin Whittle 86 | - Pink noise filter - Paul Kellett 87 | - PolyBLEP/BLAMP - adapted from Tebjan Halm (vvvv.org) 88 | - MGA JS Limiter - copyright © 2008 Michael Gruhn 89 | 90 | ## Software Disclaimer 91 | 92 | This software is provided "as is" and you use it at your own risk. 93 | 94 | The developers make no warranties as to performance, merchantability, fitness for a particular purpose, or any other warranties whether expressed or implied. No oral or written communication from or information provided by the developers shall create a warranty. 95 | 96 | Under no circumstances shall the developers or contributors be liable for direct, indirect, special, incidental, or consequential damages resulting from the use, misuse, or inability to use this software, even if the developers have been advised of the possibility of such damages. 97 | 98 | These exclusions and limitations may not apply in all jurisdictions. You may have additional rights and some of these limitations may not apply to you. 99 | 100 | -------------------------------------------------------------------------------- /Resources/about.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /Resources/audio_settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 33 | 37 | 41 | 45 | 49 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Resources/configure.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 29 | 35 | 39 | 42 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Resources/dashboard_gauge.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 30 | -------------------------------------------------------------------------------- /Resources/expand.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Resources/mute.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /Resources/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /Resources/phase_invert.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 36 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Resources/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /Resources/screenshot.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml -------------------------------------------------------------------------------- /Source/GUI/AboutComponent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | AboutComponent.cpp 5 | Created: 16 Mar 2019 4:17:47pm 6 | Author: Andrew 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #include "AboutComponent.h" 12 | 13 | AboutComponent::AboutComponent() 14 | { 15 | addAndMakeVisible (txtEditor); 16 | txtEditor.setMultiLine (true); 17 | txtEditor.setReadOnly (true); 18 | txtEditor.setCaretVisible (false); 19 | txtEditor.setPopupMenuEnabled (false); 20 | txtEditor.setColour (TextEditor::ColourIds::outlineColourId, Colours::transparentBlack); 21 | txtEditor.setColour (TextEditor::ColourIds::backgroundColourId, Colours::black); 22 | 23 | Timer::callAfterDelay (10, [this] { addAboutText(); }); 24 | 25 | setSize (800, 600); 26 | } 27 | void AboutComponent::paint(Graphics & g) 28 | { 29 | g.fillAll (DspTestBenchLnF::ApplicationColours::componentBackground()); 30 | } 31 | void AboutComponent::resized() 32 | { 33 | txtEditor.setBounds(getLocalBounds().reduced(2,2)); 34 | } 35 | void AboutComponent::addAboutText() 36 | { 37 | txtEditor.clear(); 38 | 39 | insertBreak(); 40 | insertTitle ("Application description", Colours::white, false); 41 | insertText ("DSP Testbench is designed to help developers using the JUCE framework to analyse their DSP by providing "); 42 | insertText ("a test harness for code inheriting from juce::dsp::ProcessorBase. The harness provides signal sources, "); 43 | insertText ("routing, analysis and monitoring functions. See README.md for developer notes.", true); 44 | 45 | insertSubtitle ("Title bar controls"); 46 | insertText ("Besides the usual window sizing buttons, the title bar hosts the following controls:", true); 47 | insertBullet(); insertText ("CPU meter"); 48 | insertBullet(); insertText ("Snapshot"); 49 | insertBullet(); insertText ("Performance benchmarks"); 50 | insertBullet(); insertText ("Audio device settings"); 51 | insertBullet(); insertText ("About (you already know what this does :) )", true); 52 | insertBreak(); 53 | insertText ("Most of the application settings are automatically saved and restored each time you restart the app.", true); 54 | 55 | insertSubtitle ("Signal sources"); 56 | insertText ("Two individual signal source modules generate synthesised signals, play back audio files, or pass through from an audio interface. "); 57 | insertText ("The synthesis tab provides periodic waveforms with sweepable frequencies, as well as impulse & step functions and noise generators. "); 58 | insertText ("Each source can be muted, inverted or gain trimmed, and the periodic waveforms can be synchronised between the two source modules.", true); 59 | insertBreak(); 60 | insertText ("The triangle, square and saw oscillators are implemented with a PolyBLEP implementation to reduce aliasing, however it will still be "); 61 | insertText ("visible in the analyser at higher frequencies.", true); 62 | insertBreak(); 63 | insertText ("Note that white and pink noise show up as a circle on the phase scope because we generate different samples on each channel. "); 64 | insertText ("The other oscillators generate the same samples on each channel.", true); 65 | 66 | insertSubtitle ("Processor control"); 67 | insertText ("Each of the two processor modules are used to host and control your DSP code. Either or both signal sources can be routed "); 68 | insertText ("to each processor; and the output can be inverted, or muted.", true); 69 | insertBreak(); 70 | insertText ("One use case is to verify that code optimisations do not alter the output. You can achieve this by hosting different versions "); 71 | insertText ("of your DSP code in either module, routing the same audio to both, and inverting the output of one processor to ensure perfect cancellation.", true); 72 | 73 | insertSubtitle ("Analysis"); 74 | insertText ("The analyser provides the following:", true); 75 | insertBullet(); insertText ("FFT scope with logarithmic frequency scale (0 to -80dB amplitude scale)"); 76 | insertBullet(); insertText ("Oscilloscope"); 77 | insertBullet(); insertText ("Phase scope"); 78 | insertBullet(); insertText ("Level meter with VU (narrow) and peak (wide) meters for each channel"); 79 | insertBullet(); insertText ("Clip indicators (click to popup clip stats window with reset button)"); 80 | insertBullet(); insertText ("Pause button to freeze the display (audio is not paused)"); 81 | insertBullet(); insertText ("Expand button"); 82 | insertBullet(); insertText ("Advanced settings for scopes", true); 83 | insertBreak(); 84 | insertText ("The oscilloscope can be zoomed using the mouse wheel (hold shift to zoom amplitude instead of time) and you can pan by "); 85 | insertText ("clicking and dragging. Double click anywhere on the oscilloscope to reset scale", true); 86 | 87 | insertSubtitle ("Monitoring"); 88 | insertText ("The monitoring section has a gain control and mute button to control the output level of the application. An optional output limiter "); 89 | insertText ("is also provided to prevent digital overs (this is applied after the processors so does not affect their behaviour).", true); 90 | 91 | insertSubtitle ("Snapshot"); 92 | insertText ("The snapshot functionality allows you to pass 4096 samples through the processor then pause the analysis and audio so you can forensically "); 93 | insertText ("examine the resulting output. Normal operation can be resumed by toggling the snapshot button again. When a snapshot is triggered, the audio "); 94 | insertText ("device is stopped and restarted and all modules are reset so that the same 4096 samples will be generated and processed every single time. "); 95 | insertText ("The only exception to this is if the wave file player has its' right hand button disabled, in which case playback will be from the current position.", true); 96 | 97 | insertSubtitle ("Performance benchmarks"); 98 | insertText ("The benchmark functionality starts your processor(s) on another thread and pumps audio through, gathering statistics on how much time has "); 99 | insertText ("been spent running your routines. A single block of audio is repeated from source A (using live audio input will not work).", true); 100 | 101 | insertTitle ("Credits & Attributions"); 102 | insertText ("ASIO Interface Technology by Steinberg Media Technologies GmbH", true); 103 | insertBreak(); 104 | insertText ("This software makes use of certain code libraries, those portions of code are copyright as per below:", true); 105 | insertBullet(); insertText ("JUCE 8"); insertCopyright ("Raw Material Software", 2022); 106 | insertBullet(); insertText ("Application code"); insertCopyright ("Oblique Audio", 2022); 107 | insertBullet(); insertText ("Fast maths approximations"); insertCopyright ("Paul Mineiro", 2011); 108 | insertBullet(); insertText ("rand31pmc white noise generator"); insertCopyright ("Robin Whittle", 2005); 109 | insertBullet(); insertText ("Pink noise filter - Paul Kellett"); 110 | insertBullet(); insertText ("PolyBLEP/BLAMP - adapted from Tebjan Halm (vvvv.org)"); 111 | insertBullet(); insertText ("MGA JS Limiter"); insertCopyright ("Michael Gruhn", 2008); 112 | insertBreak(); 113 | 114 | insertTitle ("Software Disclaimer"); 115 | insertText ("This software is provided \"as is\" and you use it at your own risk.", true); 116 | insertBreak(); 117 | insertText ("The developers make no warranties as to performance, merchantability, fitness for a particular purpose, or any other warranties whether expressed or implied. "); 118 | insertText ("No oral or written communication from or information provided by the developers shall create a warranty.", true); 119 | insertBreak(); 120 | insertText ("Under no circumstances shall the developers or contributors be liable for direct, indirect, special, incidental, or consequential damages resulting from the use, "); 121 | insertText ("misuse, or inability to use this software, even if the developers have been advised of the possibility of such damages.", true); 122 | insertBreak(); 123 | insertText ("These exclusions and limitations may not apply in all jurisdictions. You may have additional rights and some of these limitations may not apply to you.", true); 124 | insertBreak (0.5f); 125 | 126 | txtEditor.setCaretPosition (0); 127 | } 128 | void AboutComponent::insertTitle (const String& title, const Colour textColour, const bool insertLineBefore) 129 | { 130 | txtEditor.setColour (TextEditor::ColourIds::textColourId, textColour); 131 | if (insertLineBefore) 132 | insertBreak (1.2f); 133 | txtEditor.setFont (titleFont); 134 | txtEditor.insertTextAtCaret (title.toUpperCase() + "\n"); 135 | insertBreak (0.3f); 136 | } 137 | void AboutComponent::insertSubtitle(const String & subtitle, const Colour textColour, const bool insertLineBefore) 138 | { 139 | txtEditor.setColour (TextEditor::ColourIds::textColourId, textColour); 140 | if (insertLineBefore) 141 | insertBreak (0.5f); 142 | txtEditor.setFont (subtitleFont); 143 | txtEditor.insertTextAtCaret (subtitle.toUpperCase() + "\n"); 144 | insertBreak (0.15f); 145 | } 146 | void AboutComponent::insertText (const String& text, const bool breakLine, const Colour textColour) 147 | { 148 | txtEditor.setColour (TextEditor::ColourIds::textColourId, textColour); 149 | txtEditor.setFont (textFont); 150 | txtEditor.insertTextAtCaret (text); 151 | if (breakLine) 152 | txtEditor.insertTextAtCaret ("\n"); 153 | } 154 | void AboutComponent::insertBreak (const float height) 155 | { 156 | txtEditor.setFont (Font (FontOptions (GUI_SIZE_F(height)))); 157 | txtEditor.insertTextAtCaret ("\n"); 158 | } 159 | void AboutComponent::insertBullet (const bool insertBreakBefore) 160 | { 161 | if (insertBreakBefore) 162 | insertBreak(); 163 | txtEditor.setFont (textFont); 164 | txtEditor.insertTextAtCaret (CharPointer_UTF8("\xE2\x80\xA2 ")); 165 | } 166 | void AboutComponent::insertCopyright(const String& copyrightOwner, const int year) 167 | { 168 | jassert (year > 1900); 169 | jassert (copyrightOwner.length() > 0); 170 | txtEditor.setFont (textFont); 171 | txtEditor.insertTextAtCaret (String(CharPointer_UTF8(" - copyright \xc2\xa9 ")) + String (year) + " " + copyrightOwner); 172 | } -------------------------------------------------------------------------------- /Source/GUI/AboutComponent.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | AboutComponent.h 5 | Created: 16 Mar 2019 4:17:47pm 6 | Author: Andrew 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "../JuceLibraryCode/JuceHeader.h" 14 | #include "LookAndFeel.h" 15 | 16 | class AboutComponent : public Component 17 | { 18 | public: 19 | 20 | AboutComponent(); 21 | ~AboutComponent() override = default; 22 | void paint (Graphics& g) override; 23 | void resized() override; 24 | 25 | private: 26 | 27 | using cols = DspTestBenchLnF::ApplicationColours; 28 | 29 | void addAboutText(); 30 | void insertTitle (const String& title, const Colour textColour = cols::titleFontColour(), const bool insertLineBefore = true); 31 | void insertSubtitle (const String& subtitle, const Colour textColour = cols::titleFontColour(), const bool insertLineBefore = true); 32 | void insertText (const String& text, const bool breakLine = false, const Colour textColour = cols::normalFontColour()); 33 | void insertBreak (const float height = 0.2f); 34 | void insertBullet (const bool insertBreakBefore = true); 35 | void insertCopyright (const String& copyrightOwner, const int year); 36 | 37 | TextEditor txtEditor; 38 | const Font titleFont = Font (FontOptions (GUI_SIZE_F (0.85))); 39 | const Font subtitleFont = Font (FontOptions (GUI_SIZE_F (0.65))); 40 | const Font textFont = Font (FontOptions (GUI_SIZE_F (0.60))); 41 | 42 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AboutComponent) 43 | }; -------------------------------------------------------------------------------- /Source/GUI/AnalyserComponent.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | AnalyserComponent.h 5 | Created: 11 Jan 2018 4:37:59pm 6 | Author: Andrew Jerrim 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "../JuceLibraryCode/JuceHeader.h" 14 | #include "FftScope.h" 15 | #include "Oscilloscope.h" 16 | #include "Goniometer.h" 17 | #include "MeteringComponents.h" 18 | #include "../Processing/FftProcessor.h" 19 | #include "../Processing/AudioScopeProcessor.h" 20 | #include "../Processing/MeteringProcessors.h" 21 | 22 | class AnalyserComponent final : public Component, public dsp::ProcessorBase, public Timer 23 | { 24 | public: 25 | 26 | AnalyserComponent(); 27 | ~AnalyserComponent() override; 28 | 29 | void paint (Graphics& g) override; 30 | void resized() override; 31 | void timerCallback() override; 32 | 33 | void prepare (const dsp::ProcessSpec& spec) override; 34 | void process (const dsp::ProcessContextReplacing& context) override; 35 | void reset() override; 36 | 37 | bool isProcessing() const noexcept; 38 | void activateProcessing(); 39 | void suspendProcessing(); 40 | 41 | void showClipStats(); 42 | 43 | private: 44 | 45 | int getOscilloscopeMaximumBlockSize() const; 46 | 47 | class AnalyserConfigComponent : public Component 48 | { 49 | public: 50 | explicit AnalyserConfigComponent (AnalyserComponent* analyserToConfigure); 51 | ~AnalyserConfigComponent() override 52 | = default; 53 | 54 | //void paint (Graphics& g) override; 55 | void resized () override; 56 | 57 | private: 58 | AnalyserComponent* analyserComponent; 59 | Label lblFftAggregation; 60 | ComboBox cmbFftAggregation; 61 | Label lblFftRelease; 62 | ComboBox cmbFftRelease; 63 | Label lblScopeAggregation; 64 | ComboBox cmbScopeAggregation; 65 | TextEditor txtHelp; 66 | 67 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnalyserConfigComponent); 68 | }; 69 | 70 | String keyName; 71 | std::unique_ptr config{}; 72 | 73 | Label lblTitle; 74 | std::unique_ptr btnConfig{}; 75 | std::unique_ptr btnPause{}; 76 | std::unique_ptr btnExpand{}; 77 | std::unique_ptr configComponent{}; 78 | 79 | FftProcessor<12> fftProcessor; 80 | FftScope<12> fftScope; 81 | 82 | AudioScopeProcessor audioScopeProcessor; 83 | Oscilloscope oscilloscope; 84 | Goniometer goniometer; 85 | 86 | PeakMeterProcessor peakMeterProcessor{}; 87 | VUMeterProcessor vuMeterProcessor{}; 88 | MainMeterBackground mainMeterBackground{}; 89 | OwnedArray peakMeterBars{}; 90 | OwnedArray vuMeterBars{}; 91 | OwnedArray clipIndicators{}; 92 | 93 | ClipCounterProcessor clipCounterProcessor{}; 94 | ClipStatsComponent clipStatsComponent{}; 95 | Viewport clipStatsViewport{}; 96 | std::unique_ptr clipStatsWindow{}; 97 | 98 | int numChannels = 0; 99 | 100 | Atomic statusActive = true; 101 | 102 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnalyserComponent) 103 | }; -------------------------------------------------------------------------------- /Source/GUI/BenchmarkComponent.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | BenchmarkComponent.h 5 | Created: 24 Apr 2019 9:26:12am 6 | Author: Andrew 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "../JuceLibraryCode/JuceHeader.h" 14 | #include "../Processing/ProcessorHarness.h" 15 | #include "SourceComponent.h" 16 | 17 | class BenchmarkComponent : public Component, public Timer 18 | { 19 | public: 20 | 21 | /** Pass in pointers to both process harnesses and the source component for the audio to into them. */ 22 | BenchmarkComponent (ProcessorHarness* processorHarnessA, ProcessorHarness* processorHarnessB, SourceComponent* sourceComponent); 23 | ~BenchmarkComponent() override; 24 | void paint (Graphics& g) override; 25 | void resized() override; 26 | void timerCallback() override; 27 | void setBufferAlignmentStatus (const String &status); 28 | 29 | private: 30 | 31 | class BenchmarkThread : public ThreadWithProgressWindow 32 | { 33 | public: 34 | BenchmarkThread (std::vector* harnesses, SourceComponent* sourceComponent, BenchmarkComponent* benchmarkComponent); 35 | ~BenchmarkThread() override = default; 36 | 37 | void run() override; 38 | void threadComplete (bool userPressedCancel) override; 39 | 40 | /** Set number of full test cycles to run (reset, prepare, processing). */ 41 | void setTestCycles (const int cycles); 42 | 43 | /** Set number of times to iterate the processing within each cycle. */ 44 | void setProcessingIterations (const int iterations); 45 | 46 | /**< Set ProcessSpec to test against. */ 47 | void setProcessSpec (dsp::ProcessSpec& spec); 48 | 49 | private: 50 | 51 | /** Returns true if the specified pointer points to 16 byte aligned data. */ 52 | static inline bool isSseAligned (const float* data); 53 | 54 | /** Returns a string describing the buffer alignment status. */ 55 | String getAudioBlockAlignmentStatus() const; 56 | 57 | std::vector* processingHarnesses{}; 58 | SourceComponent* srcComponent; 59 | BenchmarkComponent* parent; 60 | int testCycles = 0; 61 | int processingIterations = 0; 62 | dsp::ProcessSpec testSpec {}; 63 | HeapBlock heapBlock{}; 64 | std::unique_ptr> audioBlock{}; 65 | }; 66 | 67 | int getValueLabelIndex (const int processorIndex, const int routineIndex, const int valueIndex) const; 68 | 69 | OwnedArray