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
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...
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
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
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*/)
66 level
= velocity
* 0.15;
69 double cyclesPerSecond
= MidiMessage::getMidiNoteInHertz (midiNoteNumber
);
70 double cyclesPerSample
= cyclesPerSecond
/ getSampleRate();
72 angleDelta
= cyclesPerSample
* 2.0 * double_Pi
;
75 void stopNote (const bool 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.
88 // we're being told to stop playing immediately, so reset everything..
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)
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
;
123 if (tailOff
<= 0.005)
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
;
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
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
;
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()
188 synth
.addSound (new SineWaveSound());
191 void setUsingSampledSound()
195 WavAudioFormat wavFormat
;
197 ScopedPointer
<AudioFormatReader
> audioReader (wavFormat
.createReaderFor (new MemoryInputStream (BinaryData::cello_wav
,
198 BinaryData::cello_wavSize
,
203 allNotes
.setRange (0, 128, true);
205 synth
.addSound (new SamplerSound ("demo sound",
208 74, // root midi note
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
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
);
249 //==============================================================================
250 AudioDemoSynthPage::AudioDemoSynthPage (AudioDeviceManager
& deviceManager_
)
251 : deviceManager (deviceManager_
),
252 keyboardComponent (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());
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
));
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
);
299 deleteAndZero (keyboardComponent
);
300 deleteAndZero (sineButton
);
301 deleteAndZero (sampledButton
);
302 deleteAndZero (liveAudioDisplayComp
);
305 //[Destructor]. You can add your own custom destruction code here..
309 //==============================================================================
310 void AudioDemoSynthPage::paint (Graphics
& g
)
312 //[UserPrePaint] Add your own custom painting code here..
315 g
.fillAll (Colours::lightgrey
);
317 //[UserPaint] Add your own custom painting code here..
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..
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...
359 //==============================================================================
361 /* -- Jucer information section --
363 This is where the Jucer puts all of its metadata, so don't change anything in here!
367 <JUCER_COMPONENT documentType="Component" className="AudioDemoSynthPage" componentName=""
368 parentClasses="public Component" constructorParams="AudioDeviceManager& 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"