changeset 3:7fb593d53361

added comments
author Fiore Martin <f.martin@qmul.ac.uk>
date Tue, 12 Jul 2016 18:29:38 +0200
parents dd889fff8423
children ab6db404403a
files CollidoscopeApp/include/DrawInfo.h CollidoscopeApp/include/EnvASR.h CollidoscopeApp/include/Log.h CollidoscopeApp/include/MIDI.h CollidoscopeApp/include/Messages.h CollidoscopeApp/include/PGranular.h CollidoscopeApp/include/PGranularNode.h CollidoscopeApp/include/ParticleController.h CollidoscopeApp/include/RingBufferPack.h CollidoscopeApp/include/Wave.h CollidoscopeApp/src/PGranularNode.cpp CollidoscopeApp/src/Wave.cpp
diffstat 12 files changed, 227 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/CollidoscopeApp/include/DrawInfo.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/DrawInfo.h	Tue Jul 12 18:29:38 2016 +0200
@@ -2,10 +2,20 @@
 
 #include "cinder/Area.h"
 
+/**
+ * The DrawInfo class holds size information for drawing the waves in the screen. 
+ * Every time the screen is resized the draw info is updated with the new information about the window size.
+ *
+ * Every wave has its own drawInfo.
+ *
+ */ 
 class DrawInfo
 {
 public:
 
+    /**
+     * Constructor. Takes the index of the wave as argument.
+     */ 
     DrawInfo( size_t waveIndex ):
         mWaveIndex( waveIndex ),
         mWindowWidth(0),
@@ -14,6 +24,10 @@
         mShrinkFactor(1)
     {}
 
+    /**
+     * Reset this DrawInfo using the new bounding area for the wave.  \a shrinkFactor 
+     * makes the wave shrink on the y axis with respect to the area. A factor 1 makes the wave as big as the area, whereas a factor >1 makes it shrink.
+     */ 
     void reset( const ci::Area &bounds, float shrinkFactor )
     {
         mWindowWidth = bounds.getWidth();
@@ -22,6 +36,10 @@
         mShrinkFactor = shrinkFactor;
     }
 
+    /**
+     * Maps a value in the audio space [-1.0, 1.0] to a position on the y axis of this DrawInf's bounding area.
+     *
+     */ 
 	float audioToHeigt(float audioSample) const {
         /* clip into range [-1.1] */
         if (audioSample < -1.0f) {
@@ -48,6 +66,9 @@
         return mSelectionBarHeight;
     }
 
+    /**
+     * Returns the center position on the y axis of this DrawInfo's the bounding area. 
+     */ 
     int32_t getWaveCenterY() const
     {
         if ( mWaveIndex == 0 )
@@ -56,14 +77,21 @@
             return mWindowHeight / (NUM_WAVES * 2);
     }
 
+    /**
+     * Flips y according to the index of the wave. It is needed because the second wave in collidoscope is upside down from the orientation oftthe screen.
+     */ 
 	int flipY(int y) const 
     {
         if ( mWaveIndex == 0)
-		    return mWindowHeight - y /*+ 24*/;
+		    return mWindowHeight - y;
         else
-            return y /*- 24*/;
+            return y;
 	}
 
+    /**
+     * Returns x. not used at he moment.
+     *
+     */ 
 	int flipX(int x) const
     {
         return x;
@@ -86,6 +114,9 @@
         return mWindowHeight;
     }
 
+    /**
+     * Draw infos cannot be copied and should be passed as const reference.
+     */ 
     DrawInfo( const DrawInfo &original ) = delete;
     DrawInfo & operator=( const DrawInfo &original ) = delete;
 
--- a/CollidoscopeApp/include/EnvASR.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/EnvASR.h	Tue Jul 12 18:29:38 2016 +0200
@@ -17,6 +17,7 @@
 {
 public:
 
+    /** Possible states of the envelope. Idle means the envelope ouputs 0 */
     enum class State {
         eAttack,
         eSustain,
@@ -40,6 +41,7 @@
         mReleaseRate = T( 1.0 ) / (releaseTime * sampleRate);
     }
 
+    /** Produces one sample worth of envelope */
     T tick()
     {
 
--- a/CollidoscopeApp/include/Log.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/Log.h	Tue Jul 12 18:29:38 2016 +0200
@@ -1,8 +1,17 @@
 #pragma once 
 
 
-
+/**
+ * Utility function to log errors using the cinder::log library.
+ * Errors are logged to collidoscope_error.log file. 
+ *
+ */ 
 void logError( const std::string &errorMsg );
 
 
-void logInfo( const std::string &infoMsg );
\ No newline at end of file
+/**
+ * Utility function to log info using the cinder::log library.
+ * Errors are logged to the terminal. Used only for debugging.
+ *
+ */ 
+void logInfo( const std::string &infoMsg );
--- a/CollidoscopeApp/include/MIDI.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/MIDI.h	Tue Jul 12 18:29:38 2016 +0200
@@ -29,6 +29,9 @@
     std::string mMessage;
 };
 
+/**
+ * A MIDI message 
+ */ 
 class MIDIMessage
 {
     friend class MIDI;
@@ -40,8 +43,14 @@
 
     unsigned char getChannel() { return mChannel; }
 
+    /**
+     * First byte of MIDI data 
+     */ 
     unsigned char getData_1() { return mData1; }
 
+    /**
+     * Second byte of MIDI data 
+     */ 
     unsigned char getData_2() { return mData2; }
 
 private:
@@ -54,7 +63,10 @@
     
 };
 
-
+/**
+ * Handles MIDI messages from the keyboards and Teensy. It uses RtMidi library.
+ *
+ */ 
 class MIDI
 {
 
@@ -65,22 +77,32 @@
 
     void setup( const Config& );
 
+    /**
+     * Check new incoming messages and stores them into the vector passed as argument by reference.
+     */ 
     void checkMessages( std::vector< MIDIMessage >&  );
 
 private:
 
+    // callback passed to RtMidi library 
     static void RtMidiInCallback( double deltatime, std::vector<unsigned char> *message, void *userData );
 
+    // parse RtMidi messages and turns them into more readable collidoscope::MIDIMessages
     MIDIMessage parseRtMidiMessage( std::vector<unsigned char> *message );
 
-    // messages to pass to checkMessages caller
+    // messages to pass to checkMessages caller 
     std::vector< MIDIMessage > mMIDIMessages;
+    // use specific variables for pitch bend messages. Pitch bend messages are coming 
+    // from the strip sensors that are very jerky and send a lot of values. So instead 
+    // of saving all the messages in mMIDIMessages just save the last received in mPitchBendMessages 
+    // and optimize away redundant messages.
     std::array< MIDIMessage, NUM_WAVES > mPitchBendMessages;
+    // Same principle of pitch bend messages 
     std::array< MIDIMessage, NUM_WAVES > mFilterMessages;
 
-
-
+    // vecotr containing all the MIDI input devices detected.
     std::vector< std::unique_ptr <RtMidiIn> > mInputs;
+    // Used for mutual access to the MIDI messages by the MIDI thread and the graphic thread.  
     std::mutex mMutex;
 };
 
--- a/CollidoscopeApp/include/Messages.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/Messages.h	Tue Jul 12 18:29:38 2016 +0200
@@ -1,6 +1,9 @@
 #pragma once
 
-
+/**
+ * Enumeration of all the possible commands exchanged between audio thread and graphic thread.
+ *
+ */ 
 enum class Command {
     // message carrying info about one chunk of recorder audio. 
     WAVE_CHUNK,
@@ -17,19 +20,24 @@
     LOOP_OFF
 };
 
-/* Messages sent from the audio thread to the graphic wave. 
-   This includes the wave chunks when the audio is recorder in the buffer and 
-   the cursor position when the grains are reset.
-*/
+/** Message sent from the audio thread to the graphic wave when a new wave is recorded. 
+ *  
+ *  The graphic thread set the chunks of the wave to reflect the level of the recorded audio. 
+ *  The algorithm takes the maximum and minimum value of a group of samples and this becomes the top and bottom of the samples.
+ *  It contains the inde
+ *  the cursor position when the grains are reset.
+ */
 struct RecordWaveMsg
 {
-    Command cmd;
+    Command cmd; // WAVE_CHUNK or WAVE_START
     std::size_t index;
     float arg1;
     float arg2;
 };
 
-
+/**
+ * Utility function to create a new RecordWaveMsg.
+ */ 
 inline RecordWaveMsg makeRecordWaveMsg( Command cmd, std::size_t index, float arg1, float arg2 )
 {
     RecordWaveMsg msg;
@@ -41,13 +49,20 @@
     return msg;
 }
 
-
+/**
+ * Message sent from the audio thread to the graphic thread when a new grain is triggered in the granular synthesizer. 
+ * This creates a new cursor that travels from the beginning to the end of the selection to graphically represent the evolution of the grain in time. 
+ *
+ */ 
 struct CursorTriggerMsg
 {
-    Command cmd;
+    Command cmd; // TRIGGER_UPDATE or TRIGGER_END
     int synthID;
 };
 
+/**
+ * Utility function to create a new CursorTriggerMsg.
+ */ 
 inline CursorTriggerMsg makeCursorTriggerMsg( Command cmd, std::uint8_t synthID )
 {
     CursorTriggerMsg msg;
@@ -58,13 +73,19 @@
     return msg;
 }
 
+/**
+ * Message sent from the graphic (main) thread to the audio thread to start a new voice of the granular synthesizer.
+ */ 
 struct NoteMsg
 {
-    Command cmd;
+    Command cmd; // NOTE_ON/OFF ot LOOP_ON/OFF 
     int midiNote;
     double rate;
 };
 
+/**
+ * Utility function to create a new NoteMsg.
+ */ 
 inline NoteMsg makeNoteMsg( Command cmd, int midiNote, double rate )
 {
     NoteMsg msg;
@@ -74,4 +95,4 @@
     msg.rate = rate;
 
     return msg;
-}
\ No newline at end of file
+}
--- a/CollidoscopeApp/include/PGranular.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/PGranular.h	Tue Jul 12 18:29:38 2016 +0200
@@ -10,6 +10,29 @@
 
 using std::size_t;
 
+/**
+ * The very core of the Collidoscope audio engine: the granular synthesizer.
+ * Based on SuperCollider's TGrains and Ross Becina's "Implementing Real-Time Granular Synthesis" 
+ *
+ * It implements Collidoscope's selection-based approach to granular synthesis. 
+ * A grain is basically a selection of a recorded sample of audio. 
+ * Grains are played in a loop: they are retriggered each time they reach the end of the selection.
+ * However, if the duration coefficient is greater than one, a new grain is re-triggered before the previous one is done. 
+ * The grains start to overlap with each other and create the typical eerie sound of grnular synthesis.
+ * Also every time a new grain is triggered, it is offset of a few samples from the initial position to make the timbre more interesting.
+ *
+ *
+ * PGranular uses a linear ASR envelope with 10 milliseconds attack and 50 milliseconds release.
+ *
+ * Note that PGranular is header based and only depends on std library and on "EnvASR.h" (also header based).
+ * This means you can embedd it in two your project just by copying these two files over.
+ *
+ * Template arguments: 
+ * T: type of the audio samples (normally float or double) 
+ * RandOffsetFunc: type of the callable passed as argument to the contructor
+ * TriggerCallbackFunc: type of the callable passed as argument to the contructor
+ *
+ */ 
 template <typename T, typename RandOffsetFunc, typename TriggerCallbackFunc>
 class PGranular
 {
@@ -24,6 +47,9 @@
         return static_cast<T> ((1 - decimal) * xn + decimal * xn_1);
     }
 
+    /**
+     * A single grain of the granular synthesis 
+     */ 
     struct PGrain
     {
         double phase;    // read pointer to mBuffer of this grain 
@@ -32,13 +58,24 @@
         size_t age;      // age of this grain in samples 
         size_t duration; // duration of this grain in samples. minimum = 4
 
-        double b1;       // hann envelope from Ross Becina "Implementing real time Granular Synthesis"
+        double b1;       // hann envelope from Ross Becina's "Implementing real time Granular Synthesis"
         double y1;
         double y2;
     };
 
 
 
+    /**
+     * Constructor.
+     *
+     * \param buffer a pointer to an array of T that contains the original sample that will be granulized
+     * \param bufferLen length of buffer in samples 
+     * \rand function returning of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used 
+     * to offset the starting sample of the grain. This adds more colour to the sound especially with small selections. 
+     * \triggerCallback function of type void ()(char, int) that is called back each time a new grain is triggered.
+     *      The function is passed the character 't' as first parameter when a new grain is triggered and the characted 't' when the synths becomes idle.
+     * \ID id of this PGrain is passed to the triggerCallback function as second parameter to identify this PGranular as the caller.
+     */ 
     PGranular( const T* buffer, size_t bufferLen, size_t sampleRate, RandOffsetFunc & rand, TriggerCallbackFunc & triggerCallback, int ID ) :
         mBuffer( buffer ),
         mBufferLen( bufferLen ),
@@ -71,29 +108,30 @@
 
     ~PGranular(){}
 
-    /* sets multiplier of duration of grains in seconds */
+    /** Sets multiplier of duration of grains in seconds */
     void setGrainsDurationCoeff( double coeff )
     {
         mGrainsDurationCoeff = coeff;
 
-        mGrainsDuration = std::lround( mTriggerRate * coeff ); // FIXME check if right rounding 
+        mGrainsDuration = std::lround( mTriggerRate * coeff ); 
 
         if ( mGrainsDuration < kMinGrainsDuration )
             mGrainsDuration = kMinGrainsDuration;
     }
 
-    /* sets rate of grains. e.g rate = 2 means one octave higer */
+    /** Sets rate of grains. e.g rate = 2 means one octave higer */
     void setGrainsRate( double rate )
     {
         mGrainsRate = rate;
     }
 
-    // sets trigger rate in samples 
+    /** sets the selection start in samples */
     void setSelectionStart( size_t start )
     {
         mGrainsStart = start;
     }
 
+    /** Sets the selection size ( and therefore the trigger rate) in samples */
     void setSelectionSize( size_t size )
     {
 
@@ -107,11 +145,14 @@
 
     }
 
+    /** Sets the attenuation of the grains with respect to the level of the recorded sample
+     *  attenuation is in amp value and defaule value is 0.25118864315096 (-12dB) */
     void setAttenuation( T attenuation )
     {
         mAttenuation = attenuation;
     }
 
+    /** Starts the synthesis engine */
     void noteOn( double rate )
     {
         if ( mEnvASR.getState() == EnvASR<T>::State::eIdle ){
@@ -125,6 +166,7 @@
         }
     }
 
+    /** Stops the synthesis engine */
     void noteOff()
     {
         if ( mEnvASR.getState() != EnvASR<T>::State::eIdle ){
@@ -132,11 +174,19 @@
         }
     }
 
+    /** Whether the synthesis engine is active or not. After noteOff is called the synth stays active until the envelope decays to 0 */
     bool isIdle()
     {
         return mEnvASR.getState() == EnvASR<T>::State::eIdle;
     }
 
+    /**
+     * Runs the granular engine and stores the output in \a audioOut
+     * 
+     * \param pointer to an array of T. This will be filled with the output of PGranular. It needs to be at least \a numSamples lond
+     * \param tempBuffer a temporary buffer used to store the envelope value. It needs to be at leas \a numSamples long
+     * \param numSamples number of samples to be processed 
+     */ 
     void process( T* audioOut, T* tempBuffer, size_t numSamples )
     {
         
@@ -144,7 +194,7 @@
         size_t envSamples = 0;
         bool becameIdle = false;
 
-        // do the envelope first and store it in the tempBuffer 
+        // process the envelope first and store it in the tempBuffer 
         for ( size_t i = 0; i < numSamples; i++ ){
             tempBuffer[i] = mEnvASR.tick();
             envSamples++;
@@ -156,8 +206,10 @@
             }
         }
 
+        // does the actual grains processing 
         processGrains( audioOut, tempBuffer, envSamples );
 
+        // becomes idle if the envelope goes to idle state 
         if ( becameIdle ){
             mTriggerCallback( 'e', mID );
             reset();
@@ -174,7 +226,7 @@
             synthesizeGrain( mGrains[grainIdx], audioOut, envelopeValues, numSamples );
 
             if ( !mGrains[grainIdx].alive ){
-                // this grain is dead so copyu the last of the active grains here 
+                // this grain is dead so copy the last of the active grains here 
                 // so as to keep all active grains at the beginning of the array 
                 // don't increment grainIdx so the last active grain is processed next cycle
                 // if this grain is the last active grain then mNumAliveGrains is decremented 
@@ -243,6 +295,7 @@
         }
     }
 
+    // synthesize a single grain 
     // audioOut = pointer to audio block to fill 
     // numSamples = numpber of samples to process for this block
     void synthesizeGrain( PGrain &grain, T* audioOut, T* envelopeValues, size_t numSamples )
--- a/CollidoscopeApp/include/PGranularNode.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/PGranularNode.h	Tue Jul 12 18:29:38 2016 +0200
@@ -30,12 +30,13 @@
     explicit PGranularNode( ci::audio::Buffer *grainBuffer, CursorTriggerMsgRingBuffer &triggerRingBuffer );
     ~PGranularNode();
 
-    // set selection size in samples 
+    /** Set selection size in samples */
     void setSelectionSize( size_t size )
     {
         mSelectionSize.set( size );
     }
 
+    /** Set selection start in samples */
     void setSelectionStart( size_t start )
     {
         mSelectionStart.set( start );
@@ -46,7 +47,7 @@
         mGrainDurationCoeff.set( coeff );
     }
 
-    // used for trigger callback in PGRanular 
+    /* PGranularNode passes itself as trigger callback in PGranular */
     void operator()( char msgType, int ID );
 
     ci::audio::dsp::RingBufferT<NoteMsg>& getNoteRingBuffer() { return mNoteMsgRingBufferPack.getBuffer(); }
@@ -59,6 +60,8 @@
 
 private:
 
+    // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed. 
+    //  It is used to avoid calling PGranulat setter methods with *  the same value at each audio callback.
     template< typename T>
     class LazyAtomic
     {
@@ -90,17 +93,19 @@
         T mPreviousVal;
     };
 
+    // creates or re-start a PGranular and sets the pitch according to the MIDI note passed as argument
     void handleNoteMsg( const NoteMsg &msg );
 
-    // pointer to PGranular object 
+    // pointers to PGranular objects 
     std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop;
     std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes;
+    // maps midi notes to pgranulars. When a noteOff is received maks sure the right PGranular is turned off
     std::array<int, kMaxVoices> mMidiNotes;
 
     // pointer to the random generator struct passed over to PGranular 
     std::unique_ptr< RandomGenerator > mRandomOffset;
     
-    /* buffer containing the recorder audio, to pass to PGranular in initialize() */
+    // buffer containing the recorder audio, to pass to PGranular in initialize()
     ci::audio::Buffer *mGrainBuffer;
 
     ci::audio::BufferRef mTempBuffer;
--- a/CollidoscopeApp/include/ParticleController.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/ParticleController.h	Tue Jul 12 18:29:38 2016 +0200
@@ -3,7 +3,9 @@
 #include "cinder/gl/gl.h"
 #include <vector>
 
-
+/**
+ * The ParticleController creates/updates/draws and destroys particles
+ */ 
 class ParticleController {
 
     struct Particle {
@@ -23,19 +25,34 @@
 	std::vector<Particle> mParticles;
     std::vector< ci::vec2 > mParticlePositions;
 
+    // current number of active particles
     size_t mNumParticles;
 
     ci::gl::VboRef			mParticleVbo;
     ci::gl::BatchRef		mParticleBatch;
 
  public:
+    /**
+     * Every time addParticles is run, up to kMaxParticleAdd are added at once
+     */ 
     static const int kMaxParticleAdd = 22;
 
     ParticleController();
+
+    /**
+     * Adds \a amount particles and places them in \a initialLocation. 
+     * \cloudSize determines how far the particles can go
+     */ 
 	void addParticles(int amount, const ci::vec2 &initialLocation, const float cloudSize);
 	
+    /**
+     * Updates position and age of the particles
+     */ 
     void updateParticles();
 
+    /**
+     * Draws all the particles
+     */ 
     inline void draw()
     {
         mParticleBatch->draw();
--- a/CollidoscopeApp/include/RingBufferPack.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/RingBufferPack.h	Tue Jul 12 18:29:38 2016 +0200
@@ -3,8 +3,7 @@
 #include "cinder/audio/dsp/RingBuffer.h"
 
 
-/* Packs together a RingBuffer and the erlated array used to exchange data (read/write) with the ring buffer 
-*/
+/** Packs together a cinder::audio::dsp::RingBuffer and the related array used passed as argument to exchange data (read/write) with the ring buffer  */
 template <typename T>
 class RingBufferPack {
 
@@ -40,4 +39,4 @@
     T* mArray;
 
 
-};
\ No newline at end of file
+};
--- a/CollidoscopeApp/include/Wave.h	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/include/Wave.h	Tue Jul 12 18:29:38 2016 +0200
@@ -30,29 +30,42 @@
 using ci::Color;
 using ci::ColorA;
 
+/**
+ * A Cursor is the white thingy that loops through the selection when Collidoscope is played.
+ */ 
 struct Cursor {
     static const int kNoPosition = -100;
     int pos;
     double lastUpdate;
 };
 
-
+/**
+ * Collidoscope's graphical wave 
+ *
+ */ 
 class Wave
 {
 	friend class ParticleController;
 
 public:
 
+    /**
+     * The selection of the wave that is controlled by the big horizontal knob
+     *
+     */ 
 	class Selection {
 		
 	public:
 
         Selection( Wave * w, Color color );
         
+        /** Sets the start of selection. start is the index of the first chunk of the selection  */
         void setStart( size_t start );
 
+        /** Sets the size of selection. size is the number of chunks the selection is made of */
 		void setSize( size_t size );
 		
+        /** Particle spread is used to calculate the size of the cloud of particles */
         void inline setParticleSpread( float spread ){
             mParticleSpread = spread;
 		}
@@ -70,6 +83,7 @@
 
 		float inline  getParticleSpread() const { return mParticleSpread; }
 
+        /** When selection is null no selection is showed on the wave */
 		inline void setToNull(){
             mParticleSpread = 1.0f;
 			mNull = true;
@@ -107,13 +121,14 @@
 
 	
 
-	/* there is one cursor for each Synth being played */
+	/* Maps id of the synth to cursor. There is one cursor for each Synth being played */
 	std::map < SynthID, Cursor > mCursors;
+    /** Holds the positions of the cursor, namely on which chunk the cursor is currently */
 	std::vector<int> mCursorsPos;
 
 public:
 	
-    // note used to identify the loop for cursor position 
+    // value used to identify the loop for cursor position 
     static const int kLoopNote = -1;
 	static const cinder::Color CURSOR_CLR;
 	/* must be in sync with supercollider durationFactor ControlSpec max */
@@ -122,12 +137,21 @@
 	static const int PARTICLESIZE_COEFF = 40;
 #endif
 
+    /** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorder the wave is reset
+     *  \param onlyChunks if false the selection is also set to null, if true only the chunks are reset
+     */
 	void reset(bool onlyChunks);
 
+    /** sets top and bottom values for the chunk. 
+     * \a bottom and \a top are in audio coordinates [-1.0, 1.0]
+     */
 	void setChunk(size_t index, float bottom, float top);
 
 	const Chunk & getChunk(size_t index);
 
+    /** places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine. 
+     *  The synth id identifies uniquely the cursor in the internal map of the wave.
+     *  If the cursor doesn't exist it is created */
     inline void setCursorPos( SynthID id, int pos, const DrawInfo& di ){
 
 	    Cursor & cursor = mCursors[id];
@@ -135,9 +159,8 @@
 	    cursor.lastUpdate = ci::app::getElapsedSeconds();
 
 #ifdef USE_PARTICLES
-	    /* if the duration is greater than 1.0 carry on the cursor as a particle
-	    the smaller the selection the more particles
-	    the bigger the duration the more particles */
+	    // The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles
+	    // The smaller the selection the more particles; the bigger the duration the more particles 
 	    if (mSelection.getParticleSpread() > 1.0f){
 		    /* amountCoeff ranges from 1/8 to 1 */
             const float amountCoeff = (mSelection.getParticleSpread() / MAX_DURATION);
@@ -167,7 +190,7 @@
 
     void removeCursor( SynthID id ) { mCursors.erase( id ); }
 
-    // parameter ranges from 0 to 1 
+    /** Sets the transparency of this wave. \a alpha ranges from 0 to 1 */
 	inline void setselectionAlpha(float alpha){ mFilterCoeff = alpha;}
 
     void draw( const DrawInfo& di );
@@ -180,7 +203,7 @@
 
     Wave( size_t numChunks, Color selectionColor );
 
-    // no copies 
+    /** no copies */
     Wave( const Wave &copy ) = delete;
     Wave & operator=(const Wave &copy) = delete;
 
@@ -197,6 +220,7 @@
 
     float mFilterCoeff;
 
+    // cinder gl batch for batch drawing 
     ci::gl::BatchRef mChunkBatch;
 
 };
--- a/CollidoscopeApp/src/PGranularNode.cpp	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/src/PGranularNode.cpp	Tue Jul 12 18:29:38 2016 +0200
@@ -59,7 +59,6 @@
 void PGranularNode::process (ci::audio::Buffer *buffer )
 {
     // only update PGranular if the atomic value has changed from the previous time
-
     const boost::optional<size_t> selectionSize = mSelectionSize.get();
     if ( selectionSize ){
         mPGranularLoop->setSelectionSize( *selectionSize );
@@ -112,6 +111,7 @@
     }
 }
 
+// Called back when new grnular is triggered of turned off. Sends notification message to graphic thread.
 void PGranularNode::operator()( char msgType, int ID ) {
 
     switch ( msgType ){
--- a/CollidoscopeApp/src/Wave.cpp	Mon Jul 11 17:03:40 2016 +0200
+++ b/CollidoscopeApp/src/Wave.cpp	Tue Jul 12 18:29:38 2016 +0200
@@ -96,7 +96,7 @@
 
 	
 	const float wavePixelLen =  ( mNumChunks * ( 2 + Chunk::kWidth ) );
-	/* scale the x-axis for the wave to fit the window */
+	/* scale the x-axis for the wave to fit the window precisely */
 	gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
 	/* draw the chunks */
 	if (mSelection.isNull()){