Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / extras / JuceDemo / Source / demos / AudioDemoSynthPage.cpp
blob8c2f3d0f4fe12d107004ad5d8f39c49e32123e7c
1 /*
2 ==============================================================================
4 This is an automatically generated file created by the Jucer!
6 Creation date: 1 May 2011 12:06:00pm
8 Be careful when adding custom code to these files, as only the code within
9 the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
10 and re-saved.
12 Jucer version: 1.12
14 ------------------------------------------------------------------------------
16 The Jucer is part of the JUCE library - "Jules' Utility Class Extensions"
17 Copyright 2004-6 by Raw Material Software ltd.
19 ==============================================================================
22 //[Headers] You can add your own extra header files here...
23 //[/Headers]
25 #include "AudioDemoSynthPage.h"
28 //[MiscUserDefs] You can add your own user definitions and misc code here...
30 //==============================================================================
31 /** Our demo synth sound is just a basic sine wave..
33 class SineWaveSound : public SynthesiserSound
35 public:
36 SineWaveSound()
40 bool appliesToNote (const int /*midiNoteNumber*/) { return true; }
41 bool appliesToChannel (const int /*midiChannel*/) { return true; }
45 //==============================================================================
46 /** Our demo synth voice just plays a sine wave..
48 class SineWaveVoice : public SynthesiserVoice
50 public:
51 SineWaveVoice()
52 : angleDelta (0.0),
53 tailOff (0.0)
57 bool canPlaySound (SynthesiserSound* sound)
59 return dynamic_cast <SineWaveSound*> (sound) != 0;
62 void startNote (const int midiNoteNumber, const float velocity,
63 SynthesiserSound* /*sound*/, const int /*currentPitchWheelPosition*/)
65 currentAngle = 0.0;
66 level = velocity * 0.15;
67 tailOff = 0.0;
69 double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
70 double cyclesPerSample = cyclesPerSecond / getSampleRate();
72 angleDelta = cyclesPerSample * 2.0 * double_Pi;
75 void stopNote (const bool allowTailOff)
77 if (allowTailOff)
79 // start a tail-off by setting this flag. The render callback will pick up on
80 // this and do a fade out, calling clearCurrentNote() when it's finished.
82 if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
83 // stopNote method could be called more than once.
84 tailOff = 1.0;
86 else
88 // we're being told to stop playing immediately, so reset everything..
90 clearCurrentNote();
91 angleDelta = 0.0;
95 void pitchWheelMoved (const int /*newValue*/)
97 // can't be bothered implementing this for the demo!
100 void controllerMoved (const int /*controllerNumber*/, const int /*newValue*/)
102 // not interested in controllers in this case.
105 void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples)
107 if (angleDelta != 0.0)
109 if (tailOff > 0)
111 while (--numSamples >= 0)
113 const float currentSample = (float) (sin (currentAngle) * level * tailOff);
115 for (int i = outputBuffer.getNumChannels(); --i >= 0;)
116 *outputBuffer.getSampleData (i, startSample) += currentSample;
118 currentAngle += angleDelta;
119 ++startSample;
121 tailOff *= 0.99;
123 if (tailOff <= 0.005)
125 clearCurrentNote();
127 angleDelta = 0.0;
128 break;
132 else
134 while (--numSamples >= 0)
136 const float currentSample = (float) (sin (currentAngle) * level);
138 for (int i = outputBuffer.getNumChannels(); --i >= 0;)
139 *outputBuffer.getSampleData (i, startSample) += currentSample;
141 currentAngle += angleDelta;
142 ++startSample;
148 private:
149 double currentAngle, angleDelta, level, tailOff;
153 // This is an audio source that streams the output of our demo synth.
154 class SynthAudioSource : public AudioSource
156 public:
157 //==============================================================================
158 // this collects real-time midi messages from the midi input device, and
159 // turns them into blocks that we can process in our audio callback
160 MidiMessageCollector midiCollector;
162 // this represents the state of which keys on our on-screen keyboard are held
163 // down. When the mouse is clicked on the keyboard component, this object also
164 // generates midi messages for this, which we can pass on to our synth.
165 MidiKeyboardState& keyboardState;
167 // the synth itself!
168 Synthesiser synth;
170 //==============================================================================
171 SynthAudioSource (MidiKeyboardState& keyboardState_)
172 : keyboardState (keyboardState_)
174 // add some voices to our synth, to play the sounds..
175 for (int i = 4; --i >= 0;)
177 synth.addVoice (new SineWaveVoice()); // These voices will play our custom sine-wave sounds..
178 synth.addVoice (new SamplerVoice()); // and these ones play the sampled sounds
181 // and add some sounds for them to play...
182 setUsingSineWaveSound();
185 void setUsingSineWaveSound()
187 synth.clearSounds();
188 synth.addSound (new SineWaveSound());
191 void setUsingSampledSound()
193 synth.clearSounds();
195 WavAudioFormat wavFormat;
197 ScopedPointer<AudioFormatReader> audioReader (wavFormat.createReaderFor (new MemoryInputStream (BinaryData::cello_wav,
198 BinaryData::cello_wavSize,
199 false),
200 true));
202 BigInteger allNotes;
203 allNotes.setRange (0, 128, true);
205 synth.addSound (new SamplerSound ("demo sound",
206 *audioReader,
207 allNotes,
208 74, // root midi note
209 0.1, // attack time
210 0.1, // release time
211 10.0 // maximum sample length
215 void prepareToPlay (int /*samplesPerBlockExpected*/, double sampleRate)
217 midiCollector.reset (sampleRate);
219 synth.setCurrentPlaybackSampleRate (sampleRate);
222 void releaseResources()
226 void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
228 // the synth always adds its output to the audio buffer, so we have to clear it
229 // first..
230 bufferToFill.clearActiveBufferRegion();
232 // fill a midi buffer with incoming messages from the midi input.
233 MidiBuffer incomingMidi;
234 midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples);
236 // pass these messages to the keyboard state so that it can update the component
237 // to show on-screen which keys are being pressed on the physical midi keyboard.
238 // This call will also add midi messages to the buffer which were generated by
239 // the mouse-clicking on the on-screen keyboard.
240 keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true);
242 // and now get the synth to process the midi events and generate its output.
243 synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples);
247 //[/MiscUserDefs]
249 //==============================================================================
250 AudioDemoSynthPage::AudioDemoSynthPage (AudioDeviceManager& deviceManager_)
251 : deviceManager (deviceManager_),
252 keyboardComponent (0),
253 sineButton (0),
254 sampledButton (0),
255 liveAudioDisplayComp (0)
257 addAndMakeVisible (keyboardComponent = new MidiKeyboardComponent (keyboardState, MidiKeyboardComponent::horizontalKeyboard));
259 addAndMakeVisible (sineButton = new ToggleButton (String::empty));
260 sineButton->setButtonText (L"Use sine wave");
261 sineButton->setRadioGroupId (321);
262 sineButton->addListener (this);
263 sineButton->setToggleState (true, false);
265 addAndMakeVisible (sampledButton = new ToggleButton (String::empty));
266 sampledButton->setButtonText (L"Use sampled sound");
267 sampledButton->setRadioGroupId (321);
268 sampledButton->addListener (this);
270 addAndMakeVisible (liveAudioDisplayComp = new LiveAudioInputDisplayComp());
273 //[UserPreSize]
274 //[/UserPreSize]
276 setSize (600, 400);
279 //[Constructor] You can add your own custom stuff here..
280 deviceManager.addAudioCallback (liveAudioDisplayComp);
282 synthAudioSource = new SynthAudioSource (keyboardState);
283 audioSourcePlayer.setSource (synthAudioSource);
285 deviceManager.addAudioCallback (&audioSourcePlayer);
286 deviceManager.addMidiInputCallback (String::empty, &(synthAudioSource->midiCollector));
287 //[/Constructor]
290 AudioDemoSynthPage::~AudioDemoSynthPage()
292 //[Destructor_pre]. You can add your own custom destruction code here..
293 audioSourcePlayer.setSource (0);
294 deviceManager.removeMidiInputCallback (String::empty, &(synthAudioSource->midiCollector));
295 deviceManager.removeAudioCallback (&audioSourcePlayer);
296 deviceManager.removeAudioCallback (liveAudioDisplayComp);
297 //[/Destructor_pre]
299 deleteAndZero (keyboardComponent);
300 deleteAndZero (sineButton);
301 deleteAndZero (sampledButton);
302 deleteAndZero (liveAudioDisplayComp);
305 //[Destructor]. You can add your own custom destruction code here..
306 //[/Destructor]
309 //==============================================================================
310 void AudioDemoSynthPage::paint (Graphics& g)
312 //[UserPrePaint] Add your own custom painting code here..
313 //[/UserPrePaint]
315 g.fillAll (Colours::lightgrey);
317 //[UserPaint] Add your own custom painting code here..
318 //[/UserPaint]
321 void AudioDemoSynthPage::resized()
323 keyboardComponent->setBounds (8, 96, getWidth() - 16, 64);
324 sineButton->setBounds (16, 176, 150, 24);
325 sampledButton->setBounds (16, 200, 150, 24);
326 liveAudioDisplayComp->setBounds (8, 8, getWidth() - 16, 64);
327 //[UserResized] Add your own custom resize handling here..
328 //[/UserResized]
331 void AudioDemoSynthPage::buttonClicked (Button* buttonThatWasClicked)
333 //[UserbuttonClicked_Pre]
334 //[/UserbuttonClicked_Pre]
336 if (buttonThatWasClicked == sineButton)
338 //[UserButtonCode_sineButton] -- add your button handler code here..
339 synthAudioSource->setUsingSineWaveSound();
340 //[/UserButtonCode_sineButton]
342 else if (buttonThatWasClicked == sampledButton)
344 //[UserButtonCode_sampledButton] -- add your button handler code here..
345 synthAudioSource->setUsingSampledSound();
346 //[/UserButtonCode_sampledButton]
349 //[UserbuttonClicked_Post]
350 //[/UserbuttonClicked_Post]
355 //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
356 //[/MiscUserCode]
359 //==============================================================================
360 #if 0
361 /* -- Jucer information section --
363 This is where the Jucer puts all of its metadata, so don't change anything in here!
365 BEGIN_JUCER_METADATA
367 <JUCER_COMPONENT documentType="Component" className="AudioDemoSynthPage" componentName=""
368 parentClasses="public Component" constructorParams="AudioDeviceManager&amp; deviceManager_"
369 variableInitialisers="deviceManager (deviceManager_)" snapPixels="8"
370 snapActive="1" snapShown="1" overlayOpacity="0.330000013" fixedSize="0"
371 initialWidth="600" initialHeight="400">
372 <BACKGROUND backgroundColour="ffd3d3d3"/>
373 <GENERICCOMPONENT name="" id="86605ec4f02c4320" memberName="keyboardComponent"
374 virtualName="" explicitFocusOrder="0" pos="8 96 16M 64" class="MidiKeyboardComponent"
375 params="keyboardState, MidiKeyboardComponent::horizontalKeyboard"/>
376 <TOGGLEBUTTON name="" id="d75101df45006ba9" memberName="sineButton" virtualName=""
377 explicitFocusOrder="0" pos="16 176 150 24" buttonText="Use sine wave"
378 connectedEdges="0" needsCallback="1" radioGroupId="321" state="1"/>
379 <TOGGLEBUTTON name="" id="2d687b4ac3dad628" memberName="sampledButton" virtualName=""
380 explicitFocusOrder="0" pos="16 200 150 24" buttonText="Use sampled sound"
381 connectedEdges="0" needsCallback="1" radioGroupId="321" state="0"/>
382 <GENERICCOMPONENT name="" id="7d70eb2617f56220" memberName="liveAudioDisplayComp"
383 virtualName="" explicitFocusOrder="0" pos="8 8 16M 64" class="LiveAudioInputDisplayComp"
384 params=""/>
385 </JUCER_COMPONENT>
387 END_JUCER_METADATA
389 #endif