To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / CollidoscopeApp / include / Wave.h @ 3:7fb593d53361

History | View | Annotate | Download (5.78 KB)

1 0:02467299402e f
#pragma once
2
3
4
#include "cinder/app/App.h"
5
#include "cinder/gl/gl.h"
6
#include "cinder/gl/Batch.h"
7
8
9
#include "Chunk.h"
10
#include "DrawInfo.h"
11
12
#ifdef USE_PARTICLES
13
#include "ParticleController.h"
14
#endif
15
16
#include "cinder/Color.h"
17
#include "cinder/PolyLine.h"
18
#include "cinder/Rand.h"
19
20
#include <vector>
21
#include <map>
22
23
24
class DrawInfo;
25
typedef int SynthID;
26
27
28
using ci::ivec2;
29
using ci::vec2;
30
using ci::Color;
31
using ci::ColorA;
32
33 3:7fb593d53361 f
/**
34
 * A Cursor is the white thingy that loops through the selection when Collidoscope is played.
35
 */
36 0:02467299402e f
struct Cursor {
37
    static const int kNoPosition = -100;
38
    int pos;
39
    double lastUpdate;
40
};
41
42 3:7fb593d53361 f
/**
43
 * Collidoscope's graphical wave
44
 *
45
 */
46 0:02467299402e f
class Wave
47
{
48
        friend class ParticleController;
49
50
public:
51
52 3:7fb593d53361 f
    /**
53
     * The selection of the wave that is controlled by the big horizontal knob
54
     *
55
     */
56 0:02467299402e f
        class Selection {
57
58
        public:
59
60
        Selection( Wave * w, Color color );
61
62 3:7fb593d53361 f
        /** Sets the start of selection. start is the index of the first chunk of the selection  */
63 0:02467299402e f
        void setStart( size_t start );
64
65 3:7fb593d53361 f
        /** Sets the size of selection. size is the number of chunks the selection is made of */
66 0:02467299402e f
                void setSize( size_t size );
67
68 3:7fb593d53361 f
        /** Particle spread is used to calculate the size of the cloud of particles */
69 0:02467299402e f
        void inline setParticleSpread( float spread ){
70
            mParticleSpread = spread;
71
                }
72
73
                size_t getStart(void) const { return mSelectionStart; }
74
75
        size_t getEnd(void) const { return mSelectionEnd; }
76
77
                size_t inline getSize(void) const {
78
                        if (mNull)
79
                                return 0;
80
                        else
81
                                return 1 + mSelectionEnd - mSelectionStart;
82
                }
83
84
                float inline  getParticleSpread() const { return mParticleSpread; }
85
86 3:7fb593d53361 f
        /** When selection is null no selection is showed on the wave */
87 0:02467299402e f
                inline void setToNull(){
88
            mParticleSpread = 1.0f;
89
                        mNull = true;
90
                }
91
92
                inline bool isNull() const{
93
                        return mNull;
94
                }
95
96
                inline const Color & getColor() const{
97
                        return mColor;
98
                }
99
100
    private:
101
102
        size_t mSelectionStart;
103
104
        size_t mSelectionEnd;
105
106
        float mParticleSpread;
107
108
        bool mNull = true;
109
110
        Color mColor;
111
112
        Wave * mWave;
113
114
        }; // class Selection
115
116
117
118
#ifdef USE_PARTICLES
119
        ParticleController mParticleController;
120
#endif
121
122
123
124 3:7fb593d53361 f
        /* Maps id of the synth to cursor. There is one cursor for each Synth being played */
125 0:02467299402e f
        std::map < SynthID, Cursor > mCursors;
126 3:7fb593d53361 f
    /** Holds the positions of the cursor, namely on which chunk the cursor is currently */
127 0:02467299402e f
        std::vector<int> mCursorsPos;
128
129
public:
130
131 3:7fb593d53361 f
    // value used to identify the loop for cursor position
132 0:02467299402e f
    static const int kLoopNote = -1;
133
        static const cinder::Color CURSOR_CLR;
134
        /* must be in sync with supercollider durationFactor ControlSpec max */
135
        static const int MAX_DURATION = 8;
136
#ifdef USE_PARTICLES
137
        static const int PARTICLESIZE_COEFF = 40;
138
#endif
139
140 3:7fb593d53361 f
    /** Resetting a wave makes it shrink until it disappears. Each time a new sample is recorder the wave is reset
141
     *  \param onlyChunks if false the selection is also set to null, if true only the chunks are reset
142
     */
143 0:02467299402e f
        void reset(bool onlyChunks);
144
145 3:7fb593d53361 f
    /** sets top and bottom values for the chunk.
146
     * \a bottom and \a top are in audio coordinates [-1.0, 1.0]
147
     */
148 0:02467299402e f
        void setChunk(size_t index, float bottom, float top);
149
150
        const Chunk & getChunk(size_t index);
151
152 3:7fb593d53361 f
    /** places the cursor on the wave. Every cursor is associated to a synth voice of the audio engine.
153
     *  The synth id identifies uniquely the cursor in the internal map of the wave.
154
     *  If the cursor doesn't exist it is created */
155 0:02467299402e f
    inline void setCursorPos( SynthID id, int pos, const DrawInfo& di ){
156
157
            Cursor & cursor = mCursors[id];
158
            cursor.pos = pos;
159
            cursor.lastUpdate = ci::app::getElapsedSeconds();
160
161
#ifdef USE_PARTICLES
162 3:7fb593d53361 f
            // The idea is that, if the duration is greater than 1.0, the cursor continues in form of particles
163
            // The smaller the selection the more particles; the bigger the duration the more particles
164 0:02467299402e f
            if (mSelection.getParticleSpread() > 1.0f){
165
                    /* amountCoeff ranges from 1/8 to 1 */
166
            const float amountCoeff = (mSelection.getParticleSpread() / MAX_DURATION);
167
168
            /* get radom point within seleciton as center of the particle */
169
            vec2 centrePoint; // was former getRandomPoint
170
            const int randomChunkIndex = ci::Rand::randInt(mSelection.getStart(), mSelection.getEnd() );
171
172
            centrePoint.x = di.flipX( 1 + (randomChunkIndex * (2 + Chunk::kWidth)) + Chunk::kWidth / 2 );
173
            centrePoint.y = di.flipY( di.audioToHeigt(0.0) );
174
175
            const float wavePixelLen = mNumChunks * ( 2 + Chunk::kWidth);
176
                    centrePoint.x *= float(di.getWindowWidth()) / wavePixelLen;
177
178
                    mParticleController.addParticles(
179
                std::max( 1, (int)(amountCoeff * ParticleController::kMaxParticleAdd * mFilterCoeff) ), // amount of particles to add
180
                            centrePoint,
181
                mSelection.getParticleSpread() * PARTICLESIZE_COEFF   // size of the cloud
182
                            );
183
            }
184
#endif
185
186
187
        }
188
189
    void update( double secondsPerChunk, const DrawInfo& di );
190
191
    void removeCursor( SynthID id ) { mCursors.erase( id ); }
192
193 3:7fb593d53361 f
    /** Sets the transparency of this wave. \a alpha ranges from 0 to 1 */
194 0:02467299402e f
        inline void setselectionAlpha(float alpha){ mFilterCoeff = alpha;}
195
196
    void draw( const DrawInfo& di );
197
198
        Selection& getSelection() { return mSelection; };
199
200
        size_t getSize() const{ return mChunks.size();  }
201
202
        void setScopePoint(int index, float audioVal);
203
204
    Wave( size_t numChunks, Color selectionColor );
205
206 3:7fb593d53361 f
    /** no copies */
207 0:02467299402e f
    Wave( const Wave &copy ) = delete;
208
    Wave & operator=(const Wave &copy) = delete;
209
210
211
private:
212
213
    const size_t mNumChunks;
214
215
    std::vector<Chunk> mChunks;
216
217
    Selection mSelection;
218
219
    cinder::Color mColor;
220
221
    float mFilterCoeff;
222
223 3:7fb593d53361 f
    // cinder gl batch for batch drawing
224 0:02467299402e f
    ci::gl::BatchRef mChunkBatch;
225
226
};