Need Help to Implement VST in PureBasic

Windows specific forum
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Need Help to Implement VST in PureBasic

Post by zapman* »

I try to implement the VST host support in PureBasic. My Sources in C are :

Code: Select all

00001 #ifndef __AEffect__
00002 #define __AEffect__
00003 
00004 /*
00005         to create an Audio Effect for power pc's, create a
00006         code resource
00007         file type: 'aPcs'
00008         resource type: 'aEff'
00009         ppc header: none (raw pef)
00010 
00011         for windows, it's a .dll
00012 
00013         the only symbol searched for is:
00014         AEffect *main(float (*audioMaster)(AEffect *effect, long opcode, long index,
00015                 long value, void *ptr, float opt));
00016 */
00017 
00018 #if 0
00019 
00020 /* dmazzoni: PRAGMA_ALIGN_SUPPORTED is obsolete in mwerks */
00021 #ifdef __MWERKS__
00022 #undef PRAGMA_ALIGN_SUPPORTED
00023 #endif
00024 
00025 #if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
00026 #pragma options align=mac68k
00027 #elif defined CBUILDER
00028 #pragma -a8
00029 #elif defined(WIN32) || defined(__FLAT__)
00030 #pragma pack(push)
00031 #pragma pack(8)
00032 #endif
00033 
00034 #endif
00035 
00036 #if defined(WIN32) || defined(__FLAT__) || defined CBUILDER
00037 #define VSTCALLBACK __cdecl
00038 #else
00039 #define VSTCALLBACK
00040 #endif
00041 
00042 //---------------------------------------------------------------------------------------------
00043 // misc def's
00044 //---------------------------------------------------------------------------------------------
00045 
00046 typedef struct AEffect AEffect;
00047 typedef long (VSTCALLBACK * audioMasterCallback) (AEffect * effect,
00048                                                   long opcode, long index,
00049                                                   long value, void *ptr,
00050                                                   float opt);
00051 
00052 // prototype for plug-in main
00053 // AEffect *main(audioMasterCallback audioMaster);
00054 
00055 #ifdef CBUILDER
00056 #define kEffectMagic 'PtsV'
00057 #else
00058 #define kEffectMagic 'VstP'
00059 #endif
00060 
00061 //---------------------------------------------------------------------------------------------
00062 //---------------------------------------------------------------------------------------------
00063 
00064 struct AEffect {
00065    long magic;                  // must be kEffectMagic ('VstP')
00066    long (VSTCALLBACK * dispatcher) (AEffect * effect, long opCode,
00067                                     long index, long value, void *ptr,
00068                                     float opt);
00069    void (VSTCALLBACK * process) (AEffect * effect, float **inputs,
00070                                  float **outputs, long sampleframes);
00071    void (VSTCALLBACK * setParameter) (AEffect * effect, long index,
00072                                       float parameter);
00073    float (VSTCALLBACK * getParameter) (AEffect * effect, long index);
00074 
00075    long numPrograms;
00076    long numParams;              // all programs are assumed to have numParams parameters
00077    long numInputs;              //
00078    long numOutputs;             //
00079    long flags;                  // see constants
00080    long resvd1;                 // reserved, must be 0
00081    long resvd2;                 // reserved, must be 0
00082    long initialDelay;           // for algorithms which need input in the first place
00083    long realQualities;          // number of realtime qualities (0: realtime)
00084    long offQualities;           // number of offline qualities (0: realtime only)
00085    float ioRatio;               // input samplerate to output samplerate ratio, not used yet
00086    void *object;                // for class access (see AudioEffect.hpp), MUST be 0 else!
00087    void *user;                  // user access
00088    long uniqueID;               // pls choose 4 character as unique as possible.
00089    // this is used to identify an effect for save+load
00090    long version;                //
00091    void (VSTCALLBACK * processReplacing) (AEffect * effect, float **inputs,
00092                                           float **outputs,
00093                                           long sampleframes);
00094    char future[60];             // pls zero
00095 };
00096 
00097 
00098 //---------------------------------------------------------------------------------------------
00099 // flags bits
00100 //---------------------------------------------------------------------------------------------
00101 
00102 #define effFlagsHasEditor               1       // if set, is expected to react to editor messages
00103 #define effFlagsHasClip                 2       // return > 1. in getVu() if clipped
00104 #define effFlagsHasVu                   4       // return vu value in getVu(); > 1. means clipped
00105 #define effFlagsCanMono                 8       // if numInputs == 2, makes sense to be used for mono in
00106 #define effFlagsCanReplacing    16      // supports in place output (processReplacing() exsists)
00107 #define effFlagsProgramChunks   32      // program data are handled in formatless chunks
00108 
00109 //---------------------------------------------------------------------------------------------
00110 // dispatcher opCodes
00111 //---------------------------------------------------------------------------------------------
00112 
00113 enum {
00114    effOpen = 0,                 // initialise
00115    effClose,                    // exit, release all memory and other resources!
00116 
00117    effSetProgram,               // program no in <value>
00118    effGetProgram,               // return current program no.
00119    effSetProgramName,           // user changed program name (max 24 char + 0) to as passed in string 
00120    effGetProgramName,           // stuff program name (max 24 char + 0) into string 
00121 
00122    effGetParamLabel,            // stuff parameter <index> label (max 8 char + 0) into string
00123    // (examples: sec, dB, type)
00124    effGetParamDisplay,          // stuff parameter <index> textual representation into string
00125    // (examples: 0.5, -3, PLATE)
00126    effGetParamName,             // stuff parameter <index> label (max 8 char + 0) into string
00127    // (examples: Time, Gain, RoomType) 
00128    effGetVu,                    // called if (flags & (effFlagsHasClip | effFlagsHasVu))
00129 
00130    // system
00131 
00132    effSetSampleRate,            // in opt (float)
00133    effSetBlockSize,             // in value
00134    effMainsChanged,             // the user has switched the 'power on' button to
00135    // value (0 off, else on). This only switches audio
00136    // processing; you should flush delay buffers etc.
00137    // editor
00138 
00139    effEditGetRect,              // stuff rect (top, left, bottom, right) into ptr
00140    effEditOpen,                 // system dependant Window pointer in ptr
00141    effEditClose,                // no arguments
00142    effEditDraw,                 // draw method, ptr points to rect
00143    effEditMouse,                // index: x, value: y
00144    effEditKey,                  // system keycode in value
00145    effEditIdle,                 // no arguments. Be gentle!
00146    effEditTop,                  // window has topped, no arguments
00147    effEditSleep,                // window goes to background
00148 
00149    // new
00150 
00151    effIdentify,                 // returns 'NvEf'
00152    effGetChunk,                 // host requests pointer to chunk into (void**)ptr, byteSize returned
00153    effSetChunk,                 // plug-in receives saved chunk, byteSize passed
00154 
00155    effNumOpcodes
00156 };
00157 
00158 //---------------------------------------------------------------------------------------------
00159 // audioMaster opCodes
00160 //---------------------------------------------------------------------------------------------
00161 
00162 enum {
00163    audioMasterAutomate = 0,     // index, value, returns 0
00164    audioMasterVersion,          // vst version, currently 2 (0 for older)
00165    audioMasterCurrentId,        // returns the unique id of a plug that's currently
00166    // loading
00167    audioMasterIdle,             // call application idle routine (this will
00168    // call effEditIdle for all open editors too) 
00169    audioMasterPinConnected      // inquire if an input or output is beeing connected;
00170        // index enumerates input or output counting from zero,
00171        // value is 0 for input and != 0 otherwise. note: the
00172        // return value is 0 for <true> such that older versions
00173        // will always return true.
00174 };
00175 
00176 #if 0
00177 
00178 #if PRAGMA_ALIGN_SUPPORTED || __MWERKS__
00179 #pragma options align=reset
00180 #elif defined(WIN32) || defined(__FLAT__)
00181 #pragma pack(pop)
00182 #elif defined CBUILDER
00183 #pragma -a-
00184 #endif
00185 
00186 #endif
00187 
00188 #endif                          // __AEffect__


AND


Code: Select all

//host.cpp
//attempts to load and make use of a VST plugin

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream.h>
#include <fstream.h>
#include <string.h>

#include "aeffectx.h"

const int blocksize=512;
const float samplerate=44100.0f;

long VSTCALLBACK host(AEffect *effect, long opcode, long index, long value, void *ptr, float opt);

void main()
{
	////////////////////////////////////////////////////////////////////////////
	//
	//	Loading a plugin
	//
	////////////////////////////////////////////////////////////////////////////

	//create a pointer for the plugin we're going to load
	AEffect* ptrPlug=NULL;
	bool editor;

	//find and load the DLL and get a pointer to its main function
	//this has a protoype like this: AEffect *main (audioMasterCallback audioMaster)

	HINSTANCE libhandle=LoadLibrary("c:\\program files\\steinberg\\vstplugins\\muon\\cm101.dll");

	if (libhandle!=NULL)
	{
		//DLL was loaded OK
		AEffect* (__cdecl* getNewPlugInstance)(audioMasterCallback);
		getNewPlugInstance=(AEffect*(__cdecl*)(audioMasterCallback))GetProcAddress(libhandle, "main");

		if (getNewPlugInstance!=NULL)
		{
			//main function located OK
			ptrPlug=getNewPlugInstance(host);

			if (ptrPlug!=NULL)
			{
				//plugin instantiated OK
				cout << "Plugin was loaded OK" << endl;

				if (ptrPlug->magic==kEffectMagic)
				{
					cout << "It's a valid VST plugin" << endl;
				}
				else
				{
					cout << "Not a VST plugin" << endl;
					FreeLibrary(libhandle);
					Sleep(5000);
					return;
				}
			}
			else
			{
				cout << "Plugin could not be instantiated" << endl;
				FreeLibrary(libhandle);
				Sleep(5000);
				return;
			}
		}
		else
		{
			cout << "Plugin main function could not be located" << endl;
			FreeLibrary(libhandle);
			Sleep(5000);
			return;
		}
	}
	else
	{
		cout << "Plugin DLL could not be loaded" << endl;
		Sleep(5000);
		return;
	};


	////////////////////////////////////////////////////////////////////////////
	//
	//	Examining the plugin
	//
	////////////////////////////////////////////////////////////////////////////

	if (ptrPlug->dispatcher(ptrPlug,effGetVstVersion,0,0,NULL,0.0f)==2)
	{
		cout << "This is a VST 2 plugin" << endl;
	}
	else
	{
		cout << "This is a VST 1 plugin" << endl;
	}

	//Member variables:
	cout << "numPrograms " << ptrPlug->numPrograms << endl;
	cout << "numParams " << ptrPlug->numParams << endl;
	cout << "numInputs " << ptrPlug->numInputs << endl;
	cout << "numOutputs " << ptrPlug->numOutputs << endl;
	cout << "resvd1 " << ptrPlug->resvd1 << endl;
	cout << "resvd2 " << ptrPlug->resvd2 << endl;
	cout << "initialDelay " << ptrPlug->initialDelay << endl;
	cout << "realQualities " << ptrPlug->realQualities << endl;
	cout << "offQualities " << ptrPlug->offQualities << endl;
	cout << "ioRatio (float)" << ptrPlug->ioRatio << endl;
	cout << "object (ptr)" << ptrPlug->object << endl;
	cout << "user (ptr)" << ptrPlug->user << endl;
	cout << "uniqueID " << ptrPlug->uniqueID << endl;
	cout << "version " << ptrPlug->version << endl;

	//VST 1.0 flags
	if (ptrPlug->flags & effFlagsHasEditor)
	{
		//Meaning: plugin has its own GUI editor
		cout << "plug has the effFlagsHasEditor flag" << endl;
		editor=true;
	}

	if (ptrPlug->flags & effFlagsHasClip)
	{
		//Meaning: plugin can provide information to drive a clipping display
		cout << "plug has the effFlagsHasClip flag" << endl;
	}

	if (ptrPlug->flags & effFlagsHasVu)
	{
		//Meaning: plugin can provide information to drive a VU display
		cout << "plug has the effFlagsHasVu flag" << endl;
	}

	if (ptrPlug->flags & effFlagsCanMono)
	{
		//Meaning: plugin can accept mono input

		//NB - if the plugin has two input buffers they can both be the same
		cout << "plug has the effFlagsCanMono flag" << endl;
	}

	if (ptrPlug->flags & effFlagsCanReplacing)
	{
		//Meaning: plugin supports a replacing process
		//The values in any output buffer given to the plug will be overwritten
		//however, due to glitches in a few VST instruments it's advisable to
		//zero these buffers anyway before handing them over.
		cout << "plug has the effFlagsCanReplacing flag" << endl;
	}

	if (ptrPlug->flags & effFlagsProgramChunks)
	{
		//Meaning: plugin receives program and bank information via chunk method
		cout << "plug has the effFlagsProgramChunks flag" << endl;
	}

	if (ptrPlug->dispatcher(ptrPlug,effGetVstVersion,0,0,NULL,0.0f)==2)
	{
		//VST 2.0 flags
		if (ptrPlug->flags & effFlagsIsSynth)
		{
			//Meaning: plugin will require MIDI events, and processEvents must be
			//called before process or processReplacing. Also, plugin cannot be
			//used as an insert or send effect and will declare its own number of
			//outputs, which should be assigned by the host as mixer channels
			cout << "plug has the effFlagsIsSynth flag" << endl;
		}

		if (ptrPlug->flags & effFlagsNoSoundInStop)
		{
			//Meaning: if the transport is stopped the host need not call process
			//or processReplacing - or if no input available?
			cout << "plug has the effFlagsNoSoundInStop flag" << endl;
		}

		//also effFlagsExtIsAsync and effFlagsExtHasBuffer - refers to plugin that
		//supports external DSP

		//VST 2.0 Plugin Can Do's
		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"sendVstEvents",0.0f)>0)
		{
			cout << "plug can sendVstEvents" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"sendVstMidiEvent",0.0f)>0)
		{
			cout << "plug can sendVstMidiEvent" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"sendVstTimeInfo",0.0f)>0)
		{
			cout << "plug can sendVstTimeInfo" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"receiveVstEvents",0.0f)>0)
		{
			cout << "plug can receiveVstEvents" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"receiveVstMidiEvent",0.0f)>0)
		{
			cout << "plug can receiveVstMidiEvent" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"receiveVstTimeInfo",0.0f)>0)
		{
			cout << "plug can receiveVstTimeInfo" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"offline",0.0f)>0)
		{
			cout << "plug can offline" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"plugAsChannelInsert",0.0f)>0)
		{
			cout << "plug can plugAsChannelInsert" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"plugAsSend",0.0f)>0)
		{
			cout << "plug can plugAsSend" << endl;
		}

		if (ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"mixDryWet",0.0f)>0)
		{
			cout << "plug can mixDryWet" << endl;
		}

	}	//end VST2 specific

	////////////////////////////////////////////////////////////////////////////
	//
	//	Using the plugin's C Interface - an example
	//
	////////////////////////////////////////////////////////////////////////////

	long rc=0;

	//try some dispatcher functions...
	ptrPlug->dispatcher(ptrPlug,effOpen,0,0,NULL,0.0f);

	//switch the plugin off (calls Suspend)
	ptrPlug->dispatcher(ptrPlug,effMainsChanged,0,0,NULL,0.0f);

	//set sample rate and block size
	ptrPlug->dispatcher(ptrPlug,effSetSampleRate,0,0,NULL,samplerate);
	ptrPlug->dispatcher(ptrPlug,effSetBlockSize,0,blocksize,NULL,0.0f);

	if ((ptrPlug->dispatcher(ptrPlug,effGetVstVersion,0,0,NULL,0.0f)==2) &&
		(ptrPlug->flags & effFlagsIsSynth))
	{
		//get I/O configuration for synth plugins - they will declare their
		//own output and input channels
		for (int i=0; i<ptrPlug->numInputs+ptrPlug->numOutputs;i++)
		{
			if (i<ptrPlug->numInputs)
			{
				//input pin
				VstPinProperties temp;

				if (ptrPlug->dispatcher(ptrPlug,effGetInputProperties,i,0,&temp,0.0f)==1)
				{
					cout << "Input pin " << (i+1) << " label " << temp.label << endl;
					//cout << "Input pin " << (i+1) << " shortLabel " << temp.shortLabel << endl;

					if (temp.flags & kVstPinIsActive)
					{
						cout << "Input pin " << (i+1) << " is active" << endl;
					}

					if (temp.flags & kVstPinIsStereo)
					{
						// is index even or zero?
						if (i%2==0 || i==0)
						{
							cout << "Input pin " << (i+1) << " is left channel of a stereo pair" << endl;
						}
						else
						{
							cout << "Input pin " << (i+1) << " is right channel of a stereo pair" << endl;
						}
					}
				}
			}
			else
			{
				//output pin
				VstPinProperties temp;

				if (ptrPlug->dispatcher(ptrPlug,effGetOutputProperties,i,0,&temp,0.0f)==1)
				{
					cout << "Output pin " << (i-ptrPlug->numInputs+1) << " label " << temp.label << endl;
					//cout << "Output pin " << (i-ptrPlug->numInputs+1) << " shortLabel " << temp.shortLabel << endl;

					if (temp.flags & kVstPinIsActive)
					{
						cout << "Output pin " << (i-ptrPlug->numInputs+1) << " is active" << endl;
					}
					else
					{
						cout << "Output pin " << (i-ptrPlug->numInputs+1) << " is inactive" << endl;
					}

					if (temp.flags & kVstPinIsStereo)
					{
						// is index even or zero?
						if ((i-ptrPlug->numInputs)%2==0 || (i-ptrPlug->numInputs)==0)
						{
							cout << "Output pin " << (i+1) << " is left channel of a stereo pair" << endl;
						}
						else
						{
							cout << "Output pin " << (i+1) << " is right channel of a stereo pair" << endl;
						}
					}
					else
					{
						cout <<  "Output pin " << (i+1) << " is mono" << endl;
					}
				}
			}
		}
	}	//end VST2 specific

	//switch the plugin back on (calls Resume)
	ptrPlug->dispatcher(ptrPlug,effMainsChanged,0,1,NULL,0.0f);

	////////////////////////////////////////////////////////////////////////////

	//set to program zero and fetch back the name
	ptrPlug->dispatcher(ptrPlug,effSetProgram,0,0,NULL,0.0f);

	char strProgramName[24+2];
	ptrPlug->dispatcher(ptrPlug,effGetProgramName,0,0,strProgramName,0.0f);

	cout << "Set plug to program zero, name is " <<  strProgramName << endl;

	//get the parameter strings
	char strName[24];
	char strDisplay[24];
	char strLabel[24];

	ptrPlug->dispatcher(ptrPlug,effGetParamName,0,0,strName,0.0f);
	cout << "Parameter name is " << strName << endl;

	ptrPlug->dispatcher(ptrPlug,effGetParamLabel,0,0,strLabel,0.0f);
	cout << "Parameter label is " << strLabel << endl;

	ptrPlug->dispatcher(ptrPlug,effGetParamDisplay,0,0,strDisplay,0.0f);
	cout << "Parameter display is " << strDisplay << endl;

	//call the set and get parameter functions
	ptrPlug->setParameter(ptrPlug,0,0.7071f);
	float newval=ptrPlug->getParameter(ptrPlug,0);

	cout << "Parameter 0 was changed to " << newval << endl;
	ptrPlug->dispatcher(ptrPlug,effGetParamDisplay,0,0,strDisplay,0.0f);
	cout << "Parameter display is now " << strDisplay << endl;

	////////////////////////////////////////////////////////////////////////////

	VstEvent* ptrEvents=NULL;
	char* ptrEventBuffer=NULL;
	int nEvents=4;

	if ((ptrPlug->dispatcher(ptrPlug,effGetVstVersion,0,0,NULL,0.0f)==2) &&
	   ((ptrPlug->flags & effFlagsIsSynth) ||
		(ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"receiveVstEvents",0.0f)>0)))
	{
		//create some MIDI messages to send to the plug if it is a synth or can
		//receive MIDI messages

		//create a block of appropriate size
		int pointersize=sizeof(VstEvent*);
		int bufferSize=sizeof(VstEvents)-(pointersize*2);
		bufferSize+=pointersize*(nEvents);

		//create the buffer
		ptrEventBuffer=new char[bufferSize+1];

		//now, create some memory for the events themselves
		VstMidiEvent* ptrEvents=new VstMidiEvent[nEvents];
		VstMidiEvent* ptrWrite=ptrEvents;

		//Create first event
		ptrWrite->type=kVstMidiType;
		ptrWrite->byteSize=24L;
		ptrWrite->deltaFrames=0L;
		ptrWrite->flags=0L;
		ptrWrite->noteLength=0L;
		ptrWrite->noteOffset=0L;

		ptrWrite->midiData[0]=(char)0x90;	//status & channel
		ptrWrite->midiData[1]=(char)0x3C;	//MIDI byte #2
		ptrWrite->midiData[2]=(char)0xFF;	//MIDI byte #3
		ptrWrite->midiData[3]=(char)0x00;	//MIDI byte #4 - blank

		ptrWrite->detune=0x00;
		ptrWrite->noteOffVelocity=0x00;
		ptrWrite->reserved1=0x00;
		ptrWrite->reserved2=0x00;

		//Create second event
		ptrWrite++;
		ptrWrite->type=kVstMidiType;
		ptrWrite->byteSize=24L;
		ptrWrite->deltaFrames=128L;
		ptrWrite->flags=0L;
		ptrWrite->noteLength=0L;
		ptrWrite->noteOffset=0L;

		ptrWrite->midiData[0]=(char)0x90;	//status & channel
		ptrWrite->midiData[1]=(char)0x3C;	//MIDI byte #2
		ptrWrite->midiData[2]=(char)0x00;	//MIDI byte #3
		ptrWrite->midiData[3]=(char)0x00;	//MIDI byte #4 - blank

		ptrWrite->detune=0x00;
		ptrWrite->noteOffVelocity=0x00;
		ptrWrite->reserved1=0x00;
		ptrWrite->reserved2=0x00;

		//Create third event
		ptrWrite++;
		ptrWrite->type=kVstMidiType;
		ptrWrite->byteSize=24L;
		ptrWrite->deltaFrames=256L;
		ptrWrite->flags=0L;
		ptrWrite->noteLength=0L;
		ptrWrite->noteOffset=0L;

		ptrWrite->midiData[0]=(char)0x90;	//status & channel
		ptrWrite->midiData[1]=(char)0x3C;	//MIDI byte #2
		ptrWrite->midiData[2]=(char)0xFF;	//MIDI byte #3
		ptrWrite->midiData[3]=(char)0x00;	//MIDI byte #4 - blank

		ptrWrite->detune=0x00;
		ptrWrite->noteOffVelocity=0x00;
		ptrWrite->reserved1=0x00;
		ptrWrite->reserved2=0x00;

		//Create fourth event
		ptrWrite++;
		ptrWrite->type=kVstMidiType;
		ptrWrite->byteSize=24L;
		ptrWrite->deltaFrames=384L;
		ptrWrite->flags=0L;
		ptrWrite->noteLength=0L;
		ptrWrite->noteOffset=0L;

		ptrWrite->midiData[0]=(char)0x90;	//status & channel
		ptrWrite->midiData[1]=(char)0x3C;	//MIDI byte #2
		ptrWrite->midiData[2]=(char)0x00;	//MIDI byte #3
		ptrWrite->midiData[3]=(char)0x00;	//MIDI byte #4 - blank

		ptrWrite->detune=0x00;
		ptrWrite->noteOffVelocity=0x00;
		ptrWrite->reserved1=0x00;
		ptrWrite->reserved2=0x00;

		//copy the addresses of our events into the eventlist structure
		VstEvents* ev=(VstEvents*)ptrEventBuffer;
		for (int i=0;i<nEvents;i++)
		{
			ev->events[i]=(VstEvent*)(ptrEvents+i);
		}

		//do the block header
		ev->numEvents=nEvents;
		ev->reserved=0L;

	}

	////////////////////////////////////////////////////////////////////////////
	float** ptrInputBuffers=NULL;
	float** ptrOutputBuffers=NULL;

	if (ptrPlug->numInputs)
	{

		if (ptrPlug->flags & effFlagsCanMono)
		{
			//only one input buffer required, others are just copies?
			//This could be an incorrect interpretation

			ptrInputBuffers=new float*[ptrPlug->numInputs];

			//create the input buffers
			for (int i=0;i<ptrPlug->numInputs;i++)
			{
				if (i==0)
				{
					cout << "Input buffer " << (i+1) << " created" << endl;
					ptrInputBuffers[i]=new float[blocksize];
				}
				else
				{
					cout << "Input buffer " << (i+1) << " is a copy of input buffer 1" << endl;
					ptrInputBuffers[i]=ptrInputBuffers[0];
				}
			}
		}
		else
		{
			//Plug requires independent input signals
			ptrInputBuffers=new float*[ptrPlug->numInputs];

			//create the input buffers
			for (int i=0;i<ptrPlug->numInputs;i++)
			{
				cout << "Input buffer " << (i+1) << " created" << endl;
				ptrInputBuffers[i]=new float[blocksize];
			}
		}
	}

	if (ptrPlug->numOutputs)
	{
		ptrOutputBuffers=new float*[ptrPlug->numOutputs];

		//create the output buffers
		for (int i=0;i<ptrPlug->numOutputs;i++)
		{
			cout << "Output buffer " << (i+1) << " created" << endl;
			ptrOutputBuffers[i]=new float[blocksize];
		}
	}

	if (ptrPlug->numInputs>0)
	{
		//fill the input buffers with ones to simulate some input having been
		//received

		//We don't have to do this for synths, obviously
		for (int i=0;i<ptrPlug->numInputs;i++)
		{
			for (int j=0;j<blocksize;j++)
			{
				*(ptrInputBuffers[i]+j)=1.0f;
			}
		}
	}

	if (ptrPlug->numOutputs>0)
	{
		//fill the output buffers with ones to simulate some prior output to be
		//accumulated on
		for (int i=0;i<ptrPlug->numOutputs;i++)
		{
			for (int j=0;j<blocksize;j++)
			{
				//*(ptrOutputBuffers[i]+j)=-1.0f;

				//note that VSTXsynth, when replacing, requires the host
				//to clear the buffer first!
				*(ptrOutputBuffers[i]+j)=0.0f;
			}
		}
	}

	////////////////////////////////////////////////////////////////////////////

	ofstream outfile;
	outfile.open("hello.txt");

	//ProcessEvents
	if ((ptrPlug->dispatcher(ptrPlug,effGetVstVersion,0,0,NULL,0.0f)==2) &&
	   ((ptrPlug->flags & effFlagsIsSynth) ||
		(ptrPlug->dispatcher(ptrPlug,effCanDo,0,0,"receiveVstEvents",0.0f)>0)))
	{
		if (ptrPlug->dispatcher(ptrPlug,effProcessEvents,0,0,(VstEvents*)ptrEventBuffer,0.0f)==1)
		{
			cout << "plug processed events OK and wants more" << endl;
		}
		else
		{
			cout << "plug does not want any more events" << endl;
		}
	}

	//process (replacing)
	if (ptrPlug->flags & effFlagsCanReplacing)
	{
		cout << "Process (replacing)" << endl;
		ptrPlug->processReplacing(ptrPlug,ptrInputBuffers,ptrOutputBuffers,blocksize);
	}
/*
	//process (accumulating)
	cout << "Process (accumulating)" << endl;
	ptrPlug->process(ptrPlug,ptrInputBuffers,ptrOutputBuffers,sampleframes);
*/

	//Dump output to disk
	for (int i=0;i<ptrPlug->numOutputs;i++)
	{
		for (int j=0;j<blocksize;j++)
		{
			outfile << i << "," << j << "," << *(ptrOutputBuffers[i]+j) << endl;
		}
	}

	outfile.close();


	
	////////////////////////////////////////////////////////////////////////////

	ptrPlug->dispatcher(ptrPlug,effMainsChanged,0,0,NULL,0.0f);	//calls suspend

	////////////////////////////////////////////////////////////////////////////
	
	//delete the MIDI data
	if (ptrEventBuffer!=NULL)
	{
		delete[] ptrEventBuffer;
	}

	if (ptrEvents!=NULL)
	{
		delete[] ptrEvents;
	}

	//delete the input buffers
	if (ptrPlug->numInputs>0)
	{
		if (!(ptrPlug->flags & effFlagsCanMono))
		{
			//independent buffers have been assigned, delete them
			for (i=0;i<ptrPlug->numInputs;i++)
			{
				delete[] ptrInputBuffers[i];
			}
		}
		else
		{
			//there's only one buffer, delete it
			delete[] ptrInputBuffers[0];
		}

		//remove the pointers to the buffers
		delete[] ptrInputBuffers;
	}


	//delete the output buffers
	if (ptrPlug->numOutputs>0)
	{
		for (i=0;i<ptrPlug->numOutputs;i++)
		{
			delete[] ptrOutputBuffers[i];
		}

		//remove the pointers to the buffers
		delete[] ptrOutputBuffers;
	}


	//Shut the plugin down and free the library (this deletes the C++ class
	//memory and calls the appropriate destructors...)
	ptrPlug->dispatcher(ptrPlug,effClose,0,0,NULL,0.0f);
	FreeLibrary(libhandle);

	////////////////////////////////////////////////////////////////////////////

	cout << "Done!" << endl;

	Sleep(10000);
}



//host callback function
//this is called directly by the plug-in!!
//
long VSTCALLBACK host(AEffect *effect, long opcode, long index, long value, void *ptr, float opt)
{
	long retval=0;

	switch (opcode)
	{
		//VST 1.0 opcodes
		case audioMasterVersion:
			//Input values:
			//none

			//Return Value:
			//0 or 1 for old version
			//2 or higher for VST2.0 host?
			cout << "plug called audioMasterVersion" << endl;
			retval=2;
			break;

		case audioMasterAutomate:
			//Input values:
			//<index> parameter that has changed
			//<opt> new value

			//Return value:
			//not tested, always return 0

			//NB - this is called when the plug calls
			//setParameterAutomated

			cout << "plug called audioMasterAutomate" << endl;
			break;

		case audioMasterCurrentId:
			//Input values:
			//none

			//Return Value
			//the unique id of a plug that's currently loading
			//zero is a default value and can be safely returned if not known
			cout << "plug called audioMasterCurrentId" << endl;
			break;

		case audioMasterIdle:
			//Input values:
			//none

			//Return Value
			//not tested, always return 0

			//NB - idle routine should also call effEditIdle for all open editors
			Sleep(1);
			cout << "plug called audioMasterIdle" << endl;
			break;

		case audioMasterPinConnected:
			//Input values:
			//<index> pin to be checked
			//<value> 0=input pin, non-zero value=output pin

			//Return values:
			//0=true, non-zero=false
			cout << "plug called audioMasterPinConnected" << endl;
			break;

		//VST 2.0 opcodes
		case audioMasterWantMidi:
			//Input Values:
			//<value> filter flags (which is currently ignored, no defined flags?)

			//Return Value:
			//not tested, always return 0
			cout << "plug called audioMasterWantMidi" << endl;
			break;

		case audioMasterGetTime:
			//Input Values:
			//<value> should contain a mask indicating which fields are required
			//...from the following list?
			//kVstNanosValid
			//kVstPpqPosValid
			//kVstTempoValid
			//kVstBarsValid
			//kVstCyclePosValid
			//kVstTimeSigValid
			//kVstSmpteValid
			//kVstClockValid

			//Return Value:
			//ptr to populated const VstTimeInfo structure (or 0 if not supported)

			//NB - this structure will have to be held in memory for long enough
			//for the plug to safely make use of it
			cout << "plug called audioMasterGetTime" << endl;
			break;

		case audioMasterProcessEvents:
			//Input Values:
			//<ptr> Pointer to a populated VstEvents structure

			//Return value:
			//0 if error
			//1 if OK
			cout << "plug called audioMasterProcessEvents" << endl;
			break;

		case audioMasterSetTime:
			//IGNORE!
			break;

		case audioMasterTempoAt:
			//Input Values:
			//<value> sample frame location to be checked

			//Return Value:
			//tempo (in bpm * 10000)
			cout << "plug called audioMasterTempoAt" << endl;
			break;

		case audioMasterGetNumAutomatableParameters:
			//Input Values:
			//None

			//Return Value:
			//number of automatable parameters
			//zero is a default value and can be safely returned if not known

			//NB - what exactly does this mean? can the host set a limit to the
			//number of parameters that can be automated?
			cout << "plug called audioMasterGetNumAutomatableParameters" << endl;
			break;

		case audioMasterGetParameterQuantization:
			//Input Values:
			//None

			//Return Value:
			//integer value for +1.0 representation,
			//or 1 if full single float precision is maintained
			//in automation.

			//NB - ***possibly bugged***
			//Steinberg notes say "parameter index in <value> (-1: all, any)"
			//but in aeffectx.cpp no parameters are taken or passed
			cout << "plug called audioMasterGetParameterQuantization" << endl;
			break;

		case audioMasterIOChanged:
			//Input Values:
			//None

			//Return Value:
			//0 if error
			//non-zero value if OK
			cout << "plug called audioMasterIOChanged" << endl;
			break;

		case audioMasterNeedIdle:
			//Input Values:
			//None

			//Return Value:
			//0 if error
			//non-zero value if OK

			//NB plug needs idle calls (outside its editor window)
			//this means that effIdle must be dispatched to the plug
			//during host idle process and not effEditIdle calls only when its
			//editor is open
			//Check despatcher notes for any return codes from effIdle
			cout << "plug called audioMasterNeedIdle" << endl;
			break;

		case audioMasterSizeWindow:
			//Input Values:
			//<index> width
			//<value> height

			//Return Value:
			//0 if error
			//non-zero value if OK
			cout << "plug called audioMasterSizeWindow" << endl;
			break;

		case audioMasterGetSampleRate:
			//Input Values:
			//None

			//Return Value:
			//not tested, always return 0

			//NB - Host must despatch effSetSampleRate to the plug in response
			//to this call
			//Check despatcher notes for any return codes from effSetSampleRate
			cout << "plug called audioMasterGetSampleRate" << endl;
			effect->dispatcher(effect,effSetSampleRate,0,0,NULL,samplerate);
			break;

		case audioMasterGetBlockSize:
			//Input Values:
			//None

			//Return Value:
			//not tested, always return 0

			//NB - Host must despatch effSetBlockSize to the plug in response
			//to this call
			//Check despatcher notes for any return codes from effSetBlockSize
			cout << "plug called audioMasterGetBlockSize" << endl;
			effect->dispatcher(effect,effSetBlockSize,0,blocksize,NULL,0.0f);

			break;

		case audioMasterGetInputLatency:
			//Input Values:
			//None

			//Return Value:
			//input latency (in sampleframes?)
			cout << "plug called audioMasterGetInputLatency" << endl;
			break;

		case audioMasterGetOutputLatency:
			//Input Values:
			//None

			//Return Value:
			//output latency (in sampleframes?)
			cout << "plug called audioMasterGetOutputLatency" << endl;
			break;

		case audioMasterGetPreviousPlug:
			//Input Values:
			//None

			//Return Value:
			//pointer to AEffect structure or NULL if not known?

			//NB - ***possibly bugged***
			//Steinberg notes say "input pin in <value> (-1: first to come)"
			//but in aeffectx.cpp no parameters are taken or passed
			cout << "plug called audioMasterGetPreviousPlug" << endl;
			break;

		case audioMasterGetNextPlug:
			//Input Values:
			//None

			//Return Value:
			//pointer to AEffect structure or NULL if not known?

			//NB - ***possibly bugged***
			//Steinberg notes say "output pin in <value> (-1: first to come)"
			//but in aeffectx.cpp no parameters are taken or passed
			cout << "plug called audioMasterGetNextPlug" << endl;
			break;

		case audioMasterWillReplaceOrAccumulate:
			//Input Values:
			//None

			//Return Value:
			//0: not supported
			//1: replace
			//2: accumulate
			cout << "plug called audioMasterWillReplaceOrAccumulate" << endl;
			break;

		case audioMasterGetCurrentProcessLevel:
			//Input Values:
			//None

			//Return Value:
			//0: not supported,
			//1: currently in user thread (gui)
			//2: currently in audio thread (where process is called)
			//3: currently in 'sequencer' thread (midi, timer etc)
			//4: currently offline processing and thus in user thread
			//other: not defined, but probably pre-empting user thread.
			cout << "plug called audioMasterGetCurrentProcessLevel" << endl;
			break;

		case audioMasterGetAutomationState:
			//Input Values:
			//None

			//Return Value:
			//0: not supported
			//1: off
			//2:read
			//3:write
			//4:read/write
			cout << "plug called audioMasterGetAutomationState" << endl;
			break;

		case audioMasterGetVendorString:
			//Input Values:
			//<ptr> string (max 64 chars) to be populated

			//Return Value:
			//0 if error
			//non-zero value if OK
			cout << "plug called audioMasterGetVendorString" << endl;
			break;

		case audioMasterGetProductString:
			//Input Values:
			//<ptr> string (max 64 chars) to be populated

			//Return Value:
			//0 if error
			//non-zero value if OK
			cout << "plug called audioMasterGetProductString" << endl;
			break;

		case audioMasterGetVendorVersion:
			//Input Values:
			//None

			//Return Value:
			//Vendor specific host version as integer
			cout << "plug called audioMasterGetVendorVersion" << endl;
			break;

		case audioMasterVendorSpecific:
			//Input Values:
			//<index> lArg1
			//<value> lArg2
			//<ptr> ptrArg
			//<opt>	floatArg

			//Return Values:
			//Vendor specific response as integer
			cout << "plug called audioMasterVendorSpecific" << endl;
			break;

		case audioMasterSetIcon:
			//IGNORE
			break;

		case audioMasterCanDo:
			//Input Values:
			//<ptr> predefined "canDo" string

			//Return Value:
			//0 = Not Supported
			//non-zero value if host supports that feature

			//NB - Possible Can Do strings are:
			//"sendVstEvents",
			//"sendVstMidiEvent",
			//"sendVstTimeInfo",
			//"receiveVstEvents",
			//"receiveVstMidiEvent",
			//"receiveVstTimeInfo",
			//"reportConnectionChanges",
			//"acceptIOChanges",
			//"sizeWindow",
			//"asyncProcessing",
			//"offline",
			//"supplyIdle",
			//"supportShell"
			cout << "plug called audioMasterCanDo" << endl;

			if (strcmp((char*)ptr,"sendVstEvents")==0 ||
				strcmp((char*)ptr,"sendVstMidiEvent")==0 ||
				strcmp((char*)ptr,"supplyIdle")==0)
			{
				retval=1;
			}
			else
			{
				retval=0;
			}

			break;

		case audioMasterGetLanguage:
			//Input Values:
			//None

			//Return Value:
			//kVstLangEnglish
			//kVstLangGerman
			//kVstLangFrench
			//kVstLangItalian
			//kVstLangSpanish
			//kVstLangJapanese
			cout << "plug called audioMasterGetLanguage" << endl;
			retval=1;
			break;
/*
		MAC SPECIFIC?

		case audioMasterOpenWindow:
			//Input Values:
			//<ptr> pointer to a VstWindow structure

			//Return Value:
			//0 if error
			//else platform specific ptr
			cout << "plug called audioMasterOpenWindow" << endl;
			break;

		case audioMasterCloseWindow:
			//Input Values:
			//<ptr> pointer to a VstWindow structure

			//Return Value:
			//0 if error
			//Non-zero value if OK
			cout << "plug called audioMasterCloseWindow" << endl;
			break;
*/
		case audioMasterGetDirectory:
			//Input Values:
			//None

			//Return Value:
			//0 if error
			//FSSpec on MAC, else char* as integer

			//NB Refers to which directory, exactly?
			cout << "plug called audioMasterGetDirectory" << endl;
			break;

		case audioMasterUpdateDisplay:
			//Input Values:
			//None

			//Return Value:
			//Unknown
			cout << "plug called audioMasterUpdateDisplay" << endl;
			break;
	}

	return retval;
};


I began to do this :

Code: Select all

Structure AEffect
  magic.l;         must be kEffectMagic ('VstP')
  dispatcher.l;    long (VSTCALLBACK * dispatcher) (AEffect * effect, long opCode,long index, long value, void *ptr,float opt)
  process.l;       void (VSTCALLBACK * process) (AEffect * effect, float **inputs,float **outputs, long sampleframes);
  setParameter.l;  void (VSTCALLBACK * setParameter) (AEffect * effect, long index, float parameter);
  getParameter.l;  float (VSTCALLBACK * getParameter) (AEffect * effect, long index);
  numPrograms.l
  numParams.l;              // all programs are assumed to have numParams parameters
  numInputs.l;              //
  numOutputs.l;             //
  flags.l;                  // see constants
  resvd1.l;                 // reserved, must be 0
  resvd2.l;                 // reserved, must be 0
  initialDelay.l;           // for algorithms which need input in the first place
  realQualities.l;          // number of realtime qualities (0: realtime)
  offQualities.l;           // number of offline qualities (0: realtime only)
  ioRatio.f;                // input samplerate to output samplerate ratio, not used yet
  *object.l;                // for class access (see AudioEffect.hpp), MUST be 0 else!
  *user.l;                  // user access
  uniqueID.l;               // pls choose 4 character as unique as possible.
                           ;// this is used To identify an effect For save+load
  version.l;                //
  processReplacing.l;    void (VSTCALLBACK * processReplacing) (AEffect * effect, float **inputs,
  *outputs.f
  sampleframes.l
  future.b[60] ;             // pls zero
EndStructure
;
Procedure host(*effect.AEffect, opcode.l, index.l, value.l, *ptr.l, opt.f)
  Debug "Opcode : "+Str(opcode)
  ProcedureReturn 0
EndProcedure



LibName$ = OpenFileRequester("Choose a VST (.dll file)", "", ".DLL|*.dll",0)
If LibName$
  If OpenLibrary(0, LibName$)
    If ExamineLibraryFunctions(0)
      Result = IsFunction(0, "main")
      If Result
        *ptrPlug.AEffect = CallFunctionFast(Result,@host,0)
      Else
        MessageRequester("Error","This library is not a VST",0)
      EndIf
    Else
      MessageRequester("Error","Can't examine this library.",0)
    EndIf
    CloseLibrary(0)
  Else
    MessageRequester("Error","Can't open this library.",0)
  EndIf
EndIf
but it crashes when trying to open a VST DLL. I just need to understand why it crashes. If anybody can help me, I thinck that I can go alone over the rest of the job.
Last edited by zapman* on Thu Oct 28, 2004 10:05 am, edited 1 time in total.
Don't try - DO it !
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Re: Need Help to Implement VST in PureBasic

Post by traumatic »

what's your question?
Good programmers don't comment their code. It was hard to write, should be hard to read.
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post by zapman* »

oops! :oops: the end of the message was missing. I corrected it.
Don't try - DO it !
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Code: Select all

Structure AEffect
  magic.l;         must be kEffectMagic ('VstP')
  dispatcher.l;    long (VSTCALLBACK * dispatcher) (AEffect * effect, long opCode,long index, long value, void *ptr,float opt)
  process.l;       void (VSTCALLBACK * process) (AEffect * effect, float **inputs,float **outputs, long sampleframes);
  setParameter.l;  void (VSTCALLBACK * setParameter) (AEffect * effect, long index, float parameter);
  getParameter.l;  float (VSTCALLBACK * getParameter) (AEffect * effect, long index);
  numPrograms.l
  numParams.l;              // all programs are assumed to have numParams parameters
  numInputs.l;              //
  numOutputs.l;             //
  flags.l;                  // see constants
  resvd1.l;                 // reserved, must be 0
  resvd2.l;                 // reserved, must be 0
  initialDelay.l;           // for algorithms which need input in the first place
  realQualities.l;          // number of realtime qualities (0: realtime)
  offQualities.l;           // number of offline qualities (0: realtime only)
  ioRatio.f;                // input samplerate to output samplerate ratio, not used yet
  *object.l;                // for class access (see AudioEffect.hpp), MUST be 0 else!
  *user.l;                  // user access
  uniqueID.l;               // pls choose 4 character as unique as possible.
  ;// this is used To identify an effect For save+load
  version.l;                //
  processReplacing.l;    void (VSTCALLBACK * processReplacing) (AEffect * effect, float **inputs,
  ;*outputs.f               // en trop : fait partis des paramèttres de la fonction callback
  ;sampleframes.l           // en trop : fait partis des paramèttres de la fonction callback
  future.b[60] ;            // pls zero
EndStructure
;
ProcedureCDLL host(*effect.AEffect, opcode.l, index.l, Value.l, *ptr.l, opt.f)
  Debug "Opcode : "+Str(opcode)
  ProcedureReturn 0
EndProcedure



LibName$ = OpenFileRequester("Choose a VST (.dll file)", "", ".DLL|*.dll",0)
If LibName$
  If OpenLibrary(0, LibName$)
    If ExamineLibraryFunctions(0)
      *ptrFunc = IsFunction(0, "main")
      If *ptrFunc
        *ptrPlug.AEffect = CallFunctionFast(*ptrFunc, @host())  ; oublie des parenthèses ^_^
      Else
        MessageRequester("Error","This library is not a VST",0)
      EndIf
    Else
      MessageRequester("Error","Can't examine this library.",0)
    EndIf
    CloseLibrary(0)
  Else
    MessageRequester("Error","Can't open this library.",0)
  EndIf
EndIf
Last edited by KarLKoX on Sun Oct 31, 2004 3:48 pm, edited 2 times in total.
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Post by traumatic »

OT: Sorry, just wondering, are you the same KarLKoX as the one on the skale tracker forum?
Good programmers don't comment their code. It was hard to write, should be hard to read.
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Yes i am :wink:
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
zapman*
Enthusiast
Enthusiast
Posts: 115
Joined: Wed Jun 02, 2004 10:17 pm
Location: New Caledonia (South Pacific)
Contact:

Post by zapman* »

Thanks a lot, KarLKox!!!!!! My problem come from a very stupid mistake!

I did examine your rar and I've seen that you've done a big part of the job. Thanks again!
Don't try - DO it !
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

No prob :)
The archive is often updated so if you want to see the progress, don't forget to download it from time to time :)
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
eriansa
Enthusiast
Enthusiast
Posts: 277
Joined: Wed Mar 17, 2004 12:31 am
Contact:

Post by eriansa »

If you need any help just contact me.

I've made a VST-Host with PB :
(and it took me 1 month to make it stable) :oops:

http://www.sq4.be
soerenkj
User
User
Posts: 95
Joined: Mon Jun 14, 2004 10:19 pm

Post by soerenkj »

good for you eriansa!
I once tried to make a vst host myself, but failed completely, and wasted a lot of time..
I would be very interested to see how you did that..
could you post code for a minimal vst host, or is it too much code..?!
sonicfire
New User
New User
Posts: 1
Joined: Sat Feb 04, 2006 2:10 am
Location: berlin

Post by sonicfire »

soerenkj wrote:good for you eriansa!
I once tried to make a vst host myself, but failed completely, and wasted a lot of time..
I would be very interested to see how you did that..
could you post code for a minimal vst host, or is it too much code..?!
would also love to know that ... the topic is a bit old, but who cares :lol: :wink:
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

eriansa wrote:If you need any help just contact me.

I've made a VST-Host with PB :
(and it took me 1 month to make it stable) :oops:

http://www.sq4.be
Very nice! Im waiting for the release :) Btw do you support gear like midi keyboards or the U
UC-33?
eriansa
Enthusiast
Enthusiast
Posts: 277
Joined: Wed Mar 17, 2004 12:31 am
Contact:

Post by eriansa »

the successor of SQ4² is almost finished AND this time it's stable as a rock! (PB 3.94).

The VST Host now supports 16 VSTI's/VSTe's+Rewire.
It has real time midiIn (+support for MidiControllers (I use UC33))

The mixer and audio engine are mostly written in fasm and are SSE optimized.
(did some comparisons with Tracktion/Acid/FLStudio/Energy/Orion (I own them all -Great Coders!/Fantastic software) and, to be honest, I can go as low as 48samples latency! (Asio))

I've planned to release a beta within a couple of weeks. I am especially looking for people owning :

1/ PC's with AMD processors.
2/ Asio cards/drivers that support INT32MSB/INT32LSB/Int32Float/96Khz etc...

But today PB4.0 is available : damn! :wink:
(35.000lines of code need to be re-checked)
So the release date will be postponed a little... :roll:

Anyway, PB+Fasm can beat C/C++/Delphi, and I really hope that other audio-developers start looking for this great language (I do not need OOP).
coma
Enthusiast
Enthusiast
Posts: 164
Joined: Fri Aug 15, 2003 3:46 am
Location: Canada

Post by coma »

is it possible to create VST/VSTi in pb ?
Post Reply