diff --git a/src/add-ons/media/media-add-ons/vst_host/VSTHost.cpp b/src/add-ons/media/media-add-ons/vst_host/VSTHost.cpp index 2626226131..d8fe4bd0b4 100644 --- a/src/add-ons/media/media-add-ons/vst_host/VSTHost.cpp +++ b/src/add-ons/media/media-add-ons/vst_host/VSTHost.cpp @@ -1,559 +1,559 @@ -/* - * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. - * All rights reserved. - * Distributed under the terms of the MIT License. - */ - -#include -#include -#include - -#include - -#include "VSTHost.h" - -static int32 VHostCallback(VSTEffect* effect, int32 opcode, int32 index, - int32 value, void* ptr, float opt); - -//Trim string -static void -TrimString(BString *string) { - char* str = string->LockBuffer(256); - uint32 k = 0; - uint32 i = 0; - for(i=0; str[i]!='\0';) { - if (isspace(str[i])) { - k = i; - for(uint32 j = i; j < strlen(str) - 1; j++) - str[j] = str[j + 1]; - str[strlen(str) - 1] = '\0'; - i = k; - } else - i++; - } - string->UnlockBuffer(); -} - -//VST Parameter class -VSTParameter::VSTParameter(VSTPlugin* plugin, int index) -{ - fIndex = index; - fEffect = plugin->Effect(); - fDropList.MakeEmpty(); - - char temp[256]; - //get parameter name - temp[0] = 0; - fEffect->dispatcher(fEffect, VST_GET_PARAM_NAME, index, 0, temp, 0); - fName.SetTo(temp); - TrimString(&fName); - //get parameter label (unit) - temp[0] = 0; - fEffect->dispatcher(fEffect, VST_GET_PARAM_UNIT, index, 0, temp, 0); - fUnit.SetTo(temp); - ValidateValues(&fUnit); - //store current value - float val = fEffect->getParameter(fEffect, index); - //test for minimum value - fEffect->setParameter(fEffect, index, 0); - temp[0] = 0; - fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, 0, temp, 0); - fMinValue.SetTo(temp); - ValidateValues(&fMinValue); - //test for maximum value - temp[0] = 0; - fEffect->setParameter(fEffect, index, 1.0); - fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, 0, temp, 0); - fMaxValue.SetTo(temp); - ValidateValues(&fMaxValue); - //test for discrete values - char test_disp[VST_PARAM_TEST_COUNT][256]; - float test_values[VST_PARAM_TEST_COUNT]; - float delta = 1.0 / (float)VST_PARAM_TEST_COUNT; - int test_cnt = 0; - for(int tst_val = 0; tst_val < VST_PARAM_TEST_COUNT; tst_val++) { - float v = (float)tst_val / (float)VST_PARAM_TEST_COUNT; - - if (tst_val >= VST_PARAM_TEST_COUNT - 1) - v = 1.0; - - fEffect->setParameter(fEffect, index, v); - - float new_value = fEffect->getParameter(fEffect, index); - bool valtest = false; - for(int i = 0; i < test_cnt; i++) { - if (fabs(test_values[i] - new_value) < delta) { - valtest = true; - break; - } - } - if (valtest == false) { - test_values[test_cnt] = new_value; - fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, - 0, test_disp[test_cnt], 0); - test_cnt++; - } - } - - //restore value - fEffect->setParameter(fEffect, index, val); - - //detect param type - if (test_cnt == 2) { - fType = VST_PARAM_CHECKBOX; - - DropListValue* min_item = new DropListValue(); - min_item->Value = 0.0; - min_item->Index = 0; - min_item->Name = fMinValue; - fDropList.AddItem(min_item); - - DropListValue* max_item = new DropListValue(); - max_item->Value = 1.0; - max_item->Index = 1; - max_item->Name = fMaxValue; - fDropList.AddItem(max_item); - } else if (test_cnt > 2 && test_cnt < VST_PARAM_TEST_COUNT / 2) { - fType = VST_PARAM_DROPLIST; - - for(int i = 0; i < test_cnt; i++) { - DropListValue* item = new DropListValue(); - item->Value = test_values[i]; - item->Index = i; - item->Name = test_disp[i]; - fDropList.AddItem(item); - } - } else { - fType = VST_PARAM_SLIDER; - } - fChanged = 0LL; -} - -VSTParameter::~VSTParameter() -{ -} - -BString* -VSTParameter::ValidateValues(BString* string) -{ - if (string->Length() == 0) - return string; - - bool isNum = true; - - const char *ptr = string->String(); - for(; *ptr!=0; ptr++) { - char ch = *ptr; - if (!((ch >= '0' && ch <= '9') || ch == '.' || ch == '-')) { - isNum = false; - break; - } - } - - if (isNum) { - float val = atof(string->String()); - - if (val <= -pow(2, 31)) { - string->SetTo("-∞"); - } else if (val >= pow(2, 31)) { - string->SetTo("∞"); - } else { - char temp[256]; - sprintf(temp, "%g", val); - string->SetTo(temp); - } - } else { - TrimString(string); - if (*string == "oo" || *string == "inf") - string->SetTo("∞"); - if (*string == "-oo" || *string == "-inf") - string->SetTo("-∞"); - - } - return string; -} - -int -VSTParameter::ListCount(void) -{ - return fDropList.CountItems(); -} - -DropListValue* -VSTParameter::ListItemAt(int index) -{ - DropListValue* item = NULL; - if (index >= 0 && index < fDropList.CountItems()) - item = (DropListValue*)fDropList.ItemAt(index); - return item; -} - - -float -VSTParameter::Value() -{ - float value = fEffect->getParameter(fEffect, fIndex); - if (fType == VST_PARAM_DROPLIST) { - //scan for near value - int min_index = 0; - float min_delta = 1.0; - for(int i = 0; i < fDropList.CountItems(); i++) { - DropListValue* item = (DropListValue*)fDropList.ItemAt(i); - float delta = fabs(item->Value - value); - if (delta <= min_delta) { - min_delta = delta; - min_index = i; - } - } - value = min_index; - } - fLastValue = value; - return value; -} - -void -VSTParameter::SetValue(float value) -{ - if (value == fLastValue) - return; - - if (fType == VST_PARAM_DROPLIST) { - //take value by index - int index = (int)round(value); - if (index >= 0 && index < fDropList.CountItems()) { - DropListValue *item = (DropListValue*)fDropList.ItemAt(index); - value = item->Value; - fLastValue = index; - } else { - return; - } - } else { - fLastValue = value; - } - fChanged = system_time(); - fEffect->setParameter(fEffect, fIndex, value); -} - -bigtime_t -VSTParameter::LastChangeTime(void) -{ - return fChanged; -} - -const char* -VSTParameter::MinimumValue(void) -{ - return fMinValue.String(); -} - -const char* -VSTParameter::MaximumValue(void) -{ - return fMaxValue.String(); -} - -const char* -VSTParameter::Unit(void) -{ - return fUnit.String(); -} - -int -VSTParameter::Index(void) -{ - return fIndex; -} - -int -VSTParameter::Type(void) -{ - return fType; -} - -const char* -VSTParameter::Name(void) -{ - return fName.String(); -} - -//VST Plugin class -VSTPlugin::VSTPlugin() -{ - fActive = false; - fEffect = NULL; - VSTMainProc = NULL; - fInputChannels = 0; - fOutputChannels = 0; - fSampleRate = 44100.f; - fBlockSize = 0; - inputs = NULL; - outputs = NULL; - fParameters.MakeEmpty(); -} - -VSTPlugin::~VSTPlugin() -{ - fParameters.MakeEmpty(); - UnLoadModule(); -} - -int -VSTPlugin::LoadModule(const char *path) -{ - char effectName[256] = {0}; - char vendorString[256] = {0}; - char productString[256] = {0}; - - if (fActive) - return VST_ERR_ALREADY_LOADED; - - fPath = BPath(path); - - fModule = load_add_on(path); - if (fModule <= 0) - return VST_ERR_NOT_LOADED; - - if (get_image_symbol(fModule, "main_plugin", B_SYMBOL_TYPE_TEXT, - (void**)&VSTMainProc) != B_OK) { - unload_add_on(fModule); - return VST_ERR_NO_MAINPROC; - } - - fEffect = VSTMainProc(VHostCallback); - if (fEffect==NULL) { - unload_add_on(fModule); - return VST_ERR_NOT_LOADED; - } - - fEffect->dispatcher(fEffect, VST_OPEN, 0, 0, 0, 0); - - fEffect->dispatcher(fEffect, VST_GET_EFFECT_NAME, 0, 0, effectName, 0); - fEffectName.SetTo(effectName); - TrimString(&fEffectName); - - fModuleName.SetTo("VST:"); - fModuleName.Append(fPath.Leaf()); - - fEffect->dispatcher(fEffect, VST_GET_VENDOR_STR, 0, 0, vendorString, 0); - fVendorString.SetTo(vendorString); - TrimString(&fVendorString); - - fEffect->dispatcher(fEffect, VST_GET_PRODUCT_STR, 0, 0, productString, 0); - fProductString.SetTo(productString); - TrimString(&fProductString); - - fInputChannels = fEffect->numInputs; - fOutputChannels = fEffect->numOutputs; - - for(int i=0; i < fEffect->numParams; i++) { - VSTParameter *param = new VSTParameter(this, i); - fParameters.AddItem(param); - } - - fEffect->dispatcher(fEffect, VST_STATE_CHANGED, 0, 1, 0, 0); - - ReAllocBuffers(); - - fActive = true; - return B_OK; -} - -int -VSTPlugin::UnLoadModule(void) -{ - if (!fActive || fModule <= 0) - return VST_ERR_NOT_LOADED; - - fEffect->dispatcher(fEffect, VST_STATE_CHANGED, 0, 0, 0, 0); - fEffect->dispatcher(fEffect, VST_CLOSE, 0, 0, 0, 0); - - unload_add_on(fModule); - - return B_OK; -} - -int -VSTPlugin::Channels(int mode) -{ - switch(mode) { - case VST_INPUT_CHANNELS: - return fInputChannels; - case VST_OUTPUT_CHANNELS: - return fOutputChannels; - default: - return 0; - } -} - -int -VSTPlugin::SetSampleRate(float rate) -{ - fSampleRate = rate; - fEffect->dispatcher(fEffect, VST_SET_SAMPLE_RATE, 0, 0, 0, rate); - return B_OK; -} - -float -VSTPlugin::SampleRate(void) -{ - return fSampleRate; -} - -int -VSTPlugin::SetBlockSize(size_t size) -{ - fBlockSize = size; - fEffect->dispatcher(fEffect, VST_SET_BLOCK_SIZE, 0, size, 0, 0); - ReAllocBuffers(); - return B_OK; -} - -const char* -VSTPlugin::Path(void) -{ - return fPath.Path(); -} - -int -VSTPlugin::ReAllocBuffers(void) -{ - if (inputs != NULL) { - for(int32 i = 0; i < fInputChannels; i++) - delete inputs[i]; - } - - if (outputs != NULL) { - for(int32 i = 0; i < fOutputChannels; i++) - delete outputs[i]; - } - - if (fInputChannels > 0) { - inputs = new float*[fInputChannels]; - for(int32 i = 0; i < fInputChannels; i++) { - inputs[i] = new float[fBlockSize]; - memset(inputs[i], 0, fBlockSize * sizeof(float)); - } - } - - if (fOutputChannels > 0) { - outputs = new float*[fOutputChannels]; - for(int32_t i = 0; i < fOutputChannels; i++) { - outputs[i] = new float[fBlockSize]; - memset (outputs[i], 0, fBlockSize * sizeof(float)); - } - } - return B_OK; -} - -size_t -VSTPlugin::BlockSize(void) -{ - return fBlockSize; -} - -int -VSTPlugin::ParametersCount(void) -{ - return fParameters.CountItems(); -} - -VSTParameter* -VSTPlugin::Parameter(int index) -{ - VSTParameter* param = NULL; - - if (index >= 0 && index < fParameters.CountItems()) - param = (VSTParameter*)fParameters.ItemAt(index); - - return param; -} - -VSTEffect* -VSTPlugin::Effect(void) -{ - return fEffect; -} - -const char* -VSTPlugin::EffectName(void) -{ - return fEffectName.String(); -} - -const char* -VSTPlugin::ModuleName(void) -{ - return fModuleName.String(); -} - -const char* -VSTPlugin::Vendor(void) -{ - return fVendorString.String(); -} - -const char* -VSTPlugin::Product(void) -{ - return fProductString.String(); -} - - -void -VSTPlugin::Process(float *buffer, int samples, int channels) -{ - //todo: full channels remapping needed - float* src = buffer; - - if (channels == fInputChannels) { //channel to channel - for(int j = 0; j < samples; j++) { - for(int c = 0; c < fInputChannels; c++) - inputs[c][j] = *src++; - } - } else if ( channels == 1) { //from mone to multichannel - for(int j = 0; j < samples; j++, src++) { - for(int c = 0; c < fInputChannels; c++) - inputs[c][j] = *src; - } - } - - fEffect->processReplacing(fEffect, inputs, outputs, fBlockSize); - - float* dst = buffer; - - if (channels == fOutputChannels) { //channel to channel - for(int j = 0; j < samples; j++) { - for(int c = 0; c < fOutputChannels; c++) - *dst++ = outputs[c][j]; - } - } else if (channels == 1) { //from multichannel to mono - for(int j = 0; j < samples; j++, dst++) { - float mix = 0; - for(int c = 0; c < fOutputChannels; c++) - mix += outputs[c][j]; - *dst = mix / (float)fOutputChannels; - } - } -} - -static int32 -VHostCallback(VSTEffect* effect, int32 opcode, int32 index, int32 value, - void* ptr, float opt) -{ - intptr_t result = 0; - - switch(opcode) - { - case VST_MASTER_PRODUCT: - if (ptr) { - strcpy((char*)ptr, "VSTHost Media AddOn"); - result = 1; - } - break; - case VST_MASTER_VERSION : - result = 2300; - break; - } - - return result; -} +/* + * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. + * All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include +#include +#include + +#include + +#include "VSTHost.h" + +static int32 VHostCallback(VSTEffect* effect, int32 opcode, int32 index, + int32 value, void* ptr, float opt); + +//Trim string +static void +TrimString(BString *string) { + char* str = string->LockBuffer(256); + uint32 k = 0; + uint32 i = 0; + for(i=0; str[i]!='\0';) { + if (isspace(str[i])) { + k = i; + for(uint32 j = i; j < strlen(str) - 1; j++) + str[j] = str[j + 1]; + str[strlen(str) - 1] = '\0'; + i = k; + } else + i++; + } + string->UnlockBuffer(); +} + +//VST Parameter class +VSTParameter::VSTParameter(VSTPlugin* plugin, int index) +{ + fIndex = index; + fEffect = plugin->Effect(); + fDropList.MakeEmpty(); + + char temp[256]; + //get parameter name + temp[0] = 0; + fEffect->dispatcher(fEffect, VST_GET_PARAM_NAME, index, 0, temp, 0); + fName.SetTo(temp); + TrimString(&fName); + //get parameter label (unit) + temp[0] = 0; + fEffect->dispatcher(fEffect, VST_GET_PARAM_UNIT, index, 0, temp, 0); + fUnit.SetTo(temp); + ValidateValues(&fUnit); + //store current value + float val = fEffect->getParameter(fEffect, index); + //test for minimum value + fEffect->setParameter(fEffect, index, 0); + temp[0] = 0; + fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, 0, temp, 0); + fMinValue.SetTo(temp); + ValidateValues(&fMinValue); + //test for maximum value + temp[0] = 0; + fEffect->setParameter(fEffect, index, 1.0); + fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, 0, temp, 0); + fMaxValue.SetTo(temp); + ValidateValues(&fMaxValue); + //test for discrete values + char test_disp[VST_PARAM_TEST_COUNT][256]; + float test_values[VST_PARAM_TEST_COUNT]; + float delta = 1.0 / (float)VST_PARAM_TEST_COUNT; + int test_cnt = 0; + for(int tst_val = 0; tst_val < VST_PARAM_TEST_COUNT; tst_val++) { + float v = (float)tst_val / (float)VST_PARAM_TEST_COUNT; + + if (tst_val >= VST_PARAM_TEST_COUNT - 1) + v = 1.0; + + fEffect->setParameter(fEffect, index, v); + + float new_value = fEffect->getParameter(fEffect, index); + bool valtest = false; + for(int i = 0; i < test_cnt; i++) { + if (fabs(test_values[i] - new_value) < delta) { + valtest = true; + break; + } + } + if (valtest == false) { + test_values[test_cnt] = new_value; + fEffect->dispatcher(fEffect, VST_GET_PARAM_STR, index, + 0, test_disp[test_cnt], 0); + test_cnt++; + } + } + + //restore value + fEffect->setParameter(fEffect, index, val); + + //detect param type + if (test_cnt == 2) { + fType = VST_PARAM_CHECKBOX; + + DropListValue* min_item = new DropListValue(); + min_item->Value = 0.0; + min_item->Index = 0; + min_item->Name = fMinValue; + fDropList.AddItem(min_item); + + DropListValue* max_item = new DropListValue(); + max_item->Value = 1.0; + max_item->Index = 1; + max_item->Name = fMaxValue; + fDropList.AddItem(max_item); + } else if (test_cnt > 2 && test_cnt < VST_PARAM_TEST_COUNT / 2) { + fType = VST_PARAM_DROPLIST; + + for(int i = 0; i < test_cnt; i++) { + DropListValue* item = new DropListValue(); + item->Value = test_values[i]; + item->Index = i; + item->Name = test_disp[i]; + fDropList.AddItem(item); + } + } else { + fType = VST_PARAM_SLIDER; + } + fChanged = 0LL; +} + +VSTParameter::~VSTParameter() +{ +} + +BString* +VSTParameter::ValidateValues(BString* string) +{ + if (string->Length() == 0) + return string; + + bool isNum = true; + + const char *ptr = string->String(); + for(; *ptr!=0; ptr++) { + char ch = *ptr; + if (!((ch >= '0' && ch <= '9') || ch == '.' || ch == '-')) { + isNum = false; + break; + } + } + + if (isNum) { + float val = atof(string->String()); + + if (val <= -pow(2, 31)) { + string->SetTo("-∞"); + } else if (val >= pow(2, 31)) { + string->SetTo("∞"); + } else { + char temp[256]; + sprintf(temp, "%g", val); + string->SetTo(temp); + } + } else { + TrimString(string); + if (*string == "oo" || *string == "inf") + string->SetTo("∞"); + if (*string == "-oo" || *string == "-inf") + string->SetTo("-∞"); + + } + return string; +} + +int +VSTParameter::ListCount(void) +{ + return fDropList.CountItems(); +} + +DropListValue* +VSTParameter::ListItemAt(int index) +{ + DropListValue* item = NULL; + if (index >= 0 && index < fDropList.CountItems()) + item = (DropListValue*)fDropList.ItemAt(index); + return item; +} + + +float +VSTParameter::Value() +{ + float value = fEffect->getParameter(fEffect, fIndex); + if (fType == VST_PARAM_DROPLIST) { + //scan for near value + int min_index = 0; + float min_delta = 1.0; + for(int i = 0; i < fDropList.CountItems(); i++) { + DropListValue* item = (DropListValue*)fDropList.ItemAt(i); + float delta = fabs(item->Value - value); + if (delta <= min_delta) { + min_delta = delta; + min_index = i; + } + } + value = min_index; + } + fLastValue = value; + return value; +} + +void +VSTParameter::SetValue(float value) +{ + if (value == fLastValue) + return; + + if (fType == VST_PARAM_DROPLIST) { + //take value by index + int index = (int)vstround(value); + if (index >= 0 && index < fDropList.CountItems()) { + DropListValue *item = (DropListValue*)fDropList.ItemAt(index); + value = item->Value; + fLastValue = index; + } else { + return; + } + } else { + fLastValue = value; + } + fChanged = system_time(); + fEffect->setParameter(fEffect, fIndex, value); +} + +bigtime_t +VSTParameter::LastChangeTime(void) +{ + return fChanged; +} + +const char* +VSTParameter::MinimumValue(void) +{ + return fMinValue.String(); +} + +const char* +VSTParameter::MaximumValue(void) +{ + return fMaxValue.String(); +} + +const char* +VSTParameter::Unit(void) +{ + return fUnit.String(); +} + +int +VSTParameter::Index(void) +{ + return fIndex; +} + +int +VSTParameter::Type(void) +{ + return fType; +} + +const char* +VSTParameter::Name(void) +{ + return fName.String(); +} + +//VST Plugin class +VSTPlugin::VSTPlugin() +{ + fActive = false; + fEffect = NULL; + VSTMainProc = NULL; + fInputChannels = 0; + fOutputChannels = 0; + fSampleRate = 44100.f; + fBlockSize = 0; + inputs = NULL; + outputs = NULL; + fParameters.MakeEmpty(); +} + +VSTPlugin::~VSTPlugin() +{ + fParameters.MakeEmpty(); + UnLoadModule(); +} + +int +VSTPlugin::LoadModule(const char *path) +{ + char effectName[256] = {0}; + char vendorString[256] = {0}; + char productString[256] = {0}; + + if (fActive) + return VST_ERR_ALREADY_LOADED; + + fPath = BPath(path); + + fModule = load_add_on(path); + if (fModule <= 0) + return VST_ERR_NOT_LOADED; + + if (get_image_symbol(fModule, "main_plugin", B_SYMBOL_TYPE_TEXT, + (void**)&VSTMainProc) != B_OK) { + unload_add_on(fModule); + return VST_ERR_NO_MAINPROC; + } + + fEffect = VSTMainProc(VHostCallback); + if (fEffect==NULL) { + unload_add_on(fModule); + return VST_ERR_NOT_LOADED; + } + + fEffect->dispatcher(fEffect, VST_OPEN, 0, 0, 0, 0); + + fEffect->dispatcher(fEffect, VST_GET_EFFECT_NAME, 0, 0, effectName, 0); + fEffectName.SetTo(effectName); + TrimString(&fEffectName); + + fModuleName.SetTo("VST:"); + fModuleName.Append(fPath.Leaf()); + + fEffect->dispatcher(fEffect, VST_GET_VENDOR_STR, 0, 0, vendorString, 0); + fVendorString.SetTo(vendorString); + TrimString(&fVendorString); + + fEffect->dispatcher(fEffect, VST_GET_PRODUCT_STR, 0, 0, productString, 0); + fProductString.SetTo(productString); + TrimString(&fProductString); + + fInputChannels = fEffect->numInputs; + fOutputChannels = fEffect->numOutputs; + + for(int i=0; i < fEffect->numParams; i++) { + VSTParameter *param = new VSTParameter(this, i); + fParameters.AddItem(param); + } + + fEffect->dispatcher(fEffect, VST_STATE_CHANGED, 0, 1, 0, 0); + + ReAllocBuffers(); + + fActive = true; + return B_OK; +} + +int +VSTPlugin::UnLoadModule(void) +{ + if (!fActive || fModule <= 0) + return VST_ERR_NOT_LOADED; + + fEffect->dispatcher(fEffect, VST_STATE_CHANGED, 0, 0, 0, 0); + fEffect->dispatcher(fEffect, VST_CLOSE, 0, 0, 0, 0); + + unload_add_on(fModule); + + return B_OK; +} + +int +VSTPlugin::Channels(int mode) +{ + switch(mode) { + case VST_INPUT_CHANNELS: + return fInputChannels; + case VST_OUTPUT_CHANNELS: + return fOutputChannels; + default: + return 0; + } +} + +int +VSTPlugin::SetSampleRate(float rate) +{ + fSampleRate = rate; + fEffect->dispatcher(fEffect, VST_SET_SAMPLE_RATE, 0, 0, 0, rate); + return B_OK; +} + +float +VSTPlugin::SampleRate(void) +{ + return fSampleRate; +} + +int +VSTPlugin::SetBlockSize(size_t size) +{ + fBlockSize = size; + fEffect->dispatcher(fEffect, VST_SET_BLOCK_SIZE, 0, size, 0, 0); + ReAllocBuffers(); + return B_OK; +} + +const char* +VSTPlugin::Path(void) +{ + return fPath.Path(); +} + +int +VSTPlugin::ReAllocBuffers(void) +{ + if (inputs != NULL) { + for(int32 i = 0; i < fInputChannels; i++) + delete inputs[i]; + } + + if (outputs != NULL) { + for(int32 i = 0; i < fOutputChannels; i++) + delete outputs[i]; + } + + if (fInputChannels > 0) { + inputs = new float*[fInputChannels]; + for(int32 i = 0; i < fInputChannels; i++) { + inputs[i] = new float[fBlockSize]; + memset(inputs[i], 0, fBlockSize * sizeof(float)); + } + } + + if (fOutputChannels > 0) { + outputs = new float*[fOutputChannels]; + for(int32_t i = 0; i < fOutputChannels; i++) { + outputs[i] = new float[fBlockSize]; + memset (outputs[i], 0, fBlockSize * sizeof(float)); + } + } + return B_OK; +} + +size_t +VSTPlugin::BlockSize(void) +{ + return fBlockSize; +} + +int +VSTPlugin::ParametersCount(void) +{ + return fParameters.CountItems(); +} + +VSTParameter* +VSTPlugin::Parameter(int index) +{ + VSTParameter* param = NULL; + + if (index >= 0 && index < fParameters.CountItems()) + param = (VSTParameter*)fParameters.ItemAt(index); + + return param; +} + +VSTEffect* +VSTPlugin::Effect(void) +{ + return fEffect; +} + +const char* +VSTPlugin::EffectName(void) +{ + return fEffectName.String(); +} + +const char* +VSTPlugin::ModuleName(void) +{ + return fModuleName.String(); +} + +const char* +VSTPlugin::Vendor(void) +{ + return fVendorString.String(); +} + +const char* +VSTPlugin::Product(void) +{ + return fProductString.String(); +} + + +void +VSTPlugin::Process(float *buffer, int samples, int channels) +{ + //todo: full channels remapping needed + float* src = buffer; + + if (channels == fInputChannels) { //channel to channel + for(int j = 0; j < samples; j++) { + for(int c = 0; c < fInputChannels; c++) + inputs[c][j] = *src++; + } + } else if ( channels == 1) { //from mone to multichannel + for(int j = 0; j < samples; j++, src++) { + for(int c = 0; c < fInputChannels; c++) + inputs[c][j] = *src; + } + } + + fEffect->processReplacing(fEffect, inputs, outputs, fBlockSize); + + float* dst = buffer; + + if (channels == fOutputChannels) { //channel to channel + for(int j = 0; j < samples; j++) { + for(int c = 0; c < fOutputChannels; c++) + *dst++ = outputs[c][j]; + } + } else if (channels == 1) { //from multichannel to mono + for(int j = 0; j < samples; j++, dst++) { + float mix = 0; + for(int c = 0; c < fOutputChannels; c++) + mix += outputs[c][j]; + *dst = mix / (float)fOutputChannels; + } + } +} + +static int32 +VHostCallback(VSTEffect* effect, int32 opcode, int32 index, int32 value, + void* ptr, float opt) +{ + intptr_t result = 0; + + switch(opcode) + { + case VST_MASTER_PRODUCT: + if (ptr) { + strcpy((char*)ptr, "VSTHost Media AddOn"); + result = 1; + } + break; + case VST_MASTER_VERSION : + result = 2300; + break; + } + + return result; +} diff --git a/src/add-ons/media/media-add-ons/vst_host/VSTHost.h b/src/add-ons/media/media-add-ons/vst_host/VSTHost.h index 914e37efae..1689fac829 100644 --- a/src/add-ons/media/media-add-ons/vst_host/VSTHost.h +++ b/src/add-ons/media/media-add-ons/vst_host/VSTHost.h @@ -2,8 +2,8 @@ * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. * All rights reserved. * Distributed under the terms of the MIT License. - */ - + */ + #ifndef __VST_HOST_H__ #define __VST_HOST_H__ @@ -61,7 +61,7 @@ struct VSTEffect { int cookie; - int32 (*dispatcher)(struct VSTEffect*, int32, + int32 (*dispatcher)(struct VSTEffect*, int32, int32, int32, void*, float); void (*process)(struct VSTEffect*, float**, float**, int32); @@ -87,7 +87,7 @@ struct VSTEffect //typedefs typedef int32 (*audioMasterCallback)(VSTEffect*, int32, int32, int32, void*, float); typedef VSTEffect* (*VSTEntryProc)(audioMasterCallback audioMaster); -inline float round(float x) {return ceil(x-0.5);} +inline float vstround(float x) {return ceil(x-0.5);} //structure for droplist parameters struct DropListValue { @@ -130,7 +130,7 @@ private: //vst plugin interface class VSTPlugin { -public: +public: VSTPlugin(); ~VSTPlugin(); int LoadModule(const char *path); @@ -150,11 +150,11 @@ public: int Channels(int mode); int ReAllocBuffers(void); void Process(float *buffer, int samples, int channels); -private: +private: VSTEntryProc GetMainEntry(); VSTEffect* fEffect; VSTEntryProc VSTMainProc; - bool fActive; + bool fActive; image_id fModule; BPath fPath; size_t fBlockSize;