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