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
29 ==============================================================================
33 #include "TalComponent.h"
34 #include "ProgramChunk.h"
37 This function must be implemented to create a new instance of your
40 AudioProcessor
* JUCE_CALLTYPE
createPluginFilter()
48 if (this->getSampleRate() > 0)
49 sampleRate
= (float)this->getSampleRate();
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();
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;
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()
90 float TalCore::getParameter (int index
)
93 return talPresets
[curProgram
]->programData
[index
];
98 void TalCore::setParameter (int index
, float newValue
)
100 if (index
< NUMPARAM
)
102 params
[index
] = newValue
;
103 talPresets
[curProgram
]->programData
[index
] = newValue
;
108 engine
->setWet(newValue
);
111 engine
->setDry(newValue
);
114 engine
->setDecayTime(newValue
);
117 engine
->setPreDelay(newValue
);
120 engine
->setStereoWidth(newValue
);
123 engine
->setStereoMode(newValue
);
126 case LOWSHELFFREQUENCY
:
127 engine
->setLowShelfFrequency(newValue
);
129 case HIGHSHELFFREQUENCY
:
130 engine
->setHighShelfFrequency(newValue
);
133 engine
->setPeakFrequency(newValue
);
137 engine
->setLowShelfGain(newValue
);
140 engine
->setHighShelfGain(newValue
);
143 engine
->setPeakGain(newValue
);
147 sendChangeMessage ();
150 lastMovedController
= index
;
154 const String
TalCore::getParameterName (int 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
201 bool TalCore::isOutputChannelStereoPair (int index
) const
206 bool TalCore::acceptsMidi() const
211 bool TalCore::producesMidi() const
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();
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);
254 int numSamples
= buffer
.getNumSamples();
255 while (numSamples
> 0)
257 processMidiPerSample(&midiIterator
, controllerMidiMessage
, samplePos
);
258 engine
->process(samples0
++, samples1
++);
264 if (numberOfChannels
== 1)
266 float *samples0
= buffer
.getSampleData(0, 0);
267 float *samples1
= buffer
.getSampleData(0, 0);
270 int numSamples
= buffer
.getNumSamples();
271 while (numSamples
> 0)
273 processMidiPerSample(&midiIterator
, controllerMidiMessage
, samplePos
);
274 engine
->process(samples0
++, samples1
++);
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
)
307 //if (params[REALSTEREOMODE] > 0.0f)
309 // for (int i = 0; i < NUMPROGRAMS; i++)
311 // talPresets[i].midiMap[controllerNumber] = lastMovedController;
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
333 XmlElement
tal("tal");
334 tal
.setAttribute (T("curprogram"), curProgram
);
335 tal
.setAttribute (T("version"), 1);
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
);
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);
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
);
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")))
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
);
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);
441 setCurrentProgram(curProgram
);
442 sendChangeMessage ();
446 int TalCore::getNumPrograms ()
451 int TalCore::getCurrentProgram ()
456 void TalCore::setCurrentProgram (int index
)
458 if (index
< NUMPROGRAMS
)
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
;
477 void TalCore::changeProgramName (int index
, const String
& newName
)
479 if (index
< NUMPROGRAMS
)
480 talPresets
[index
]->name
= newName
;