Files
JaySynth/Source/PluginProcessor.cpp
T
jens ea4397907f - added load of fxb through GUI
- added load of fxp through GUI
2023-04-28 14:08:59 +02:00

958 lines
26 KiB
C++

/*
==============================================================================
This file was auto-generated!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include <math.h>
#include "PluginProcessor.h"
#include "JaySynthAudioProcessorEditor.h"
#include "synth/vector_utils.h"
using namespace juce;
JaySynthAudioProcessorEditor* getEditor(JaySynthAudioProcessor *pThis)
{
return dynamic_cast<JaySynthAudioProcessorEditor*>(pThis->getActiveEditor());
}
//==============================================================================
JaySynthAudioProcessor::JaySynthAudioProcessor()
{
currProgram = 0;
currpatch = &patches[currProgram];
the_editor = NULL;
m_isWavesAvailable = isWavesAvailable();
// Initialise the synth...
pSynth = new JaySynth(MAX_POLYPHONY, wavesGetPath());
pSynth->setNoteStealingEnabled(true);
pSynth->addListener(this);
setCurrentProgram(0);
m_limiter_env = 0;
startTimer (10);
#ifdef DEBUG
SynthDebug ("Jay Synth V %s (DEBUG) initialized.\n", JucePlugin_VersionString);
#else
SynthDebug ("Jay Synth V %s initialized.\n", JucePlugin_VersionString);
#endif
}
JaySynthAudioProcessor::~JaySynthAudioProcessor()
{
delete (pSynth);
}
void JaySynthAudioProcessor::timerCallback()
{
if (getEditor(this))
actionListener.callLimiterChanged(m_limiter_active);
}
String JaySynthAudioProcessor::wavesGetPath()
{
bool isExistent, isValid;
File pluginfile = File::getSpecialLocation (File::currentExecutableFile).getParentDirectory();
#if LINUX
String wavespath = pluginfile.getFullPathName() + String("/waves.bin");
#else
// that'S probably windows
String wavespath = pluginfile.getFullPathName() + String("\\waves.bin");
#endif
File wavesfile = File(wavespath);
isExistent = wavesfile.existsAsFile();
isValid = true;
if (isExistent && isValid)
return wavespath;
return String::empty;
}
bool JaySynthAudioProcessor::isWavesAvailable()
{
return (wavesGetPath() != String::empty);
}
//==============================================================================
const String JaySynthAudioProcessor::getName() const
{
return JucePlugin_Name;
}
int JaySynthAudioProcessor::getNumParameters()
{
return SYNTH_NUM_PARAMS;
}
void JaySynthAudioProcessor::applyCurrentMidiControllers(void)
{
JaySynth::midiCC_info_t *pMidiCC_info;
int i;
for (i=0; i < NUM_MIDI_CONTROLLERS; i++)
{
pMidiCC_info = pSynth->getLastMidiCC_info(i);
if (pMidiCC_info)
applyMidiController(pMidiCC_info, false);
}
}
void JaySynthAudioProcessor::applyMidiController(JaySynth::midiCC_info_t *pMidiCC_info, bool forceApply)
{
int i, numDst, paramID;
midiCC_container_t *pMidi_container;
numDst = midCC_editBuffer.getNumDestinations(pMidiCC_info->ID);
for (i=0; i < numDst; i++)
{
pMidi_container = midCC_editBuffer.getDestination(pMidiCC_info->ID, i);
paramID = midCC_editBuffer.getParamID(pMidi_container);
if (midCC_editBuffer.doApplyOnPatchInit(pMidi_container) || forceApply)
{
if (midCC_editBuffer.doChangeParameter(pMidi_container))
{
setParam(paramID, toParam(midCC_editBuffer.getParam(pMidi_container), pMidiCC_info->value), false, false);
}
else
{
controlParam(midCC_editBuffer.getParamID(pMidi_container), toParam(midCC_editBuffer.getControl(pMidi_container), pMidiCC_info->value));
}
}
}
}
void JaySynthAudioProcessor::synthChanged(int type, void *pData)
{
JaySynth::midiCC_info_t *pMidiCC_info;
JaySynth::midi_note_info_t *pMidi_note_info;
JaySynth::midi_quarter_clock_info_t *pMidi_quarter_info;
switch(type)
{
case JaySynth::SYNTH_CHANGED_PARAM:
if (getEditor(this) != NULL)
actionListener.callParamChanged(*((int*)pData));
break;
case JaySynth::SYNTH_CHANGED_MIDICC:
pMidiCC_info = (JaySynth::midiCC_info_t*)pData;
applyMidiController(pMidiCC_info, true);
if (getEditor(this) != NULL)
actionListener.callMidiControllerChanged(pMidiCC_info->channel, pMidiCC_info->ID, (float)pMidiCC_info->value);
break;
case JaySynth::SYNTH_CHANGED_NOTE_PRESSED:
pMidi_note_info = (JaySynth::midi_note_info_t*)pData;
if (getEditor(this) != NULL)
actionListener.callMidiNotePressed(pMidi_note_info->note, (float)pMidi_note_info->velocity);
break;
case JaySynth::SYNTH_CHANGED_NOTE_RELEASED:
pMidi_note_info = (JaySynth::midi_note_info_t*)pData;
if (getEditor(this) != NULL)
actionListener.callMidiNoteReleased(pMidi_note_info->note, (float)pMidi_note_info->velocity);
break;
case JaySynth::SYNTH_CHANGED_NUM_VOICES_PLAYING:
if (getEditor(this) != NULL)
actionListener.callNumVoicesPlaying(*((int*)pData));
break;
case JaySynth::SYNTH_CHANGED_MIDICLOCK:
pMidi_quarter_info = (JaySynth::midi_quarter_clock_info_t*)pData;
if (getEditor(this) != NULL)
actionListener.callMidiClock(pMidi_quarter_info->bpm, pMidi_quarter_info->type);
break;
default:
break;
}
};
float JaySynthAudioProcessor::getParameter (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return 0;
return (float)toSlider(pParamInfo, pSynth->getParameter(index));
}
void JaySynthAudioProcessor::setParameter (int index, float newValue)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return;
setParam(index, toParam(pParamInfo, (synth_float_t)newValue), true, false);
}
synth_float_t JaySynthAudioProcessor::getParam(int index)
{
return (synth_float_t)pSynth->getParameter(index);
}
void JaySynthAudioProcessor::setParam(int index, synth_float_t param, bool doModifyPatch, bool doNotifyHost)
{
param_info_t *pParamInfo = getParamInfo(index);
if (!pParamInfo)
return;
if (doModifyPatch)
{
setPatchModified();
}
if (doNotifyHost)
sendParamChangeToHost(index, (float)toSlider(pParamInfo, param));
pSynth->setParameter(index, clampParam(pParamInfo, param));
}
void JaySynthAudioProcessor::controlParam(int index, synth_float_t param)
{
pSynth->setControl(index, param);
}
const String JaySynthAudioProcessor::getParameterName (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
if (pParamInfo)
return pParamInfo->pName;
return String::empty;
}
const String JaySynthAudioProcessor::getParameterText (int index)
{
param_info_t *pParamInfo = getParamInfo(index);
switch (index)
{
case SYNTH_PARAM_VCF_TYPE:
switch ((int)pSynth->getParameter(index))
{
case VCF_FILTERTYPE_LOWPASS:
return "LPF";
case VCF_FILTERTYPE_HIGHPASS:
return "HPF";
case VCF_FILTERTYPE_BANDPASS:
return "BPF";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_NOISE_ENABLE:
case SYNTH_PARAM_OSC_0_ENABLE:
case SYNTH_PARAM_OSC_1_ENABLE:
if (!(int)pSynth->getParameter(index))
return "Off";
return "On";
case SYNTH_PARAM_NOISE_SHAPE:
switch ((int)pSynth->getParameter(index))
{
case VOICE_NOISE_SHAPE_WHITE:
return "Uniform";
case VOICE_NOISE_SHAPE_PINK:
return "Gauss";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_OSC_0_WAVEFORM:
case SYNTH_PARAM_OSC_1_WAVEFORM:
switch ((int)pSynth->getParameter(index))
{
case OSC_WAVEFORM_SAWTOOTH:
return "Saw";
case OSC_WAVEFORM_SQUARE:
return "Pulse";
case OSC_WAVEFORM_TRIANGLE:
return "Tri";
case OSC_WAVEFORM_SINE:
return "Sine";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_SHAPE:
case SYNTH_PARAM_LFO_1_SHAPE:
case SYNTH_PARAM_LFO_2_SHAPE:
case SYNTH_PARAM_LFO_3_SHAPE:
switch ((int)pSynth->getParameter(index))
{
case LFO_WAVEFORM_SINE:
return "Sine";
case LFO_WAVEFORM_COSINE:
return "Cosine";
case LFO_WAVEFORM_SAW:
return "Saw";
case LFO_WAVEFORM_SQUARE:
return "Square";
case LFO_WAVEFORM_TRIANGLE:
return "Tri";
case LFO_WAVEFORM_SH_UNI:
return "S/H 1";
case LFO_WAVEFORM_SH_GAUSS:
return "S/H 2";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_OSC_0_AM_SRC_0:
case SYNTH_PARAM_OSC_1_AM_SRC_0:
case SYNTH_PARAM_OSC_0_FM_SRC_0:
case SYNTH_PARAM_OSC_1_FM_SRC_0:
case SYNTH_PARAM_OSC_0_PWM_SRC_0:
case SYNTH_PARAM_OSC_1_PWM_SRC_0:
case SYNTH_PARAM_VCF_F_SRC_0:
case SYNTH_PARAM_VCF_Q_SRC_0:
case SYNTH_PARAM_VCA_AM_SRC_0:
case SYNTH_PARAM_VCA_PAN_SRC_0:
case SYNTH_PARAM_OSC_0_AM_SRC_1:
case SYNTH_PARAM_OSC_1_AM_SRC_1:
case SYNTH_PARAM_OSC_0_FM_SRC_1:
case SYNTH_PARAM_OSC_1_FM_SRC_1:
case SYNTH_PARAM_OSC_0_PWM_SRC_1:
case SYNTH_PARAM_OSC_1_PWM_SRC_1:
case SYNTH_PARAM_VCF_F_SRC_1:
case SYNTH_PARAM_VCF_Q_SRC_1:
switch ((int)pSynth->getParameter(index))
{
case 0:
return "Off";
case 1:
return "LFO 1";
case 2:
return "LFO 2";
case 3:
return "LFO 3";
case 4:
return "LFO 4";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_MODE:
case SYNTH_PARAM_LFO_1_MODE:
case SYNTH_PARAM_LFO_2_MODE:
case SYNTH_PARAM_LFO_3_MODE:
switch ((int)pSynth->getParameter(index))
{
case VOICE_LFO_MODE_GLOBAL:
return "Global";
case VOICE_LFO_MODE_INDIVIDUAL:
return "Individual";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_SYNC:
case SYNTH_PARAM_LFO_1_SYNC:
case SYNTH_PARAM_LFO_2_SYNC:
case SYNTH_PARAM_LFO_3_SYNC:
switch ((int)pSynth->getParameter(index))
{
case VOICE_LFO_SYNC_FREE:
return "Free";
case VOICE_LFO_SYNC_RESTART:
return "Restart";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
case SYNTH_PARAM_LFO_0_MIDISYNC_MODE:
case SYNTH_PARAM_LFO_1_MIDISYNC_MODE:
case SYNTH_PARAM_LFO_2_MIDISYNC_MODE:
case SYNTH_PARAM_LFO_3_MIDISYNC_MODE:
switch ((int)pSynth->getParameter(index))
{
case VOICE_LFO_MIDISYNC_OFF:
return "Off";
case VOICE_LFO_MIDISYNC_F:
return "Freq";
case VOICE_LFO_MIDISYNC_P:
return "Phase";
case VOICE_LFO_MIDISYNC_F_P:
return "Freq+Phase";
default:
return "Unknown (" + String((int)pSynth->getParameter(index)) + ")";
}
default:
if (pParamInfo->pinterval == 0.0)
return String (pSynth->getParameter(index));
else
return String (pSynth->getParameter(index), (int)(-log(pParamInfo->pinterval)/log(10.0) + 0.5));
}
}
const String JaySynthAudioProcessor::getInputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
const String JaySynthAudioProcessor::getOutputChannelName (int channelIndex) const
{
return String (channelIndex + 1);
}
bool JaySynthAudioProcessor::isInputChannelStereoPair (int /*index*/) const
{
return true;
}
bool JaySynthAudioProcessor::isOutputChannelStereoPair (int /*index*/) const
{
return true;
}
bool JaySynthAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool JaySynthAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
int JaySynthAudioProcessor::getNumPrograms()
{
return NUM_PROGRAMS;
}
int JaySynthAudioProcessor::getCurrentProgram()
{
return currProgram;
}
void JaySynthAudioProcessor::setCurrentProgram (int index)
{
int i;
param_info_t *pParamInfo;
if ((unsigned)index >= NUM_PROGRAMS)
index = 0;
currProgram = index;
currpatch = &patches[index];
// Set SYNTH_PARAM_TOTAL_NUM_VOICES first
setParam(SYNTH_PARAM_TOTAL_NUM_VOICES, currpatch->getParameter(SYNTH_PARAM_TOTAL_NUM_VOICES), false, false);
midCC_editBuffer = *((JaySynthMidiCC*)currpatch->getMidiCC());
pSynth->setMidiCC_editBuffer(&midCC_editBuffer);
pSynth->ClearControls();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
{
pParamInfo = getParamInfo(i);
setParam(i, currpatch->getParameter(i), false, true);
}
unisonoModeChanged();
humanizeModeChanged();
humanizeVarianceChanged_VCO();
humanizeVarianceChanged_VCF();
humanizeVarianceChanged_ENV();
perVoiceControlsChanged();
clearPatchModified();
// toDo: do this by synth->setParam via message
if (getEditor(this))
{
actionListener.callProgramChanged();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
getEditor(this)->paramUpdate(i, false);
}
applyCurrentMidiControllers();
updateHostDisplay();
}
const String JaySynthAudioProcessor::getProgramName (int index)
{
return patches[index].getName();
}
void JaySynthAudioProcessor::changeProgramName (int index, const String& newName)
{
patches[index].setName(newName);
if (getEditor(this))
{
actionListener.callProgramChanged();
}
}
//==============================================================================
void JaySynthAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// Use this method as the place to do any pre-playback
// initialisation that you need..
m_fs = sampleRate;
pSynth->setSampleRate (sampleRate);
pSynth->setBufsize (samplesPerBlock);
keyboardState.reset();
}
void JaySynthAudioProcessor::releaseResources()
{
// When playback stops, you can use this as an opportunity to free up any
// spare memory, etc.
keyboardState.reset();
}
void JaySynthAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
const int numSamples = buffer.getNumSamples();
int i;
float *buf1 = buffer.getWritePointer (0, 0);
float *buf2 = buffer.getWritePointer (1, 0);
synth_float_t limiter_env[SYNTH_MAX_BUFSIZE];
synth_float_t limiter_gain[SYNTH_MAX_BUFSIZE];
synth_float_t buf[2][SYNTH_MAX_BUFSIZE];
synth_float_t x, limiter_ar, limiter_af, limiter_threshold;
float synth_gain;
AudioPlayHead::CurrentPositionInfo pos;
getPlayHead()->getCurrentPosition(pos);
m_JK_MidiClock.generateMidiclock(pos, &midiMessages, numSamples, getSampleRate());
// Now pass any incoming midi messages to our keyboard state object, and let it
// add messages to the buffer if the user is clicking on the on-screen keys
keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);
// First remove garbage from buffers
buffer.clear (0, 0, numSamples);
buffer.clear (1, 0, numSamples);
// and now get the synth to process these midi events and generate its output.
// Render individual voices
pSynth->renderNextBlock (buffer, midiMessages, 0, numSamples);
// apply master volume
synth_gain = (float)pSynth->getVolume();
for (i=0; i <numSamples; i++)
buf[0][i] = (synth_float_t)buf1[i] * synth_gain;
for (i=0; i <numSamples; i++)
buf[1][i] = (synth_float_t)buf2[i] * synth_gain;
// Limiter
limiter_ar = 5.0/(SYNTH_LIMITER_RISE_TIME*m_fs);
limiter_af = 5.0/(SYNTH_LIMITER_FALL_TIME*m_fs);
limiter_threshold = pow((synth_float_t)10.0, (synth_float_t)SYNTH_LIMITER_THRESHOLD/20);
for (i=0; i <numSamples; i++)
{
x = jsy_max(fabs(buf[0][i]), fabs(buf[1][i]));
if (x > m_limiter_env)
{
m_limiter_env = (1.0-limiter_ar)*m_limiter_env + limiter_ar*x;
}
else
{
m_limiter_env = (1.0-limiter_af)*m_limiter_env;
}
limiter_env[i] = m_limiter_env;
}
m_limiter_active = 0;
for (i=0; i <numSamples; i++)
{
limiter_gain[i] = jsy_min(1.0, 1.0/(limiter_env[i] + 1.0e-6));
if (limiter_gain[i] < 1.0)
{
m_limiter_active = 1;
}
}
for (i=0; i <numSamples; i++)
buf1[i] = (float)(buf[0][i]*limiter_gain[i]);
for (i=0; i <numSamples; i++)
buf2[i] = (float)(buf[1][i]*limiter_gain[i]);
// In case we have more outputs than inputs, we'll clear any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
// {
// buffer.clear (i, 0, buffer.getNumSamples());
// }
}
//==============================================================================
bool JaySynthAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
}
AudioProcessorEditor* JaySynthAudioProcessor::createEditor()
{
int i;
the_editor = (void*) new JaySynthAudioProcessorEditor (this, m_isWavesAvailable);
if (the_editor)
{
actionListener.callProgramChanged();
for (i=0; i < SYNTH_NUM_PARAMS; i++)
((JaySynthAudioProcessorEditor*)the_editor)->paramUpdate(i, false);
}
return (AudioProcessorEditor*)the_editor;
}
//==============================================================================
// magic number to identify memory blocks that we've stored as XML
const uint32 magicXmlNumber = 0x21324356;
void JaySynthAudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& destData)
{
const String xmlString (xml.createDocument (String::empty, true, false));
const int stringLength = xmlString.getNumBytesAsUTF8();
destData.setSize ((size_t) stringLength + 10);
char* const d = static_cast<char*> (destData.getData());
*(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber);
*(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength);
xmlString.copyToUTF8 (d + 8, stringLength + 1);
}
XmlElement* JaySynthAudioProcessor::getXmlFromBinary (const void* data,
const int sizeInBytes)
{
XmlElement *pResult = nullptr;
if (sizeInBytes > 8
&& ByteOrder::littleEndianInt (data) == magicXmlNumber)
{
const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4));
XmlDocument doc(String::fromUTF8 ((static_cast<const char*> (data)) + 8, jmin ((sizeInBytes - 8), stringLength)));
if (stringLength > 0)
pResult = doc.getDocumentElement();
if (doc.getLastParseError() != String::empty)
{
deleteAndZero(pResult);
}
}
return pResult;
}
const String JaySynthAudioProcessor::getParameterNameXML (int index)
{
String name = getParameterName(index);
name = name.removeCharacters (String("."));
name = name.replaceCharacter (' ','_');
return name;
}
void JaySynthAudioProcessor::commitEditBuffer()
{
if (isPatchModified() || midCC_editBuffer.isMidiCCmodified())
{
for (int i=0; i < SYNTH_NUM_PARAMS; i++)
{
synth_float_t value = getParam(i);
currpatch->setParameter(i, value); // Copy synth param to current program
}
JaySynthMidiCC *midiCC = (JaySynthMidiCC*)currpatch->getMidiCC();
midiCC->copyMidiCC(&midCC_editBuffer); // Copy MidiCC edit buffer to patch
}
}
void JaySynthAudioProcessor::patch2xml(XmlElement& xml, JaySynthSound const *patch)
{
xml.setAttribute ("NAME", patch->getName());
for (int i=0; i < SYNTH_NUM_PARAMS; i++)
{
synth_float_t value = patch->getParameter(i);
xml.setAttribute (getParameterNameXML(i), String(value, 10));
}
patch->getMidiCC()->exportXML(&xml);
}
void JaySynthAudioProcessor::xml2patch(const XmlElement& xml, JaySynthSound *patch)
{
// ok, now pull out our parameters..
patch->setName(xml.getStringAttribute("NAME"));
for (int i=0; i < SYNTH_NUM_PARAMS; i++)
{
synth_float_t value = (synth_float_t) xml.getDoubleAttribute (getParameterNameXML(i), patch->getParameter(i));
if (i==SYNTH_PARAM_TUNE)
{
if (value > 400.0)
{
value = 1200*log(value/440)/log(2.0);
}
}
patch->setParameter(i, value);
}
((JaySynthMidiCC*)patch->getMidiCC())->importXML(&xml);
}
void JaySynthAudioProcessor::bank2xml(XmlElement& xml)
{
for (int i=0; i < NUM_PROGRAMS; i++)
{
XmlElement *pXml = xml.createNewChildElement (String("PATCH_") + String(i));
JaySynthSound *pPatch = &patches[i];
pXml->setAttribute ("ID", i);
patch2xml(*pXml, pPatch);
}
}
void JaySynthAudioProcessor::xml2bank(const XmlElement& xml)
{
// make sure that it's actually our type of XML object..
XmlElement *pXML = (XmlElement*)&xml;
while(pXML)
{
int progID = pXML->getIntAttribute("ID");
if (progID >= NUM_PROGRAMS)
break;
JaySynthSound *pPatch = &patches[progID];
// ok, now pull out our parameters..
pPatch->setName(pXML->getStringAttribute("NAME"));
for (int i=0; i < SYNTH_NUM_PARAMS; i++)
{
synth_float_t value = (synth_float_t) pXML->getDoubleAttribute (getParameterNameXML(i), pPatch->getParameter(i));
if (i==SYNTH_PARAM_TUNE)
{
if (value > 400.0)
{
value = 1200*log(value/440)/log(2.0);
}
}
pPatch->setParameter(i, value);
}
((JaySynthMidiCC*)pPatch->getMidiCC())->importXML(pXML);
pXML = pXML->getNextElement();
}
}
void JaySynthAudioProcessor::getStateInformation (MemoryBlock& destData)
{
commitEditBuffer();
// Create an outer XML element..
ScopedPointer<XmlElement>xml = new XmlElement("JSYNTH_BANK");
bank2xml(*xml);
setCurrentProgram(getCurrentProgram());
MemoryOutputStream outputStream(destData, false);
MemoryBlock tmpBlock(destData.getSize(), /*initialiseToZero*/true);
GZIPCompressorOutputStream GZIPEnc(&outputStream, /*compressionLevel*/0, /*deleteDestStreamWhenDestroyed*/false, /*windowBits*/0);
// then use this helper function to stuff it into the binary blob and return it..
copyXmlToBinary (*xml, tmpBlock);
GZIPEnc.write(tmpBlock.getData(), tmpBlock.getSize());
outputStream.flush();
}
void JaySynthAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
int uncompressedSize;
String lastError;
ScopedPointer<XmlElement> xmlState = NULL;
void* pData;
int size;
ScopedPointer<char> pUncompressedData;
pUncompressedData = new char[8192*1024];
MemoryInputStream inputStream(data, sizeInBytes, false);
GZIPDecompressorInputStream GZIPDec(inputStream);
uncompressedSize = GZIPDec.read(pUncompressedData, 8192*1024);
pData = (void *)data;
size = sizeInBytes;
if (uncompressedSize)
{
pData = (void *)pUncompressedData;
size = uncompressedSize;
}
xmlState = getXmlFromBinary(pData, size);
if (xmlState != 0)
{
// make sure that it's actually our type of XML object..
if (xmlState->hasTagName ("JSYNTH_BANK"))
{
XmlElement *pXML = xmlState->getFirstChildElement();
xml2bank(*pXML);
}
setCurrentProgram(getCurrentProgram());
}
}
void JaySynthAudioProcessor::getCurrentProgramStateInformation (MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
// You should use this method to store your parameters in the memory block.
// Here's an example of how you can use XML to make it easy and more robust:
commitEditBuffer();
MemoryOutputStream outputStream (destData, false);
MemoryBlock tmpBlock(2*65536, /*initialiseToZero*/true);
GZIPCompressorOutputStream GZIPEnc(&outputStream, /*compressionLevel*/0, /*deleteDestStreamWhenDestroyed*/false, /*windowBits*/0);
// Create an outer XML element..
ScopedPointer<XmlElement>xml = new XmlElement("JSYNTH_PATCH");
patch2xml(*xml, currpatch);
setCurrentProgram(getCurrentProgram());
// then use this helper function to stuff it into the binary blob and return it..
copyXmlToBinary (*xml, tmpBlock);
GZIPEnc.write(tmpBlock.getData(), tmpBlock.getSize());
}
void JaySynthAudioProcessor::setCurrentProgramStateInformation (const void* data, int sizeInBytes)
{
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
int i, uncompressedSize;
synth_float_t value;
ScopedPointer<XmlElement> xmlState = NULL;
void* pData;
int size;
ScopedPointer<char> pUncompressedData;
pUncompressedData = new char[2*65536];
MemoryInputStream inputStream(data, sizeInBytes, false);
GZIPDecompressorInputStream GZIPDec(inputStream);
uncompressedSize = GZIPDec.read(pUncompressedData, 2*65536);
pData = (void *)data;
size = sizeInBytes;
if (uncompressedSize)
{
pData = (void *)pUncompressedData;
size = uncompressedSize;
}
xmlState = getXmlFromBinary(pData, size);
if (xmlState != 0)
{
// make sure that it's actually our type of XML object..
if (xmlState->hasTagName ("JSYNTH_PATCH"))
{
xml2patch(*xmlState, currpatch);
setCurrentProgram(getCurrentProgram());
}
}
}
void JaySynthAudioProcessor::loadPatch (const File &file, int index)
{
String ext = file.getFileExtension();
if (String(".fxp") == ext)
{
MemoryBlock mem;
file.loadFileAsData(mem);
fxProgram *program = (fxProgram*)mem.getData();
if (String((const char*)&program->chunkMagic) == String(cMagic))
{
bool is_regular = String((const char*)&program->fxMagic) == String(fMagic);
bool is_opaque = String((const char*)&program->fxMagic) == String(chunkPresetMagic);
if (is_opaque)
{
uint32_t size = ByteOrder::swap((uint32_t)program->content.data.size);
setCurrentProgramStateInformation(program->content.data.chunk, (int)size);
}
}
}
}
void JaySynthAudioProcessor::savePatch (const File &file, int index)
{
String filename(file.getFullPathName());
}
//#include <juce_ByteOrder.h>
void JaySynthAudioProcessor::loadBank (const File &file)
{
String ext = file.getFileExtension();
if (String(".fxb") == ext)
{
MemoryBlock mem;
file.loadFileAsData(mem);
fxBank *bank = (fxBank*)mem.getData();
if (String((const char*)&bank->chunkMagic) == String(cMagic))
{
bool is_regular = String((const char*)&bank->fxMagic) == String(bankMagic);
bool is_opaque = String((const char*)&bank->fxMagic) == String(chunkBankMagic);
if (is_opaque)
{
uint32_t size = ByteOrder::swap((uint32_t)bank->content.data.size);
setStateInformation(bank->content.data.chunk, (int)size);
}
}
}
}
void JaySynthAudioProcessor::saveBank (const File &file)
{
String filename(file.getFullPathName());
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new JaySynthAudioProcessor();
}