| 
							- /*
 -  * Carla Native Plugins
 -  * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
 -  *
 -  * This program is free software; you can redistribute it and/or
 -  * modify it under the terms of the GNU General Public License as
 -  * published by the Free Software Foundation; either version 2 of
 -  * the License, or any later version.
 -  *
 -  * This program is distributed in the hope that it will be useful,
 -  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 -  * GNU General Public License for more details.
 -  *
 -  * For a full copy of the GNU General Public License see the GPL.txt file
 -  */
 - 
 - // for UINT32_MAX
 - #define __STDC_LIMIT_MACROS
 - #include <cstdint>
 - 
 - #include "carla_native.hpp"
 - #include "carla_midi.h"
 - 
 - #include "zynaddsubfx/Misc/Master.h"
 - #include "zynaddsubfx/Misc/Util.h"
 - 
 - #include <ctime>
 - 
 - // Dummy variables and functions for linking purposes
 - class WavFile;
 - namespace Nio {
 -    bool start(void){return 1;}
 -    void stop(void){}
 -    void waveNew(WavFile*){}
 -    void waveStart(void){}
 -    void waveStop(void){}
 -    void waveEnd(void){}
 - }
 - 
 - SYNTH_T* synth = nullptr;
 - 
 - class ZynAddSubFxPlugin : public PluginDescriptorClass
 - {
 - public:
 -     enum Parameters {
 -         PARAMETER_COUNT = 0
 -     };
 - 
 -     ZynAddSubFxPlugin(const HostDescriptor* const host)
 -         : PluginDescriptorClass(host),
 -           m_master(new Master)
 -     {
 -         // refresh banks
 -         m_master->bank.rescanforbanks();
 - 
 -         for (uint32_t i=0, size = m_master->bank.banks.size(); i < size; i++)
 -         {
 -             if (m_master->bank.banks[i].dir.empty())
 -                 continue;
 - 
 -             m_master->bank.loadbank(m_master->bank.banks[i].dir);
 - 
 -             for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
 -             {
 -                 const std::string insName(m_master->bank.getname(instrument));
 - 
 -                 if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
 -                     continue;
 - 
 -                 ProgramInfo pInfo(i, instrument, insName.c_str());
 -                 m_programs.push_back(pInfo);
 -             }
 -         }
 -     }
 - 
 -     ~ZynAddSubFxPlugin()
 -     {
 -         //ensure that everything has stopped with the mutex wait
 -         pthread_mutex_lock(&m_master->mutex);
 -         pthread_mutex_unlock(&m_master->mutex);
 - 
 -         m_programs.clear();
 - 
 -         delete m_master;
 -     }
 - 
 - protected:
 -     // -------------------------------------------------------------------
 -     // Plugin parameter calls
 - 
 -     uint32_t getParameterCount()
 -     {
 -         return PARAMETER_COUNT;
 -     }
 - 
 -     const Parameter* getParameterInfo(const uint32_t index)
 -     {
 -         CARLA_ASSERT(index < getParameterCount());
 - 
 -         //if (index >= PARAMETER_COUNT)
 -         return nullptr;
 - 
 -         static Parameter param;
 - 
 -         param.ranges.step      = PARAMETER_RANGES_DEFAULT_STEP;
 -         param.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
 -         param.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
 -         param.scalePointCount  = 0;
 -         param.scalePoints      = nullptr;
 - 
 -         switch (index)
 -         {
 - #if 0
 -         case PARAMETER_MASTER:
 -             param.hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
 -             param.name  = "Master Volume";
 -             param.unit  = nullptr;
 -             param.ranges.min = 0.0f;
 -             param.ranges.max = 100.0f;
 -             param.ranges.def = 100.0f;
 -             break;
 - #endif
 -         }
 - 
 -         return ¶m;
 -     }
 - 
 -     float getParameterValue(const uint32_t index)
 -     {
 -         CARLA_ASSERT(index < getParameterCount());
 - 
 -         switch (index)
 -         {
 - #if 0
 -         case PARAMETER_MASTER:
 -             return m_master->Pvolume;
 - #endif
 -         default:
 -             return 0.0f;
 -         }
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin midi-program calls
 - 
 -     uint32_t getMidiProgramCount()
 -     {
 -         return m_programs.size();
 -     }
 - 
 -     const MidiProgram* getMidiProgramInfo(const uint32_t index)
 -     {
 -         CARLA_ASSERT(index < getMidiProgramCount());
 - 
 -         if (index >= m_programs.size())
 -             return nullptr;
 - 
 -         const ProgramInfo& pInfo(m_programs[index]);
 - 
 -         static MidiProgram midiProgram;
 -         midiProgram.bank    = pInfo.bank;
 -         midiProgram.program = pInfo.prog;
 -         midiProgram.name    = pInfo.name;
 - 
 -         return &midiProgram;
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin state calls
 - 
 -     void setParameterValue(const uint32_t index, const float value)
 -     {
 -         CARLA_ASSERT(index < getParameterCount());
 - 
 -         switch (index)
 -         {
 -         }
 - 
 -         return;
 - 
 -         // unused, TODO
 -         Q_UNUSED(value);
 -     }
 - 
 -     void setMidiProgram(const uint32_t bank, const uint32_t program)
 -     {
 -         if (bank >= m_master->bank.banks.size())
 -             return;
 -         if (program >= BANK_SIZE)
 -             return;
 - 
 -         const std::string bankdir(m_master->bank.banks[bank].dir);
 - 
 -         if (! bankdir.empty())
 -         {
 -             pthread_mutex_lock(&m_master->mutex);
 - 
 -             m_master->bank.loadbank(bankdir);
 -             m_master->bank.loadfromslot(program, m_master->part[0]);
 - 
 -             pthread_mutex_unlock(&m_master->mutex);
 -         }
 -     }
 - 
 -     // -------------------------------------------------------------------
 -     // Plugin process calls
 - 
 -     void activate()
 -     {
 -         m_master->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);
 -     }
 - 
 -     void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents)
 -     {
 -         if (pthread_mutex_trylock(&m_master->mutex) != 0)
 -         {
 -             carla_zeroFloat(outBuffer[0], frames);
 -             carla_zeroFloat(outBuffer[1], frames);
 -             return;
 -         }
 - 
 -         uint32_t fromFrame      = 0;
 -         uint32_t eventIndex     = 0;
 -         uint32_t nextEventFrame = 0;
 -         uint32_t toFrame = 0;
 - 
 -         do {
 -             // Find the time of the next event, if any
 -             if (eventIndex >= midiEventCount)
 -                 nextEventFrame = UINT32_MAX;
 -             else
 -                 nextEventFrame = midiEvents[eventIndex].time;
 - 
 -             // find the end of the sub-sample to be processed this time round...
 -             // if the next event falls within the desired sample interval...
 -             if ((nextEventFrame < frames) && (nextEventFrame >= toFrame))
 -                 // set the end to be at that event
 -                 toFrame = nextEventFrame;
 -             else
 -                 // ...else go for the whole remaining sample
 -                 toFrame = frames;
 - 
 -             if (fromFrame < toFrame)
 -             {
 -                 // call master to fill from `fromFrame` to `toFrame`:
 -                 m_master->GetAudioOutSamples(toFrame - fromFrame, (unsigned)getSampleRate(), &outBuffer[0][fromFrame], &outBuffer[1][fromFrame]);
 -                 // next sub-sample please...
 -                 fromFrame = toFrame;
 -             }
 - 
 -             // Now process any event(s) at the current timing point
 -             while (eventIndex < midiEventCount && midiEvents[eventIndex].time == toFrame)
 -             {
 -                 const uint8_t status  = MIDI_GET_STATUS_FROM_DATA(midiEvents[eventIndex].data);
 -                 const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvents[eventIndex].data);
 - 
 -                 if (MIDI_IS_STATUS_NOTE_OFF(status))
 -                 {
 -                     const uint8_t note = midiEvents[eventIndex].data[1];
 - 
 -                     m_master->noteOff(channel, note);
 -                 }
 -                 else if (MIDI_IS_STATUS_NOTE_ON(status))
 -                 {
 -                     const uint8_t note = midiEvents[eventIndex].data[1];
 -                     const uint8_t velo = midiEvents[eventIndex].data[2];
 - 
 -                     m_master->noteOn(channel, note, velo);
 -                 }
 -                 else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
 -                 {
 -                     const uint8_t note     = midiEvents[eventIndex].data[1];
 -                     const uint8_t pressure = midiEvents[eventIndex].data[2];
 - 
 -                     m_master->polyphonicAftertouch(channel, note, pressure);
 -                 }
 - 
 -                 eventIndex++;
 -             }
 - 
 -         // Keep going until we have the desired total length of sample...
 -         } while (toFrame < frames);
 - 
 -         pthread_mutex_unlock(&m_master->mutex);
 -     }
 - 
 -     // -------------------------------------------------------------------
 - 
 - private:
 -     struct ProgramInfo {
 -         uint32_t bank;
 -         uint32_t prog;
 -         CarlaString name;
 - 
 -         ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
 -           : bank(bank_),
 -             prog(prog_),
 -             name(name_) {}
 - 
 -         ProgramInfo() = delete;
 -     };
 - 
 -     std::vector<ProgramInfo> m_programs;
 - 
 -     Master* const m_master;
 - 
 - public:
 -     static int s_instanceCount;
 - 
 -     static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
 -     {
 -         if (s_instanceCount++ == 0)
 -         {
 -             synth = new SYNTH_T;
 -             synth->buffersize = host->get_buffer_size(host->handle);
 -             synth->samplerate = host->get_sample_rate(host->handle);
 -             synth->alias();
 - 
 -             config.init();
 -             config.cfg.SoundBufferSize = synth->buffersize;
 -             config.cfg.SampleRate      = synth->samplerate;
 -             config.cfg.GzipCompression = 0;
 - 
 -             sprng(std::time(nullptr));
 -             denormalkillbuf = new float[synth->buffersize];
 -             for (int i=0; i < synth->buffersize; i++)
 -                 denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
 -         }
 - 
 -         return new ZynAddSubFxPlugin(host);
 -     }
 - 
 -     static void _cleanup(PluginHandle handle)
 -     {
 -         delete (ZynAddSubFxPlugin*)handle;
 - 
 -         if (--s_instanceCount == 0)
 -         {
 -             delete[] denormalkillbuf;
 -             denormalkillbuf = nullptr;
 - 
 -             delete synth;
 -             synth = nullptr;
 -         }
 -     }
 - 
 -     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
 - };
 - 
 - int ZynAddSubFxPlugin::s_instanceCount = 0;
 - 
 - // -----------------------------------------------------------------------
 - 
 - static const PluginDescriptor zynAddSubFxDesc = {
 -     /* category  */ PLUGIN_CATEGORY_SYNTH,
 -     /* hints     */ PLUGIN_IS_SYNTH,
 -     /* audioIns  */ 2,
 -     /* audioOuts */ 2,
 -     /* midiIns   */ 1,
 -     /* midiOuts  */ 0,
 -     /* paramIns  */ ZynAddSubFxPlugin::PARAMETER_COUNT,
 -     /* paramOuts */ 0,
 -     /* name      */ "ZynAddSubFX",
 -     /* label     */ "zynaddsubfx",
 -     /* maker     */ "falkTX",
 -     /* copyright */ "GNU GPL v2+",
 -     PluginDescriptorFILL(ZynAddSubFxPlugin)
 - };
 - 
 - // -----------------------------------------------------------------------
 - 
 - void carla_register_native_plugin_zynaddsubfx()
 - {
 -     carla_register_native_plugin(&zynAddSubFxDesc);
 - }
 - 
 - // -----------------------------------------------------------------------
 
 
  |