annotate CollidoscopeApp/src/Wave.cpp @ 4:ab6db404403a

commented JackDevice
author Fiore Martin <f.martin@qmul.ac.uk>
date Wed, 13 Jul 2016 12:31:37 +0200
parents 7fb593d53361
children 75b744078d66
rev   line source
f@0 1 #include "Wave.h"
f@0 2 #include "DrawInfo.h"
f@0 3
f@0 4
f@0 5 using namespace ci;
f@0 6
f@0 7 Wave::Wave( size_t numChunks, Color selectionColor ):
f@0 8 mNumChunks( numChunks ),
f@0 9 mSelection( this, selectionColor ),
f@0 10 mColor(Color(0.5f, 0.5f, 0.5f)),
f@0 11 mFilterCoeff( 1.0f )
f@0 12 {
f@0 13 mChunks.reserve( numChunks );
f@0 14
f@0 15 for ( size_t i = 0; i < numChunks; i++ ){
f@0 16 mChunks.emplace_back( i );
f@0 17 }
f@0 18
f@4 19 // init cinder batch drawing
f@0 20 auto lambert = gl::ShaderDef().color();
f@0 21 gl::GlslProgRef shader = gl::getStockShader( lambert );
f@0 22 mChunkBatch = gl::Batch::create( geom::Rect( ci::Rectf( 0, 0, Chunk::kWidth, 1 ) ), shader );
f@0 23 }
f@0 24
f@0 25 void Wave::reset( bool onlyChunks )
f@0 26 {
f@0 27 for (size_t i = 0; i < getSize(); i++){
f@0 28 mChunks[i].reset();
f@0 29 }
f@0 30
f@0 31 if (onlyChunks)
f@0 32 return;
f@0 33
f@0 34 mSelection.setToNull();
f@0 35 }
f@0 36
f@0 37
f@0 38 void Wave::setChunk(size_t index, float bottom, float top)
f@0 39 {
f@0 40 Chunk &c = mChunks[index];
f@0 41 c.setTop(top);
f@0 42 c.setBottom(bottom);
f@0 43 }
f@0 44
f@0 45 inline const Chunk & Wave::getChunk(size_t index)
f@0 46 {
f@0 47 return mChunks[index];
f@0 48 }
f@0 49
f@0 50 void Wave::update( double secondsPerChunk, const DrawInfo& di ) {
f@0 51 typedef std::map<int, Cursor>::iterator MapItr;
f@0 52
f@0 53
f@0 54 // update the cursor positions
f@0 55 double now = ci::app::getElapsedSeconds();
f@0 56 for (MapItr itr = mCursors.begin(); itr != mCursors.end(); ++itr){
f@0 57 if (mSelection.isNull()){
f@0 58 itr->second.pos = Cursor::kNoPosition;
f@0 59 }
f@0 60
f@0 61 if ( itr->second.pos == Cursor::kNoPosition )
f@0 62 continue;
f@0 63
f@0 64
f@0 65 double elapsed = now - itr->second.lastUpdate;
f@0 66
f@4 67 // A chunk of audio corresponds to a certain time according to sample rate.
f@4 68 // Use elapsed time to advance through chunks so that the cursor is animated
f@4 69 // and goes from start to end of the seleciton in the time span of the grain
f@0 70 itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk );
f@0 71
f@4 72 // check we don't go too far off
f@0 73 if (itr->second.pos > mSelection.getEnd()){
f@0 74 itr->second.pos = Cursor::kNoPosition;
f@0 75 }
f@0 76 }
f@0 77
f@0 78 // update chunks for animation
f@0 79 for ( auto &chunk : mChunks ){
f@0 80 chunk.update( di );
f@0 81 }
f@0 82
f@0 83 #ifdef USE_PARTICLES
f@0 84 mParticleController.updateParticles();
f@0 85 #endif
f@0 86
f@0 87 }
f@0 88
f@0 89 void Wave::draw( const DrawInfo& di ){
f@0 90
f@0 91
f@0 92 /* ########### draw the particles ########## */
f@0 93 #ifdef USE_PARTICLES
f@0 94 mParticleController.draw();
f@0 95 #endif
f@0 96
f@0 97 /* ########### draw the wave ########## */
f@0 98 /* scale the wave to fit the window */
f@0 99 gl::pushModelView();
f@0 100
f@0 101
f@0 102 const float wavePixelLen = ( mNumChunks * ( 2 + Chunk::kWidth ) );
f@3 103 /* scale the x-axis for the wave to fit the window precisely */
f@0 104 gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
f@0 105 /* draw the chunks */
f@0 106 if (mSelection.isNull()){
f@0 107 /* no selection: all chunks the same color */
f@0 108 gl::color(mColor);
f@0 109 for (size_t i = 0; i < getSize(); i++){
f@0 110 mChunks[i].draw( di, mChunkBatch );
f@0 111 }
f@0 112 }
f@0 113 else{
f@0 114 // Selection not null
f@0 115 gl::color(this->mColor);
f@0 116
f@0 117 // update the array with cursor positions
f@0 118 mCursorsPos.clear();
f@0 119 for ( auto cursor : mCursors ){
f@0 120 mCursorsPos.push_back( cursor.second.pos );
f@0 121 }
f@0 122
f@0 123 gl::enableAlphaBlending();
f@0 124
f@0 125 const float selectionAlpha = 0.5f + mFilterCoeff * 0.5f;
f@0 126
f@0 127
f@0 128 for (size_t i = 0; i < getSize(); i++){
f@0 129 /* when in selection use selection color */
f@0 130
f@0 131 if (i == mSelection.getStart()){
f@0 132 /* draw the selection bar with a transparent selection color */
f@0 133 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
f@0 134 mChunks[i].drawBar( di, mChunkBatch );
f@0 135
f@0 136 /* set the color to the selection */
f@0 137 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
f@0 138 }
f@0 139
f@0 140 // check if one of the cursors is positioned in this chunk
f@0 141 if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
f@0 142 gl::color(CURSOR_CLR);
f@0 143 mChunks[i].draw( di, mChunkBatch );
f@0 144 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
f@0 145 }
f@0 146 else{
f@0 147 /* just draw with current color */
f@0 148 mChunks[i].draw( di, mChunkBatch );
f@0 149 }
f@0 150
f@0 151 /* exit selection: go back to wave color */
f@0 152 if (i == mSelection.getEnd()){
f@0 153 /* draw the selection bar with a transparent selection color */
f@0 154 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
f@0 155 mChunks[i].drawBar( di, mChunkBatch );
f@0 156 /* set the colo to the wave */
f@0 157 gl::color(this->mColor);
f@0 158 }
f@0 159 }
f@0 160 gl::disableAlphaBlending();
f@0 161 }
f@0 162
f@0 163
f@0 164 gl::popModelView();
f@0 165
f@0 166 }
f@0 167
f@0 168
f@0 169
f@0 170 //**************** Selection ***************//
f@0 171
f@0 172 Wave::Selection::Selection(Wave * w, Color color) :
f@0 173 mWave( w ),
f@0 174 mSelectionStart( 0 ),
f@0 175 mSelectionEnd( 0 ),
f@0 176 mColor( color ),
f@0 177 mParticleSpread( 1 )
f@0 178 {}
f@0 179
f@0 180
f@0 181 void Wave::Selection::setStart(size_t start) {
f@0 182
f@0 183 /* deselect the previous */
f@0 184 mWave->mChunks[mSelectionStart].setAsSelectionStart( false );
f@0 185 /* select the next */
f@0 186 mWave->mChunks[start].setAsSelectionStart( true );
f@0 187
f@0 188 mNull = false;
f@0 189
f@0 190 size_t size = getSize();
f@0 191
f@0 192 mSelectionStart = start;
f@0 193 mSelectionEnd = start + size - 1;
f@0 194 if ( mSelectionEnd > mWave->getSize() - 1 )
f@0 195 mSelectionEnd = mWave->getSize() - 1;
f@0 196
f@0 197 }
f@0 198
f@0 199 void Wave::Selection::setSize(size_t size) {
f@0 200
f@0 201 if ( size <= 0 ){
f@0 202 mNull = true;
f@0 203 return;
f@0 204 }
f@0 205
f@0 206 size -= 1;
f@0 207
f@0 208 // check boundaries: size cannot bring the selection end beyond the end of the wave
f@0 209 if ( mSelectionStart+size >= mWave->mNumChunks ){
f@0 210 size = mWave->mNumChunks - mSelectionStart - 1;
f@0 211 }
f@0 212
f@0 213 /* deselect the previous */
f@0 214 mWave->mChunks[mSelectionEnd].setAsSelectionEnd( false );
f@0 215
f@0 216 mSelectionEnd = mSelectionStart + size;
f@0 217 /* select the next */
f@0 218 mWave->mChunks[mSelectionEnd].setAsSelectionEnd( true );
f@0 219
f@0 220 mNull = false;
f@0 221 }
f@0 222
f@0 223
f@0 224 const cinder::Color Wave::CURSOR_CLR = Color(1.f, 1.f, 1.f);
f@0 225
f@0 226