| 
							- /*
 -   ==============================================================================
 - 
 -    JUCE demo code - use at your own risk!
 - 
 -   ==============================================================================
 - */
 - 
 - 
 - /**
 -     A very basic generator of a simulated plucked string sound, implementing
 -     the Karplus-Strong algorithm.
 - 
 -     Not performance-optimised!
 - */
 - class StringSynthesiser
 - {
 - public:
 -     //==============================================================================
 -     /** Constructor.
 - 
 -         @param sampleRate      The audio sample rate to use.
 -         @param frequencyInHz   The fundamental frequency of the simulated string in
 -                                Hertz.
 -     */
 -     StringSynthesiser (double sampleRate, double frequencyInHz)
 -     {
 -         doPluckForNextBuffer.set (false);
 -         prepareSynthesiserState (sampleRate, frequencyInHz);
 -     }
 - 
 -     //==============================================================================
 -     /** Excite the simulated string by plucking it at a given position.
 - 
 -         @param pluckPosition The position of the plucking, relative to the length
 -                              of the string. Must be between 0 and 1.
 -     */
 -     void stringPlucked (float pluckPosition)
 -     {
 -         jassert (pluckPosition >= 0.0 && pluckPosition <= 1.0);
 - 
 -         // we choose a very simple approach to communicate with the audio thread:
 -         // simply tell the synth to perform the plucking excitation at the beginning
 -         // of the next buffer (= when generateAndAddData is called the next time).
 - 
 -         if (doPluckForNextBuffer.compareAndSetBool (1, 0))
 -         {
 -             // plucking in the middle gives the largest amplitude;
 -             // plucking at the very ends will do nothing.
 -             amplitude = std::sin (float_Pi * pluckPosition);
 -         }
 -     }
 - 
 -     //==============================================================================
 -     /** Generate next chunk of mono audio output and add it into a buffer.
 - 
 -         @param outBuffer  Buffer to fill (one channel only). New sound will be
 -                           added to existing content of the buffer (instead of
 -                           replacing it).
 -         @param numSamples Number of samples to generate (make sure that outBuffer
 -                           has enough space).
 -     */
 -     void generateAndAddData (float* outBuffer, int numSamples)
 -     {
 -         if (doPluckForNextBuffer.compareAndSetBool (0, 1))
 -             exciteInternalBuffer();
 - 
 -         // cycle through the delay line and apply a simple averaging filter
 -         for (int i = 0; i < numSamples; ++i)
 -         {
 -             const int nextPos = (pos + 1) % delayLine.size();
 - 
 -             delayLine[nextPos] = (float) (decay * 0.5 * (delayLine[nextPos] + delayLine[pos]));
 -             outBuffer[i] += delayLine[pos];
 - 
 -             pos = nextPos;
 -         }
 -     }
 - 
 - private:
 -     //==============================================================================
 -     void prepareSynthesiserState (double sampleRate, double frequencyInHz)
 -     {
 -         size_t delayLineLength = (size_t) roundToInt (sampleRate / frequencyInHz);
 - 
 -         // we need a minimum delay line length to get a reasonable synthesis.
 -         // if you hit this assert, increase sample rate or decrease frequency!
 -         jassert (delayLineLength > 50);
 - 
 -         delayLine.resize (delayLineLength);
 -         std::fill (delayLine.begin(), delayLine.end(), 0.0f);
 - 
 -         excitationSample.resize (delayLineLength);
 - 
 -         // as the excitation sample we use random noise between -1 and 1
 -         // (as a simple approximation to a plucking excitation)
 - 
 -         std::generate (excitationSample.begin(),
 -                        excitationSample.end(),
 -                        [] { return (Random::getSystemRandom().nextFloat() * 2.0f) - 1.0f; } );
 -     }
 - 
 -     void exciteInternalBuffer()
 -     {
 -         // fill the buffer with the precomputed excitation sound (scaled with amplitude)
 - 
 -         jassert (delayLine.size() >= excitationSample.size());
 - 
 -         std::transform (excitationSample.begin(),
 -                         excitationSample.end(),
 -                         delayLine.begin(),
 -                         [this] (double sample) { return amplitude * sample; } );
 -     };
 - 
 -     //==============================================================================
 -     const double decay = 0.998;
 -     double amplitude = 0.0;
 - 
 -     Atomic<int> doPluckForNextBuffer;
 - 
 -     std::vector<float> excitationSample, delayLine;
 -     int pos = 0;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringSynthesiser)
 - };
 
 
  |