Error when run new plugin

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Hi all!
Help me please make the right plugin!
I write this code in pure C.
I can not understand what is wrong, the code is written correctly and everything compiles without errors.
Plugin kills host when scanning vstpluginss.

I think the problem is somewhere in the body of VSTPluginMain (), but as a beginner in VST-development I cannot understand where I wrote the wrong code.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <vst2\aeffect.h>
#include <vst2\aeffectx.h>

#define vst_export --declspec(dllexport)

// prototype for external function
struct AEffect* VSTPluginMain(audioMasterCallback audioMaster);

// constants
const VstInt32 plugversion = 1010;

// AuDioPlugin class
typedef struct AudioPlugin
{
VstInt32 samplerate;
VstInt32 left_channel;
VstInt32 right_channel;
} APlugin;

// Dispatcher function
VstIntPtr VSTCALLBACK Dispatcher(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
{
AEffect* aef = (AEffect*) malloc(sizeof(AEffect));
VstIntPtr ptr = 0;
FILE *fp;
switch (opcode)
{
case effClose:
free(aef);
break;
case effGetPlugCategory:
return kPlugCategEffect;
case effGetVendorString:
vst_strncpy(0, "Alex Longard", kVstMaxVendorStrLen);
case effGetVendorVersion:
return plugversion;
default:
break;
}
fp = fopen("log.txt", "w");
fprintf(fp, "worked! %d\n", ptr);
fclose(fp);
return ptr;
}


vst_export AEffect* VSTPluginMain(audioMasterCallback audioMaster)
{
AEffect* aef = (AEffect*) malloc(sizeof(AEffect));

aef->magic = kEffectMagic;
aef->dispatcher = &Dispatcher;
aef->numInputs = 2;
aef->numOutputs = 2;
aef->flags = effFlagsCanReplacing;
// aef->processReplacing = &ProcessProc;
aef->uniqueID = 4321;
aef->version = plugversion;
FILE *fp;
fp = fopen("data.txt", "w");
fprintf(fp, "i'am work %d\n", aef);
fclose(fp);
return aef;
}
			

Post

Code: Select all

// aef->processReplacing = &ProcessProc;
The host may try using the audio processing during the scan stage, so you should provide a valid processing function pointer. The same goes for the setParameter and getParameter function pointers. You might want to zero out the whole struct after allocating it.

The Dispatcher implementation seems a bit suspicious, the host might expect you to return zeros or something else for some of the opcodes during the scanning stage. You are returning the incoming ptr argument which might not be zero or what the host expects. (edit : Oh well, actually in my compiler that doesn't even compile because you are redeclaring the ptr variable...) You are needlessly creating a new AEffect struct instance in the Dispatcher and freeing that instance for the effClose case. Obviously not right. In your particular code, you just need to return 1 for the effClose case. You give a null pointer as the destination for the vst_strncpy call. The destination needs to be the incoming ptr.

If it still crashes after dealing with those issues, you should use the debugger to find where exactly the fault happens.

edit : This version compiles for me with Visual Studio 2017 and runs in 64 bit Reaper (obviously crashes when trying to run audio through it because I left the process function pointer null in the code) :

https://gist.github.com/Xenakios/09143c ... fcb17f4258
Last edited by Xenakios on Thu Jan 10, 2019 6:12 pm, edited 2 times in total.

Post

Hi Xenakios,
very big thanks for help!
I will now look at your code example, and correct the errors in my code.

I wrote in PHP for a long time to forget how memory is allocated for the structure, and how the pointers work :(((

Post

Alex_Longard wrote: Thu Jan 10, 2019 5:41 pm Hi Xenakios,
very big thanks for help!
I will now look at your code example, and correct the errors in my code.

I wrote in PHP for a long time to forget how memory is allocated for the structure, and how the pointers work :(((
There may be some bugs left in my version too...I have not looked into doing plain C VST2 plugins in a long time. Using C++ stuff like JUCE or IPlug is much more convenient and less error prone.

Post

Xenakios,
The main thing is what you explained where were my errors and showed an example of working code. I compiled your example and ran it in Reaper x86, it went through the scan correctly and showed the test files.

I do not like Juce, the plugins are heavy and uncomfortable. I have a very special task and it is better for me to make a plugin myself, since all the vst-developers to whom I addressed refuse to write such a plugin.

I will can switch to C++, but so far my hard drive in notebook does not allow to allocate space for Visual studio.

Post

If you want a simple way to start, try https://github.com/AndrewBelt/HelloDAW, which only requires MSYS2 and no IDE like Visual Studio. If you're still shaky on pointers, I'd avoid C for now and use pointerless C++, but you should learn them eventually. Not too difficult.
VCV Rack, the Eurorack simulator

Post

Hi Vortico,
I tried to compile hellovst a lot, but I catch a lot of errors and I do not know the mingw-make commands well.

I asked you to help compile the example
https://github.com/AndrewBelt/HelloDAW/issues/2

You wrote that you are too lazy to compile using cmd-files for Windows.
I’ll probably more quickly deal with the work of vst-plugins if I write all the code itself, and studying someone else’s code.

Post

Nowhere did I say that, but good luck with your endeavors!
VCV Rack, the Eurorack simulator

Post

Code: Select all

// Dispatcher function
VstIntPtr VSTCALLBACK Dispatcher(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
{
AEffect* aef = (AEffect*) malloc(sizeof(AEffect));
//VstIntPtr ptr = 0;
//FILE *fp;
switch (opcode)
{
case effClose:
free(aef);
break;
case effGetPlugCategory:
return kPlugCategEffect;
case effGetVendorString:
vst_strncpy(0, "Alex Longard", kVstMaxVendorStrLen);
case effGetVendorVersion:
return plugversion;
default:
break;
}
//fp = fopen("log.txt", "w");
//fprintf(fp, "worked! %d\n", ptr);
//fclose(fp);
//return ptr;
}
You shouldn't add stuff like your test code inside the dispatch, it's unnecessary. Doing it in VSTPluginMain is ok.

Post

Vortico, thanks for your code, Some details useful and interesting to me.

Camsr, i rewrite code:
It's work correctly, I while try to write functions setParam and getParam.

Code: Select all

//  Compile with TinyCC 0.97 x86 / x64.
// Big thanks for examples: Jon Ayres, Xenakios, Vortico, Yan Pujante.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include "aeffect.h"
#include "aeffectx.h"

#define vst_export __declspec(dllexport)
vst_export AEffect* VSTPluginMain(audioMasterCallback audioMaster);

typedef struct VstEvents VstEvents;
typedef struct VstMidiEvent VstMidiEvent;

const int channels = 2;
const int NumParams = 1;

float param_volume = 1.f;

VstInt32 processEvents(VstEvents* ev)
{
for (int i = 0; i < ev->numEvents; i++) {
VstEvent* event = ev->events[i];
if (event->type == kVstMidiType) {
VstMidiEvent* midiEvent = (VstMidiEvent*) event;
uint8_t status = midiEvent->midiData[0];
uint8_t data1 = midiEvent->midiData[0];
uint8_t data2 = midiEvent->midiData[0];
printf("MIDI: %02x %02x %02x\n", status, data1, data2);
}
}
return 0;
}

enum ParamNames {
parameter1 };

bool getVendorString(char* ptr) {
vst_strncpy((char*)ptr, "Alex Longard", kVstMaxVendorStrLen);
return true; }

void getParameterName(VstInt32 index, char* text) {
switch (index) {
case parameter1:
vst_strncpy((char*)text, "Volume", kVstMaxParamStrLen);
break; } }

VstIntPtr VSTCALLBACK Dispatcher(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
{
VstIntPtr result = 0;
switch (opcode)
{
case effProcessEvents:
result = processEvents((VstEvents*)ptr);
break;
case effGetPlugCategory:
result = kPlugCategEffect | kPlugCategAnalysis;
break;
case effGetVendorString:
result = getVendorString(ptr);
break;
case effGetEffectName:
vst_strncpy((char*)ptr, "VST test plugin", kVstMaxEffectNameLen);
break;
case effGetProductString:
vst_strncpy((char*)ptr, "magic plugin", kVstMaxEffectNameLen);
break;
case effGetParamName:
getParameterName(index, ptr);
break;
case effClose:
free(effect);
break;
default:
break;
}
return result;
}

void VSTCALLBACK process32(AEffect* effect, float** inputs, float** outputs, VstInt32 sampleframes)
{
for (int i = 0; i < sampleframes; i++)
{
for (int a = 0; a < channels; a++)
{
outputs[a][i] = inputs[a][i] * param_volume;
} } }

void VSTCALLBACK setparam(AEffect* effect, VstInt32 index, float value)
{
param_volume = value;
}

float VSTCALLBACK getparam(AEffect* effect, VstInt32 index)
{
return param_volume;
}

AEffect* VSTPluginMain(audioMasterCallback audioMaster)
{
AEffect* effect = (AEffect*) malloc(sizeof(AEffect));
memset(effect, 0, sizeof(AEffect));
effect->magic = kEffectMagic;
effect->dispatcher = &Dispatcher;
effect->setParameter = &setparam;
effect->getParameter = &getparam;
effect->numParams = NumParams;
effect->numInputs = channels;
effect->numOutputs = channels;
effect->flags = effFlagsCanReplacing;
effect->processReplacing = &process32;
effect->uniqueID = 1987;
effect->version = 1;
effect->			object = 0;
return effect;
}

Post Reply

Return to “DSP and Plugin Development”