<repo_name>marvinh/MyVstHost<file_sep>/MyVstHost/AudioIO.h
//
//  AudioIO.h
//  MyVstHost
//
//  Created by <NAME> on 8/8/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#ifndef AudioIO_h
#define AudioIO_h

#include "pluginterfaces/vst2.x/aeffectx.h"
#include "RtAudio.h"

class AudioIO
{
public:
    AudioIO();
    
    static int AudioCallback( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
                             double streamTime, RtAudioStreamStatus status, void *data );
    
    
    void InitializeAudio();

    RtAudio *dac;
    static VstEvents *events;
    static AEffect *effect;
    static std::mutex *mtx;
};

#endif /* AudioIO_h */
<file_sep>/MyVstHost/MidiState.h
//
//  MidiState.h
//  MyVstHost
//
//  Created by <NAME> on 8/8/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#ifndef MidiState_h
#define MidiState_h

#include "pluginterfaces/vst2.x/aeffectx.h"

class MidiState
{
public:
    MidiState()
    {
        baseNote = 60;
        velocity = 100;
        
        for(int i = 0; i < 128 ; i++)
        {
            noteOnArray[i] = false;
        }
        
    }
    ~MidiState()
    {
    
    }
    
    void NoteOn(char offsetFromOctave)
    {
        
        if(noteOnArray[offsetFromOctave+baseNote] == false)
        {
            mtx->lock();
            events->events[events->numEvents] = new VstEvent();
            VstMidiEvent *event = (VstMidiEvent*)events->events[events->numEvents];
            events->numEvents++;
            
            event->deltaFrames = ((int)(dac->getStreamTime()*44100))%512;
            event->midiData[0] = 0x90 | 0;
            event->midiData[1] = baseNote+offsetFromOctave;
            event->midiData[2] = velocity;
            event->type = kVstMidiType;
            event->byteSize = sizeof(VstMidiEvent);
            event->flags = 1;
            
            noteOnArray[offsetFromOctave+baseNote] = true;
            
            mtx->unlock();
        }
    }
    void NoteOff(char offsetFromOctave)
    {
        mtx->lock();
        
        events->events[events->numEvents] = new VstEvent();
        VstMidiEvent *event = (VstMidiEvent*)events->events[events->numEvents];
        events->numEvents++;
        
        event->deltaFrames = ((int)(dac->getStreamTime()*44100))%512;
        event->midiData[0] = 0x80 | 0;
        event->midiData[1] = baseNote+offsetFromOctave;
        event->midiData[2] = velocity;
        event->type = kVstMidiType;
        event->byteSize = sizeof(VstMidiEvent);
        event->flags = 1;
        
        noteOnArray[offsetFromOctave+baseNote] = false;
        
        mtx->unlock();
    }
    void AllNotesOff()
    {
        mtx->lock();
        
        effect->dispatcher(effect, effProcessEvents, 0, 0, events, 0);
        
        for(int i = 0; i < events->numEvents; i++)
        {
            if(events->events[i])
            {
                delete events->events[i];
            }
        }
        
        events->numEvents = 0;
        
        
        for(int i = 0; i < 128; i++)
        {
            
            events->events[events->numEvents] = new VstEvent();
            VstMidiEvent *event = (VstMidiEvent*)events->events[events->numEvents];
            event->deltaFrames = ((int)(dac->getStreamTime()*44100))%512;
            event->midiData[0] = 0x80 | 0;
            event->midiData[1] = i;
            event->midiData[2] = velocity;
            event->type = kVstMidiType;
            event->byteSize = sizeof(VstMidiEvent);
            event->flags = 1;
            events->numEvents++;
            noteOnArray[i] = false;
        }
        
        effect->dispatcher(effect, effProcessEvents, 0, 0, events, 0);
        
        for(int i = 0; i < events->numEvents; i++)
        {
            if(events->events[i])
            {
                delete events->events[i];
            }
        }
        
        events->numEvents = 0;
        mtx->unlock();
    }
    
    void VelocityUp()
    {
        if(velocity < 120)
        {
            velocity += 20;
        }
        else
        {
            velocity = 127;
        }
    }
    void VelocityDown()
    {
        if(velocity == 127)
        {
            velocity = 120;
        }
        else if(velocity > 20)
        {
            velocity -=20;
        }
        else
        {
            velocity = 1;
        }
    }
    void OctaveUp()
    {
        AllNotesOff();
        if(baseNote < 100)
        {
            baseNote += 12;
        }
    }
    void OctaveDown()
    {
        AllNotesOff();
        if(baseNote > 0)
        {
            baseNote -= 12;
        }
        
    }

    AEffect *effect;
    RtAudio *dac;
    VstEvents *events;
    std::mutex *mtx;
    bool noteOnArray[128];
    
private:
    char baseNote;
    char velocity;
    
    
};

#endif /* MidiState_h */
<file_sep>/MyVstHost/PluginFunctions.h
//
//  PluginFunctions.h
//  MyVstHost
//
//  Created by <NAME> on 8/8/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#ifndef PluginFunctions_h
#define PluginFunctions_h

#include <stdio.h>
#include <Cocoa/Cocoa.h>
#include "pluginterfaces/vst2.x/aeffectx.h"


//-------------------------------------------------------------------------------------------------------
static const VstInt32 kBlockSize = 512;
static const float kSampleRate = 44100.f;
static const VstInt32 kNumProcessCycles = 5;

//-------------------------------------------------------------------------------------------------------
typedef AEffect* (*PluginEntryProc) (audioMasterCallback audioMaster);
static VstIntPtr VSTCALLBACK HostCallback (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt);

//-------------------------------------------------------------------------------------------------------
// PluginLoader
//-------------------------------------------------------------------------------------------------------
struct PluginLoader
{
    //-------------------------------------------------------------------------------------------------------
    void* module;
    
    PluginLoader ()
    : module (0)
    {}
    
    ~PluginLoader ()
    {
        if (module)
        {
#if _WIN32
            FreeLibrary ((HMODULE)module);
#elif TARGET_API_MAC_CARBON
            CFBundleUnloadExecutable ((CFBundleRef)module);
            CFRelease ((CFBundleRef)module);
#endif
        }
    }
    
    bool loadLibrary (const char* fileName)
    {
#if _WIN32
        module = LoadLibrary (fileName);
#elif TARGET_API_MAC_CARBON
        CFStringRef fileNameString = CFStringCreateWithCString (NULL, fileName, kCFStringEncodingUTF8);
        if (fileNameString == 0)
            return false;
        CFURLRef url = CFURLCreateWithFileSystemPath (NULL, fileNameString, kCFURLPOSIXPathStyle, false);
        CFRelease (fileNameString);
        if (url == 0)
            return false;
        module = CFBundleCreate (kCFAllocatorDefault, url);
        CFRelease (url);
        if (module && CFBundleLoadExecutable ((CFBundleRef)module) == false)
            return false;
#endif
        return module != 0;
    }
    
    PluginEntryProc getMainEntry ()
    {
        PluginEntryProc mainProc = 0;
#if _WIN32
        mainProc = (PluginEntryProc)GetProcAddress ((HMODULE)module, "CFBundleMain");
        if (!mainProc)
            mainProc = (PluginEntryProc)GetProcAddress ((HMODULE)module, "main");
#elif TARGET_API_MAC_CARBON
        mainProc = (PluginEntryProc)CFBundleGetFunctionPointerForName ((CFBundleRef)module, CFSTR("VSTPluginMain"));
        if (!mainProc)
            mainProc = (PluginEntryProc)CFBundleGetFunctionPointerForName ((CFBundleRef)module, CFSTR("main_macho"));
#endif
        return mainProc;
    }
    //-------------------------------------------------------------------------------------------------------
};
//-------------------------------------------------------------------------------------------------------
static bool checkPlatform ()
{
#if VST_64BIT_PLATFORM
    printf ("*** This is a 64 Bit Build! ***\n");
#else
    printf ("*** This is a 32 Bit Build! ***\n");
#endif
    
    int sizeOfVstIntPtr = sizeof (VstIntPtr);
    int sizeOfVstInt32 = sizeof (VstInt32);
    int sizeOfPointer = sizeof (void*);
    int sizeOfAEffect = sizeof (AEffect);
    
    printf ("VstIntPtr = %d Bytes, VstInt32 = %d Bytes, Pointer = %d Bytes, AEffect = %d Bytes\n\n",
            sizeOfVstIntPtr, sizeOfVstInt32, sizeOfPointer, sizeOfAEffect);
    
    return sizeOfVstIntPtr == sizeOfPointer;
}

//-------------------------------------------------------------------------------------------------------
static void checkEffectProperties (AEffect* effect);
static void checkEffectProcessing (AEffect* effect);

//-------------------------------------------------------------------------------------------------------
void checkEffectProperties (AEffect* effect)
{
    printf ("HOST> Gathering properties...\n");
    
    char effectName[256] = {0};
    char vendorString[256] = {0};
    char productString[256] = {0};
    
    effect->dispatcher (effect, effGetEffectName, 0, 0, effectName, 0);
    effect->dispatcher (effect, effGetVendorString, 0, 0, vendorString, 0);
    effect->dispatcher (effect, effGetProductString, 0, 0, productString, 0);
    
    printf ("Name = %s\nVendor = %s\nProduct = %s\n\n", effectName, vendorString, productString);
    
    printf ("numPrograms = %d\nnumParams = %d\nnumInputs = %d\nnumOutputs = %d\n\n",
            effect->numPrograms, effect->numParams, effect->numInputs, effect->numOutputs);
    
    // Iterate programs...
    for (VstInt32 progIndex = 0; progIndex < effect->numPrograms; progIndex++)
    {
        char progName[256] = {0};
        if (!effect->dispatcher (effect, effGetProgramNameIndexed, progIndex, 0, progName, 0))
        {
            effect->dispatcher (effect, effSetProgram, 0, progIndex, 0, 0); // Note: old program not restored here!
            effect->dispatcher (effect, effGetProgramName, 0, 0, progName, 0);
        }
        printf ("Program %03d: %s\n", progIndex, progName);
    }
    
    printf ("\n");
    
    // Iterate parameters...
    for (VstInt32 paramIndex = 0; paramIndex < effect->numParams; paramIndex++)
    {
        char paramName[256] = {0};
        char paramLabel[256] = {0};
        char paramDisplay[256] = {0};
        
        effect->dispatcher (effect, effGetParamName, paramIndex, 0, paramName, 0);
        effect->dispatcher (effect, effGetParamLabel, paramIndex, 0, paramLabel, 0);
        effect->dispatcher (effect, effGetParamDisplay, paramIndex, 0, paramDisplay, 0);
        float value = effect->getParameter (effect, paramIndex);
        
        printf ("Param %03d: %s [%s %s] (normalized = %f)\n", paramIndex, paramName, paramDisplay, paramLabel, value);
    }
    
    printf ("\n");
    
    // Can-do nonsense...
    static const char* canDos[] =
    {
        "receiveVstEvents",
        "receiveVstMidiEvent",
        "midiProgramNames"
    };
    
    for (VstInt32 canDoIndex = 0; canDoIndex < sizeof (canDos) / sizeof (canDos[0]); canDoIndex++)
    {
        printf ("Can do %s... ", canDos[canDoIndex]);
        VstInt32 result = (VstInt32)effect->dispatcher (effect, effCanDo, 0, 0, (void*)canDos[canDoIndex], 0);
        switch (result)
        {
            case 0  : printf ("don't know"); break;
            case 1  : printf ("yes"); break;
            case -1 : printf ("definitely not!"); break;
            default : printf ("?????");
        }
        printf ("\n");
    }
    
    printf ("\n");
}

//-------------------------------------------------------------------------------------------------------
void checkEffectProcessing (AEffect* effect)
{
    
    float** inputs = 0;
    float** outputs = 0;
    VstInt32 numInputs = effect->numInputs;
    VstInt32 numOutputs = effect->numOutputs;

    if (numInputs > 0)
    {
        inputs = new float*[numInputs];
        for (VstInt32 i = 0; i < numInputs; i++)
        {
            inputs[i] = new float[kBlockSize];
            memset (inputs[i], 0, kBlockSize * sizeof (float));
        }
    }
    
    if (numOutputs > 0)
    {
        outputs = new float*[numOutputs];
        for (VstInt32 i = 0; i < numOutputs; i++)
        {
            outputs[i] = new float[kBlockSize];
            memset (outputs[i], 0, kBlockSize * sizeof (float));
        }
    }

    printf ("HOST> Resume effect...\n");
    effect->dispatcher (effect, effMainsChanged, 0, 1, 0, 0);
   
    for (VstInt32 processCount = 0; processCount < kNumProcessCycles; processCount++)
    {
        printf ("HOST> Process Replacing...\n");
        
        effect->processDoubleReplacing (effect, (double**)inputs,(double**) outputs, kBlockSize);
       
    }
    
    printf ("HOST> Suspend effect...\n");
    effect->dispatcher (effect, effMainsChanged, 0, 0, 0, 0);
    
    if (numInputs > 0)
    {
        for (VstInt32 i = 0; i < numInputs; i++)
            delete [] inputs[i];
        delete [] inputs;
    }
    
    if (numOutputs > 0)
    {
        for (VstInt32 i = 0; i < numOutputs; i++)
            delete [] outputs[i];
        delete [] outputs;
    }
}

//-------------------------------------------------------------------------------------------------------
VstIntPtr VSTCALLBACK HostCallback (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
{
    VstIntPtr result = 0;
    
    // Filter idle calls...
    bool filtered = true;
    if (opcode == audioMasterIdle)
    {
        static bool wasIdle = false;
        if (wasIdle)
            filtered = true;
        else
        {
            printf ("(Future idle calls will not be displayed!)\n");
            wasIdle = true;
        }
    }
    
    if (!filtered)
        printf ("PLUG> HostCallback (opcode %d)\n index = %d, value = %p, ptr = %p, opt = %f\n", opcode, index, FromVstPtr<void> (value), ptr, opt);
    
    switch (opcode)
    {
        case audioMasterVersion :
            result = kVstVersion;
            break;
    }
    
    return result;
}

#endif /* PluginFunctions_h */
<file_sep>/MyVstHost/AudioIO.cpp
//
//  AudioIO.cpp
//  MyVstHost
//
//  Created by <NAME> on 8/14/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

#include <stdio.h>
#include "AudioIO.h"

AEffect *AudioIO::effect;
VstEvents *AudioIO::events;
std::mutex *AudioIO::mtx;

AudioIO::AudioIO()
{
    
}
int AudioIO::AudioCallback( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
                           double streamTime, RtAudioStreamStatus status, void *data )
{
    if ( status )
        std::cout << "Stream underflow detected!" << std::endl;
    
    float* inputBufferF = (float*)inputBuffer;
    float* outputBufferF = (float*)outputBuffer;
    
    mtx->lock();
    if(events->numEvents>0)
    {
        
        effect->dispatcher(effect, effProcessEvents, 0, 0, events, 0);
    }
    for(int i = 0; i < nBufferFrames ; i++)
    {
        if(i==0)
        {
            float *inputs[2] = {inputBufferF, inputBufferF+nBufferFrames};
            float *outputs[2] = {outputBufferF,outputBufferF+nBufferFrames};
            effect->processReplacing(effect,inputs,outputs,nBufferFrames);
        }
    }
    
    for(int i = 0; i < events->numEvents; i++)
    {
        if(events->events[i])
        {
            delete events->events[i];
        }
    }
    events->numEvents = 0;
    
    mtx->unlock();
    
    return 0;
}

void AudioIO::InitializeAudio()
{
    
    
    RtAudio::StreamParameters oParams;
    oParams.deviceId = dac->getDefaultOutputDevice();
    oParams.nChannels = 2;
    
    RtAudio::StreamParameters iParams;
    iParams.deviceId = dac->getDefaultInputDevice();
    iParams.nChannels = 2;
  
    
    
    
    unsigned int sampleRate = 44100;
    unsigned int bufferFrames = 512; // 512 sample frames
    RtAudio::StreamOptions options;
    
    options.flags = RTAUDIO_NONINTERLEAVED | RTAUDIO_SCHEDULE_REALTIME;
    options.priority = 0;
    try {
        dac->openStream( &oParams, &iParams, RTAUDIO_FLOAT32,
                        sampleRate, &bufferFrames,&AudioCallback, NULL, &options );
        dac->startStream();
    }
    catch ( RtAudioError& e ) {
        std::cout << '\n' << e.getMessage() << '\n' << std::endl;
        exit( 0 );
    }
    
}