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 / src / Wave.cpp @ 5:75b744078d66

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