Author Topic: Trying to use guitar VSTi  (Read 814 times)

Wayne McHugh

  • Posts: 58
Trying to use guitar VSTi
« on: 19 Mar '23 - 21:37 »
I have my MIDI player built using BASS/BASSMIDI, and sf2 files produce a  nice result except in relation to guitars. I am hoping I can introduce a guitar VSTi - playing with Ample Guitar M Lite. Firstly, is it even possible to use sf2 sound for all instruments except for one instrument using VSTi?  Or does it need to be all sf2 or all vsti?  I have Ample Guitar M Lite installed with Cakewalk. I have created a minimal Developer Studio C++ project in which I hope to learn the BASS/BASSVST landscape.  In this project, my simple sequence of calls is:
BASS_Init(-1, 44100, BASS_DEVICE_STEREO, win, NULL)); // runs successfully
vst_guitar = BASS_VST_ChannelCreate(44100, 2, "C:\\Program Files\\Cakewalk\\VstPlugins\\AGM2.dll", 0);  // vst_guitar receives a non-zero value
BASS_VST_ProcessEvent(vst_guitar, 0, MIDI_EVENT_NOTE, MAKEWORD(60, 100));  // just a single note to prove it works - but no sound plays
I get no sound from that final call.  It feels as though everything is in the right shape, but it doesn't play the note. It feels like I haven't setup the environment right, but I don't know what is missing. I'm a newbie to messing with VSTi.
My app and the VSTi are both x64 - if I get that wrong I get vst_guitar = 0.
Any thoughts on my goal (can it be done) and my specific startup problem?

Falcosoft

  • Posts: 167
Re: Trying to use guitar VSTi
« Reply #1 on: 20 Mar '23 - 13:59 »
Hi,
Before sending Midi events to your VSTi plugin (by calling BASS_VST_ProcessEvent) you have to call
BASS_ChannelPlay(vst_guitar, false);

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #2 on: 20 Mar '23 - 14:32 »
I have my MIDI player built using BASS/BASSMIDI, and sf2 files produce a  nice result except in relation to guitars. I am hoping I can introduce a guitar VSTi - playing with Ample Guitar M Lite. Firstly, is it even possible to use sf2 sound for all instruments except for one instrument using VSTi?  Or does it need to be all sf2 or all vsti?

I haven't tried this myself, but it may be possible to use VSTi in a BASSMIDI stream with BASS_MIDI_StreamGetChannel, ie. set a DSP function on the MIDI channel (via BASS_ChannelSetDSP) and then fetch data from the VSTi (via BASS_ChannelGetData) in there. Note the BASS_STREAM_DECODE and BASS_SAMPLE_FLOAT flags will need to be set on the VSTi stream for that. If you want the VSTi to play events from the same MIDI file as BASSMIDI then you could also use BASS_MIDI_StreamSetFilter to intercept and forward them to the VSTi.

If that doesn't work well, then another option is to have BASSMIDI and VSTi streams playing together, possibly using the BASSmix add-on to mix them into a single stream.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #3 on: 20 Mar '23 - 19:58 »
Falcosoft, that line was commented in my code, because it hadn't made any difference, and I wasn't sure it was needed. I've put it back in place and there is still no sound played. I do get a handle for vst_guitar, but no sound.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #4 on: 20 Mar '23 - 20:10 »
Thanks Ian, as usual you've said some things that I vaguely understand, but specifically do not. My #1 problem is that I've never managed to quite conceptually understand how the BASS/BASSMIDI (and now BASSVST) world actually fits together.  Is there anywhere in the documentation that the overall concept is explained?

Quote
If you want the VSTi to play events from the same MIDI file as BASSMIDI then you could also use BASS_MIDI_StreamSetFilter

By "you could also use", do you mean "an alternate approach could be", or would this approach also require the first part of your response?  If my impression of BASS_MIDI_StreamSetFilter is right, I think I understand this idea. I confess the first part of your answer is built on things I don't yet understand.

Falcosoft

  • Posts: 167
Re: Trying to use guitar VSTi
« Reply #5 on: 21 Mar '23 - 08:54 »
Can you attach your "minimal Developer Studio C++ project" so we can have a look at it?
This would be helpful to find out what your problem is.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #6 on: 21 Mar '23 - 10:23 »
I had a thought before checking back in the forum, and it was to add a couple of Sleep calls, just in case the BASS calls were running in a different thread, and not finishing in time for subsequent calls. It was successful, and now have the note playing.  There are effectively 4 calls, with the minimum required Sleep between them for it to work.

BASS_Init(-1, 44100, BASS_DEVICE_STEREO, win, NULL);
Sleep(820);
vst_guitar = BASS_VST_ChannelCreate(44100, 2, "C:\\Program Files\\Cakewalk\\VstPlugins\\AGML2.dll", 0);
Sleep(330);
BASS_ChannelPlay(vst_guitar, 0);
BASS_VST_ProcessEvent(vst_guitar, 0, MIDI_EVENT_NOTE, MAKEWORD(60, 100));

Though in my final goal it won't matter, it would be good to know what is actually going on here, so I can code the sequence properly.

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #7 on: 21 Mar '23 - 16:15 »
Quote
If you want the VSTi to play events from the same MIDI file as BASSMIDI then you could also use BASS_MIDI_StreamSetFilter

By "you could also use", do you mean "an alternate approach could be", or would this approach also require the first part of your response?  If my impression of BASS_MIDI_StreamSetFilter is right, I think I understand this idea. I confess the first part of your answer is built on things I don't yet understand.

The use of BASS_MIDI_StreamSetFilter would be in addition to BASS_MIDI_StreamGetChannel and BASS_ChannelSetDSP. The purpose of the BASS_MIDI_StreamGetChannel and BASS_ChannelSetDSP stuff is to allow a VSTi to generate the sound for a particular MIDI channel (eg. a guitar channel in your case), and the purpose of the BASS_MIDI_StreamSetFilter stuff is to forward that channel's events to the VSTi. It could look something like this:

Code: [Select]
vst_guitar = BASS_VST_ChannelCreate(44100, 2, "C:\\Program Files\\Cakewalk\\VstPlugins\\AGM2.dll", BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE); // load the VSTi
midichanstream = BASS_MIDI_StreamGetChannel(midistream, vst_channel); // get a stream for the MIDI channel to be handled by the VSTi
BASS_ChannelSetDSP(midichanstream, VSTiDSP, 0, 0); // set a DSP function on it to feed-in the VSTi output
BASS_MIDI_StreamSetFilter(midistream, true, MidiFilter, 0); // set a function to filter MIDI events

...

void CALLBACK VSTiDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
BASS_ChannelGetData(vst_guitar, buffer, length); // get data from the VSTi
}

BOOL CALLBACK MidiFilter(HSTREAM handle, int track, BASS_MIDI_EVENT *event, BOOL seeking, void *user)
{
if (event->chan == vst_channel) { // this event is for the VSTi's channel
BASS_VST_ProcessEvent(vst_guitar, event->chan, event->event, event->param); // forward it to the VSTi
if (event->event == MIDI_EVENT_NOTE) return false; // don't let BASSMIDI process notes sent to the VSTi (to avoid wasting time)
}
return true; // BASSMIDI can process the event
}

As I say, I haven't tried doing this myself, but it seems like it should work. Note the BASSMIDI and VSTi streams must have the same sample format, in the BASS_MIDI_StreamCreateFile and BASS_VST_ChannelCreate calls.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #8 on: 21 Mar '23 - 23:24 »
Ian, thank you - brilliant! It is playing the guitar channel using VSTi.  I don't yet have a sound font loaded for the rest to play, as I was attacking the VSTi first.   I will keep you posted, and should I be successful in what I'm trying to do, will happily supply the code for playing a MIDI file using VSTi on some MIDI channels.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #9 on: 22 Mar '23 - 08:06 »
Just to complete my harassment for now, I have mixed SF2/VSTi playback working beautifully.  My focus (for now) is on guitars, because they are generally so artificial in SF2, and I'm working to try and get finer control through the features offered in VSTi guitars.

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #10 on: 22 Mar '23 - 13:52 »
Great to hear that it's working well. In case you would like to be able to switch MIDI channels between BASSMIDI and the VSTi, I think it would be best to allocate an extra channel via BASS_ATTRIB_MIDI_CHANS and assign the VSTi to that (rather than an existing channel). For example, modify the code above like this:

Code: [Select]
BASS_ChannelSetAttribute(midistream, BASS_ATTRIB_MIDI_CHANS, 17); // allocate extra MIDI channel (assuming 16 originally)
midichanstream = BASS_MIDI_StreamGetChannel(midistream, 16); // get a stream for that channel to play the VSTi output

You can then freely change the MIDI channel(s) (may be multiple) that the MidiFilter function sends to the VSTi. If you want to use multiple VSTi then you can allocate an extra channel like this for each one.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #11 on: 30 Mar '23 - 01:48 »
Thanks Ian. Everything is going swimmingly well, including being able to switch from Soundfont to VSTi and (following your advice) with VSTi on multiple channels, switching back and forth.  So brilliant, I never thought it possible in my humble hands!  At this point I have only one further question: Is there any information anywhere about the VST Preset functions?  The header file lists the calls but gives no clue on the usage. Experimenting hasn't helped me.

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #12 on: 30 Mar '23 - 17:54 »
I'm not very familiar with the VST stuff, so I'm afraid I can't really help with that, but perhaps checking the source code of those functions will give some clues on usage? The BASS_VST source code is available here:

   https://github.com/r10s/BASS_VST

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #13 on: 10 Apr '23 - 12:24 »
It's been a while and I got it working beautifully on a single VSTi on a single channel, switching from VSTi to soundfont and back again.  I have since been working to make it general, allowing multiple tracks, a list of VSTi's.  To do this I've created classes to hold information about listed VSTi's, and as much as my old brain has struggled, it is holding together quite well.  However I'm concerned about the DSP callback and VSTi on multiple channels.  Ian, you supplied me with ...

Code: [Select]
vst_guitar = BASS_VST_ChannelCreate(44100, 2, "C:\\Program Files\\Cakewalk\\VstPlugins\\AGM2.dll", BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE); // load the VSTi
midichanstream = BASS_MIDI_StreamGetChannel(midistream, vst_channel); // get a stream for the MIDI channel to be handled by the VSTi
BASS_ChannelSetDSP(midichanstream, VSTiDSP, 0, 0); // set a DSP function on it to feed-in the VSTi output

...

void CALLBACK VSTiDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
BASS_ChannelGetData(vst_guitar, buffer, length); // get data from the VSTi
}

The callback receives the handle returned from BASS_ChannelSetDSP (param1) and the channel (param2). Because BASS_MIDI_StreamGetChannel is called for each channel that is running VSTi, I either need a different callback function for every possible channel (ie 16 callback functions), or there must be a different way to handle it. Have you any advice on that?

I'm still only testing it on one channel, and sadly there is a crackle and some distortion in the VSTi playing which I'm yet to understand (the simpler version played cleanly), but as I go through checking the validity of all my BASS calls, I can see a logical flaw in calling BASS_ChannelSetDSP for each VSTi channel, pointing to the one callback function.

I hope that makes sense.

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #14 on: 10 Apr '23 - 13:31 »
It should be fine to use the same DSPPROC function for all VSTi. You can use either the "channel" or "user" parameter to identify which VSTi each callback is regarding. The "channel" value is the handle that was returned by BASS_MIDI_StreamGetChannel and passed to BASS_ChannelSetDSP, while "user" is what was passed to BASS_ChannelSetDSP. For example, you could put the VSTi handle in the "user" parameter like this:

Code: [Select]
BASS_ChannelSetDSP(midichanstream, VSTiDSP, (void*)vst_guitar, 0); // set a DSP function on it to feed-in the VSTi output

...

void CALLBACK VSTiDSP(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user)
{
DWORD vsti = (DWORD)user; // VSTi handle
BASS_ChannelGetData(vsti, buffer, length); // get data from the VSTi
}
« Last Edit: 11 Apr '23 - 15:04 by Ian @ un4seen »

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #15 on: 10 Apr '23 - 20:40 »
Cool, that's pretty much what I'm doing, but was concerned my issue may have been in that area, but pleased that it isn't. Note to anyone using these discussions (as I do) that the last two parameters in your BASS_ChannelSetDSP call need to be reversed - user comes before priority.

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #16 on: 11 Apr '23 - 03:46 »
The sweet smell of success!  ;D It now allows VSTi on multiple channels, switching between soundfont and VSTi and back, and it just keeps playing.  Thanks, Ian, for all your help.  For anyone else wanting to use VSTi alongside soundfonts with MIDI, the core moves are all in this conversation.

Ian @ un4seen

  • Administrator
  • Posts: 25735
Re: Trying to use guitar VSTi
« Reply #17 on: 11 Apr '23 - 15:06 »
Note to anyone using these discussions (as I do) that the last two parameters in your BASS_ChannelSetDSP call need to be reversed - user comes before priority.

Oops, I've corrected that in the post now. Anyway, great to hear that you have it all working well now!

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #18 on: 12 Apr '23 - 23:02 »
Where a VSTi is capable of supporting multiple MIDI programs, I need to be able to automatically select the right VSTi configuration on each channel. Eg Strum Session 2 supports Nylon and steel acoustic, as well as Jazz, clean electric.  If I assign a MIDI channel to a VSTi, I need to ensure the VSTi will deliver the right instrument without the user having to intervene.  This is proving tricky because different VSTi plugins do this stuff in different ways. I've realised I can't count on the VSTi UI to save presets for me, because they often don't expose presets in files of their own, and they use their own format for the data.  I realised that I can invoke the VSTi UI, select the instrument that I want, and when I close the VSTi UI I can then call BASS_VST_StorePreset and save the presets myself.  I rashly assumed that I would be able to call BASS_VST_RecallPreset and point it to the preset file that I generated, and it would get the job done.  The preset file is generated correctly, and it contains the instrument bank and index (yay!). But alas, BASS_VST_RecallPreset reports that my preset file is either not designed to be run on Windows or it contains an error.  To anyone who has fought the battle of programmatically selecting a VSTi instrument, have you any insight?

Wayne McHugh

  • Posts: 58
Re: Trying to use guitar VSTi
« Reply #19 on: 13 Apr '23 - 03:07 »
I have successfully achieved what I need using Chunks.  I don't understand why presets wouldn't work, since the plugin is supplying them and then receiving them back, but for the moment chunks is doing the job.