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

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