1 //----------------------------------------------------------------------------- 2 // LICENSE 3 // (c) 2005-2018, Steinberg Media Technologies GmbH, All Rights Reserved 4 // (c) 2018, Guillaume Piolat (contact@auburnsounds.com) 5 //----------------------------------------------------------------------------- 6 // 7 // This Software Development Kit is licensed under the terms of the General 8 // Public License (GPL) Version 3. 9 // 10 // Details of that license can be found at: www.gnu.org/licenses/gpl-3.0.html 11 //----------------------------------------------------------------------------- 12 module dplug.vst3.ivstaudioprocessor; 13 14 version(VST3): 15 16 import dplug.vst3.ftypes; 17 18 // 64-bit seemingly need a slightly different ABI. 19 // The problem being that there is no direct pragma(pack) equivalent in D, would be simpler to have tool that displays the layout 20 version(Windows) 21 { 22 static if (size_t.sizeof == 8) 23 { 24 enum bool eventABIFix = true; 25 } 26 else 27 enum bool eventABIFix = false; 28 } 29 else version(OSX) 30 { 31 static if (size_t.sizeof == 8) 32 { 33 enum bool eventABIFix = true; 34 } 35 else 36 enum bool eventABIFix = false; 37 } 38 else 39 enum bool eventABIFix = true; 40 41 immutable string kVstAudioEffectClass = "Audio Module Class"; 42 43 struct PlugType 44 { 45 static immutable: 46 47 string kFxAnalyzer = "Fx|Analyzer"; ///< Scope, FFT-Display, Loudness Processing... 48 string kFxDelay = "Fx|Delay"; ///< Delay, Multi-tap Delay, Ping-Pong Delay... 49 string kFxDistortion = "Fx|Distortion"; ///< Amp Simulator, Sub-Harmonic, SoftClipper... 50 string kFxDynamics = "Fx|Dynamics"; ///< Compressor, Expander, Gate, Limiter, Maximizer, Tape Simulator, EnvelopeShaper... 51 string kFxEQ = "Fx|EQ"; ///< Equalization, Graphical EQ... 52 string kFxFilter = "Fx|Filter"; ///< WahWah, ToneBooster, Specific Filter,... 53 string kFx = "Fx"; ///< others type (not categorized) 54 string kFxInstrument = "Fx|Instrument"; ///< Fx which could be loaded as Instrument too 55 string kFxInstrumentExternal = "Fx|Instrument|External"; ///< Fx which could be loaded as Instrument too and is external (wrapped Hardware) 56 string kFxSpatial = "Fx|Spatial"; ///< MonoToStereo, StereoEnhancer,... 57 string kFxGenerator = "Fx|Generator"; ///< Tone Generator, Noise Generator... 58 string kFxMastering = "Fx|Mastering"; ///< Dither, Noise Shaping,... 59 string kFxModulation = "Fx|Modulation"; ///< Phaser, Flanger, Chorus, Tremolo, Vibrato, AutoPan, Rotary, Cloner... 60 string kFxPitchShift = "Fx|Pitch Shift"; ///< Pitch Processing, Pitch Correction, Vocal Tuning... 61 string kFxRestoration = "Fx|Restoration"; ///< Denoiser, Declicker,... 62 string kFxReverb = "Fx|Reverb"; ///< Reverberation, Room Simulation, Convolution Reverb... 63 string kFxSurround = "Fx|Surround"; ///< dedicated to surround processing: LFE Splitter, Bass Manager... 64 string kFxTools = "Fx|Tools"; ///< Volume, Mixer, Tuner... 65 string kFxNetwork = "Fx|Network"; ///< using Network 66 67 string kInstrument = "Instrument"; ///< Effect used as instrument (sound generator), not as insert 68 string kInstrumentDrum = "Instrument|Drum"; ///< Instrument for Drum sounds 69 string kInstrumentSampler = "Instrument|Sampler"; ///< Instrument based on Samples 70 string kInstrumentSynth = "Instrument|Synth"; ///< Instrument based on Synthesis 71 string kInstrumentSynthSampler = "Instrument|Synth|Sampler"; ///< Instrument based on Synthesis and Samples 72 string kInstrumentExternal = "Instrument|External";///< External Instrument (wrapped Hardware) 73 74 string kSpatial = "Spatial"; ///< used for SurroundPanner 75 string kSpatialFx = "Spatial|Fx"; ///< used for SurroundPanner and as insert effect 76 string kOnlyRealTime = "OnlyRT"; ///< indicates that it supports only realtime process call, no processing faster than realtime 77 string kOnlyOfflineProcess = "OnlyOfflineProcess"; ///< used for Plug-in offline processing (will not work as normal insert Plug-in) 78 string kNoOfflineProcess = "NoOfflineProcess"; ///< will be NOT used for Plug-in offline processing (will work as normal insert Plug-in) 79 string kUpDownMix = "Up-Downmix"; ///< used for Mixconverter/Up-Mixer/Down-Mixer 80 string kAnalyzer = "Analyzer"; ///< Meter, Scope, FFT-Display, not selectable as insert plugin 81 string kAmbisonics = "Ambisonics"; ///< used for Ambisonics channel (FX or Panner/Mixconverter/Up-Mixer/Down-Mixer when combined with other category) 82 83 string kMono = "Mono"; ///< used for Mono only Plug-in [optional] 84 string kStereo = "Stereo"; ///< used for Stereo only Plug-in [optional] 85 string kSurround = "Surround"; ///< used for Surround only Plug-in [optional] 86 } 87 88 89 alias ComponentFlags = int; 90 enum : ComponentFlags 91 { 92 kDistributable = 1 << 0, ///< Component can be run on remote computer 93 kSimpleModeSupported = 1 << 1 ///< Component supports simple IO mode (or works in simple mode anyway) see \ref vst3IoMode 94 } 95 96 97 // Symbolic sample size. 98 alias SymbolicSampleSizes = int; 99 enum : SymbolicSampleSizes 100 { 101 kSample32, ///< 32-bit precision 102 kSample64 ///< 64-bit precision 103 } 104 105 /** Processing mode informs the Plug-in about the context and at which frequency the process call is called. 106 VST3 defines 3 modes: 107 - kRealtime: each process call is called at a realtime frequency (defined by [numSamples of ProcessData] / samplerate). 108 The Plug-in should always try to process as fast as possible in order to let enough time slice to other Plug-ins. 109 - kPrefetch: each process call could be called at a variable frequency (jitter, slower / faster than realtime), 110 the Plug-in should process at the same quality level than realtime, Plug-in must not slow down to realtime 111 (e.g. disk streaming)! 112 The host should avoid to process in kPrefetch mode such sampler based Plug-in. 113 - kOffline: each process call could be faster than realtime or slower, higher quality than realtime could be used. 114 Plug-ins using disk streaming should be sure that they have enough time in the process call for streaming, 115 if needed by slowing down to realtime or slower. 116 . 117 Note about Process Modes switching: 118 -Switching between kRealtime and kPrefetch process modes are done in realtime thread without need of calling 119 IAudioProcessor::setupProcessing, the Plug-in should check in process call the member processMode of ProcessData 120 in order to know in which mode it is processed. 121 -Switching between kRealtime (or kPrefetch) and kOffline requires that the host calls IAudioProcessor::setupProcessing 122 in order to inform the Plug-in about this mode change. */ 123 alias ProcessModes = int; 124 enum : ProcessModes 125 { 126 kRealtime, ///< realtime processing 127 kPrefetch, ///< prefetch processing 128 kOffline ///< offline processing 129 } 130 131 /** kNoTail 132 * 133 * to be returned by getTailSamples when no tail is wanted 134 \see IAudioProcessor::getTailSamples */ 135 enum uint kNoTail = 0; 136 137 /** kInfiniteTail 138 * 139 * to be returned by getTailSamples when infinite tail is wanted 140 \see IAudioProcessor::getTailSamples */ 141 enum uint kInfiniteTail = uint.max; 142 143 /** Audio processing setup. 144 \see IAudioProcessor::setupProcessing */ 145 struct ProcessSetup 146 { 147 int32 processMode; ///< \ref ProcessModes 148 int32 symbolicSampleSize; ///< \ref SymbolicSampleSizes 149 int32 maxSamplesPerBlock; ///< maximum number of samples per audio block 150 SampleRate sampleRate; ///< sample rate 151 } 152 153 mixin SMTG_TYPE_SIZE_CHECK!(ProcessSetup, 24, 20, 24); 154 155 /** Processing buffers of an audio bus. 156 This structure contains the processing buffer for each channel of an audio bus. 157 - The number of channels (numChannels) must always match the current bus arrangement. 158 It could be set to value '0' when the host wants to flush the parameters (when the Plug-in is not processed). 159 - The size of the channel buffer array must always match the number of channels. So the host 160 must always supply an array for the channel buffers, regardless if the 161 bus is active or not. However, if an audio bus is currently inactive, the actual sample 162 buffer addresses are safe to be null. 163 - The silence flag is set when every sample of the according buffer has the value '0'. It is 164 intended to be used as help for optimizations allowing a Plug-in to reduce processing activities. 165 But even if this flag is set for a channel, the channel buffers must still point to valid memory! 166 This flag is optional. A host is free to support it or not. 167 . 168 \see ProcessData */ 169 struct AudioBusBuffers 170 { 171 int32 numChannels = 0; ///< number of audio channels in bus 172 uint64 silenceFlags = 0; ///< Bitset of silence state per channel 173 union 174 { 175 Sample32** channelBuffers32 = null; ///< sample buffers to process with 32-bit precision 176 Sample64** channelBuffers64; ///< sample buffers to process with 64-bit precision 177 } 178 } 179 180 mixin SMTG_TYPE_SIZE_CHECK!(AudioBusBuffers, 24, 16, 24); 181 182 /** Any data needed in audio processing. 183 The host prepares AudioBusBuffers for each input/output bus, 184 regardless of the bus activation state. Bus buffer indices always match 185 with bus indices used in IComponent::getBusInfo of media type kAudio. 186 \see AudioBusBuffers, IParameterChanges, IEventList, ProcessContext */ 187 struct ProcessData 188 { 189 int32 processMode = 0; ///< processing mode - value of \ref ProcessModes 190 int32 symbolicSampleSize = kSample32; ///< sample size - value of \ref SymbolicSampleSizes 191 int32 numSamples = 0; ///< number of samples to process 192 int32 numInputs = 0; ///< number of audio input buses 193 int32 numOutputs = 0; ///< number of audio output buses 194 AudioBusBuffers* inputs = null; ///< buffers of input buses 195 AudioBusBuffers* outputs = null; ///< buffers of output buses 196 197 IParameterChanges inputParameterChanges = null; ///< incoming parameter changes for this block 198 IParameterChanges outputParameterChanges = null; ///< outgoing parameter changes for this block (optional) 199 IEventList inputEvents = null; ///< incoming events for this block (optional) 200 IEventList outputEvents = null; ///< outgoing events for this block (optional) 201 ProcessContext* processContext = null; ///< processing context (optional, but most welcome) 202 } 203 204 mixin SMTG_TYPE_SIZE_CHECK!(ProcessData, 80, 48, 48); 205 206 /** Audio Processing Interface. 207 This interface must always be supported by audio processing Plug-ins. */ 208 interface IAudioProcessor: FUnknown 209 { 210 public: 211 nothrow: 212 @nogc: 213 214 /** Try to set (from host) a predefined arrangement for inputs and outputs. 215 The host should always deliver the same number of input and output buses than the Plug-in needs 216 (see \ref IComponent::getBusCount). 217 The Plug-in returns kResultFalse if wanted arrangements are not supported. 218 If the Plug-in accepts these arrangements, it should modify its buses to match the new arrangements 219 (asked by the host with IComponent::getInfo () or IAudioProcessor::getBusArrangement ()) and then return kResultTrue. 220 If the Plug-in does not accept these arrangements, but can adapt its current arrangements (according to the wanted ones), 221 it should modify its buses arrangements and return kResultFalse. */ 222 tresult setBusArrangements (SpeakerArrangement* inputs, int32 numIns, SpeakerArrangement* outputs, int32 numOuts); 223 224 /** Gets the bus arrangement for a given direction (input/output) and index. 225 Note: IComponent::getInfo () and IAudioProcessor::getBusArrangement () should be always return the same 226 information about the buses arrangements. */ 227 tresult getBusArrangement (BusDirection dir, int32 index, ref SpeakerArrangement arr); 228 229 /** Asks if a given sample size is supported see \ref SymbolicSampleSizes. */ 230 tresult canProcessSampleSize (int32 symbolicSampleSize); 231 232 /** Gets the current Latency in samples. 233 The returned value defines the group delay or the latency of the Plug-in. For example, if the Plug-in internally needs 234 to look in advance (like compressors) 512 samples then this Plug-in should report 512 as latency. 235 If during the use of the Plug-in this latency change, the Plug-in has to inform the host by 236 using IComponentHandler::restartComponent (kLatencyChanged), this could lead to audio playback interruption 237 because the host has to recompute its internal mixer delay compensation. 238 Note that for player live recording this latency should be zero or small. */ 239 uint32 getLatencySamples (); 240 241 /** Called in disable state (not active) before processing will begin. */ 242 tresult setupProcessing (ref ProcessSetup setup); 243 244 /** Informs the Plug-in about the processing state. This will be called before any process calls start with true and after with false. 245 Note that setProcessing (false) may be called after setProcessing (true) without any process calls. 246 In this call the Plug-in should do only light operation (no memory allocation or big setup reconfiguration), 247 this could be used to reset some buffers (like Delay line or Reverb). */ 248 tresult setProcessing (TBool state); 249 250 /** The Process call, where all information (parameter changes, event, audio buffer) are passed. */ 251 tresult process (ref ProcessData data); 252 253 /** Gets tail size in samples. For example, if the Plug-in is a Reverb Plug-in and it knows that 254 the maximum length of the Reverb is 2sec, then it has to return in getTailSamples() 255 (in VST2 it was getGetTailSize ()): 2*sampleRate. 256 This information could be used by host for offline processing, process optimization and 257 downmix (avoiding signal cut (clicks)). 258 It should return: 259 - kNoTail when no tail 260 - x * sampleRate when x Sec tail. 261 - kInfiniteTail when infinite tail. */ 262 uint32 getTailSamples (); 263 264 __gshared immutable TUID iid = INLINE_UID(0x42043F99, 0xB7DA453C, 0xA569E79D, 0x9AAEC33D); 265 } 266 267 268 // ivstparameterchanges.h 269 270 //---------------------------------------------------------------------- 271 /** Queue of changes for a specific parameter. 272 \ingroup vstIHost vst300 273 - [host imp] 274 - [released: 3.0.0] 275 276 The change queue can be interpreted as segment of an automation curve. For each 277 processing block a segment with the size of the block is transmitted to the processor. 278 The curve is expressed as sampling points of a linear approximation of 279 the original automation curve. If the original already is a linear curve it can 280 be transmitted precisely. A non-linear curve has to be converted to a linear 281 approximation by the host. Every point of the value queue defines a linear 282 section of the curve as a straight line from the previous point of a block to 283 the new one. So the Plug-in can calculate the value of the curve for any sample 284 position in the block. 285 286 <b>Implicit Points:</b> \n 287 In each processing block the section of the curve for each parameter is transmitted. 288 In order to reduce the amount of points, the point at block position 0 can be omitted. 289 - If the curve has a slope of 0 over a period of multiple blocks, only one point is 290 transmitted for the block where the constant curve section starts. The queue for the following 291 blocks will be empty as long as the curve slope is 0. 292 - If the curve has a constant slope other than 0 over the period of several blocks, only 293 the value for the last sample of the block is transmitted. In this case the last valid point 294 is at block position -1. The processor can calculate the value for each sample in the block 295 by using a linear interpolation: 296 \code 297 double x1 = -1; // position of last point related to current buffer 298 double y1 = currentParameterValue; // last transmitted value 299 300 int32 pointTime = 0; 301 ParamValue pointValue = 0; 302 IParamValueQueue::getPoint (0, pointTime, pointValue); 303 304 double x2 = pointTime; 305 double y2 = pointValue; 306 307 double slope = (y2 - y1) / (x2 - x1); 308 double offset = y1 - (slope * x1); 309 310 double curveValue = (slope * bufferTime) + offset; // bufferTime is any position in buffer 311 \endcode 312 313 <b>Jumps:</b> \n 314 A jump in the automation curve has to be transmitted as two points: one with the 315 old value and one with the new value at the next sample position. 316 317 \image html "automation.jpg" 318 \see IParameterChanges, ProcessData 319 */ 320 interface IParamValueQueue: FUnknown 321 { 322 public: 323 nothrow: 324 @nogc: 325 /** Returns its associated ID. */ 326 ParamID getParameterId (); 327 328 /** Returns count of points in the queue. */ 329 int32 getPointCount (); 330 331 /** Gets the value and offset at a given index. */ 332 tresult getPoint (int32 index, ref int32 sampleOffset /*out*/, ref ParamValue value /*out*/); 333 334 /** Adds a new value at the end of the queue, its index is returned. */ 335 tresult addPoint (int32 sampleOffset, ParamValue value, ref int32 index /*out*/); 336 337 __gshared immutable TUID iid = INLINE_UID(0x01263A18, 0xED074F6F, 0x98C9D356, 0x4686F9BA); 338 } 339 340 //---------------------------------------------------------------------- 341 /** All parameter changes of a processing block. 342 \ingroup vstIHost vst300 343 - [host imp] 344 - [released: 3.0.0] 345 346 This interface is used to transmit any changes that shall be applied to parameters 347 in the current processing block. A change can be caused by GUI interaction as 348 well as automation. They are transmitted as a list of queues (IParamValueQueue) 349 containing only queues for parameters that actually did change. 350 \see IParamValueQueue, ProcessData */ 351 //---------------------------------------------------------------------- 352 interface IParameterChanges: FUnknown 353 { 354 public: 355 nothrow: 356 @nogc: 357 /** Returns count of Parameter changes in the list. */ 358 int32 getParameterCount () ; 359 360 /** Returns the queue at a given index. */ 361 IParamValueQueue getParameterData (int32 index); 362 363 /** Adds a new parameter queue with a given ID at the end of the list, 364 returns it and its index in the parameter changes list. */ 365 IParamValueQueue addParameterData (ref const(ParamID) id, ref int32 index /*out*/); 366 367 __gshared immutable TUID iid = INLINE_UID(0xA4779663, 0x0BB64A56, 0xB44384A8, 0x466FEB9D); 368 } 369 370 // ivstprocesscontext.h 371 372 /** Audio processing context. 373 For each processing block the host provides timing information and 374 musical parameters that can change over time. For a host that supports jumps 375 (like cycle) it is possible to split up a processing block into multiple parts in 376 order to provide a correct project time inside of every block, but this behaviour 377 is not mandatory. Since the timing will be correct at the beginning of the next block 378 again, a host that is dependent on a fixed processing block size can choose to neglect 379 this problem. 380 \see IAudioProcessor, ProcessData*/ 381 struct ProcessContext 382 { 383 /** Transport state & other flags */ 384 alias StatesAndFlags = int; 385 enum : StatesAndFlags 386 { 387 kPlaying = 1 << 1, ///< currently playing 388 kCycleActive = 1 << 2, ///< cycle is active 389 kRecording = 1 << 3, ///< currently recording 390 391 kSystemTimeValid = 1 << 8, ///< systemTime contains valid information 392 kContTimeValid = 1 << 17, ///< continousTimeSamples contains valid information 393 394 kProjectTimeMusicValid = 1 << 9,///< projectTimeMusic contains valid information 395 kBarPositionValid = 1 << 11, ///< barPositionMusic contains valid information 396 kCycleValid = 1 << 12, ///< cycleStartMusic and barPositionMusic contain valid information 397 398 kTempoValid = 1 << 10, ///< tempo contains valid information 399 kTimeSigValid = 1 << 13, ///< timeSigNumerator and timeSigDenominator contain valid information 400 kChordValid = 1 << 18, ///< chord contains valid information 401 402 kSmpteValid = 1 << 14, ///< smpteOffset and frameRate contain valid information 403 kClockValid = 1 << 15 ///< samplesToNextClock valid 404 } 405 406 uint32 state; ///< a combination of the values from \ref StatesAndFlags 407 408 double sampleRate; ///< current sample rate (always valid) 409 TSamples projectTimeSamples; ///< project time in samples (always valid) 410 411 int64 systemTime; ///< system time in nanoseconds (optional) 412 TSamples continousTimeSamples; ///< project time, without loop (optional) 413 414 TQuarterNotes projectTimeMusic; ///< musical position in quarter notes (1.0 equals 1 quarter note) 415 TQuarterNotes barPositionMusic; ///< last bar start position, in quarter notes 416 TQuarterNotes cycleStartMusic; ///< cycle start in quarter notes 417 TQuarterNotes cycleEndMusic; ///< cycle end in quarter notes 418 419 double tempo; ///< tempo in BPM (Beats Per Minute) 420 int32 timeSigNumerator; ///< time signature numerator (e.g. 3 for 3/4) 421 int32 timeSigDenominator; ///< time signature denominator (e.g. 4 for 3/4) 422 423 Chord chord; ///< musical info 424 425 int32 smpteOffsetSubframes; ///< SMPTE (sync) offset in subframes (1/80 of frame) 426 FrameRate frameRate; ///< frame rate 427 428 int32 samplesToNextClock; ///< MIDI Clock Resolution (24 Per Quarter Note), can be negative (nearest) 429 } 430 431 mixin SMTG_TYPE_SIZE_CHECK!(ProcessContext, 112, 104, 112); 432 433 struct FrameRate 434 { 435 enum FrameRateFlags 436 { 437 kPullDownRate = 1 << 0, ///< for ex. HDTV: 23.976 fps with 24 as frame rate 438 kDropRate = 1 << 1 ///< for ex. 29.97 fps drop with 30 as frame rate 439 }; 440 uint32 framesPerSecond; ///< frame rate 441 uint32 flags; ///< flags #FrameRateFlags 442 } 443 444 mixin SMTG_TYPE_SIZE_CHECK!(FrameRate, 8, 8, 8); 445 446 /** Description of a chord. 447 A chord is described with a key note, a root note and the 448 \copydoc chordMask 449 \see ProcessContext*/ 450 451 struct Chord 452 { 453 uint8 keyNote; ///< key note in chord 454 uint8 rootNote; ///< lowest note in chord 455 456 /** Bitmask of a chord. 457 1st bit set: minor second; 2nd bit set: major second, and so on. \n 458 There is \b no bit for the keynote (root of the chord) because it is inherently always present. \n 459 Examples: 460 - XXXX 0000 0100 1000 (= 0x0048) -> major chord\n 461 - XXXX 0000 0100 0100 (= 0x0044) -> minor chord\n 462 - XXXX 0010 0100 0100 (= 0x0244) -> minor chord with minor seventh */ 463 int16 chordMask; 464 465 enum Masks { 466 kChordMask = 0x0FFF, ///< mask for chordMask 467 kReservedMask = 0xF000 ///< reserved for future use 468 } 469 } 470 471 mixin SMTG_TYPE_SIZE_CHECK!(Chord, 4, 4, 4); 472 473 /** Note-on event specific data. Used in \ref Event (union)*/ 474 struct NoteOnEvent 475 { 476 short channel; ///< channel index in event bus 477 short pitch; ///< range [0, 127] = [C-2, G8] with A3=440Hz 478 float tuning; ///< 1.f = +1 cent, -1.f = -1 cent 479 float velocity; ///< range [0.0, 1.0] 480 int length; ///< in sample frames (optional, Note Off has to follow in any case!) 481 int noteId; ///< note identifier (if not available then -1) 482 } 483 484 mixin SMTG_TYPE_SIZE_CHECK!(NoteOnEvent, 20, 20, 20); 485 486 /** Note-off event specific data. Used in \ref Event (union)*/ 487 struct NoteOffEvent 488 { 489 int16 channel; ///< channel index in event bus 490 int16 pitch; ///< range [0, 127] = [C-2, G8] with A3=440Hz 491 float velocity; ///< range [0.0, 1.0] 492 int32 noteId; ///< associated noteOn identifier (if not available then -1) 493 float tuning; ///< 1.f = +1 cent, -1.f = -1 cent 494 } 495 496 mixin SMTG_TYPE_SIZE_CHECK!(NoteOffEvent, 16, 16, 16); 497 498 /** Data event specific data. Used in \ref Event (union)*/ 499 struct DataEvent 500 { 501 uint32 size; ///< size in bytes of the data block bytes 502 uint32 type; ///< type of this data block (see \ref DataTypes) 503 const uint8* bytes; ///< pointer to the data block 504 505 /** Value for DataEvent::type */ 506 enum DataTypes 507 { 508 kMidiSysEx = 0 ///< for MIDI system exclusive message 509 } 510 } 511 512 mixin SMTG_TYPE_SIZE_CHECK!(DataEvent, 16, 12, 12); 513 514 /** PolyPressure event specific data. Used in \ref Event (union)*/ 515 struct PolyPressureEvent 516 { 517 int16 channel; ///< channel index in event bus 518 int16 pitch; ///< range [0, 127] = [C-2, G8] with A3=440Hz 519 float pressure; ///< range [0.0, 1.0] 520 int32 noteId; ///< event should be applied to the noteId (if not -1) 521 } 522 523 mixin SMTG_TYPE_SIZE_CHECK!(PolyPressureEvent, 12, 12, 12); 524 525 /** Chord event specific data. Used in \ref Event (union)*/ 526 struct ChordEvent 527 { 528 int16 root; ///< range [0, 127] = [C-2, G8] with A3=440Hz 529 int16 bassNote; ///< range [0, 127] = [C-2, G8] with A3=440Hz 530 int16 mask; ///< root is bit 0 531 uint16 textLen; ///< the number of characters (TChar) between the beginning of text and the terminating 532 ///< null character (without including the terminating null character itself) 533 const TChar* text; ///< UTF-16, null terminated Hosts Chord Name 534 } 535 536 mixin SMTG_TYPE_SIZE_CHECK!(ChordEvent, 16, 12, 12); 537 538 /** Legacy MIDI CC Out event specific data. Used in \ref Event (union)*/ 539 struct LegacyMIDICCOutEvent 540 { 541 uint8 controlNumber; ///< see enum ControllerNumbers [0, 255] 542 int8 channel; ///< channel index in event bus [0, 15] 543 int8 value; ///< value of Controller [0, 127] 544 int8 value2; ///< [0, 127] used for pitch bend (kPitchBend) and polyPressure (kCtrlPolyPressure) 545 }; 546 547 mixin SMTG_TYPE_SIZE_CHECK!(LegacyMIDICCOutEvent, 4, 4, 4); 548 549 550 551 static if (eventABIFix) 552 { 553 /** Event */ 554 struct Event 555 { 556 int32 busIndex; ///< event bus index 557 int32 sampleOffset; ///< sample frames related to the current block start sample position 558 TQuarterNotes ppqPosition; ///< position in project 559 uint16 flags; ///< combination of \ref EventFlags 560 561 /** Event Flags - used for Event::flags */ 562 enum EventFlags 563 { 564 kIsLive = 1 << 0, ///< indicates that the event is played live (directly from keyboard) 565 566 kUserReserved1 = 1 << 14, ///< reserved for user (for internal use) 567 kUserReserved2 = 1 << 15 ///< reserved for user (for internal use) 568 } 569 570 /** Event Types - used for Event::type */ 571 enum EventTypes 572 { 573 kNoteOnEvent = 0, ///< is \ref NoteOnEvent 574 kNoteOffEvent, ///< is \ref NoteOffEvent 575 kDataEvent, ///< is \ref DataEvent 576 kPolyPressureEvent, ///< is \ref PolyPressureEvent 577 kNoteExpressionValueEvent, ///< is \ref NoteExpressionValueEvent 578 kNoteExpressionTextEvent, ///< is \ref NoteExpressionTextEvent 579 kChordEvent, ///< is \ref ChordEvent 580 kScaleEvent, ///< is \ref ScaleEvent 581 kLegacyMIDICCOutEvent = 65535, ///< is \ref LegacyMIDICCOutEvent 582 } 583 584 uint16 type; ///< a value from \ref EventTypes 585 union 586 { 587 NoteOnEvent noteOn; ///< type == kNoteOnEvent 588 NoteOffEvent noteOff; ///< type == kNoteOffEvent 589 DataEvent data; ///< type == kDataEvent 590 PolyPressureEvent polyPressure; ///< type == kPolyPressureEvent 591 NoteExpressionValueEvent noteExpressionValue; ///< type == kNoteExpressionValueEvent 592 NoteExpressionTextEvent noteExpressionText; ///< type == kNoteExpressionTextEvent 593 ChordEvent chord; ///< type == kChordEvent 594 //ScaleEvent scale; ///< type == kScaleEvent 595 LegacyMIDICCOutEvent midiCCOut; ///< type == kLegacyMIDICCOutEvent 596 } 597 } 598 } 599 else 600 { 601 /** Event */ 602 struct Event 603 { 604 align(1): 605 int32 busIndex; ///< event bus index 606 int32 sampleOffset; ///< sample frames related to the current block start sample position 607 TQuarterNotes ppqPosition; ///< position in project 608 uint16 flags; ///< combination of \ref EventFlags 609 610 /** Event Flags - used for Event::flags */ 611 enum EventFlags 612 { 613 kIsLive = 1 << 0, ///< indicates that the event is played live (directly from keyboard) 614 615 kUserReserved1 = 1 << 14, ///< reserved for user (for internal use) 616 kUserReserved2 = 1 << 15 ///< reserved for user (for internal use) 617 } 618 619 /** Event Types - used for Event::type */ 620 enum EventTypes 621 { 622 kNoteOnEvent = 0, ///< is \ref NoteOnEvent 623 kNoteOffEvent, ///< is \ref NoteOffEvent 624 kDataEvent, ///< is \ref DataEvent 625 kPolyPressureEvent, ///< is \ref PolyPressureEvent 626 kNoteExpressionValueEvent, ///< is \ref NoteExpressionValueEvent 627 kNoteExpressionTextEvent, ///< is \ref NoteExpressionTextEvent 628 kChordEvent, ///< is \ref ChordEvent 629 kScaleEvent, ///< is \ref ScaleEvent 630 kLegacyMIDICCOutEvent = 65535, ///< is \ref LegacyMIDICCOutEvent 631 } 632 633 static if (size_t.sizeof == 8) 634 ubyte[2] padding0; 635 636 uint16 type; ///< a value from \ref EventTypes 637 union 638 { 639 NoteOnEvent noteOn; ///< type == kNoteOnEvent 640 NoteOffEvent noteOff; ///< type == kNoteOffEvent 641 DataEvent data; ///< type == kDataEvent 642 PolyPressureEvent polyPressure; ///< type == kPolyPressureEvent 643 NoteExpressionValueEvent noteExpressionValue; ///< type == kNoteExpressionValueEvent 644 NoteExpressionTextEvent noteExpressionText; ///< type == kNoteExpressionTextEvent 645 ChordEvent chord; ///< type == kChordEvent 646 //ScaleEvent scale; ///< type == kScaleEvent 647 LegacyMIDICCOutEvent midiCCOut; ///< type == kLegacyMIDICCOutEvent 648 } 649 650 static if (size_t.sizeof == 8) 651 ubyte[2] padding1; 652 } 653 } 654 655 mixin SMTG_TYPE_SIZE_CHECK!(Event, 48, 40, 40); 656 657 658 /** List of events to process. 659 \ingroup vstIHost vst300 660 - [host imp] 661 - [released: 3.0.0] 662 663 \see ProcessData, Event */ 664 interface IEventList : FUnknown 665 { 666 public: 667 nothrow: 668 @nogc: 669 /** Returns the count of events. */ 670 int32 getEventCount (); 671 672 /** Gets parameter by index. */ 673 tresult getEvent (int32 index, ref Event e /*out*/); 674 675 /** Adds a new event. */ 676 tresult addEvent (ref Event e /*in*/); 677 678 __gshared immutable TUID iid = INLINE_UID(0x3A2C4214, 0x346349FE, 0xB2C4F397, 0xB9695A44); 679 } 680 681 682 alias NoteExpressionTypeID = uint; 683 alias NoteExpressionValue = double; 684 685 struct NoteExpressionValueEvent 686 { 687 NoteExpressionTypeID typeId; ///< see \ref NoteExpressionTypeID 688 int32 noteId; ///< associated note identifier to apply the change 689 690 NoteExpressionValue value; ///< normalized value [0.0, 1.0]. 691 } 692 693 mixin SMTG_TYPE_SIZE_CHECK!(NoteExpressionValueEvent, 16, 16, 16); 694 695 struct NoteExpressionTextEvent 696 { 697 NoteExpressionTypeID typeId; ///< see \ref NoteExpressionTypeID (kTextTypeID or kPhoneticTypeID) 698 int32 noteId; ///< associated note identifier to apply the change 699 700 uint32 textLen; ///< the number of characters (TChar) between the beginning of text and the terminating 701 ///< null character (without including the terminating null character itself) 702 703 const TChar* text; ///< UTF-16, null terminated 704 } 705 706 mixin SMTG_TYPE_SIZE_CHECK!(NoteExpressionTextEvent, 24, 16, 16); 707 708 709 /** Basic Host Callback Interface. 710 \ingroup vstIHost vst300 711 - [host imp] 712 - [passed as 'context' in to IPluginBase::initialize () ] 713 - [released: 3.0.0] 714 715 Basic VST host application interface. */ 716 interface IHostApplication: FUnknown 717 { 718 public: 719 nothrow: 720 @nogc: 721 /** Gets host application name. */ 722 tresult getName (String128* name); 723 724 /** Creates host object (e.g. Vst::IMessage). */ 725 tresult createInstance (TUID cid, TUID _iid, void** obj); 726 727 __gshared immutable TUID iid = INLINE_UID(0x58E595CC, 0xDB2D4969, 0x8B6AAF8C, 0x36A664E5); 728 }