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 @ 5:75b744078d66

History | View | Annotate | Download (6.83 KB)

1 5:75b744078d66 f
/*
2

3
 Copyright (C) 2015  Fiore Martin
4
 Copyright (C) 2016  Queen Mary University of London
5
 Author: Fiore Martin
6

7
 This file is part of Collidoscope.
8

9
 Collidoscope is free software: you can redistribute it and/or modify
10
 it under the terms of the GNU General Public License as published by
11
 the Free Software Foundation, either version 3 of the License, or
12
 (at your option) any later version.
13

14
 This program is distributed in the hope that it will be useful,
15
 but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 GNU General Public License for more details.
18

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

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