VST audio player (virtual instrument) plugin


#1

Hi guys,

I am trying to implement VST audio player (or virtual instrument) plugin.
The main idea is to have simple interface, lets say with one button, and when button is pressed, .wav file is loaded from file system and streamed to one of virtual audio output channels.
My question is: which classes should I use and which methods should I overwrite? I am seeking for general guidelines, but some code examples would be fine too. :slight_smile:

I have spent quite a lot of time trying to find code examples on internet, but without success.
I understand “hello world” example plugin which is generated with Introjucer. There you have to overwrite AudioProcessor::processBlock(…) method in which you process input buffer and result will be streamed to output. But in my case, there is no input event which will call processBlock method. I want to call it manually, for example on button press.

Thanks,


#2

Try this:
http://www.rawmaterialsoftware.com/viewtopic.php?f=8&t=10849&hilit=rory#p62654
It’s very, very basic, but should at least get you started.


#3

Hi Rory,

Thanks for your code example. It will be useful for reading file and copying it to output buffer.
I did similar work using File, WavAudioFormat and AudioSampleBuffer classes.
But unfortunately it doesn’t give answer to my question.
If I understood plugin concept correctly, in order to run AudioProcessor.processBlock() method some signal (stream or midi message) has to come to plugin input. But I want to call it manually, for example on button press. Should I call prepareToPlay() method first and then processBlock() method myself? Which arguments should I pass for these methods? Or is there other way to get reference to output buffer?

Sorry for messy questions, but this is part which puzzles me. :slight_smile: It should be quite common way to build plugins and I can’t find any example of it. For example, it should be possible to build plugin with zero inputs and stereo output and play sounds by reading it from file system.

I was reading through API doc, and I have few ideas which I’m going to try out.

  1. Implement AudioIODevice class (has methods open(), start()… which can be called on button click), which will use AudioProcessorPlayer (has methods setProcessor(), audioDeviceIOCallback()), and for processor I am going to use my AudioProcessor (with method processBlock()).
  2. Same thing as first one, but use AudioSourcePlayer and PositionableAudioSource instead of AudioProcessorPlayer and AudioProcessor.
  3. Implement Synthesiser class and try to play my sounds with it.

Any thoughts?


#4

Ok, I see what you mean. As you know, the processBlock() is called by the host, I’m not sure it’s a good idea, or even possible to call this manually. Ok, it may be possible, but it seems quite anti-intuitive. Anyhow, some hosts will start calling processBlock() as soon as the plugin is loaded so it’s quite easy for you to have a button turn on and off the audio merely by by-passing the processBlock() and muting its outputs. Other hosts will wait until the user hits play in the transport control. The juce demo host starts calling the plugin’s processBlock() straight away. I just checked with Renoise and it seems it waits until the host is in play mode. I have a feeling this is perhaps the most common approach taken by hosts. Is it really a deal-breaker if the user has to hit play in the host first?


#5

Thanks Rory.
I agree with you that I shouldn’t call processBlock() method on my own.
I didn’t know that processBlock() method is called all the time. I though that is called only when something comes to input.

I made example plugin and added FileLogger to log methods call and loaded it in “vsthost” host. Results confirm that processBlock() method is called all the time and it seems it is called every 100ms. I guess that it depends on host, does it?

That means that I can load wav file on button click into buffer, and in processBlock() method copy that buffer to out buffer. That could work. I have to test how it behaves.

I will try few more things now. I’ll get back to you. :slight_smile:
Thanks once again.


#6

Afaik, the frequency in which processBlock() gets called depends on the buffer size set by the host. In most hosts users can change it to suit themselves, but it’s easy to check the current buffer size from your plugin if you need to.


#7

Hi,

I made test code where I was reading wav file into AudioSampleBuffer on button click and send its reference to AudioProcessor. When processBlock() method is called and reference exists, its content is copied to output buffer. And it works. :slight_smile:
Sadly, after sound is played, plugin somehow crashes. I tried to catch exception and write it to log file, but no success. I saw in your code example that you used separate thread to read file. Is that way how things should be done?

Actually, I’m asking basic framework questions. Can you refer me to some link where I can read more about Juce framework concepts? For instance how buffers are used, how processBlock method is called and so on… I wasn’t able to find something like that on my own. I like to firstly understand things and that try to code. :slight_smile: I will try to take a look in VST documentation as well.

Thanks man. :slight_smile:


#8

I’m using the Thread class because BufferingAudioSource expects one. It might be easier for you to simply step through the debugger to try to catch that exception. Does the stack trace not give you any info? As for Juce framework concepts, everything you need to know can be learned from looking at the examples and the documentation. A basic overview of programming VST plugins may also be useful. JUCE provides a wrapper for the VST SDK so if you understand how the VST SDK works it will lead to a better understanding of JUCE. A quick google search for “programming VST pdf” should get you some useful info. If you are serious about this stuff then I recommend the ‘Audio Programming Book’ from MIT Press. It has several chapters dedicated to writing VST plugins, although nothing on Juce. Who knows, perhaps the second edition will. Apart from that, just ask your question directly to the list. Try to make the questions as specific as possible. It seems a lot of developers on this list are pros, so the less time they need to spend answering questions, the better chances you have of getting a prompt reply! I’m a complete amateur, hence the lengthy replies :slight_smile: