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 @ 9:20bb004a36de

History | View | Annotate | Download (6.9 KB)

1
/*
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
#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
    mSelection( this, selectionColor ),
33
    mColor(Color(0.5f, 0.5f, 0.5f)),
34
    mFilterCoeff( 1.0f )
35
{
36
    mChunks.reserve( numChunks );
37

    
38
    for ( size_t i = 0; i < numChunks; i++ ){
39
        mChunks.emplace_back( i );
40
    }
41

    
42
    // init cinder batch drawing
43
    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
    for (size_t i = 0; i < getSize(); i++){
51
        mChunks[i].reset();
52
    }
53

    
54
    if (onlyChunks)
55
        return;
56

    
57
    mSelection.setToNull();
58
}
59

    
60

    
61
void Wave::setChunk(size_t index, float bottom, float top)
62
{
63
    Chunk &c = mChunks[index];
64
    c.setTop(top);
65
    c.setBottom(bottom);
66
}
67

    
68
inline const Chunk & Wave::getChunk(size_t index)
69
{
70
    return mChunks[index];
71
}
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
        // 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
        itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk );
94

    
95
        // check we don't go too far off 
96
        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
    /* ########### draw the particles ########## */
116
#ifdef USE_PARTICLES
117
    mParticleController.draw();
118
#endif
119

    
120
    /* ########### draw the wave ########## */
121
    /* scale the wave to fit the window */
122
    gl::pushModelView(); 
123

    
124
    
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
    else{ 
137
        // Selection not null 
138
        gl::color(this->mColor); 
139

    
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
        gl::enableAlphaBlending();
147

    
148
        const float selectionAlpha = 0.5f + mFilterCoeff * 0.5f;
149

    
150

    
151
        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
                mChunks[i].drawBar( di, mChunkBatch );
158

    
159
                /* set the color to the selection */
160
                gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
161
            }
162

    
163
            // check if one of the cursors is positioned in this chunk  
164
            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
                mChunks[i].drawBar( di, mChunkBatch );
179
                /* set the colo to the wave */
180
                gl::color(this->mColor);  
181
            }
182
        }
183
        gl::disableAlphaBlending();
184
    }
185
    
186

    
187
    gl::popModelView();
188

    
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
    /* deselect the previous */
207
    mWave->mChunks[mSelectionStart].setAsSelectionStart( false );
208
    /* select the next */
209
    mWave->mChunks[start].setAsSelectionStart( true );
210
    
211
    mNull = false;
212

    
213
    size_t size = getSize();
214

    
215
    mSelectionStart = start;
216
    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
    /* deselect the previous */
237
    mWave->mChunks[mSelectionEnd].setAsSelectionEnd( false );
238

    
239
    mSelectionEnd = mSelectionStart + size;
240
    /* select the next */
241
    mWave->mChunks[mSelectionEnd].setAsSelectionEnd( true );
242

    
243
    mNull = false;
244
}
245

    
246

    
247
const cinder::Color Wave::CURSOR_CLR = Color(1.f, 1.f, 1.f);
248

    
249