designing audio effect plugins in c++

17
Designing Audio Effect Plugins in C++ For AAX, AU, and VST3 With DSP Theory Second Edition Will C. Pirkle 13 Routledge g^^ Taylor & Francis Croup NEW YORK AND LONDON

Upload: others

Post on 28-Nov-2021

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Designing Audio Effect Plugins in C++

Designing Audio Effect Plugins in C++

For AAX, AU, and VST3 With DSP Theory

Second Edition

Will C. Pirkle

13 Routledge g ^ ^ Taylor & Francis Croup

NEW YORK AND LONDON

Page 2: Designing Audio Effect Plugins in C++

Contents

List of Figures xxiii List of Tables xliii

Preface xlvi

Chapter 1: Introduction 1

1.1 Using This Book 1 1.2 Fundamentals of Audio Signal Processing 2

1.2.1 Acquisition of Audio Samples 3 1.3 Reconstruction of the Analog Signal 4 1.4 Numerical Representation of Audio Data 5 1.5 Analytical DSP Test Signals 6

1.5.1 DC and Step (0 Hz) 7 1.5.2 Nyquist 8 1.5.3 >/2Nyquist 8 1.5.4 ^Nyquist 8 1.5.5 Impulse 8

1.6 Signal Processing Algorithms 8 1.6.1 Bookkeeping 10 1.6.2 The One-Sample Delay 10 1.6.3 Multiplication With a Scalar Value 11 1.6.4 Addition and Subtraction 12 1.6.5 Some Algorithm Examples and Difference Equations 12

1.6.5.1 Gain, Attenuation and Phase Inversion 13 1.7 1st Order Feed-Forward and Feedback Algorithms 14 1.8 Bibliography 14

Chapter 2: Anatomy of an Audio Plugin 15

2.1 Plugin Packaging: Dynamic-Link Libraries (DLLs) 15 2.2 The Plugin Description: Simple Strings 17

2.2.1 The Plugin Description: Features and Options 18 2.3 Initialization: Defining the Plugin Parameter Interface 18

2.3.1 Initialization: Defining Channel I/O Support 20 2.3.2 Initialization: Sample Rate Dependency 21

2.4 Processing: Preparing for Audio Streaming 21 2.4.1 Processing: Audio Signal Processing (DSP) 21

2.5 Mixing Parameter Changes With Audio Processing 23

vii

Page 3: Designing Audio Effect Plugins in C++

vlii Contents

2.5.1 Plugin Variables and Plugin Parameters 23 2.5.2 Parameter Smoothing 26 2.5.3 Pre and Post-Processing Updates 27 2.5.4 VST3 Sample Accurate Updates 27 2.5.5 Multi-Threaded Software 28

2.6 Monolithic Plugin Objects 30 2.7 Bibliography 31

Chapter 3: VST3 Programming Guide 32

3.1 Setting Up the VST3 SDK 32 3.1.1 VST3 Sample Projects 32 3.1.2 VST3 Documentation 33

3.2 VST3 Architecture and Anatomy 33 3.2.1 Single vs. Dual Component Architectures 34 3.2.2 VST3 Base Classes 35 3.2.3 MacOS Bundle ID 35 3.2.4 VST3 Programming Notes 35 3.2.5 VST3 and the GUID 36 3.2.6 VST3 Plugin Class Factory 37

3.3 Description: Plugin Description Strings 37 3.4 Description: Plugin Options/Features 38

3.4.1 Side Chain Input 38 3.4.2 Latency 38 3.4.3 Tail Time 38 3.4.4 Custom GUI 39 3.4.5 Factory Presets and State Save/Load 39 3.4.6 VST3 Support for 64-bit Audio 41

3.5 Initialization: Defining Plugin Parameters 41 3.5.1 Thread-Safe Parameter Access 43 3.5.2 Initialization: Defining Plugin Channel I/O Support 44 3.5.3 Initialization: Channel Counts and Sample Rate Information 45

3.6 The Buffer Process Cycle 45 3.6.1 Processing: Updating Plugin Parameters From GUI Controls 47 3.6.2 Processing: Resetting the Algorithm and Preparing for Streaming 49 3.6.3 Processing: Accessing the Audio Buffers 49 3.6.4 Processing: Writing Output Parameters 50 3.6.5 Processing: VST3 Soft Bypass 51

3.7 Destruction/Termination 51 3.8 Retrieving VST3 Host Information 52 3.9 Validating Your Plugin 52

3.10 Using ASPiK to Create VST3 Plugins 52 3.11 Bibliography 53

Chapter 4: AU Programming Guide 54

4.1 Setting Up the AU SDK 54 4.1.1 AU Sample Projects 54 4.1.2 AU Documentation 54

Page 4: Designing Audio Effect Plugins in C++

Contents ix

4.2 AU Architecture and Anatomy 55 4.2.1 AU Base Classes 56 4.2.2 MacOS Bundle ID 56 4.2.3 AU Programming Notes 56

4.3 Description: Plugin Description Strings 58 4.4 Description: Plugin Options/Features 59

4.4.1 Side Chain Input 59 4.4.2 Latency 60 4.4.3 Tail Time 60 4.4.4 Custom GUI 60 4.4.5 Factory Presets and State Save/Load 60

4.5 Initialization: Defining Plugin Parameters 61 4.5.1 Thread-Safe Parameter Access 64 4.5.2 Initialization: Defining Plugin Channel I/O Support 64 4.5.3 Initialization: Channel Counts and Sample Rate Information 65

4.6 The Buffer Process Cycle 66 4.6.1 Processing: Updating Plugin Parameters From GUI Controls 67 4.6.2 Processing: Resetting the Algorithm and Preparing for Streaming 68 4.6.3 Processing: Accessing the Audio Buffers 68 4.6.4 Processing: Writing Output Parameters 70

4.7 The AU/GUI Connection 70 4.7.1 Cocoa's Flat Namespace 72 4.7.2 The AU Event Listener System 72

4.7.2.1 The Event Lister Dispatch Callback Function 73 4.7.2.2 Creating the AU Event Listener 74 4.7.2.3 Destroying the Event Listener 75

4.8 Destruction/Termination 76 4.9 Retrieving AU Host Information 76

4.10 Validating Your Plugin 77 4.11 Using ASPiK to Create AU Plugins 77 4.12 Bibliography 77

Chapter 5: AAX Native Programming Guide 78 5.1 Setting Up the AAX SDK 79

5.1.1 AAX Sample Projects 79 5.1.2 AAX Documentation 79

5.2 AAX Architecture and Anatomy 80 5.2.1 AAX Model-Algorithm Synchronization 81 5.2.2 AAX Base Classes 82 5.2.3 MacOS Bundle ID 82 5.2.4 AAX Programming Notes 83 5.2.5 AAX Class Factory 83 5.2.6 AAX Effect Categories 83 5.2.7 AAX Algorithms: Channel-Processing Functions 84 5.2.8 AAX Algorithm Data 84 5.2.9 Algorithm Data Contents 85

Page 5: Designing Audio Effect Plugins in C++

Contents

5.3 Description: Plugin Description Strings 86 5.3.1 Description: Defining AAX Algorithms 88

5.4 Description: Plugin Options/Features 90 5.4.1 Side Chain Input 90 5.4.2 Latency 91 5.4.3 Tail Time 91 5.4.4 Custom GUI 91 5.4.5 Factory Presets and State Save/Load 92 5.4.6 AAX Notification System 92 5.4.7 AAX Custom Data 93 5.4.8 AAX EQ and Dynamics Curves 93 5.4.9 AAX Gain Reduction Meter 93

5.5 Initialization: Defining Plugin Parameters 94 5.5.1 Thread-Safe Parameter Access 97 5.5.2 Initialization: Defining Plugin Channel I/O Support 97 5.5.3 Initialization: Channel Counts and Sample Rate Information 97

5.6 The Buffer Process Cycle 98 5.6.1 Processing: Updating Plugin Parameters From GUI Controls 101 5.6.2 Processing: Resetting the Algorithm and Preparing for Streaming 101 5.6.3 Processing: Accessing the Audio Buffers 102 5.6.4 Processing: Writing Output Parameters 103 5.6.5 Processing: AAX Soft Bypass 104

5.7 Destruction/Termination 104 5.8 Retrieving AAX Host Information 104 5.9 Validating Your Plugin 105

5.10 Using ASPiK to Create AAX Plugins 106 5.11 Bibliography 106

Chapter 6: ASPiK Programming Guide 107

6.1 Plugin Kernel Portability and Native Plugin Shells 108 6.2 Organizing the SDKs: AAX, AU, and VST 111

6.2.1 Your C++Compiler Ill 6.2.2 Setting Up the AAX SDK Il l 6.2.3 Setting Up the AU SDK 112 6.2.4 Setting Up the VST SDK 112 6.2.5 Creating the Universal SDK Folder Hierarchy 112 6.2.6 Adding the VSTGU14 Library 112 6.2.7 CMake 113

6.3 Creating a Plugin Project With ASPiKreator: URFilters 114 6.3.1 ASPiK Project Folders 115 6.3.2 Running CMake 117

6.4 Adding Effect Objects to the PluginCore 117 6.4.1 The PluginCore Constructor 118 6.4.2 URFilters: GUI Parameter Lists 119 6.4.3 Parameter Smoothing 120 6.4.4 Handling the String-List Parameters 121 6.4.5 URFilters: Declaring Plugin Variables 123

Page 6: Designing Audio Effect Plugins in C++

Contents xi

6.4.6 Parameter Object Enumerations for Attributes 123 6.4.6.1 Continuous Floating Point Parameters and Discrete Integer

Parameters 125 6.4.6.2 String-List Parameters 126

6.4.7 IIRFilters: Object Declarations and Reset 127 6.4.8 IIRFilters: GUI Parameter Updates 128 6.4.9 IIRFilters: Processing Audio Data 128

6.4.10 Buffer Pre-Processing 130 6.4.11 Buffer Post-Processing 130 6.4.12 Buffer vs. Frame Processing 131 6.4.13 processAudioFrame: Information About the Frame 132 6.4.14 processAudioFrame: Input and Output Samples 133

6.5 Defining Factory Presets 135 6.6 Basic Plugin GUI Design With ASPiK's PluginGUI 136 6.7 GUI Design With VSTGUI4 137

6.7.1 Modifier Keys 138 6.7.2 Zooming (Scaling the GUI) 138 6.7.3 Reserved Control Tags 138 6.7.4 VSTGUI4 Objects 139 6.7.5 Creating a GUI With VSTGUI 139 6.7.6 Important GUI Designer Terms 140

6.8 VSTGUI C++ Objects 141 6.8.1 Basic GUI Design 142 6.8.2 The GUI Designer Workspace 144 6.8.3 Changing Your GUI Canvas Size 146 6.8.4 Setting Up the Control Tags 146 6.8.5 Importing the Graphics Files 146 6.8.6 Assembling the GUI 147 6.8.7 Setting the Background 147 6.8.8 Adding the GUI Elements 147 6.8.9 Saving and Re-Building 148

6.8.10 Scaling the GUI 148 6.8.11 More ASPiK Features 149

6.9 Bibliography 149

Chapter 7: Using RackAFX to Create ASPiK Projects 150 7.1 Installing RackAFX 151 7.2 Getting Started With RackAFX 151 7.3 Setting Up Your Project Preferences and Audio Hardware 153 7.4 Installing VSTGUI4 153 7.5 Creating a Project and Adding GUI Controls 153

7.5.1 Numerical Continuous Controls 155 7.5.2 String-List Controls 156 7.5.3 Meters 158

7.6 Anatomy of Your RackAFX Project 159 7.7 Testing Audio Algorithms With RackAFX 161 7.8 RackAFX Impulse Convolver and FIR Design Tools 163

Page 7: Designing Audio Effect Plugins in C++

xii Contents

7.9 Designing Your Custom GUI 163 7.10 Exporting Your ASPiK. Project 165 7.11 Bibliography 166

Chapter 8: C++ Conventions and How to Use This Book 167

8.1 Three Types of C++Objects 167 8.1.1 Effect Objects Become Framework Object Members 168 8.1.2 All Effect Objects and Most DSP Objects Implement Common Interfaces 169 8.1.3 DSP and Effect Objects Use Custom Data Structures for Parameter

Get/Set Operations 171 8.1.4 Effect Objects Accept Native Data From GUIs 173 8.1.5 Effect Objects Process Audio Samples 173

8.1.5.1 Series Objects 173 8.1.5.2 Parallel Objects 174

8.1.6 Effect Objects Optionally Process Frames 174 8.2 Book Projects 175

8.2.1 ASPiK Users 175 8.2.2 JUCE and Other Non-ASPiK Users 175 8.2.3 A Sample Plugin Project: GUI Control Definition 176

Chapter 9: How DSP Filters Work (Without Complex Math) 178

9.1 Frequency and Phase Response Plots 178 9.2 Frequency and Phase Adjustments From Filtering 179 9.3 1st Order Feed-Forward Filter 181 9.4 1st Order Feedback Filter 189 9.5 Final Observations 191 9.6 Homework 193 9.7 Bibliography 193

Chapter 10: Basic DSP Theory 194

10.1 The Complex Sinusoid 194 10.2 Complex Math Review 196 10.3 Time Delay as a Math Operator 198 10.4 The Sampled Sinusoid 199 10.5 1st Order Feed-Forward Filter Revisited 200

10.5.1 Negative Frequencies 201 10.6 Evaluating the Transfer Function H(co) 203

10.6.1 DC(OHz) 205 10.6.2 Nyquist (TI) 205 10.6.3 Vi Nyquist (jt/2) 205 10.6.4 VA Nyquist (JI/4) 206

10.7 Evaluating ejm 207 10.8 The z Substitution 207 10.9 The z Transform 208

10.10 The z Transform of Signals 210 10.11 The z Transform of Difference Equations 211 10.12 The z Transform of an Impulse Response 212 10.13 The Zeros of the Transfer Function 213

Page 8: Designing Audio Effect Plugins in C++

Contents xiii

10.14 Estimating the Frequency Response: Zeros 214 10.15 Filter Gain Control 214 10.16 1st Order Feedback Filter Revisited 215

10.16.1 Step 1: Take the z Transform of the Difference Equation 216 10.16.2 Step 2: Fashion the Difference Equation into a Transfer Function 216 10.16.3 Step 3: Factor out a0as the Scalar Gain Coefficient 217

10.17 The Poles of the Transfer Function 217 10.17.1 Step4: Estimate the Frequency Response 218 10.17.2 Step 5: Perform Direct Evaluation of the Frequency Response 219 10.17.3 DC(OHz) 220 10.17.4 Nyquist(Tt) 220 10.17.5 Vi Nyquist (n/2) 220 10.17.6 V* Nyquist (re/4) 221

10.18 2nd Order Feed-Forward Filter 222 10.18.1 Step 1 and Step 2: Take the z Transform of the Difference Equation

and Fashion it into a Transfer Function 222 10.18.2 Step 3: Factor Out a0 as the Scalar Gain Coefficient 222 10.18.3 Step 4: Estimate the Frequency Response 223 10.18.4 Step 5: Direct Evaluation 227 10.18.5 DC(OHz) 228 10.18.6 Nyquist (n) 228 10.18.7 Vi Nyquist (TI/2) 229 10.18.8 1/4 Nyquist (rr/4) 229 10.18.9 z Transform of Impulse Response 230

10.19 2nd Order Feedback Filter 231 10.19.1 Step 1, Step 2, and Step 3: Take the z Transform of the Difference

Equation to Get the Transfer Function, Then Factor Out a0 as the Scalar Gain Coefficient 231

10.19.2 Step 4: Estimate the Frequency Response 232 10.19.3 Step 5: Direct Evaluation 236 10.19.4 DC(OHz) 237 10.19.5 Exercise 238

10.20 1st Order Pole/Zero Filter: The Shelving Filter 238 10.20.1 Step 1, Step 2, and Step 3: Take the z Transform of the Difference

Equation to Get the Transfer Function, Then Factor Out a0 as the Scalar Gain Coefficient 239

10.20.2 Step 4: Estimate the Frequency Response 239 10.20.3 Step 5: Direct Evaluation 243 10.20.4 DC(OHz) 243

10.20.4.1 Exercise 244 10.21 The Biquadratic Filter 245

10.21.1 Step 1, Step 2, and Step 3: Take the z Transform of the Difference Equation to Get the Transfer Function, Then Factor Out a0 as the Scalar Gain Coefficient 245

10.21.2 Step 4: Plot the Poles and Zeros of the Transfer Function 246 10.21.3 The a^and bM Coefficient Naming Conventions 248

10.22 Other Biquadratic Structures 248

Page 9: Designing Audio Effect Plugins in C++

xiv Contents

10.23 C++ DSP Object: Biquad 250 10.23.1 Biquad: Enumerations and Data Structure 250 10.23.2 Biquad: Members 251 10.23.3 Biquad: Programming Notes 251

10.24 Homework 255 10.25 Bibliography 256

Chapter 11: Audio Filter Designs: HR Filters 257

11.1 Direct z-Plane Design 257 11.1.1 Simple Resonator 258 11.1.2 Smith-Angell Resonator 260

11.2 Analog Filter to Digital Filter Conversion 261 11.2.1 Example 266

11.3 Audio Biquad Filter Designs 268 11.3.1 The Audio Biquad Filter Structure 269 11.3.2 Classical Filters 270

11.3.2.1 1st Order LPF and HPF 270 11.3.2.2 2nd Order LPF and HPF 271 11.3.2.3 2nd Order BPF and BSF 272 11.3.2.4 2nd Order Butterworth LPF and HPF 273 11.3.2.5 2nd Order Butterworth BPF and BSF 274 11.3.2.6 2nd Order Linkwitz-Riley LPF and HPF 274 11.3.2.7 1st and 2nd Order APF 275 11.3.2.8 1st Order Shelving Filters 277 11.3.2.9 Low Shelving 277

11.3.2.10 High Shelf. 278 11.3.2.11 2nd Order Parametric EQ Filter: Non-Constant-Q 278 11.3.2.12 2nd Order Parametric EQ Filter: Constant-Q 279

11.4 Poles and Zeros at Infinity 280 11.4.1 1st Order All Pole Filter 282 11.4.2 2nd Order All Pole Filter: The MIDI Manufacturer's Association LPF 283 11.4.3 Vicanek's Analog Matched Magnitude 2nd Order LPF 285 11.4.4 Vicanek's Analog Matched Magnitude 2nd Order BPF 286

11.5 The Impulse Invariant Transform Method 288 11.5.1 Impulse Invariant 1st Order LPF 288 11.5.2 Impulse Invariant 2nd Order LPF 289

11.6 C++ Effect Object: AudioFilter 292 11.6.1 AudioFilter: Enumerations and Data Structure 292 11.6.2 AudioFilter: Members 292 11.6.3 AudioFilter: Programming Notes 293

11.7 Chapter Plugin: IIRFilters 296 11.7.1 IIRFilters: GUI Parameters 296 11.7.2 IIRFilters: Object Declarations and Reset 297 11.7.3 IIRFilters: GUI Parameter Update 297 11.7.4 IIRFilters: Process Audio 298

11.8 Homework 298 11.9 Bibliography 300

Page 10: Designing Audio Effect Plugins in C++

Contents

Chapter 12: Audio Filter Designs: Wave Digital and Virtual Analog 307 12.1 Wave Digital Filters 301

12.1.1 Scattering Parameters and WDFs 302 12.1.2 Simulating WDF Components 303

12.1.2.1 WDF Resistor 305 12.1.2.2 WDF Inductor 305 12.1.2.3 WDF Capacitor 305

12.1.3 Simulating WDF Component Interconnections 306 12.2 WDF Adaptors 308

12.2.1 Series Adaptors 309 12.2.2 Parallel Adaptors 310 12.2.3 More Component Combinations 311 12.2.4 Signal Flow Through a WDF Circuit 313 12.2.5 Ladder Filter WDF Library Conventions 314 12.2.6 Filter Source/Termination Impedance Matching 315 12.2.7 Bilinear Transform Frequency Warping 316

12.3 Designing Digital Ladder Filters With the WDF Library 317 12.3.1 Components and Component Combinations 317 12.3.2 Adaptors 317 12.3.3 WDF Ladder Filter Design: 3rd Order Butterworth LPF 318 12.3.4 WDF Ladder Filter Design: 3rd Order Bessel BSF 321 12.3.5 WDF Ladder Filter Design: 6th Order Constant-K BPF 324 12.3.6 WDF Ladder Filter Design: Ideal 2nd Order RLC Filters 325

12.4 Zavalishin's Virtual Analog Filters 330 12.4.1 1st Order VA Filters 330 12.4.2 2nd Order State Variable VA Filter 332

12.5 C++ DSP Object: ZVAFilter 336 12.5.1 ZVAFilter. Enumerations and Data Structure 336 12.5.2 ZVAFilter. Members 337 12.5.3 ZAFilter. Programming Notes 337

12.6 C++DSP Objects: WDF Ladder Filter Library 341 12.6.1 WDFIdealRLCxxx: Enumerations and Data Structure 342 12.6.2 WDFIdealRLCxxx: Members 342 12.6.3 WDFIdealRLCxxx: Programming Notes 342

12.7 Chapter Plugin: RLCFilters 344 12.7.1 RLCFilters: GUI Parameters 345 12.7.2 RLCFilters: Object Declarations and Reset 346 12.7.3 RLCFilters: GUI Parameter Update 346 12.7.4 RLCFilters: Process Audio 347

12.8 Homework 348 12.9 Bibliography 350

Chapter 13: Modulators: LFOs and Envelope Detectors 357 13.1 LFO Algorithms 351

13.1.1 The lAudioSignalGenerator Interface 353 13.1.2 C++ DSP Object: LFO 354 13.1.3 LFO: Enumerations and Data Structure 354

Page 11: Designing Audio Effect Plugins in C++

xvi Contents

13.1.4 LFO: Members 354 13.1.5 LFO: Programming Notes 355

13.2 Envelope Detection 357 13.2.1 C++ DSP Object: AudioDetector 359 13.2.2 AudioDetector. Enumerations and Data Structure 360 13.2.3 AudioDetector: Members 360 13.2.4 AudioDetector: Programming Notes 361

13.3 Modulating Plugin Parameters 364 13.3.1 Modulation Range, Polarity, and Depth 364 13.3.2 Modulation With the Envelope Detector 365

13.4 C++ Effect Object: EnvelopeFollower 367 13.4.1 EnvelopeFollower: Enumerations and Data Structure 367 13.4.2 EnvelopeFollower: Members 368 13.4.3 EnvelopeFollower: Programming Notes 368

13.5 Chapter Plugin 1: ModFilter 370 13.5.1 ModFilter: GUI Parameters 370 13.5.2 ModFilter: Object Declarations and Reset 371 13.5.3 ModFilter: GUI Parameter Update 372 13.5.4 ModFilter: Process Audio 372

13.6 The Phaser Effect 373 13.6.1 C++ Effect Object: PhaseShifter 375 13.6.2 PhaseShifter: Enumerations and Data Structure 376 13.6.3 PhaseShifter: Members 376 13.6.4 PhaseShifter: Programming Notes 377

13.7 Chapter Plugin 2: Phaser 380 13.7.1 Phaser: GUI Parameters 380 13.7.2 Phaser: Object Declarations and Reset 381 13.7.3 Phaser: GUI Parameter Update 381 13.7.4 Phaser: Process Audio 382

13.8 Homework 382 13.9 Bibliography 383

Chapter 14: Delay Effects and Circular Buffers 384

14.1 The Basic Digital Delay 386 14.2 Digital Delay With Wet/Dry Mix 389 14.3 An Efficient Circular Buffer Object 394

14.3.1 C++ DSP Object: CircularBuffer With Fractional Delay 397 14.3.2 CircularBuffer: Enumerations and Data Structure 398 14.3.3 CircularBuffer: Members 398 14.3.4 CircularBuffer: Programming Notes 399

14.4 Basic Delay Algorithms 401 14.4.1 Stereo Delay With Feedback 401 14.4.2 Stereo Ping-Pong Delay 401

14.5 C++ Effect Object: AudioDelay 403 14.5.1 AudioDelay: Enumerations and Data Structure 403 14.5.2 AudioDelay: Members 404 14.5.3 AudioDelay: Programming Notes 405

Page 12: Designing Audio Effect Plugins in C++

Contents xvii

14.6 Chapter Plugin: StereoDelay 408 14.6.1 StereoDelay: GUI Parameters 408 14.6.2 StereoDelay: Object Declarations and Reset 409 14.6.3 StereoDelay: GUI Parameter Update 409 14.6.4 StereoDelay: Process Audio 410 14.6.5 Synchronizing the Delay Time to BPM 410

14.6.5.1 ASPiK Users: BPM and Time Signature Information 410 14.7 More Delay Algorithms 411

14.7.1 Analog Modeling Delay 411 14.7.2 Multi-Tap Delay 412 14.7.3 LCR Delay 412 14.7.4 TC Electronics TC-2290 Dynamic Delay 412

14.8 Homework 414 14.9 Bibliography 415

Chapter 15: Modulated Delay Effects 416 15.1 The Flanger/Vibrato Effect 416

15.1.1 Stereo Flanger 418 15.2 The Chorus Effect 419

15.2.1 Stereo Chorus 421 15.3 C++ Effect Object: ModulatedDelay 422

15.3.1 ModulatedDelay: Enumerations and Data Structure 422 15.3.2 ModulatedDelay: Members 422 15.3.3 ModulatedDelay: Programming Notes 423

15.4 Chapter Plugin: ModDelay 426 15.4.1 ModDelay: GUI Parameters 426 15.4.2 ModDelay: Object Declarations and Reset 427 15.4.3 ModDelay: GUI Parameter Update 427 15.4.4 ModDelay: Process Audio 428

15.5 More Modulated Delay Algorithms 428 15.5.1 Korg Stereo Cross-Feedback Flanger/Chorus 428 15.5.2 Sony DPS-M7 Multi-Flanger 428 15.5.3 Bass Chorus 430 15.5.4 Dimension-Style Chorus (Roland Dimension D) 430 15.5.5 Sony DPS-M7 Deca Chorus 431

15.6 Homework 432 15.7 Bibliography 433

Chapter 16: Audio Filter Designs: FIR Filters 434 16.1 The Impulse Response Revisited: Convolution 434 16.2 FIR Filter Structures 437 16.3 Generating Impulse Responses 439

16.3.1 Impulse Responses of Acoustic Environments 439 16.3.2 Impulse Responses of Speakers and Cabinets 439 16.3.3 Impulse Responses by Frequency Sampling 439 16.3.4 Sampling Arbitrary Frequency Responses 439

16.3.4.1 Linear Phase FIR Using the Frequency Sampling Method 441

Page 13: Designing Audio Effect Plugins in C++

xviii Contents

16.3.5 Sampling Analog Filter Frequency Responses 441 16.3.6 Sampling Ideal Filter Frequency Responses 442

16.4 The Optimal/Parks-McClellan Method 444 16.5 Other FIR Design Methods 445 16.6 C++ DSP Function: FreqSample 446 16.7 C++ DSP Function: CalculateAnalogMagArray 446

16.7.1 calculateAnalogMagArray: Enumerations and Data Structure 447 16.7.2 calculateAnalogMagArray: Calculations 447

16.8 C++ DSP Object: LinearBuffer 448 16.8.1 LinearBuffer: Enumerations and Data Structure 448 16.8.2 LinearBuffer: Members 448 16.8.3 LinearBuffer: Programming Notes 449

16.9 C++ DSP Object: ImpulseConvolver 449 16.9.1 ImpulseConvolver: Enumerations and Data Structure 449 16.9.2 ImpulseConvolver: Members 449 16.9.3 ImpulseConvolver: Programming Notes 450

16.10 C++ Effect Object: AnalogFIRFilter 451 16.10.1 AnalogFIRFilter: Enumerations and Data Structure 452 16.10.2 AnalogFIRFilter: Members 452 16.10.3 AnalogFIRFilter: Programming Notes 453

16.11 Chapter Plugin: AnalogFIR 454 16.11.1 AnalogFIR: GUI Parameters 454 16.11.2 AnalogFIR: Object Declarations and Reset 455 16.11.3 AnalogFIR: GUI Parameter Update 456 16.11.4 AnalogFIR: Process Audio 456

16.12 Homework 457 16.13 Bibliography 457

Chapter 17: Reverb Effects 458 17.1 Anatomy of a Room Impulse Response 458

17.1.1 RT60 460 17.2 Echoes and Modes 460 17.3 The Comb Filter Reverberator 464 17.4 The Delaying All-Pass Reverberator 468

17.4.1 Alternate and Nested Delaying APF Structures 470 17.5 Schroeder's Reverberator 471 17.6 The LPF-Comb Reverberator 472 17.7 The Absorbent-APF Reverberator 474 17.8 The Modulated Delay APF 474 17.9 Moorer's Reverberator 475

17.10 Dattorro's Plate Reverb 475 17.11 The Spin Semiconductor® Reverb Tank 477 17.12 Generalized Feedback Delay Network Reverbs 479

17.12.1 Searching for FDN Coefficients 483 17.13 C++DSP Objects: Reverb Objects 483

17.13.1 C++ DSP Object: SimpleDelay 484

Page 14: Designing Audio Effect Plugins in C++

Contents xix

17.13.2 SimpleDelay: Custom Data Structure 484 17.13.3 SimpleDelay: Members 484 17.13.4 SimpleDelay: Programming Notes 485 17.13.5 C++ DSP Object: SimpleLPF 486 17.13.6 SimpleLPF: Custom Data Structure 486 17.13.7 SimpleLPF: Members 487 17.13.8 SimpleLPF: Programming Notes 487 17.13.9 C++ DSP Object: CombFilter 488

17.13.10 CombFilter: Custom Data Structure 488 17.13.11 CombFilter: Members 488 17.13.12 CombFilter: Programming Notes 488 17.13.13 C++ DSP Object: DelayAPF 489 17.13.14 DelayAPF: Custom Data Structure 490 17.13.15 DelayAPF: Members 490 17.13.16 DelayAPF Parameters: Programming Notes 491 17.13.17 C++ DSP Object: NestedDelayAPF 492 17.13.18 NestedDelayAPF: Custom Data Structure 492 17.13.19 NestedDelayAPF: Members 493 17.13.20 NestedDelayAPF: Programming Notes 493 17.13.21 C++DSP Object: TwoBandShelvingFilter 494 17.13.22 TwoBandShelvingFilter: Custom Data Structure 494 17.13.23 TwoBandShelvingFilter: Members 494 17.13.24 TwoBandShelvingFilter: Programming Notes 495

17.14 C++ Effect Object: ReverbTank 496 17.14.1 ReverbTank: Enumerations and Data Structure 498 17.14.2 ReverbTank: Members 499 17.14.3 ReverbTank: Programming Notes 499

17.15 Chapter Plugin: Reverb 504 17.15.1 Reverb:G\}\ Parameters 504 17.15.2 Reverb: Object Declarations and Reset 506 17.15.3 Reverb: GUI Parameter Update 506 17.15.4 Reverb: Process Audio 507

17.16 Homework 508 17.17 Bibliography 508

Chapter 18: Dynamics Processing 510

18.1 Compressor Output Calculation 513 18.1.1 Hard-Knee Compressor and Limiter 513 18.1.2 Soft-Knee Compressor and Limiter 514

18.2 Downward Expander Output Calculation 514 18.2.1 Hard-Knee Expander and Gate 514 18.2.2 Soft-Knee Expander 515

18.3 Final Gain Calculation 516 18.4 Stereo-Linked Dynamics Processor 516 18.5 Spectral Dynamics Processing 516 18.6 Parallel Dynamics Processing 518

Page 15: Designing Audio Effect Plugins in C++

xx Contents

18.7 Look-Ahead Processing 519 18.8 External Keying 519

18.8.1 ASPiK Users: Side Chain Code 520 18.9 Gain Reduction Metering 521

18.10 Alternate Side Chain Configurations 521 18.11 C++ DSP Object: LRFilterBank 523

18.11.1 LRFilterBank: Enumerations and Data Structure 523 18.11.2 LRFilterBank: Members 523 18.11.3 LRFilterBank: Programming Notes 523

18.12 C++ Effect Object: DynamicsProcessor 525 18.12.1 DynamicsProcessor: Enumerations and Data Structure 525 18.12.2 DynamicsProcessor: Members 526 18.12.3 DynamicsProcessor: Programming Notes 526

18.13 Chapter Plugin: Dynamics 529 18.13.1 Dynamics: GUI Parameters 529 18.13.2 Dynamics: Object Declarations and Reset 530 18.13.3 Dynamics: GUI Parameter Update 530 18.13.4 Dynamics: Process Audio and External Keying 531 18.13.5 Stereo Linking the DynamicsProcessor Objects 532 18.13.6 ASPiK Users: Enabling the Special Pro Tools Gain Reduction Meter 533

18.14 Homework 533 18.15 Bibliography 534

Chapter 19: Nonlinear Processing: Distortion, Tube Simulation, and HF Exciters 535

19.1 Frequency Domain Effects of Nonlinear Processing 536 19.2 Vacuum Tubes 538 19.3 Solid State Distortion 541 19.4 Bit Crushers 542 19.5 High Frequency Exciters 544 19.6 Virtual Bass 545 19.7 Ring Modulation 545 19.8 Nonlinear Processing Functions 547

19.8.1 Asymmetrical Waveshaping 549 19.9 C++ DSP Object: BitCrusher 550

19.9.1 BitCrusher: Enumerations and Data Structure 550 19.9.2 BitCrusher: Members 551 19.9.3 BitCrusher: Programming Notes 551

19.10 C++ DSP Object: DFOscillator 552 19.10.1 DFOscillator: Enumerations and Data Structure 552 19.10.2 DFOscillator: Members 552 19.10.3 DFOscillator: Programming Notes 553

19.11 C++DSP Functions: Waveshapers 554 19.12 C++DSP Object: TriodeClassA 554

19.12.1 TriodeClassA: Enumerations and Data Structure 554 19.12.2 TriodeClassA: Members 555 19.12.3 TriodeClassA: Programming Notes 556

19.13 C++ Effect Object: ClassATubePre 557

Page 16: Designing Audio Effect Plugins in C++

Contents xxi

19.13.1 ClassATubePre: Enumerations and Data Structure 557 19.13.2 ClassATubePre: Members 558 19.13.3 ClassATubePre: Programming Notes 558

19.14 Chapter Plugin: TubePreamp.... 560 19.14.1 TubePreamp: GUI Parameters 560 19.14.2 TubePreamp: Object Declarations and Reset 561 19.14.3 TubePreamp: GUI Parameter Update 562 19.14.4 TubePreamp: Process Audio 562

19.15 Bonus Plugin Projects 563 19.16 Homework 563 19.17 Bibliography 563

Chapter 20: FFT Processing: The Phase Vocoder 564 20.1 The Fourier Series 564 20.2 Understanding How the Fourier Kernel Works 568

20.2.1 Windowing DFT Input Data 572 20.3 The Complete DFT 573 20.4 The FFT 574

20.4.1 Overlap/Add Processing 575 20.4.2 Window Gain Correction 578 20.4.3 FFT and IFFT Magnitude and Phase 578 20.4.4 Using Phase Information 579 20.4.5 Phase Deviation 580 20.4.6 Phase Vocoder Coding 581

20.5 Some Phase Vocoder Effects 583 20.5.1 Robot and Simple Noise Reduction 583 20.5.2 Time Stretching/Shrinking 584 20.5.3 Pitch Shifting 585 20.5.4 Phase Locking 587

20.6 Fast Convolution 590 20.7 Gardner's Fast Convolution 594 20.8 Chapter Objects and Plugins 595 20.9 C++ DSP Object: FastFFT 596

20.9.1 FastFFT: Enumerations and Data Structure 596 20.9.2 FastFFT: Members 596 20.9.3 FastFFT: Programming Notes 596

20.10 C++ DSP Object: PhaseVocoder 598 20.10.1 PhaseVocoder: Enumerations and Data Structure 598 20.10.2 PhaseVocoder: Members 598 20.10.3 PhaseVocoder: Programming Notes 598

20.10.3.1 PhaseVocoder Example: Robotization 601 20.10.3.2 PhaseVocoder Example: NoiseReduction 602

20.11 C++ DSP Object: FastConvolver 602 20.11.1 FastConvolver: Members 602 20.11.2 FastConvolver: Programming Notes 603

20.12 C++ Effect Object: PSMVocoder 605 20.12.1 PSMVocoder: Enumerations and Data Structure 606

Page 17: Designing Audio Effect Plugins in C++

xxii Contents

20.12.2 PSMVocoder. Members 607 20.12.3 PSMVocoder. Programming Notes 607

20.13 Chapter Plugin: PitchShifler 610 20.13.1 PitchShifler. GUI Parameters 611 20.13.2 PitchShifler. Object Declarations and Reset 611 20.13.3 PitchShifler GUI Parameter Update 612 20.13.4 PitchShifler Process Audio 612

20.14 Third Party C++DSP Object: TwoStageFFTConvolver 612 20.15 Homework 613 20.16 Bibliography 613

Chapter 21: Displaying Custom Waveforms and FFTs 614 21.1 Custom Views for Plotting Data 614

21.1.1 ASPiK: The GUI Lifecycle and Messaging 615 21.1.2 Multi-threading: The Lock-Free Ring Buffer 617 21.1.3 A Waveform Histogram Viewer 619 21.1.4 An Audio Spectrum Analyzer View 620

Chapter 22: Sample Rate Conversion 624 22A Interpolation: Overview 624

22.1.1 Interpolation: Operations 626 22.1.2 Interpolation: Polyphase Decomposition 627

22.2 Decimation: Overview 629 22.2.1 Decimation: Operations 630 22.2.2 Decimation: Polyphase Decomposition 631

22.3 Polyphase Decomposition Math 632 22.3.1 Type-1 Decomposition 633 22.3.2 Type-2 Decomposition 634

22.3.2.1 What Is the Meaning of "Polyphase?" 635 22.4 C++ DSP Objects: Interpolator andDecimator 636

22.4.1 C++ DSP Object: Interpolator 637 22.4.2 Interpolator. Enumerations and Data Structure 638 22.4.3 Interpolator. Members 638 22.4.4 Interpolator. Programming Notes 639 22.4.5 C++ DSP Object: Decimator 639 22.4.6 Decimator. Enumerations and Data Structure 640 22.4.7 Decimator. Members 640 22.4.8 Decimator: Programming Notes 640

22.5 Chapter Plugin: TubePreamp Revisited 641 22.6 Homework 643 22.7 Bibliography 643

Index 644