VST Offline Processing

Introduction

The VST offline interface is a powerful API that allows a Plug-In to freely read audio files open in the host, to transform them or to generate new audio files. The main features are:

 

Declaring an offline Plug-In

The host knows if a given Plug-In supports the offline interface through the canDo function, as follows:

Overview of the interface

Three structures are dedicated to the offline interface:

 There are also three enums:

Three host opcodes are defined:

with the corresponding functions in AudioEffectX:

Three Plug-In opcodes are defined:

with the corresponding functions in AudioEffectX:

An offline process results from a nested sequence of calls, as follows:

  1. The host calls offlineNotify, passing an array of VstAudioFile structures that describe all files that can be read and written. There is also a "start" argument that indicates to the Plug-In whether the process should begin or not. The "start" argument is true e.g. after the user presses the "Process" button (which should be under the host control). The "start" argument is false if the call results from any change in the file environment of the host.
  2. In its implementation of offlineNotify, the Plug-In states which file(s) it wants to read and write, by setting flags in the VstAudioFile structures. Then the Plug-In calls the function offlineStart. The last argument of offlineStart allows the Plug-In to create one or more new files. 
  3. In its implementation of offlineStart, the host initializes an array of VstOfflineTask structures, one for each file to read or/and write. Then the host calls: offlinePrepare.
  4. In its implementation of offlinePrepare, the Plug-In continues the initialization of the VstOfflineTask structures (eg. set the sample rate and number of channels in new files).
  5. If offlinePrepare returns true, the host finalizes the preparation of the VstOfflineTask structures (eg. allocate i/o audio buffers), then calls offlineRun.
  6. In its implementation of offlineRun, the Plug-In can call the host functions offlineRead and offlineWrite at will, until its audio processing is completed. The approach is therefore opposite to the realtime interface: the Plug-In here instructs the host about which files to read and write, in which order, at which rate. A small diagram can illustrate the nested sequence of calls. Functions in red are called by the host and implemented by the Plug-In. Functions in blue are called by the Plug-In and implemented by the host.

offlineNotify

 {

offlineStart

{

offlinePrepare

offlineRun

 {

. ..

offlineRead

offlineWrite

 . ..

}

}

}

 

Details of the interface

struct VstAudioFile

This structure describes an audio file already open in the host. This description is systemindependent: no file path is specified. A Plug-In does not query the host about available files; instead, it gets informed about the available files when the host calls the function offlineNotify.
Note: there is an option, however, to force the host to send a notification (see kVstOfflineQueryFiles).
The host sets all the members of this structure, unless notified otherwise.

long flags

See enum VstAudioFileFlags. Both host and Plug-In can set flags.

void* hostOwned

Any data private to host.

void* plugOwned

Any data private to Plug-In. This value is (optionally) set by the Plug-In in its implementation of offlineNotify. This value is then copied by the host into the VstOfflineTask structure (plugOwned member), when offlineStart is called (this allows the Plug-In, if necessary, to make a link between the offlineNotify call and the offlinePrepare/offlineRun calls).

char name[100]

Name of the file (no path, just name without any file extension). This can be used by the Plug-In to display in its user interface the list of all files available for processing. This is useful if the Plug-In requires the user to select more than one file to perform its job (eg. mixer, file comparer, etc...).

long uniqueId

This value identifies a file instance in the host, during a session. Not two file instances must ever get the same ID during a session. If a file gets closed and is reopen later, it must be attributed an ID that was never attributed so far during the session. From the host side, this can be easily implemented with a simple global counter. This ID can be a useful reference for a Plug-In, if its user interface maintains a list of files that the user can select.

double sampleRate

sample rate of the file long numChannels number of channels: 1 for mono, 2 for stereo, etc...

double numFrames

number of frames in the audio file 

long format

reserved for future. Currently 0.

double editCursorPosition

frame index of the edit cursor, or -1 if no such cursor exists. This member represents the "edit-cursor" position, if any, but never the "playback-cursor" position.

double selectionStart

frame index of first selected frame, or -1 if there is no selection

double selectionSize

number of frames in selection. Zero if no selection.

long selectedChannelsMask

Bit mask describing which channels are selected. One bit per channel. Eg. value 3 means that both channels of a stereo file are selected.

long numMarkers

number of markers in the file. The Plug-In can use offlineRead to get details about the markers.

long timeRulerUnit

If the Plug-In needs to display time values, it might be nice to match the unit system selected by the user for the file in the host. This is the reason why this member, and the following ones, are provided. Possible values: 0: undefined 1: samples units 2: hours/minutes/seconds/milliseconds 3: smpte 4: measures and beats

double timeRulerOffset

frame offset of the time ruler for the window that displays the audio file. Usually 0 but could be negative or positive.

double tempo

-1 if not used by the file's time ruler, else BPM units.

long timeSigNumerator

-1 if not used by the file's time ruler, else number of beats per measure

long timeSigDenominator

-1 if not used by the file's time ruler, else number of beats per whole note

long ticksPerBlackNote

 -1 if not used by the file's time ruler, else sequencer resolution

long smpteFrameRate

 -1 if not used by the file's time ruler, else refers to VstTimeInfo for the meaning.


enum VstAudioFileFlags

This refers to the possible flags for the member flag of the structure VstAudioFile:

The host sets its flags before calling offlineNotify. The Plug-In sets its flags in its implementation of offlineNotify, before calling offlineStart.

kVstOfflineReadOnly

Set by host. Means that the file can't be modified, it can only be read. If the Plug-In tries to write it later, the host should return false from offlineWrite.

kVstOfflineNoRateConversion

Set by host. Means that the file can't have its sample rate modified.

kVstOfflineNoChannelChange

Set by host. Means that the number of channels can't be changed (eg. the host might not allow an in-place mono to stereo conversion).

kVstOfflineCanProcessSelection

Set by the Plug-In if its process can be applied to a limited part of a file. If no selection exists, the entire file range is used. The host checks this flag and, accordingly, initializes the members positionToProcessFrom and numFramesToProcess in the structure VstOfflineTask. Setting this flag is a common case, but a counter example is e.g. a sample rate converter (the sample rate is global to a file and can't be applied to a limited part of a file).

kVstOfflineNoCrossfade

Consider the case of a Plug-In transforming only a part of a file. To avoid a click at the edges (between the processed part and the non-processed part) the host might perform a short crossfade with the old samples, according to user preferences. However, a Plug-In might want to reject this option for some reasons (eg. the Plug-In performs a local glitch restoration and wants to perform the crossfade itself). In that case, the Plug-In should set this flag to instruct the host not to perform any crossfade.

kVstOfflineWantRead

If the Plug-In wants to read the file, it should set this flag. E.g. a signal-generator Plug-In would never set that flag. If this flag is not set and the Plug-In tries to read the file later, the host should return false from offlineRead.

kVstOfflineWantWrite

If the Plug-In wants to overwrite part or the entire file, it should set this flag. E.g. an analyzer plugin would never set that flag. Note: as an alternative, the Plug-In can choose to create a new file, rather than overwriting the source file (see offlineStart). If this flag is not set and the Plug-In tries to write the file later, the host should return false from offlineWrite.

kVstOfflineWantWriteMarker

If the Plug-In wants to modify or create markers in the file, it should set this flag. If this flag is not set and the Plug-In tries to move or create a marker later, the host should return false from offlineWrite.

kVstOfflineWantMoveCursor

If the Plug-In wants to move the edit-cursor of the file, it should set this flag. If this flag is not set and the Plug-In tries to move the edit-cursor later, the host should return false from offlineWrite.

kVstOfflineWantSelect

If the Plug-In wants to select samples in the file, it should set this flag. If this flag is not set and the Plug-In tries to select samples later, the host should return false from offlineWrite.


struct VstOfflineTask

This structure is used in offlinePrepare, offlineRun, offlineRead and offlineWrite functions. Its main purpose is to be a parameter-holder to instruct the host to read/write an existing file, or to write a new file. However, it can also be used as a parameter-holder for other purposes, as we shall see later (see VstOfflineOption). Thus, certain members of this structure have a different meaning according to the option selected when calling offlineRead and offlineWrite. For the sake of simplicity, we now mainly cover the common case of reading/writing audio samples.
An important principle to understand from the beginning, is that each file which is read or/and written is associated with a single VstOfflineTask structure.

char processName[96]

Set by Plug-In in offlinePrepare. The host to label the process can use this name. E.g. the host might display that name in a menu entry called "Undo ....".
If the process uses multiple VstOfflineTask structures, only the first one needs to have this field set (or all other VstOfflineTask structures should have the same label).
This field might be erased later during the process, therefore the host should make a copy of it.

double readPosition

Position, as frames, of the read "head" in the audio file. Set both by Plug-In and host:
This value should be set by the Plug-In, before calling offlineRead, to instruct the host.
On the other hand, the host updates the value to reflect the read position after the call to offlineRead.

double writePosition

Position, as frames, of the write "head" in the audio file. Set both by Plug-In and host:
This value should be set by the Plug-In, before calling offlineWrite, to instruct the host.
On the other hand, the host updates the value to reflect the write position after the call to offlineWrite.

long readCount

Number of audio frames to read.
Set by Plug-In, before calling offlineRead.
When returning from offlineRead, readCount contains the number of actually read frames. If the Plug-In tries to read beyond the end of the file (not considered as an error), the float buffers are completed with blank frames by the host. In that case, the number of blank frames is returned in the member value. In other words, the sum (readCount + value) after the call is equal to the value of readCount before the call.

long writeCount

Number of audio frames to write.
Set by Plug-In, before calling offlineWrite.
Never set by the host. If the host can't write the samples because of a disk-full situation, the host should return false from offlineWrite.

long sizeInputBuffer

Size, as frames, of the audio input buffer.
Set by host before calling offlineRun.
This value remains unchanged during the whole process. A Plug-In can't read more than this number of samples in a single call to offlineRead.

long sizeOutputBuffer

Size, as frames, of the audio output buffer.
Set by host before calling offlineRun.
This value remains unchanged during the whole process. A Plug-In can't write more than this number of samples in a single call to offlineWrite.

void* inputBuffer

void* outputBuffer

Both set by host, before calling offlineRun. The actual type of the pointer depends on the channel mode: if the Plug-In has set the flag kVstOfflineInterleavedAudio, then the type is float* (array of interleaved samples). In the other case, the type is float** (array of array of samples). The latter is the standard case.

double positionToProcessFrom

double numFramesToProcess

Set by host, according to the flags set in enum VstAudioFileFlags. This defines the frame range that the Plug-In should read for its process.
If required for its algorithm, the Plug-In is allowed to read before and after this range (if the range is a subset of the file), but only that range of samples should be transformed.

double maxFramesToWrite

Set by Plug-In in offlinePrepare. This value could be used by the host for optimization purposes (to select a proper write algorithm), and also to check if the disk space is sufficient before starting the process.
If the Plug-In writes no audio, this value should be 0.
If the number of written samples is the same as the number of read samples, this value should be equal to numFramesToProcess.
If the Plug-Ins does not know exactly the number of frames, this value should be an approximate value, large enough for sure, but as small as possible (if the Plug-In later tries to write more frames than this number, an error would be issued by the host).
If the Plug-Ins does not know at all, this value should be -1 (this is the default value of this member).

void* extraBuffer

This is set by the Plug-In. This is a buffer which is used to read/write other data than audio. Meaning depends on the offlineRead/offlineWrite option (see VstOfflineOption).

long value

Set by Plug-In or host. Meaning depends on the offlineRead/offlineWrite option (see VstOfflineOption).

long index

Set by Plug-In or host. Meaning depends on the offlineRead/offlineWrite option (see VstOfflineOption).
This value is also optionally set by the Plug-In during offlinePrepare, as follows:
If the Plug-In generates a new file out of an existing file, then it should initialize this value with the index of the VstOfflineTask structure corresponding to the source file. This is not mandatory, but this info could be of interest for the host. Be default, index is -1 when offlinePrepare is called.

double numFramesInSourceFile

Number of frames in source file. This is set by the host in offlineStart.
This value is only set for existing source files.
If the VstOfflineTask structure refers to a file created by the host on behalf of the Plug-In, this value is 0.

double sourceSampleRate

Sample rate of the source file. Set by host.
If the VstOfflineTask structure refers to a file created by the host on behalf of the Plug-In, this value is 0. In that case, the Plug-In must initialize this value when offlinePrepare is called (in that case, same value as destinationSampleRate).

double destinationSampleRate

Sample rate of the destination file. Set by Plug-In in offlinePrepare (but previously initialized by host as sourceSampleRate).
If the VstOfflineTask structure refers to a file created by the host on behalf of the Plug-In, this value is 0. In that case, the Plug-In must initialize this value when offlinePrepare is called (in that case, same value as sourceSampleRate).

long numSourceChannels

Number of channels in the source file. Set by host.
Note: if the mode kVstOfflineCanProcessSelection is active, and if only one channel of a stereo file is selected, then numSourceChannels should be set to 1. In that case, the file appears as a mono file from the Plug-In point of view.
If the VstOfflineTask structure refers to a file created by the host on behalf of the Plug-In, this value is 0. In that case, the Plug-In must initialize this value when offlinePrepare is called (in that case, same value as numDestinationChannels).

long numDestinationChannels

Number of channels in the destination file. Set by Plug-In in offlinePrepare (but previously initialized by host as numSourceChannels). This value is required for the host to allocate the proper outputBuffer. If the VstOfflineTask structure refers to a file created by the host on behalf of the Plug-In, this value is 0. In that case, the Plug-In must initialize this value when offlinePrepare is called (in that case, same value as numSourceChannels).

long sourceFormat

Reserved for future.
Set by host.

long destinationFormat

Reserved for future.
Set by Plug-In.

char outputText [512]

There are three uses for this member:
If the Plug-In has instructed the host to create a new file (see offlineStart), then the Plug-In can optionally provide its name in this member, with a fully qualified path (this file name must be selected by the user from the Plug-In user interface). In that case, the file is saved by the host in the default audio file format for the platform (this could also be a host specific option). This name has to be initialized when offlinePrepare is called.
Note: the host, if a demo version, might reject this option!
If outputText is empty (common case), then the host creates the file in a folder dedicated to temporary files. Later, it's up to the user to save the file from the host.
Before returning from a function with false, the Plug-In can set the flag kVstOfflinePlugError and then (over)write the outputText member. In that case, the host should display the message to the user. If the host sets the flag kVstOfflineUnvalidParameter, then the host might as well fill up the outputText member, to give a hint to the Plug-In, for pure debugging purposes.

double progress

Set by Plug-In to inform the host about the current progress of the whole operation. The value must be in the range 0 to 1. If the value is not in this range (e.g. -1), the host must ignore it.
The Plug-In should, if possible, update this value each time before calling offlineRead and offlineWrite (this would give the host enough occasions to update a progress indicator to give feedback to the user). 

 If the process has to perform several "passes", the progress value is allowed to go from 0 to 1 several times. However, ideally, a single 0 to 1 pass is better for the user's feedback.
The progress value is meant to be global: if there are several VstOfflineTask involved, the progress value should be "independent" from each task (yet, this global progress should be set in each VstOfflineTask structure passed to VstOfflineTask and offlineWrite calls).

long progressMode

Reserved for the future.

char progressText[100]

Set by Plug-In, to describe what's going on. Can be updated any time. Optional.

long flags

Set by host and Plug-In. See enum VstOfflineTaskFlags.

long returnValue

Reserved for the future.

void* hostOwned

Any data private to host void* plugOwned Any data private to Plug-In. This value is firstly initialized by the host, in offlineStart, with the value of the member plugOwned from the structure VstAudioFile (if the VstOfflineTask corresponds to an existing file).


enum VstOfflineTaskFlags

kVstOfflineUnvalidParameter

Sets by host if the Plug-In passes an unvalid parameter. In that case, the host might fill up the member outputText, to give a hint to the Plug-In, for debugging purposes.

kVstOfflineNewFile

Set by the host to indicate that this VstOfflineTask represents a task that creates/reads/writes a new file.

kVstOfflinePlugError

If an error happens in the Plug-In itself (not an error notified by the host), then the Plug-In could optionally set this flag before returning false from its function to indicate to the host that the member outputText (now) contains a description of the error. The host is then in charge of displaying the message to the user. The Plug-In should never try to display itself an error message from the offlineRun function, since offlineRun could happen in a background task.

kVstOfflineInterleavedAudio

The Plug-In should set this flag if it wants to get data in interleaved format. By default, this is not the case.

kVstOfflineTempOutputFile

The Plug-In should set this flag in offlinePrepare, if the file to create must be a temporary one. In that case, the file is deleted at the end of the process (else, the file is usually open by the host at the end of the process).
This flag can obviously be set only for a new file, not for an existing file.

kVstOfflineFloatOutputFile

If the Plug-In needs creating a file made of float samples, this flag should be set. Else, the default file format is dependant on the host (could be 16 bit, 24 bit, float...). This can be useful if the Plug-In needs to store temporary results to disk, without fear of clipping.

kVstOfflineRandomWrite

If the Plug-In needs to write randomly (not sequentially) a file, it should set this flag. This flag should also be set if the file is to be written sequentially more than once. This is a hint for the host to select a proper writing procedure. If this flag is not set, the host could return false from offlineWrite, if the Plug-In attempts a non-sequential writing.

kVstOfflineStretch

If the Plug-In time-stretches part or all of a file (eg. resampling), it should set this flag. This instructs the host to move and stretch the relative file markers, if any, to match the change. This also is of great importance in mode "process-selection" (see kVstOfflineCanProcessSelection), as it instructs the host to replace only the selection, whatever the number of written samples. Let's take an example: if there are 10000 selected input samples (from 0 to 9999) and 20000 samples are output by the Plug-In, then: 1) if the flag kVstOfflineStretch is set: the host simply replaces the samples 0-9999 with the new 20000 samples, and also moves/stretches the file markers as required. Note that this requires the host to "push" the samples above position 20000 (to insert the 10000 new samples). 2) if the flag kVstOfflineStretch is not set: the host replaces the samples 0-19999 with the new 20000 samples (eg. echo Plug-In that reads samples beyond the end of the selection, to merge the tail of the echo).

kVstOfflineNoThread

The host might either create a background thread to run the process, or run it inside the main application thread. The Plug-In does not decide about this. However, it can happen that a process is so short that creating a thread would be a waste of time. In that case, the Plug-In can set this flag as a hint to the host. 

struct VstAudioFileMarker

double position

Position of the marker

char name[32]

Name of the marker

long type

The host might not support all types. We currently define:
0: undefined
1: generic marker
2: temporary marker (not saved with the file)
3: loop start marker
4: loop end marker
5: section start (whatever "section" might mean for the host)
6: section end

long id

This value is set by the host to identify a marker in a file. It can be any value but 0, which is reserved to indicate a new marker (see option kVstOfflineMarker). Not two markers can ever get the same ID for a given file.

enum VstOfflineOption

The functions offlineRead and offlineWrite have an argument (VstOfflineOption) that allows to read/write different types of data. Let's see what these options are:

kVstOfflineAudio

Use this option to read/write audio samples. See also description of VstOfflineTask.
Reading can happen randomly. This means that any time during the process, a Plug-In is allowed to jump at any frame position and read from that point.
Random reading can occur either in a read-only file or in a file currently being written.
If a Plug-In tries to read beyond the end of the file (not to be considered as an error by the host), the buffers are completed with blank samples by the host. See comments about readCount on that subject.
Writing can happen randomly. This means that a file can be (over)written any number of times and in any order. See kVstOfflineRandomWrite.
If writing is to happen at a position beyond the end of the file, the host must extend the file as required and fill the gap with zeroes.
Delayed overwriting. When a Plug-In tries to overwrite part of an existing source file, the host should in fact write the samples in a separate file. When the process is finished, it's up to the host to actually replace the source samples. This feature is required to let to the Plug-In have the possibility to read the original samples at any time during a process.
One important consequence of the above feature is that any writing, whatever the situation, always occur in a new - possibly temporary - file. This is why all write positions that a Plug-In ever specifies, should always relate to the origin Zero.
E.g. if a Plug-In wants to overwrite samples [10000-19999], it should specify write position in the range [0-9999]. It's up to the host to do the rest, later, to achieve the desired effect.
A Plug-In can never "overwrite" before the position given by the member positionToProcessFrom; it is only possible to overwrite a continuous block starting from positionToProcessFrom. If the Plug-In starts overwriting after positionToProcessFrom, the gap if filled up with blank samples.
To ease the undo/redo handling of the host (usually based on audio blocks), there is a rule to obey when "overwriting" a source file:
Only one continuous segment of a source file can be overwritten during a single task. E.g. it is not allowed to overwrite samples 0 to 10000 then samples 50000 to 60000, hoping that intermediary samples are preserved. If a Plug-In does so, the result is undefined. However, if a Plug-In really needs to do so, it must simply transfer itself the intermediary samples. 

kVstOfflinePeaks

The Plug-In UI might need to display part or all of a file. Reading a whole file (for display purposes) is a time consuming operation; this is why most hosts maintain a "peak file" that stores a "summary" of the audio file. With the kVstOfflinePeaks option, a Plug-In can benefit from this host functionality. This option is only to be used with offlineRead, not offlineWrite. The required parameters of VstOfflineTask are the following ones:

An element of the array could be represented as follows:
struct { int16 y1; int16 y2; }
There are two ways to interpret the data written by the host into the buffer:
If the member index is set to 0 by the host, then the sound view is much "compressed". In that case, a peak at a given position is represented by a vertical line below and above the horizontal axis of the display. The value y1 represents the positive coordinate, above the axis, and the y2 coordinate, the negative value below the axis.
y1 is always in the range 0 to 32767. It has to be scaled by the Plug-In, according to its display's height.
y2 is always in the range -32767 to 0. It has to be scaled by the Plug-In, according to its display's height. If the member index is set to 1 by the host, then the sound view is less "compressed" and should be displayed as a continuous curve.
In this case, y1 is always in the range -32767 to 32767. It has to be scaled by the Plug-In, according to its display's height.
y2 is always 0 and should be ignored.
Note: since the buffer that is used with this option is the buffer normally used for audio samples, the pixel data is interleaved or not, according to the mode kVstOfflineInterleavedAudio, as selected for that VstOfflineTask structure.
It is only possible to call this function on a source file, not on a file being written during a process. If the host does not implement this function, offlineRead returns false. The Plug-In could then read itself the audio (kVstOfflineAudio option) to display the wave.

kVstOfflineParameter

If the host supports this option, the Plug-In can read and write parameters along the audio-file. A "parameter" is a float value or byte array. Each parameter is attributed an index (e.g. if there are 3 float values and 2 arrays, the indexes go from 0 to 4).
Examples of use: parameter automation; storage of meta-information (e.g. pitch) usable by the same plugin, later during the same process, or in another process by another Plug-In, etc.
The host is free to implement the underlying parameter storage, as it likes. However, it is easy to understand that parameters should be stored in a sorted vector, each one attached to a frame index.
The parameters are usually maintained in RAM by the host, therefore the Plug-In should not over-use this feature and for instance write one parameter per sample!
The host might choose to save the parameters into a project-file, or to embed them into the audio file header, or not to save them at all (ie. all parameters get erased when the audio file closes).

Writing parameters with offlineWrite:
processName: name of the parameter family.

If a Plug-In X writes parameters to a file, then a Plug-In Y can retrieve the parameters only if it provides the right family name.
The name must be made unique enough, to prevent any clash.
This member only needs to be set for the first parameter to record during the process.
If this first parameter belongs to a new family, the host destroys all previously stored parameters.

value
: version of the parameter family.

Freely under the control of the Plug-In. This member only needs to be set for the first parameter to record during the process.

index
: index of parameter to write.

writeCount
: 0 if writing a float parameter, else byte size of the parameter array.

extraBuffer
: buffer allocated by the Plug-In to pass the parameter.

For writing a float, this pointer is actually a float* pointer, else this is a pointer to the array.
If this pointer is NULL, then the parameter at that position, if any, is deleted. If this pointer is NULL and the writePosition is negative, all parameters are erased.

writePosition
: position where to write the parameter.

Since parameters are not stored "inside" the audio samples, it does not matter if the write position is temporarily beyond the end of the audio file.
For the sake of simplicity (when reading back later), it is not possible to write more than one parameter at a given position. If this happens, the old parameter gets erased. If this parameter is negative and extraBuffer is NULL, all parameters get erased.

Reading parameters with offlineRead:
At the beginning, the Plug-In is usually ignorant about what parameters are stored, and where. The first call to offlineRead is therefore a special one, as follows:
The Plug-In initializes the member extraBuffer to 0 and the member readPosition to the position it wants to get informed about (usually, 0). When returning from offlineRead, the host has initialized the following parameters:

processName
: name of the parameter family, or nothing if no recorded parameter.

If the name of this parameter family is not supported by the Plug-In, the Plug-In should not try to read the parameters.

value
: version of the recorded parameter family. Might be useful for the Plug-In.

readPosition
: the frame index at which the next parameter is found (this value was unchanged by the host if there was already a parameter there).

readCount
: if the parameter is an array, this is its size (as bytes), else the value is 0.

index
: the index of the parameter, or -1 if no parameter was found.

In order to retrieve the parameters one by one, the Plug-In can then use offlineRead in the following way:

kVstOfflineMarker

With this option, the Plug-In can create one or more markers in the file, or move existing ones.
To know which markers currently exist in a given file, the Plug-In can use offlineRead, with the following parameters:
To write new markers:
To move existing markers:
To copy markers from one file to another:
If the Plug-In creates a new file out of a source file, it might be convenient to copy the source file markers into the new file. In this case, the Plug-In can call the offlineWrite function with the following parameters:


kVstOfflineCursor

By calling offlineRead with this option, the Plug-In retrieves the file's edit-cursor position:
To move the edit cursor to a certain location, the Plug-In should initialize the following members:

kVstOfflineSelection

By calling offlineRead with this option, the Plug-In retrieves the current sample selection in the file:
To set a selection in the file, the Plug-In should initialize the above members.
If the host does not support the selection of individual channels, it should ignore index and select all channels.
If the host does not support sample selections, offlineWrite should return false.

kVstOfflineQueryFiles

If the Plug-In desires to get notified about which files are available in the host, it should call offlineRead with this option.
The first parameter of offlineRead (VstOfflineTask*) should be NULL. On receiving this call, the host should call, immedialty or later, offlineNotify, with the start parameter set to false. In other words, the kVstOfflineQueryFiles option is a way to force the host to call offlineNotify, in order to get informed about open files (normally, the host only calls offlineNotify if a change happens in the set of open files). It is important to insist on the fact that the host is free to call kVstOfflineQueryFiles asynchronously, ie. not immediatly when kVstOfflineQueryFiles is called.
Normally, this option is only used if the Plug-In needs to be notified about the file information, in order to update its user interface. 

Functions

bool offlineNotify(VstAudioFile* ptr, long numAudioFiles, bool start)

The host calls this Plug-In function in two cases:

The purpose of this notification is to give the Plug-In a chance to update its user interface according to the host environment.
For example:
The Plug-In might display the list of all files available for processing; this list needs to be updated if a new file is open or closed in the host.
The Plug-In might display some information about the file with the focus: this needs to change if a new file gains the focus.
Etc...
Tip: since the VstAudioFile structure contains parameters that are likely to often change, such as cursor position or sample selection, the offlineNotify function might be called often. Therefore, a good design for a Plug-In that needs to update its user interface would be to cache the VstAudioFile settings, so as to actually update its user interface only when really required (eg. if the Plug-In does not care about the editcursor position in a file. It should not update its user-interface only if the edit-cursor position happens to move in a file).

The host as aparameter passes an array of VstAudioFile structures.
The number of elements in this array is given by the parameter numAudioFiles.
numAudioFiles is 0 if there is no open file in the host, and in that case, the parameter "ptr" is NULL.
The first element of the array always represents the file with the focus.
If the "start" argument is true, the Plug-In should start the process by calling offlineStart. Else, the Plug-In might, or might not, starts a read-only process, to update its user-interface. See offlineStart.

Whatever the state of the start argument, the Plug-In should return false from the function if it can't process the file(s) open in the host. E.g. if the Plug-In only works with stereo files, and the file with the focus is mono, the Plug-In should return false from this function. This allows the host, for instance, to disable the process button of the user interface.
Important: the Plug-In should not initialize anything internally at this stage. All internal initialization and cleanup required for the process should happen inside offlineRun, and only there. 

bool offlinePrepare(VstOfflineTask* offline, long count)

The host calls this function so that the Plug-In complements the VstOfflineTask structure(s). If everything is fine, the function should return true. Important: the Plug-In should not initialize anything internally at this stage. All internal initialization and cleanup required for the process should happen inside offlineRun, and only there.

bool offlineRun(VstOfflineTask* offline, long count)

This function is called by the host once the VstOfflineTask structure(s) is(are) ready. Within this function, the Plug-In does its audio processing and calls offlineRead and offlineWrite at will. If any error is detected during this procedure, the function should return false.
Important: all internal initialization and cleanup required for the process should happen inside offlineRun, and only there. E.g. if the Plug-In should allocate some memory, this should be done inside this function (as well as the deallocation).

bool offlineStart(VstAudioFile* ptr, long numAudioFiles, long numNewAudioFiles)

When the function offlineNotify is called, the Plug-In might decide to start a process. For this purpose, the Plug-In has to decide which file(s) to process, and also if some new file(s) should be created.
By setting the member flag of each VstAudioFile structure, the Plug-In instructs the host about which file(s) should be processed. In many cases, only the first VstAudioFile element (the focused file) is concerned.
The parameter numAudioFiles is simply the one passed from offlineNotify.
The parameter numNewAudioFiles is the number of files that the Plug-In want to create.
E.g. if the Plug-In selects one file from the VstAudioFile array and sets the value of numNewAudioFiles to 1, the host will create two VstOfflineTask structures. By convention, all VstOfflineTask structures corresponding to new files are placed by the host at the end of the array passed to offlineRun (ie, the front of the array corresponds to already existing files).
It is not allowed for a Plug-In to call offlineStart if the Plug-In is not itself called with offlineNotify. This is to ensure a synchronous protocol with the host. If the Plug-In would call offlineStart asynchronously, maybe the VstAudioFile structures would not be valid anymore at that time, resulting in an undefined behaviour.

bool offlineRead(VstOfflineTask* offline, VstOfflineOption option, bool readSource = true)

This function is called by the Plug-In to read data. See enum VstOfflineOption to see what kind of data can be read, apart audio samples.

About the parameter readSource:

As already seen, a single VstOfflineTask structure can be used both to read an existing file, and to overwrite it. Moreover, the offline specification states that it is possible, at any time, to read both the original samples and the new ones (the "overwritten" samples). This is the reason for the readSource parameter: set it to true to read the original samples and to false to read the recently written samples.

bool offlineWrite(VstOfflineTask* offline, VstOfflineOption option)

This function is called by the Plug-In to write data.
See enum VstOfflineOption to see what kind of data can be written, apart audio samples.



Copyright ©2003 Steinberg Media Technologies GmbH. All Rights Reserved.