Add TAL-Reverb-II plugin to test
[juce-lv2.git] / tal-reverb-2-juce / src / TalCore.cpp
blob03b68feb65d1756618b1979d44b6d99bec50af9f
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-7 by Raw Material Software ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the
10 GNU General Public License, as published by the Free Software Foundation;
11 either version 2 of the License, or (at your option) any later version.
13 JUCE is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with JUCE; if not, visit www.gnu.org/licenses or write to the
20 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 Boston, MA 02111-1307 USA
23 ------------------------------------------------------------------------------
25 If you'd like to release a closed-source product which uses JUCE, commercial
26 licenses are also available: visit www.rawmaterialsoftware.com/juce for
27 more information.
29 ==============================================================================
32 #include "includes.h"
33 #include "TalComponent.h"
34 #include "ProgramChunk.h"
36 /**
37 This function must be implemented to create a new instance of your
38 plugin object.
40 AudioProcessor* JUCE_CALLTYPE createPluginFilter()
42 return new TalCore();
45 TalCore::TalCore()
47 // init engine
48 if (this->getSampleRate() > 0)
49 sampleRate = (float)this->getSampleRate();
50 else
51 sampleRate = 44100.0f;
53 engine = new ReverbEngine(sampleRate);
54 params = engine->param;
55 talPresets = new TalPreset*[NUMPROGRAMS];
57 for (int i = 0; i < NUMPROGRAMS; i++) talPresets[i] = new TalPreset();
58 curProgram = 0;
60 // load factory presets
61 ProgramChunk *chunk = new ProgramChunk();
62 XmlDocument myDocument (chunk->getXmlChunk());
63 XmlElement* mainElement = myDocument.getDocumentElement();
65 MemoryBlock* destData = new MemoryBlock();
66 copyXmlToBinary(*mainElement, *destData);
67 setStateInformation(destData->getData(), destData->getSize());
68 setCurrentProgram(curProgram);
70 // used for midi learn
71 lastMovedController = 0;
74 TalCore::~TalCore()
76 if (talPresets) delete[] talPresets;
77 if (engine) delete engine;
80 const String TalCore::getName() const
82 return "Tal-Reverb-II";
85 int TalCore::getNumParameters()
87 return (int)NUMPARAM;
90 float TalCore::getParameter (int index)
92 if (index < NUMPARAM)
93 return talPresets[curProgram]->programData[index];
94 else
95 return 0;
98 void TalCore::setParameter (int index, float newValue)
100 if (index < NUMPARAM)
102 params[index] = newValue;
103 talPresets[curProgram]->programData[index] = newValue;
105 switch(index)
107 case WET:
108 engine->setWet(newValue);
109 break;
110 case DRY:
111 engine->setDry(newValue);
112 break;
113 case DECAYTIME:
114 engine->setDecayTime(newValue);
115 break;
116 case PREDELAY:
117 engine->setPreDelay(newValue);
118 break;
119 case STEREO:
120 engine->setStereoWidth(newValue);
121 break;
122 case REALSTEREOMODE:
123 engine->setStereoMode(newValue);
124 break;
126 case LOWSHELFFREQUENCY:
127 engine->setLowShelfFrequency(newValue);
128 break;
129 case HIGHSHELFFREQUENCY:
130 engine->setHighShelfFrequency(newValue);
131 break;
132 case PEAKFREQUENCY:
133 engine->setPeakFrequency(newValue);
134 break;
136 case LOWSHELFGAIN:
137 engine->setLowShelfGain(newValue);
138 break;
139 case HIGHSHELFGAIN:
140 engine->setHighShelfGain(newValue);
141 break;
142 case PEAKGAIN:
143 engine->setPeakGain(newValue);
144 break;
147 sendChangeMessage ();
149 // for midi learn
150 lastMovedController = index;
154 const String TalCore::getParameterName (int index)
156 switch(index)
158 case WET: return T("wet");
159 case DRY: return T("dry");
160 case DECAYTIME: return T("room size");
161 case PREDELAY: return T("pre delay");
163 case LOWSHELFFREQUENCY: return T("low shelf frequency");
164 case HIGHSHELFFREQUENCY: return T("high shelf frequency");
165 case PEAKFREQUENCY: return T("peak frequency");
167 case LOWSHELFGAIN: return T("low shelf gain");
168 case HIGHSHELFGAIN: return T("high shelf gain");
169 case PEAKGAIN: return T("peak gain");
171 case STEREO: return T("stereo");
172 case REALSTEREOMODE: return T("stereo input");
174 return String::empty;
177 const String TalCore::getParameterText (int index)
179 if (index < NUMPARAM)
181 return String(talPresets[curProgram]->programData[index], 2);
183 return String::empty;
186 const String TalCore::getInputChannelName (const int channelIndex) const
188 return String (channelIndex + 1);
191 const String TalCore::getOutputChannelName (const int channelIndex) const
193 return String (channelIndex + 1);
196 bool TalCore::isInputChannelStereoPair (int index) const
198 return true;
201 bool TalCore::isOutputChannelStereoPair (int index) const
203 return true;
206 bool TalCore::acceptsMidi() const
208 return true;
211 bool TalCore::producesMidi() const
213 return false;
216 void TalCore::prepareToPlay (double sampleRate, int samplesPerBlock)
220 void TalCore::releaseResources()
222 // when playback stops, you can use this as an opportunity to free up any
223 // spare memory, etc.
226 void TalCore::processBlock (AudioSampleBuffer& buffer,
227 MidiBuffer& midiMessages)
229 // Change sample rate if required
230 if (sampleRate != this->getSampleRate())
232 sampleRate = this->getSampleRate();
233 engine->setSampleRate(sampleRate);
234 setCurrentProgram(curProgram);
236 const ScopedLock sl (this->getCallbackLock());
238 // for each of our input channels, we'll attenuate its level by the
239 // amount that our volume parameter is set to.
240 int numberOfChannels = getNumInputChannels();
241 int bufferSize = buffer.getNumSamples();
243 // midi buffer
244 MidiMessage controllerMidiMessage (0xF0);
245 MidiBuffer::Iterator midiIterator(midiMessages);
246 hasMoreMidiMessages = midiIterator.getNextEvent(controllerMidiMessage, midiEventPos);
248 if (numberOfChannels == 2)
250 float *samples0 = buffer.getSampleData(0, 0);
251 float *samples1 = buffer.getSampleData(1, 0);
253 int samplePos = 0;
254 int numSamples = buffer.getNumSamples();
255 while (numSamples > 0)
257 processMidiPerSample(&midiIterator, controllerMidiMessage, samplePos);
258 engine->process(samples0++, samples1++);
260 numSamples--;
261 samplePos++;
264 if (numberOfChannels == 1)
266 float *samples0 = buffer.getSampleData(0, 0);
267 float *samples1 = buffer.getSampleData(0, 0);
269 int samplePos = 0;
270 int numSamples = buffer.getNumSamples();
271 while (numSamples > 0)
273 processMidiPerSample(&midiIterator, controllerMidiMessage, samplePos);
274 engine->process(samples0++, samples1++);
276 numSamples--;
277 samplePos++;
280 // in case we have more outputs than inputs, we'll clear any output
281 // channels that didn't contain input data, (because these aren't
282 // guaranteed to be empty - they may contain garbage).
283 for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i)
285 buffer.clear (i, 0, buffer.getNumSamples());
289 void TalCore::processMidiPerSample(MidiBuffer::Iterator *midiIterator, MidiMessage controllerMidiMessage, int samplePos)
291 // There can be more than one event at the same position
292 while (hasMoreMidiMessages && midiEventPos == samplePos)
294 if (controllerMidiMessage.isController())
296 handleController (controllerMidiMessage.getControllerNumber(),
297 controllerMidiMessage.getControllerValue());
299 hasMoreMidiMessages = midiIterator->getNextEvent (controllerMidiMessage, midiEventPos);
303 void TalCore::handleController (const int controllerNumber,
304 const int controllerValue)
306 // no midi
307 //if (params[REALSTEREOMODE] > 0.0f)
309 // for (int i = 0; i < NUMPROGRAMS; i++)
310 // {
311 // talPresets[i].midiMap[controllerNumber] = lastMovedController;
312 // }
314 //if (talPresets[curProgram].midiMap[controllerNumber] > 0)
316 // setParameter (talPresets[curProgram].midiMap[controllerNumber], controllerValue / 127.0f);
320 AudioProcessorEditor* TalCore::createEditor()
322 return new TalComponent (this);
325 void TalCore::getStateInformation (MemoryBlock& destData)
327 // you can store your parameters as binary data if you want to or if you've got
328 // a load of binary to put in there, but if you're not doing anything too heavy,
329 // XML is a much cleaner way of doing it - here's an example of how to store your
330 // params as XML..
332 // header
333 XmlElement tal("tal");
334 tal.setAttribute (T("curprogram"), curProgram);
335 tal.setAttribute (T("version"), 1);
337 // programs
338 XmlElement *programList = new XmlElement ("programs");
339 for (int i = 0; i < NUMPROGRAMS; i++)
341 XmlElement* program = new XmlElement ("program");
342 program->setAttribute (T("programname"), talPresets[i]->name);
343 program->setAttribute (T("dry"), talPresets[i]->programData[DRY]);
344 program->setAttribute (T("wet"), talPresets[i]->programData[WET]);
345 program->setAttribute (T("roomsize"), talPresets[i]->programData[DECAYTIME]);
346 program->setAttribute (T("predelay"), talPresets[i]->programData[PREDELAY]);
348 program->setAttribute (T("lowshelffrequency"), talPresets[i]->programData[LOWSHELFFREQUENCY]);
349 program->setAttribute (T("highshelffrequency"), talPresets[i]->programData[HIGHSHELFFREQUENCY]);
350 program->setAttribute (T("peakfrequency"), talPresets[i]->programData[PEAKFREQUENCY]);
352 program->setAttribute (T("lowshelfgain"), talPresets[i]->programData[LOWSHELFGAIN]);
353 program->setAttribute (T("highshelfgain"), talPresets[i]->programData[HIGHSHELFGAIN]);
354 program->setAttribute (T("peakgain"), talPresets[i]->programData[PEAKGAIN]);
356 program->setAttribute (T("stereowidth"), talPresets[i]->programData[STEREO]);
357 program->setAttribute (T("realstereomode"), talPresets[i]->programData[REALSTEREOMODE]);
358 programList->addChildElement(program);
360 tal.addChildElement(programList);
362 // midi params
363 XmlElement *midiMapList = new XmlElement ("midimap");
364 for (int i = 0; i < 255; i++)
366 if (talPresets[0]->midiMap[i] != 0)
368 XmlElement* map = new XmlElement ("map");
369 map->setAttribute (T("param"), talPresets[0]->midiMap[i]);
370 map->setAttribute (T("controllernumber"), i);
371 midiMapList->addChildElement(map);
374 tal.addChildElement(midiMapList);
376 // then use this helper function to stuff it into the binary blob and return it..
377 copyXmlToBinary (tal, destData);
379 // use this for new factory presets
380 //#ifdef _DEBUG && WIN32
381 //File *file = new File("e:/presets.txt");
382 //String myXmlDoc = tal.createDocument (String::empty);
383 //file->replaceWithText(myXmlDoc);
384 //#endif
387 void TalCore::setStateInformation (const void* data, int sizeInBytes)
389 // use this helper function to get the XML from this binary blob..
390 XmlElement* const xmlState = getXmlFromBinary (data, sizeInBytes);
392 curProgram = 0;
393 if (xmlState != 0 && xmlState->hasTagName(T("tal")))
395 curProgram = (int)xmlState->getIntAttribute (T("curprogram"), 1);
396 XmlElement* programs = xmlState->getFirstChildElement();
397 if (programs->hasTagName(T("programs")))
399 int i = 0;
400 forEachXmlChildElement (*programs, e)
402 if (e->hasTagName(T("program")) && i < NUMPROGRAMS)
404 talPresets[i]->name = e->getStringAttribute (T("programname"), T("Not Saved"));
405 talPresets[i]->programData[DRY] = (float) e->getDoubleAttribute (T("dry"), 0.8f);
406 talPresets[i]->programData[WET] = (float) e->getDoubleAttribute (T("wet"), 0.8f);
407 talPresets[i]->programData[DECAYTIME] = (float) e->getDoubleAttribute (T("roomsize"), 0.8f);
408 talPresets[i]->programData[PREDELAY] = (float) e->getDoubleAttribute (T("predelay"), 0.0f);
410 talPresets[i]->programData[LOWSHELFFREQUENCY] = (float) e->getDoubleAttribute (T("lowshelffrequency"), 0.5f);
411 talPresets[i]->programData[HIGHSHELFFREQUENCY] = (float) e->getDoubleAttribute (T("highshelffrequency"), 0.5f);
412 talPresets[i]->programData[PEAKFREQUENCY] = (float) e->getDoubleAttribute (T("peakfrequency"), 0.5f);
414 talPresets[i]->programData[LOWSHELFGAIN] = (float) e->getDoubleAttribute (T("lowshelfgain"), 1.0f);
415 talPresets[i]->programData[HIGHSHELFGAIN] = (float) e->getDoubleAttribute (T("highshelfgain"), 1.0f);
416 talPresets[i]->programData[PEAKGAIN] = (float) e->getDoubleAttribute (T("peakgain"), 1.0f);
418 talPresets[i]->programData[STEREO] = (float) e->getDoubleAttribute (T("stereowidth"), 1.0f);
419 talPresets[i]->programData[REALSTEREOMODE] = (float) e->getDoubleAttribute (T("realstereomode"), 0.0f);
420 i++;
424 // restore midi mapping
425 XmlElement* midiMap = xmlState->getChildByName(T("midimap"));
426 if (midiMap != 0 && midiMap->hasTagName(T("midimap")))
428 forEachXmlChildElement (*midiMap, e)
430 for (int j = 0; j < NUMPROGRAMS; j++)
432 int controller = e->getIntAttribute(T("controllernumber"), 0);
433 if (controller < 255 && controller > 0)
435 talPresets[j]->midiMap[controller] = e->getIntAttribute(T("param"), 0);
440 delete xmlState;
441 setCurrentProgram(curProgram);
442 sendChangeMessage ();
446 int TalCore::getNumPrograms ()
448 return NUMPROGRAMS;
451 int TalCore::getCurrentProgram ()
453 return curProgram;
456 void TalCore::setCurrentProgram (int index)
458 if (index < NUMPROGRAMS)
460 curProgram = index;
461 for (int i = 0; i < NUMPARAM; i++)
463 setParameter(i, talPresets[index]->programData[i]);
465 sendChangeMessage ();
469 const String TalCore::getProgramName (int index)
471 if (index < NUMPROGRAMS)
472 return talPresets[index]->name;
473 else
474 return T("Invalid");
477 void TalCore::changeProgramName (int index, const String& newName)
479 if (index < NUMPROGRAMS)
480 talPresets[index]->name = newName;