annotate CollidoscopeApp/src/Wave.cpp @ 18:f1ff1a81be20 tip

Changed licenses names. Fixed one comment and usage text in CollidoscopeApp.cpp.
author Fiore Martin <f.martin@qmul.ac.uk>
date Thu, 25 Aug 2016 12:07:50 +0200
parents 4dad0b810f18
children
rev   line source
f@5 1 /*
f@5 2
f@5 3 Copyright (C) 2015 Fiore Martin
f@5 4 Copyright (C) 2016 Queen Mary University of London
f@5 5 Author: Fiore Martin
f@5 6
f@5 7 This file is part of Collidoscope.
f@5 8
f@5 9 Collidoscope is free software: you can redistribute it and/or modify
f@5 10 it under the terms of the GNU General Public License as published by
f@5 11 the Free Software Foundation, either version 3 of the License, or
f@5 12 (at your option) any later version.
f@5 13
f@5 14 This program is distributed in the hope that it will be useful,
f@5 15 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@5 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@5 17 GNU General Public License for more details.
f@5 18
f@5 19 You should have received a copy of the GNU General Public License
f@5 20 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@5 21
f@5 22 */
f@5 23
f@0 24 #include "Wave.h"
f@0 25 #include "DrawInfo.h"
f@0 26
f@0 27
f@0 28 using namespace ci;
f@0 29
f@0 30 Wave::Wave( size_t numChunks, Color selectionColor ):
f@0 31 mNumChunks( numChunks ),
f@5 32 mSelection( this, selectionColor ),
f@5 33 mColor(Color(0.5f, 0.5f, 0.5f)),
f@0 34 mFilterCoeff( 1.0f )
f@0 35 {
f@5 36 mChunks.reserve( numChunks );
f@0 37
f@5 38 for ( size_t i = 0; i < numChunks; i++ ){
f@5 39 mChunks.emplace_back( i );
f@5 40 }
f@0 41
f@4 42 // init cinder batch drawing
f@0 43 auto lambert = gl::ShaderDef().color();
f@0 44 gl::GlslProgRef shader = gl::getStockShader( lambert );
f@0 45 mChunkBatch = gl::Batch::create( geom::Rect( ci::Rectf( 0, 0, Chunk::kWidth, 1 ) ), shader );
f@0 46 }
f@0 47
f@0 48 void Wave::reset( bool onlyChunks )
f@0 49 {
f@5 50 for (size_t i = 0; i < getSize(); i++){
f@5 51 mChunks[i].reset();
f@5 52 }
f@0 53
f@5 54 if (onlyChunks)
f@5 55 return;
f@0 56
f@5 57 mSelection.setToNull();
f@0 58 }
f@0 59
f@0 60
f@0 61 void Wave::setChunk(size_t index, float bottom, float top)
f@0 62 {
f@5 63 Chunk &c = mChunks[index];
f@5 64 c.setTop(top);
f@5 65 c.setBottom(bottom);
f@0 66 }
f@0 67
f@0 68 inline const Chunk & Wave::getChunk(size_t index)
f@0 69 {
f@5 70 return mChunks[index];
f@0 71 }
f@0 72
f@0 73 void Wave::update( double secondsPerChunk, const DrawInfo& di ) {
f@0 74 typedef std::map<int, Cursor>::iterator MapItr;
f@0 75
f@0 76
f@0 77 // update the cursor positions
f@0 78 double now = ci::app::getElapsedSeconds();
f@0 79 for (MapItr itr = mCursors.begin(); itr != mCursors.end(); ++itr){
f@0 80 if (mSelection.isNull()){
f@0 81 itr->second.pos = Cursor::kNoPosition;
f@0 82 }
f@0 83
f@0 84 if ( itr->second.pos == Cursor::kNoPosition )
f@0 85 continue;
f@0 86
f@0 87
f@0 88 double elapsed = now - itr->second.lastUpdate;
f@0 89
f@16 90 // A chunk of audio corresponds to a certain time lenght of audio, according to sample rate.
f@16 91 // Use elapsed time to advance through chunks so that the cursor is animated.
f@16 92 // So it goes from start to end of the selection in the time span of the grain
f@0 93 itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk );
f@0 94
f@4 95 // check we don't go too far off
f@0 96 if (itr->second.pos > mSelection.getEnd()){
f@0 97 itr->second.pos = Cursor::kNoPosition;
f@0 98 }
f@0 99 }
f@0 100
f@0 101 // update chunks for animation
f@0 102 for ( auto &chunk : mChunks ){
f@0 103 chunk.update( di );
f@0 104 }
f@0 105
f@0 106 #ifdef USE_PARTICLES
f@0 107 mParticleController.updateParticles();
f@0 108 #endif
f@0 109
f@0 110 }
f@0 111
f@0 112 void Wave::draw( const DrawInfo& di ){
f@0 113
f@0 114
f@5 115 /* ########### draw the particles ########## */
f@0 116 #ifdef USE_PARTICLES
f@5 117 mParticleController.draw();
f@0 118 #endif
f@0 119
f@5 120 /* ########### draw the wave ########## */
f@5 121 /* scale the wave to fit the window */
f@5 122 gl::pushModelView();
f@0 123
f@5 124
f@5 125 const float wavePixelLen = ( mNumChunks * ( 2 + Chunk::kWidth ) );
f@5 126 /* scale the x-axis for the wave to fit the window precisely */
f@5 127 gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
f@5 128 /* draw the chunks */
f@5 129 if (mSelection.isNull()){
f@5 130 /* no selection: all chunks the same color */
f@5 131 gl::color(mColor);
f@5 132 for (size_t i = 0; i < getSize(); i++){
f@5 133 mChunks[i].draw( di, mChunkBatch );
f@5 134 }
f@5 135 }
f@0 136 else{
f@0 137 // Selection not null
f@5 138 gl::color(this->mColor);
f@0 139
f@0 140 // update the array with cursor positions
f@0 141 mCursorsPos.clear();
f@0 142 for ( auto cursor : mCursors ){
f@0 143 mCursorsPos.push_back( cursor.second.pos );
f@0 144 }
f@0 145
f@5 146 gl::enableAlphaBlending();
f@0 147
f@5 148 const float selectionAlpha = 0.5f + mFilterCoeff * 0.5f;
f@0 149
f@0 150
f@5 151 for (size_t i = 0; i < getSize(); i++){
f@5 152 /* when in selection use selection color */
f@5 153
f@5 154 if (i == mSelection.getStart()){
f@5 155 /* draw the selection bar with a transparent selection color */
f@5 156 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
f@0 157 mChunks[i].drawBar( di, mChunkBatch );
f@0 158
f@5 159 /* set the color to the selection */
f@5 160 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
f@5 161 }
f@0 162
f@16 163 // check if one of the cursors is positioned in this chunk, and draw it white if it is
f@5 164 if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
f@5 165 gl::color(CURSOR_CLR);
f@5 166 mChunks[i].draw( di, mChunkBatch );
f@5 167 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
f@5 168 }
f@5 169 else{
f@5 170 /* just draw with current color */
f@5 171 mChunks[i].draw( di, mChunkBatch );
f@5 172 }
f@5 173
f@5 174 /* exit selection: go back to wave color */
f@5 175 if (i == mSelection.getEnd()){
f@5 176 /* draw the selection bar with a transparent selection color */
f@5 177 gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
f@0 178 mChunks[i].drawBar( di, mChunkBatch );
f@16 179 /* set the color to the wave */
f@5 180 gl::color(this->mColor);
f@5 181 }
f@5 182 }
f@5 183 gl::disableAlphaBlending();
f@5 184 }
f@5 185
f@0 186
f@5 187 gl::popModelView();
f@0 188
f@0 189 }
f@0 190
f@0 191
f@0 192
f@0 193 //**************** Selection ***************//
f@0 194
f@0 195 Wave::Selection::Selection(Wave * w, Color color) :
f@0 196 mWave( w ),
f@0 197 mSelectionStart( 0 ),
f@0 198 mSelectionEnd( 0 ),
f@0 199 mColor( color ),
f@0 200 mParticleSpread( 1 )
f@0 201 {}
f@0 202
f@0 203
f@0 204 void Wave::Selection::setStart(size_t start) {
f@0 205
f@5 206 /* deselect the previous */
f@0 207 mWave->mChunks[mSelectionStart].setAsSelectionStart( false );
f@5 208 /* select the next */
f@0 209 mWave->mChunks[start].setAsSelectionStart( true );
f@5 210
f@5 211 mNull = false;
f@0 212
f@0 213 size_t size = getSize();
f@0 214
f@5 215 mSelectionStart = start;
f@0 216 mSelectionEnd = start + size - 1;
f@0 217 if ( mSelectionEnd > mWave->getSize() - 1 )
f@0 218 mSelectionEnd = mWave->getSize() - 1;
f@0 219
f@0 220 }
f@0 221
f@0 222 void Wave::Selection::setSize(size_t size) {
f@0 223
f@0 224 if ( size <= 0 ){
f@0 225 mNull = true;
f@0 226 return;
f@0 227 }
f@0 228
f@0 229 size -= 1;
f@0 230
f@0 231 // check boundaries: size cannot bring the selection end beyond the end of the wave
f@0 232 if ( mSelectionStart+size >= mWave->mNumChunks ){
f@0 233 size = mWave->mNumChunks - mSelectionStart - 1;
f@0 234 }
f@0 235
f@5 236 /* deselect the previous */
f@0 237 mWave->mChunks[mSelectionEnd].setAsSelectionEnd( false );
f@0 238
f@0 239 mSelectionEnd = mSelectionStart + size;
f@5 240 /* select the next */
f@0 241 mWave->mChunks[mSelectionEnd].setAsSelectionEnd( true );
f@0 242
f@5 243 mNull = false;
f@0 244 }
f@0 245
f@0 246
f@0 247 const cinder::Color Wave::CURSOR_CLR = Color(1.f, 1.f, 1.f);
f@0 248
f@0 249