Revision 16:4dad0b810f18 CollidoscopeApp

View differences:

CollidoscopeApp/include/AudioEngine.h
75 75
    */ 
76 76
    size_t getRecordWaveAvailable( size_t index );
77 77
    /**
78
    * Called from the graphic thread. Reads count elements from the wave ring buffer into \a buffer.
78
    * Called from the graphic thread. Reads \a count elements from the wave ring buffer into \a buffer.
79 79
    * The wave ring buffer is used to pass the size of the wave chunks from the audio thread to the graphic thread, 
80 80
    * when a new wave is recorded.
81 81
    *
......
106 106
    // nodes for recording audio input into buffer. Also sends chunks information through 
107 107
    // non-blocking queue 
108 108
    std::array< BufferToWaveRecorderNodeRef, NUM_WAVES > mBufferRecorderNodes;
109
    // pgranulars for loop synths 
109
    // pgranulars wrapped in a Cinder::Node 
110 110
    std::array< PGranularNodeRef, NUM_WAVES > mPGranularNodes;
111 111

  
112 112

  
CollidoscopeApp/include/BufferToWaveRecorderNode.h
60 60
/**
61 61
 * A \a Node in the audio graph of the Cinder audio library that records input in a buffer.
62 62
 *
63
 * This class is similar to \a cinder::audio::BufferRecorderNode (it's a derivative work of this class indeed) but it has an additional feature.
64
 * When recording it uses the audio input samples to compute the size values of the visual chunks. 
63
 * This class is similar to \a cinder::audio::BufferRecorderNode (it's a derivative work of this class indeed) but it has an additional feature:
64
 * when recording, it uses the audio input samples to compute the size values of the visual chunks. 
65 65
 * The chunks values are stored in a ring buffer and fetched by the graphic thread to paint the wave as it gets recorded.
66 66
 *
67 67
 */
CollidoscopeApp/include/Chunk.h
33 33
 *
34 34
 * A chunk of audio in Collidoscope low-fi visual wave. 
35 35
 *
36
 * The visual wave of Collidoscope is made out of a number of bars that mimics in a low-fi fashion the typical waveform based representation of audio.
36
 * The visual wave of Collidoscope is made out of a number of bars that mimic, in a low-fi fashion, the typical waveform-based representation of audio.
37 37
 * A Chunk is one of the bars of the visual wave. 
38 38
 *
39 39
 */
......
47 47
    const static float kHalfWidth;
48 48

  
49 49
    /**
50
     * Constructor, takes as argument the index of this chunk in the wave
50
     * Constructor, takes as argument the index of this chunk in the wave that contains it
51 51
     */ 
52 52
    Chunk( size_t index );
53 53

  
......
69 69
    float inline getBottom() const { return mAudioBottom; }
70 70

  
71 71
    /**
72
     * Reset this chunks. When a chunk is reset it starts shrinking until it disappears.
72
     * Reset this chunks. When a chunk is reset, it starts shrinking until it disappears or setTop/setBottom are called again
73 73
     *
74 74
     */ 
75 75
    void reset(){
CollidoscopeApp/include/Config.h
66 66
    }
67 67

  
68 68
    /**
69
     * Returns wave's selection color
69
     * Returns wave selection color
70 70
     */ 
71 71
    ci::Color getWaveSelectionColor(size_t waveIdx) const
72 72
    {
......
123 123
    /**
124 124
     * The value returned is used when creating the oscilloscope. 
125 125
     * The oscilloscope represents the audio output buffer graphically. However it doesn't need to be as refined as the 
126
     * audio wave and it's downsampled using the following formula :  number of oscilloscope points = size o audio output buffer / getOscilloscopeNumPointsDivider() 
126
     * audio wave and it's downsampled using the following formula :  (number of oscilloscope points) = (size of audio output buffer) / getOscilloscopeNumPointsDivider() 
127 127
     */ 
128 128
    size_t getOscilloscopeNumPointsDivider() const
129 129
    {
CollidoscopeApp/include/DrawInfo.h
58 58
    }
59 59

  
60 60
    /**
61
     * Maps a value in the audio space [-1.0, 1.0] to a position on the y axis of this DrawInf's bounding area.
61
     * Maps a value in the audio space [-1.0, 1.0] to a position on the y axis of this DrawInfo's bounding area.
62 62
     *
63 63
     */ 
64 64
    float audioToHeigt(float audioSample) const {
......
99 99
    }
100 100

  
101 101
    /**
102
     * 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.
102
     * Flips y according to the index of the wave. It is needed because the second wave in collidoscope is drawn upside down in the screen.
103 103
     */ 
104 104
    int flipY(int y) const 
105 105
    {
......
110 110
    }
111 111

  
112 112
    /**
113
     * Returns x. not used at he moment.
113
     * Returns x. not used at the moment.
114 114
     *
115 115
     */ 
116 116
    int flipX(int x) const
CollidoscopeApp/include/EnvASR.h
1 1
/*
2 2

  
3 3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
4
 Author: Fiore Martin, based on CCRMA STK ADSR.h (https://ccrma.stanford.edu/software/stk/classstk_1_1ADSR.html) 
5 5

  
6 6
 This file is part of Collidoscope.
7 7
 
......
17 17

  
18 18
 You should have received a copy of the GNU General Public License
19 19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice:
22

  
23
    The Synthesis ToolKit in C++ (STK)
24

  
25
    Copyright (c) 1995--2016 Perry R. Cook and Gary P. Scavone
26

  
27
    Permission is hereby granted, free of charge, to any person obtaining
28
    a copy of this software and associated documentation files (the
29
    "Software"), to deal in the Software without restriction, including
30
    without limitation the rights to use, copy, modify, merge, publish,
31
    distribute, sublicense, and/or sell copies of the Software, and to
32
    permit persons to whom the Software is furnished to do so, subject to
33
    the following conditions:
34

  
35
    The above copyright notice and this permission notice shall be
36
    included in all copies or substantial portions of the Software.
37

  
38
    Any person wishing to distribute modifications to the Software is
39
    asked to send the modifications to the original developer so that they
40
    can be incorporated into the canonical version.  This is, however, not
41
    a binding provision of this license.
42

  
43
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
44
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
47
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
48
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
49
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50

  
20 51
*/
21 52

  
22 53
#pragma once 
CollidoscopeApp/include/MIDI.h
31 31

  
32 32
namespace collidoscope {
33 33

  
34

  
34
// Exception thrown by MIDI system
35 35
class MIDIException : public std::exception
36 36
{
37 37
public:
......
118 118
    // of saving all the messages in mMIDIMessages just save the last received in mPitchBendMessages 
119 119
    // and optimize away redundant messages.
120 120
    std::array< MIDIMessage, NUM_WAVES > mPitchBendMessages;
121
    // Same principle of pitch bend messages 
121
    // Same principle as mPitchBendMessages
122 122
    std::array< MIDIMessage, NUM_WAVES > mFilterMessages;
123 123

  
124
    // vecotr containing all the MIDI input devices detected.
124
    // vector containing all the MIDI input devices detected.
125 125
    std::vector< std::unique_ptr <RtMidiIn> > mInputs;
126 126
    // Used for mutual access to the MIDI messages by the MIDI thread and the graphic thread.  
127 127
    std::mutex mMutex;
CollidoscopeApp/include/Messages.h
31 31
    // message sent when a new recording starts. The gui resets the wave upon receiving it. 
32 32
    WAVE_START,
33 33

  
34
    // new grain created 
34 35
    TRIGGER_UPDATE,
36
    // synth became idle
35 37
    TRIGGER_END,
36 38

  
37 39
    NOTE_ON,
......
43 45

  
44 46
/** Message sent from the audio thread to the graphic wave when a new wave is recorded. 
45 47
 *  
46
 *  The graphic thread set the chunks of the wave to reflect the level of the recorded audio. 
47
 *  The algorithm takes the maximum and minimum value of a group of samples and this becomes the top and bottom of the samples.
48
 *  It contains the inde
49
 *  the cursor position when the grains are reset.
48
 *  The graphic thread sets the chunks of the wave to reflect the level of the recorded audio. 
49
 *  The algorithm takes the maximum and minimum value of a group of samples and this becomes the top and bottom of the chunk.
50
 *  The message carries also the index of the chunk it refers to 
50 51
 */
51 52
struct RecordWaveMsg
52 53
{
CollidoscopeApp/include/Oscilloscope.h
44 44
        {}
45 45

  
46 46
    /**
47
     * Sets the value of a point of the oscilloscope. The value is passed as an audio coordinate [-1.0, 1.0].
48
     * A reference to DrawInfo is passed to calculate the graphic coordinate of the point based on the audio value passed. 
47
     * Sets the value of a point of the oscilloscope. The value is passed in audio coordinates [-1.0, 1.0].
48
     * A reference to DrawInfo is passed to calculate the graphic coordinate of the point based on the audio values passed. 
49 49
     */ 
50 50
    void  setPoint( int index, float audioVal, const DrawInfo &di ){
51 51

  
......
66 66
        mLine.getPoints()[index].x = float( di.flipX( int(xRatio) ) );
67 67
        mLine.getPoints()[index].y = float( di.flipY( int(yRatio) ) );
68 68

  
69
        // add the missing line to reach the right of the window
70
        // indeed the scope starts from 0 to size -1 and adds xRatio
71
        // to each new point to the line from n-1 to n is missing 
69
        // add the missing line to reach the right of the window.
70
        // Indeed, the scope starts from 0 to size-1 and adds xRatio
71
        // to each new point. The line from n-1 to n is therefore missing.
72 72
        if (index == mNumPoints - 1){
73 73
            xRatio += ( di.getWindowWidth() / mNumPoints );
74 74
            xRatio = ceil( xRatio ); // ceil because the division might left one pixel out
CollidoscopeApp/include/PGranular.h
1 1
/*
2 2

  
3
 Copyright (C) 2002 James McCartney.
3 4
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5
 Author: Fiore Martin, based on Supercollider's (http://supercollider.github.io) TGrains code and Ross Bencina's "Implementing Real-Time Granular Synthesis"
5 6

  
6 7
 This file is part of Collidoscope.
7 8
 
......
33 34

  
34 35
/**
35 36
 * The very core of the Collidoscope audio engine: the granular synthesizer.
36
 * Based on SuperCollider's TGrains and Ross Becina's "Implementing Real-Time Granular Synthesis" 
37
 * Based on SuperCollider's TGrains and Ross Bencina's "Implementing Real-Time Granular Synthesis" 
37 38
 *
38 39
 * It implements Collidoscope's selection-based approach to granular synthesis. 
39 40
 * A grain is basically a selection of a recorded sample of audio. 
40
 * Grains are played in a loop: they are retriggered each time they reach the end of the selection.
41
 * However, if the duration coefficient is greater than one, a new grain is re-triggered before the previous one is done. 
42
 * The grains start to overlap with each other and create the typical eerie sound of grnular synthesis.
41
 * Grains are played in a loop: they are re-triggered each time they reach the end of the selection.
42
 * However, if the duration coefficient is greater than one, a new grain is re-triggered before the previous one is done,
43
 * the grains start to overlap with each other and create the typical eerie sound of grnular synthesis.
43 44
 * 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.
44 45
 *
45 46
 *
......
75 76
    {
76 77
        double phase;    // read pointer to mBuffer of this grain 
77 78
        double rate;     // rate of the grain. e.g. rate = 2 the grain will play twice as fast
78
        bool alive;      // whether this grain is alive. Not alive means it has been processed and can be replanced by another grain
79
        bool alive;      // whether this grain is alive. Not alive means it has been processed and can be replaced by another grain
79 80
        size_t age;      // age of this grain in samples 
80 81
        size_t duration; // duration of this grain in samples. minimum = 4
81 82

  
......
91 92
     *
92 93
     * \param buffer a pointer to an array of T that contains the original sample that will be granulized
93 94
     * \param bufferLen length of buffer in samples 
94
     * \rand function returning of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used 
95
     * \rand function of type size_t ()(void) that is called back each time a new grain is generated. The returned value is used 
95 96
     * to offset the starting sample of the grain. This adds more colour to the sound especially with small selections. 
96
     * \triggerCallback function of type void ()(char, int) that is called back each time a new grain is triggered.
97
     *      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.
98
     * \ID id of this PGrain is passed to the triggerCallback function as second parameter to identify this PGranular as the caller.
97
     * \triggerCallback function of type void ()(char, int) that is called back each time a new grain is generated.
98
     *      The function is passed the character 't' as first parameter when a new grain is triggered and the characted 'e' when the synth becomes idle (no sound).
99
     * \ID id of this PGrain. Passed to the triggerCallback function as second parameter to identify this PGranular as the caller.
99 100
     */ 
100 101
    PGranular( const T* buffer, size_t bufferLen, size_t sampleRate, RandOffsetFunc & rand, TriggerCallbackFunc & triggerCallback, int ID ) :
101 102
        mBuffer( buffer ),
......
204 205
    /**
205 206
     * Runs the granular engine and stores the output in \a audioOut
206 207
     * 
207
     * \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
208
     * \param tempBuffer a temporary buffer used to store the envelope value. It needs to be at leas \a numSamples long
208
     * \param pointer to an array of T. This will be filled with the output of PGranular. It needs to be at least \a numSamples long
209
     * \param tempBuffer a temporary buffer used to store the envelope value. It needs to be at least \a numSamples long
209 210
     * \param numSamples number of samples to be processed 
210 211
     */ 
211 212
    void process( T* audioOut, T* tempBuffer, size_t numSamples )
......
318 319

  
319 320
    // synthesize a single grain 
320 321
    // audioOut = pointer to audio block to fill 
321
    // numSamples = numpber of samples to process for this block
322
    // numSamples = number of samples to process for this block
322 323
    void synthesizeGrain( PGrain &grain, T* audioOut, T* envelopeValues, size_t numSamples )
323 324
    {
324 325

  
325
        // copy all grain data into local variable for faster porcessing
326
        // copy all grain data into local variable for faster processing
326 327
        const auto rate = grain.rate;
327 328
        auto phase = grain.phase;
328 329
        auto age = grain.age;
......
364 365
        }
365 366

  
366 367
        if ( age == duration ){
367
            // if it porocessed all the samples left to leave ( numSamplesToOut = duration-age)
368
            // then the grain is had finished 
368
            // if it processed all the samples left to leave ( numSamplesToOut = duration-age)
369
            // then the grain is finished 
369 370
            grain.alive = false;
370 371
        }
371 372
        else{
......
398 399
    // length of mBuffer in samples 
399 400
    const size_t mBufferLen;
400 401

  
401
    // offset in the buffer where the grains start. a.k.a. seleciton start 
402
    // offset in the buffer where the grains start. a.k.a. selection start 
402 403
    size_t mGrainsStart;
403 404

  
404
    // attenuates signal prevents clipping of grains 
405
    // attenuates signal prevents clipping of grains (to some degree)
405 406
    T mAttenuation;
406 407

  
407 408
    // grain duration in samples 
408 409
    double mGrainsDurationCoeff;
409
    // duration of grains is selcection size * duration coeff
410
    // duration of grains is selection size * duration coeff
410 411
    size_t mGrainsDuration;
411 412
    // rate of grain, affects pitch 
412 413
    double mGrainsRate;
CollidoscopeApp/include/PGranularNode.h
40 40
struct RandomGenerator;
41 41

  
42 42
/*
43
A node in the Cinder audio graph that holds a PGranular 
43
A node in the Cinder audio graph that holds PGranulars for loop and keyboard playing  
44 44
*/
45 45
class PGranularNode : public ci::audio::Node
46 46
{
......
82 82
private:
83 83

  
84 84
    // Wraps a std::atomic but get() returns a boost::optional that is set to a real value only when the atomic has changed. 
85
    //  It is used to avoid calling PGranulat setter methods with *  the same value at each audio callback.
85
    //  It is used to avoid calling PGranular setter methods with the same value at each audio callback.
86 86
    template< typename T>
87 87
    class LazyAtomic
88 88
    {
......
120 120
    // pointers to PGranular objects 
121 121
    std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > > mPGranularLoop;
122 122
    std::array<std::unique_ptr < collidoscope::PGranular<float, RandomGenerator, PGranularNode > >, kMaxVoices> mPGranularNotes;
123
    // maps midi notes to pgranulars. When a noteOff is received maks sure the right PGranular is turned off
123
    // maps midi notes to pgranulars. When a noteOff is received makes sure the right PGranular is turned off
124 124
    std::array<int, kMaxVoices> mMidiNotes;
125 125

  
126 126
    // pointer to the random generator struct passed over to PGranular 
127 127
    std::unique_ptr< RandomGenerator > mRandomOffset;
128 128
    
129
    // buffer containing the recorder audio, to pass to PGranular in initialize()
129
    // buffer containing the recorded audio, to pass to PGranular in initialize()
130 130
    ci::audio::Buffer *mGrainBuffer;
131 131

  
132 132
    ci::audio::BufferRef mTempBuffer;
CollidoscopeApp/include/ParticleController.h
36 36
        ci::vec2	mCloudCenter; // initial positin of the particle 
37 37
        ci::vec2	mVel;         // velocity 
38 38
        float       mCloudSize;   // how big is the area where particle float around. When a particle hits the 
39
                                  //   border of the area it gets deflected 
39
                                  // border of the area it gets deflected 
40 40

  
41 41
        int			mAge;      // when mAge == mLifeSpan the particle is disposed 
42 42
        int			mLifespan; // how long a particle lives
CollidoscopeApp/include/Wave.h
88 88
        void setSize( size_t size );
89 89
        
90 90
        /** The particle spread parameter affects the size of the cloud of particles
91
         *  The cloud is the visual conterpart of the grain duration coefficien in sound.
91
         *  The cloud is the visual counterpart of the grain duration coefficient in sound.
92 92
         *  Indeed spread accepts values from 1 to 8, exactly as the duration coefficient
93 93
         */
94 94
        void inline setParticleSpread( float spread ){
......
148 148

  
149 149
    /* Maps id of the synth to cursor. There is one cursor for each Synth being played */
150 150
    std::map < SynthID, Cursor > mCursors;
151
    /** Holds the positions of the cursor, namely on which chunk the cursor is currently */
151
    /** Holds the positions of the cursor, namely on which chunk the cursor is currently on */
152 152
    std::vector<int> mCursorsPos;
153 153

  
154 154
public:
......
156 156
    // value used to identify the loop for cursor position 
157 157
    static const int kLoopNote = -1;
158 158
    static const cinder::Color CURSOR_CLR;
159
    /* must be in sync with supercollider durationFactor ControlSpec max */
160 159
    static const int MAX_DURATION = 8;
161 160
#ifdef USE_PARTICLES
162 161
    static const int PARTICLESIZE_COEFF = 40;
163 162
#endif
164 163

  
165
    /** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorder the wave is reset
164
    /** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorded, the wave is reset.
166 165
     *  \param onlyChunks if false the selection is also set to null, if true only the chunks are reset
167 166
     */
168 167
    void reset(bool onlyChunks);
......
174 173

  
175 174
    const Chunk & getChunk(size_t index);
176 175

  
177
    /** places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine. 
176
    /** Places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine. 
178 177
     *  The synth id identifies uniquely the cursor in the internal map of the wave.
179 178
     *  If the cursor doesn't exist it is created */
180 179
    inline void setCursorPos( SynthID id, int pos, const DrawInfo& di ){
......
184 183
        cursor.lastUpdate = ci::app::getElapsedSeconds();
185 184

  
186 185
#ifdef USE_PARTICLES
187
        // The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles
188
        // The smaller the selection the more particles; the bigger the duration the more particles 
186
        // The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles.
187
        // The smaller the selection the more particles; the bigger the duration the more particles. 
189 188
        if (mSelection.getParticleSpread() > 1.0f){
190 189
            /* amountCoeff ranges from 1/8 to 1 */
191 190
            const float amountCoeff = (mSelection.getParticleSpread() / MAX_DURATION);
192 191
                
193 192
            /* get radom point within seleciton as center of the particle */
194
            vec2 centrePoint; // was former getRandomPoint
193
            vec2 centrePoint;
195 194
            const int randomChunkIndex = ci::Rand::randInt(mSelection.getStart(), mSelection.getEnd() );
196 195

  
197 196
            centrePoint.x = di.flipX( 1 + (randomChunkIndex * (2 + Chunk::kWidth)) + Chunk::kWidth / 2 );
......
243 242

  
244 243
    cinder::Color mColor;
245 244

  
245
    // How much filter is applied in audio. It affects the alpha value of the selection color.
246 246
    float mFilterCoeff;
247 247

  
248 248
    // cinder gl batch for batch drawing 
CollidoscopeApp/src/AudioEngine.cpp
21 21
*/
22 22

  
23 23
#include "AudioEngine.h"
24
// app.h include not used 
24 25
#include "cinder/app/App.h"
25
//FIXME remove App.h include 
26 26
#include "Log.h"
27 27

  
28 28
using namespace ci::audio;
......
87 87
    /* audio context */
88 88
    auto ctx = Context::master();
89 89

  
90
    /* audio inpu device */
90
    /* audio input device */
91 91
    auto inputDeviceNode = ctx->createInputDeviceNode( Device::getDefaultInput() );
92 92
 
93 93

  
......
102 102
        /* this prevents the node from recording before record is pressed */
103 103
        mBufferRecorderNodes[chan]->setAutoEnabled( false );
104 104

  
105
        // route the input part of the audio graph. Two channels input goes into
106
        // one channel route and to one channel buffer recorder 
105
        // route the input part of the audio graph. Two channels input goes into one channel route
106
        // and from one channel route to one channel buffer recorder 
107 107
        inputDeviceNode >> mInputRouterNodes[chan]->route( chan, 0, 1 ) >> mBufferRecorderNodes[chan];
108 108

  
109 109

  
110 110
        // create PGranular loops passing the buffer of the RecorderNode as argument to the contructor 
111
        // use -1 as ID 
111
        // use -1 as ID as the loop corresponds to no midi note 
112 112
        mPGranularNodes[chan] = ctx->makeNode( new PGranularNode( mBufferRecorderNodes[chan]->getRecorderBuffer(), mCursorTriggerRingBufferPacks[chan]->getBuffer() ) );
113 113

  
114 114
        // create filter nodes 
......
126 126
        // filter goes to output 
127 127
        mLowPassFilterNodes[chan] >> mOutputRouterNodes[chan]->route( 0, chan, 1 ) >> ctx->getOutput();
128 128
        
129
        // what goes to output goes to scope 
129
        // what goes to output goes to oscilloscope as well
130 130
        mLowPassFilterNodes[chan] >> mOutputMonitorNodes[chan];
131 131

  
132 132
    }
CollidoscopeApp/src/Chunk.cpp
44 44
void Chunk::update( const DrawInfo &di )
45 45
{
46 46
    using namespace ci;
47
    /* if resetting animate the chunks to shrink to 0 size */
47
    /* if resetting animate the chunks to nicely shrink to 0 size */
48 48
    if ( mResetting ){
49 49
        if ( mAnimate > 0.0f ){
50 50
            mAnimate -= 0.1f;
......
64 64
        }
65 65
    }
66 66

  
67
    mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME this should happen only once when resized 
67
    mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME more efficient if it happens only once when resized 
68 68
}
69 69

  
70 70
void Chunk::draw( const DrawInfo& di, ci::gl::BatchRef &batch ){
......
74 74

  
75 75
    const float chunkHeight = mAnimate * mAudioTop * di.getMaxChunkHeight();
76 76

  
77
    // place the chunk in the right position brigns back the y of chunkHeight/2 so
77
    // place the chunk in the right position brings back the y of chunkHeight/2 so
78 78
    // so that after scaling the wave is still centered at the wave center 
79 79
    gl::translate( mX, di.getWaveCenterY() - ( chunkHeight / 2 ) - 1 );
80 80

  
81
    // FIXME todo use max between top and bottom
82 81
    // scale according to audio amplitude 
83 82
    gl::scale( 1.0f, chunkHeight );
84 83
    batch->draw();
CollidoscopeApp/src/CollidoscopeApp.cpp
65 65
    array< shared_ptr< Wave >, NUM_WAVES > mWaves;
66 66
    array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos;
67 67
    array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes;
68
    // buffers to read the wave messages as a new wave gets recorded 
68
    // buffer to read the WAVE_* messages as a new wave gets recorded 
69 69
    array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers;
70
    //buffer to read the TRIGGER_* messages as the pgranulars play
70 71
    array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers;
71 72

  
72 73
    double mSecondsPerChunk;
CollidoscopeApp/src/PGranularNode.cpp
65 65
{
66 66
    mTempBuffer = std::make_shared< ci::audio::Buffer >( getFramesPerBlock() );
67 67

  
68
    mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to times 0.01 in the time domain 
68
    mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to multiplied by 0.01 in the time domain 
69 69

  
70 70
    /* create the PGranular object for looping */
71 71
    mPGranularLoop.reset( new collidoscope::PGranular<float, RandomGenerator, PGranularNode>( mGrainBuffer->getData(), mGrainBuffer->getNumFrames(), getSampleRate(), *mRandomOffset, *this, -1 ) );
......
132 132
    }
133 133
}
134 134

  
135
// Called back when new grnular is triggered of turned off. Sends notification message to graphic thread.
135
// Called back when new PGranular is triggered or turned off. Sends notification message to graphic thread.
136 136
void PGranularNode::operator()( char msgType, int ID ) {
137 137

  
138 138
    switch ( msgType ){
......
167 167
        }
168 168

  
169 169
        if ( !synthFound ){
170
            // then look for a free synth 
170
            // then look for a free voice 
171 171
            for ( int i = 0; i < kMaxVoices; i++ ){
172 172

  
173 173
                if ( mMidiNotes[i] == kNoMidiNote ){
CollidoscopeApp/src/ParticleController.cpp
33 33
mNumParticles( 0 )
34 34

  
35 35
{
36
    // uses Cinder (and OpenGL) virtual buffer object based drawing
36
    // uses Cinder (and OpenGL) drawing based on virtual buffer object
37 37
    // see ParticleSphereCPU example in Cinder library 
38 38
     
39 39
    mParticles.assign( kMaxParticles, Particle() );
......
97 97

  
98 98
void ParticleController::updateParticles()
99 99
{
100
    // update the positions of the particles and dispose them if they're reached their timespan
100
    // update the positions of the particles and dispose them if they've reached their timespan
101 101
    for ( size_t i = 0; i < mNumParticles; i++ ){
102 102

  
103 103
        Particle &particle = mParticles[i];
......
132 132

  
133 133
void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize)
134 134
{
135
    // reduce the particles liearly to the total number of particles already present 
135
    // reduce the particles linearly to the total number of particles already present 
136 136
    // the more particles aleary present the less particle are added
137 137
    int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd);
138 138
    amount -= reduction;
CollidoscopeApp/src/Wave.cpp
87 87

  
88 88
        double elapsed = now - itr->second.lastUpdate;
89 89

  
90
        // A chunk of audio corresponds to a certain time according to sample rate.
91
        // Use elapsed time to advance through chunks so that the cursor is animated 
92
        // and goes from start to end of the seleciton in the time span of the grain 
90
        // A chunk of audio corresponds to a certain time lenght of audio, according to sample rate.
91
        // Use elapsed time to advance through chunks so that the cursor is animated. 
92
        // So it goes from start to end of the selection in the time span of the grain 
93 93
        itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk );
94 94

  
95 95
        // check we don't go too far off 
......
160 160
                gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
161 161
            }
162 162

  
163
            // check if one of the cursors is positioned in this chunk  
163
            // check if one of the cursors is positioned in this chunk, and draw it white if it is 
164 164
            if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
165 165
                gl::color(CURSOR_CLR);
166 166
                mChunks[i].draw( di, mChunkBatch );
......
176 176
                /* draw the selection bar with a transparent selection color */
177 177
                gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
178 178
                mChunks[i].drawBar( di, mChunkBatch );
179
                /* set the colo to the wave */
179
                /* set the color to the wave */
180 180
                gl::color(this->mColor);  
181 181
            }
182 182
        }

Also available in: Unified diff