Revision 0:02467299402e CollidoscopeApp/src

View differences:

CollidoscopeApp/src/AudioEngine.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
*/
22

  
23 1
#include "AudioEngine.h"
24
// app.h include not used 
25 2
#include "cinder/app/App.h"
3
//FIXME remove App.h include 
26 4
#include "Log.h"
27 5

  
28 6
using namespace ci::audio;
29 7

  
30
/* Frequency ratios in the chromatic scale */
31 8
double chromaticRatios[] = { 
32 9
    1, 
33 10
    1.0594630943591, 
......
43 20
    1.8877486253586 
44 21
};
45 22

  
46

  
47
/*
48
 * Calculates the ratio between the frequency of the midi note passed as argument and middle C note ( MIDI value = 60 ).
49
 * This is used for pitch shifting the granular synth output, according to the key pressed by the user.
50
 * The middle C is taken as reference in pitch in the pitch shifting of Collidoscope output.
51
 * That is, with the middle C the output is not pitch shifted at all and is equal in frequency to the recorder sample.
52
 *
53
 */ 
54 23
inline double calculateMidiNoteRatio( int midiNote )
55 24
{
56 25
    int distanceFromCenter = midiNote - 60; // 60 is the central midi note 
......
87 56
    /* audio context */
88 57
    auto ctx = Context::master();
89 58

  
90
    /* audio input device */
59
    /* audio inpu device */
91 60
    auto inputDeviceNode = ctx->createInputDeviceNode( Device::getDefaultInput() );
92 61
 
93 62

  
......
102 71
        /* this prevents the node from recording before record is pressed */
103 72
        mBufferRecorderNodes[chan]->setAutoEnabled( false );
104 73

  
105
        // route the input part of the audio graph. Two channels input goes into one channel route
106
        // and from one channel route to one channel buffer recorder 
74
        // route the input part of the audio graph. Two channels input goes into
75
        // one channel route and to one channel buffer recorder 
107 76
        inputDeviceNode >> mInputRouterNodes[chan]->route( chan, 0, 1 ) >> mBufferRecorderNodes[chan];
108 77

  
109 78

  
110 79
        // create PGranular loops passing the buffer of the RecorderNode as argument to the contructor 
111
        // use -1 as ID as the loop corresponds to no midi note 
80
        // use -1 as ID 
112 81
        mPGranularNodes[chan] = ctx->makeNode( new PGranularNode( mBufferRecorderNodes[chan]->getRecorderBuffer(), mCursorTriggerRingBufferPacks[chan]->getBuffer() ) );
113 82

  
114 83
        // create filter nodes 
......
126 95
        // filter goes to output 
127 96
        mLowPassFilterNodes[chan] >> mOutputRouterNodes[chan]->route( 0, chan, 1 ) >> ctx->getOutput();
128 97
        
129
        // what goes to output goes to oscilloscope as well
98
        // what goes to output goes to scope 
130 99
        mLowPassFilterNodes[chan] >> mOutputMonitorNodes[chan];
131 100

  
132 101
    }
......
205 174
    return mBufferRecorderNodes[waveIdx]->getRingBuffer().getAvailableRead();
206 175
}
207 176

  
208
 
209 177
bool AudioEngine::readRecordWave( size_t waveIdx, RecordWaveMsg* buffer, size_t count )
210 178
{
211 179
    return mBufferRecorderNodes[waveIdx]->getRingBuffer().read( buffer, count );
CollidoscopeApp/src/BufferToWaveRecorderNode.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

  
21
 This file incorporates work covered by the following copyright and permission notice: 
22

  
23
    Copyright (c) 2014, The Cinder Project
24

  
25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

  
27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

  
30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

  
35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

  
46 1
#include "BufferToWaveRecorderNode.h"
47 2
#include "cinder/audio/Context.h"
48 3
#include "cinder/audio/Target.h"
CollidoscopeApp/src/Chunk.cpp
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

  
25 1
#include "Chunk.h"
26 2
#include "DrawInfo.h"
27 3

  
......
44 20
void Chunk::update( const DrawInfo &di )
45 21
{
46 22
    using namespace ci;
47
    /* if resetting animate the chunks to nicely shrink to 0 size */
23
    /* if resetting animate the chunks to shrink to 0 size */
48 24
    if ( mResetting ){
49 25
        if ( mAnimate > 0.0f ){
50 26
            mAnimate -= 0.1f;
......
64 40
        }
65 41
    }
66 42

  
67
    mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME more efficient if it happens only once when resized 
43
    mX = di.flipX( 1 + (mIndex * (2 + kWidth)) ); // FIXME this should happen only once when resized 
68 44
}
69 45

  
70 46
void Chunk::draw( const DrawInfo& di, ci::gl::BatchRef &batch ){
71 47
    using namespace ci;
72
    
48
	
73 49
    gl::pushModelMatrix();
74 50

  
75 51
    const float chunkHeight = mAnimate * mAudioTop * di.getMaxChunkHeight();
76 52

  
77
    // place the chunk in the right position brings back the y of chunkHeight/2 so
53
    // place the chunk in the right position brigns back the y of chunkHeight/2 so
78 54
    // so that after scaling the wave is still centered at the wave center 
79 55
    gl::translate( mX, di.getWaveCenterY() - ( chunkHeight / 2 ) - 1 );
80 56

  
57
    // FIXME todo use max between top and bottom
81 58
    // scale according to audio amplitude 
82 59
    gl::scale( 1.0f, chunkHeight );
83 60
    batch->draw();
......
88 65

  
89 66

  
90 67
void Chunk::drawBar( const DrawInfo& di, ci::gl::BatchRef &batch ){
91
    using namespace ci;
68
	using namespace ci;
92 69

  
93 70
    gl::pushModelMatrix();
94 71

  
......
104 81

  
105 82

  
106 83
const float Chunk::kWidth = 7.0f;
107
const float Chunk::kHalfWidth = 3.5f;
84
const float Chunk::kHalfWidth = 3.5f;
CollidoscopeApp/src/CollidoscopeApp.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

  
22

  
23 1
#include "cinder/app/App.h"
24 2
#include "cinder/app/RendererGl.h"
25 3
#include "cinder/gl/gl.h"
26 4
#include "cinder/Exception.h"
27
#include <stdexcept>
28 5

  
29 6

  
30 7
#include "Config.h"
......
45 22
class CollidoscopeApp : public App {
46 23
  public:
47 24

  
48
    void setup() override;
25
	void setup() override;
49 26
    void setupGraphics();
50 27

  
51
    /** Receives MIDI command messages from MIDI thread */
52 28
    void receiveCommands();
53
    /** Prints command line usage */
54
    void usage();
55 29

  
56
    void keyDown( KeyEvent event ) override;
57
    void update() override;
58
    void draw() override;
30
	void keyDown( KeyEvent event ) override;
31
	void update() override;
32
	void draw() override;
59 33
    void resize() override;
60 34

  
61
    Config mConfig;
35
	Config mConfig;
62 36
    collidoscope::MIDI mMIDI;
63 37
    AudioEngine mAudioEngine;
64
    
38
	
65 39
    array< shared_ptr< Wave >, NUM_WAVES > mWaves;
66 40
    array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos;
67 41
    array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes;
68
    // buffer to read the WAVE_* messages as a new wave gets recorded 
42
    // buffers to read the wave messages as a new wave gets recorded 
69 43
    array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers;
70
    //buffer to read the TRIGGER_* messages as the pgranulars play
71 44
    array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers;
72 45

  
73 46
    double mSecondsPerChunk;
......
125 98
{
126 99
    char c = event.getChar();
127 100

  
128
    const size_t waveIdx = 0;
129

  
130 101
    switch (c){
131 102
    case 'r' : 
132
        mAudioEngine.record( waveIdx );
103
        mAudioEngine.record( 0 );
104
        mAudioEngine.record( 1 );
133 105
        break;
134 106

  
135 107
    case 'w': {
108
        mWaves[0]->getSelection().setSize(mWaves[0]->getSelection().getSize() + 1);
136 109

  
137
        mWaves[waveIdx]->getSelection().setSize(mWaves[waveIdx]->getSelection().getSize() + 1);
138

  
139
        size_t numSelectionChunks = mWaves[waveIdx]->getSelection().getSize();
110
        size_t numSelectionChunks = mWaves[0]->getSelection().getSize();
140 111
        // how many samples in one selection ?
141 112
        size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
142 113

  
143
        mAudioEngine.setSelectionSize(waveIdx, selectionSize);
114
        mAudioEngine.setSelectionSize(0, selectionSize);
115
    };
116
        break;
117

  
118
    case 'e': {
119
        mWaves[1]->getSelection().setSize(mWaves[1]->getSelection().getSize() + 1);
120

  
121
        size_t numSelectionChunks = mWaves[1]->getSelection().getSize();
122
        // how many samples in one selection ?
123
        size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
124

  
125
        mAudioEngine.setSelectionSize(1, selectionSize);
144 126
    };
145 127
        break;
146 128

  
147 129
    case 's': {
148 130

  
149
        mWaves[waveIdx]->getSelection().setSize( mWaves[waveIdx]->getSelection().getSize() - 1 );
131
        mWaves[0]->getSelection().setSize( mWaves[0]->getSelection().getSize() - 1 );
150 132

  
151
        size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
152
        mAudioEngine.setSelectionSize( waveIdx, selectionSize );
133
        size_t selectionSize = mWaves[0]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
134
        mAudioEngine.setSelectionSize( 0, selectionSize );
153 135
    };
154 136
        break;
155 137

  
156 138
    case 'd': {
157 139

  
158
        size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
159
        mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 );
140
        for( size_t waveIdx = 0; waveIdx < NUM_WAVES; waveIdx++){
141
            size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
142
            mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 );
160 143

  
161
        selectionStart = mWaves[waveIdx]->getSelection().getStart();
162
        mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
144
            selectionStart = mWaves[waveIdx]->getSelection().getStart();
145
            mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
146
        }
163 147
    };
164 148

  
165 149
        break;
166 150

  
167 151
    case 'a': {
168
        size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
152
        size_t selectionStart = mWaves[0]->getSelection().getStart();
169 153
        
170 154
        if ( selectionStart == 0 )
171 155
            return;
172 156

  
173
        mWaves[waveIdx]->getSelection().setStart( selectionStart - 1 );
157
        mWaves[0]->getSelection().setStart( selectionStart - 1 );
174 158

  
175
        selectionStart = mWaves[waveIdx]->getSelection().getStart();
159
        selectionStart = mWaves[0]->getSelection().getStart();
176 160

  
177
        mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
161
        mAudioEngine.setSelectionStart( 0, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
178 162
    };
179 163
        break;
180 164

  
165

  
166
    case 'p':
167

  
168
        mWaves[0]->setCursorPos(  4, mWaves[0]->getSelection().getStart(), *mDrawInfos[0] ) ;
169
        break;
170

  
181 171
    case 'f':
182 172
        setFullScreen( !isFullScreen() );
183 173
        break;
......
186 176
        static bool isOn = false;
187 177
        isOn = !isOn;
188 178
        if ( isOn ){
189
            mAudioEngine.loopOn( waveIdx );
179
            mAudioEngine.loopOn( 0 );
180
            mAudioEngine.loopOn( 1 );
190 181
        }
191 182
        else{
192
            mAudioEngine.loopOff( waveIdx );
183
            mAudioEngine.loopOff( 0 );
184
            mAudioEngine.loopOff( 1 );
193 185
        }
194 186
    };
195 187
        break;
196 188

  
189
	case 'm' :
190
		mAudioEngine.setGrainDurationCoeff(0, 8);
191
		break;
192

  
193
    case 'n': {
194
        mAudioEngine.setGrainDurationCoeff( 0, 1 );
195
    };
196
        break;
197

  
197 198
    case '9': {
198
        int c = mWaves[waveIdx]->getSelection().getParticleSpread();
199
        int c = mWaves[0]->getSelection().getParticleSpread();
199 200
        if ( c == 1 )
200 201
            return;
201 202
        else
202 203
            c -= 1;
203 204

  
204
        mAudioEngine.setGrainDurationCoeff( waveIdx, c );
205
        mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) );
206

  
205
        mAudioEngine.setGrainDurationCoeff( 0, c );
206
        mWaves[0]->getSelection().setParticleSpread( float( c ) );
207
        mAudioEngine.setGrainDurationCoeff( 1, c );
208
        mWaves[1]->getSelection().setParticleSpread( float( c ) );
207 209
    }; break;
208 210

  
209 211
    case '0': {
210
        int c = mWaves[waveIdx]->getSelection().getParticleSpread();
212
        int c = mWaves[0]->getSelection().getParticleSpread();
211 213
        if ( c == 8 )
212 214
            return;
213 215
        else
214 216
            c += 1;
215 217

  
216
        mAudioEngine.setGrainDurationCoeff( waveIdx, c );
217
        mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) );
218
        mAudioEngine.setGrainDurationCoeff( 0, c );
219
        mWaves[0]->getSelection().setParticleSpread( float( c ) );
218 220
    }; break;
221

  
219 222
    }
220 223

  
221 224
}
......
290 293

  
291 294
void CollidoscopeApp::draw()
292 295
{
293
    gl::clear( Color( 0, 0, 0 ) );
296
	gl::clear( Color( 0, 0, 0 ) );
294 297

  
295 298
    for ( int i = 0; i < NUM_WAVES; i++ ){
296 299
        if ( i == 1 ){
......
356 359
            value |= MSB;
357 360
            
358 361

  
359
            // value ranges from 0 to 149. check boundaries in case sensor gives bad values 
360
            if ( value > 149 ){ // FIXME can use wave.size() 
362
            // value ranges from 0 to 1050. check boundaries in case sensor gives bad values 
363
            if ( value > 149 ){ // FIXME pareametrizer 
361 364
                continue;
362 365
            }
363 366

  
......
385 388
                mWaves[waveIdx]->getSelection().setSize( numSelectionChunks );
386 389

  
387 390
                // how many samples in one selection ?
388
                size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
391
				size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
389 392
                mAudioEngine.setSelectionSize( waveIdx, selectionSize );
390 393

  
391 394
            };
......
443 446
    }
444 447
}
445 448

  
446

  
447 449
CINDER_APP( CollidoscopeApp, RendererGl, [] ( App::Settings *settings) {
448

  
449
    const std::vector< string > args = settings->getCommandLineArgs();
450

  
451
    int width = 0;
452
    int height = 0;
453

  
454
    try {
455
        if( args.size() != 3 )
456
            throw std::invalid_argument("");
457

  
458
        width  = std::stoi( args[1] );
459
        height = std::stoi( args[2] );
460

  
461
    }
462
    catch( std::invalid_argument & e ){
463
        console() << "Error: invalid arguments" << std::endl;
464
        console() << "Usage: ./CollidoscopeApp window_width window_height" << std::endl;  
465
        console() << "For example: ./CollidoscopeApp 1024 768 " << std::endl;  
466

  
467
        settings->setShouldQuit( true );
468
        return;
469
    }
470

  
471
    settings->setWindowSize( width, height );
472
    settings->setMultiTouchEnabled( false );
473
    settings->disableFrameRate();
450
        settings->setWindowSize( 1920, 1080 );
451
        settings->setMultiTouchEnabled( false );
452
        settings->disableFrameRate();
474 453

  
475 454
} )
CollidoscopeApp/src/Config.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

  
22 1
#include "Config.h"
23 2

  
24 3

  
......
38 17

  
39 18
}
40 19

  
41
// uses Cinder api to parse configuration in XML file 
20

  
42 21
void Config::loadFromFile( std::string&& path )
43 22
{
44 23
    try {
CollidoscopeApp/src/Log.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

  
22 1

  
23 2
#include "cinder/Log.h"
24 3

  
CollidoscopeApp/src/MIDI.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

  
22 1
#include "MIDI.h"
23 2
#include "Config.h"
24 3

  
......
152 131
    msg.mData2 = (numBytes == 3 ? (*rtMidiMessage)[2] : 0);
153 132

  
154 133
    return msg;
155
}
134
}
CollidoscopeApp/src/PGranularNode.cpp
1
/*
2

  
3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

  
6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

  
13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

  
18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21

  
22 1
#include "PGranularNode.h"
23 2

  
24 3
#include "cinder/audio/Context.h"
......
65 44
{
66 45
    mTempBuffer = std::make_shared< ci::audio::Buffer >( getFramesPerBlock() );
67 46

  
68
    mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to multiplied by 0.01 in the time domain 
47
    mRandomOffset.reset( new RandomGenerator( getSampleRate() / 100 ) ); // divided by 100 corresponds to times 0.01 in the time domain 
69 48

  
70 49
    /* create the PGranular object for looping */
71 50
    mPGranularLoop.reset( new collidoscope::PGranular<float, RandomGenerator, PGranularNode>( mGrainBuffer->getData(), mGrainBuffer->getNumFrames(), getSampleRate(), *mRandomOffset, *this, -1 ) );
......
80 59
void PGranularNode::process (ci::audio::Buffer *buffer )
81 60
{
82 61
    // only update PGranular if the atomic value has changed from the previous time
62

  
83 63
    const boost::optional<size_t> selectionSize = mSelectionSize.get();
84 64
    if ( selectionSize ){
85 65
        mPGranularLoop->setSelectionSize( *selectionSize );
......
132 112
    }
133 113
}
134 114

  
135
// Called back when new PGranular is triggered or turned off. Sends notification message to graphic thread.
136 115
void PGranularNode::operator()( char msgType, int ID ) {
137 116

  
138 117
    switch ( msgType ){
......
167 146
        }
168 147

  
169 148
        if ( !synthFound ){
170
            // then look for a free voice 
149
            // then look for a free synth 
171 150
            for ( int i = 0; i < kMaxVoices; i++ ){
172 151

  
173 152
                if ( mMidiNotes[i] == kNoMidiNote ){
CollidoscopeApp/src/ParticleController.cpp
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 1
#include "ParticleController.h"
25 2
#include "cinder/Rand.h"
26 3

  
......
33 10
mNumParticles( 0 )
34 11

  
35 12
{
36
    // uses Cinder (and OpenGL) drawing based on virtual buffer object
37
    // see ParticleSphereCPU example in Cinder library 
38
     
39 13
    mParticles.assign( kMaxParticles, Particle() );
40 14
    mParticlePositions.assign( kMaxParticles, vec2( -1, -1 ) );
41 15

  
......
46 20

  
47 21
    auto mesh = gl::VboMesh::create( mParticlePositions.size(), GL_POINTS, { { particleLayout, mParticleVbo } } );
48 22

  
49
    // creates glsl program to run the batch with 
50 23
#if ! defined( CINDER_GL_ES )
51 24
    auto glsl = gl::GlslProg::create( gl::GlslProg::Format()
52 25
        .vertex( CI_GLSL( 150,
......
97 70

  
98 71
void ParticleController::updateParticles()
99 72
{
100
    // update the positions of the particles and dispose them if they've reached their timespan
101 73
    for ( size_t i = 0; i < mNumParticles; i++ ){
102 74

  
103 75
        Particle &particle = mParticles[i];
......
123 95
        }
124 96
    }
125 97

  
126
    // Copy particle data onto the GPU.
127
	// Map the GPU memory and write over it.
128 98
    void *gpuMem = mParticleVbo->mapReplace();
129 99
    memcpy( gpuMem, mParticlePositions.data(), mParticlePositions.size() * sizeof( vec2 ) );
130 100
    mParticleVbo->unmap();
......
132 102

  
133 103
void ParticleController::addParticles(int amount, const vec2 &initialLocation, const float cloudSize)
134 104
{
135
    // reduce the particles linearly to the total number of particles already present 
136
    // the more particles aleary present the less particle are added
137 105
    int reduction = ci::lmap<int>(mNumParticles, 0, kMaxParticles, 0, kMaxParticleAdd);
138 106
    amount -= reduction;
139 107

  
140 108
    if ( mNumParticles + amount > kMaxParticles ){
141
		//a.k.a. return if reached kMaxParticles 
109
		//return;
142 110
        amount = kMaxParticles - mNumParticles;
143 111
	}
144 112

  
CollidoscopeApp/src/Wave.cpp
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 1
#include "Wave.h"
25 2
#include "DrawInfo.h"
26 3

  
......
29 6

  
30 7
Wave::Wave( size_t numChunks, Color selectionColor ):
31 8
    mNumChunks( numChunks ),
32
    mSelection( this, selectionColor ),
33
    mColor(Color(0.5f, 0.5f, 0.5f)),
9
	mSelection( this, selectionColor ),
10
	mColor(Color(0.5f, 0.5f, 0.5f)),
34 11
    mFilterCoeff( 1.0f )
35 12
{
36
    mChunks.reserve( numChunks );
13
	mChunks.reserve( numChunks );
37 14

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

  
42
    // init cinder batch drawing
43 19
    auto lambert = gl::ShaderDef().color();
44 20
    gl::GlslProgRef shader = gl::getStockShader( lambert );
45 21
    mChunkBatch = gl::Batch::create( geom::Rect( ci::Rectf( 0, 0, Chunk::kWidth, 1 ) ), shader );
......
47 23

  
48 24
void Wave::reset( bool onlyChunks )
49 25
{
50
    for (size_t i = 0; i < getSize(); i++){
51
        mChunks[i].reset();
52
    }
26
	for (size_t i = 0; i < getSize(); i++){
27
		mChunks[i].reset();
28
	}
53 29

  
54
    if (onlyChunks)
55
        return;
30
	if (onlyChunks)
31
		return;
56 32

  
57
    mSelection.setToNull();
33
	mSelection.setToNull();
58 34
}
59 35

  
60 36

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

  
68 44
inline const Chunk & Wave::getChunk(size_t index)
69 45
{
70
    return mChunks[index];
46
	return mChunks[index];
71 47
}
72 48

  
73 49
void Wave::update( double secondsPerChunk, const DrawInfo& di ) {
......
87 63

  
88 64
        double elapsed = now - itr->second.lastUpdate;
89 65

  
90
        // A chunk of audio corresponds to a certain time lenght of audio, according to sample rate.
91
        // Use elapsed time to advance through chunks so that the cursor is animated. 
92
        // So it goes from start to end of the selection in the time span of the grain 
93 66
        itr->second.pos = mSelection.getStart() + int( elapsed / secondsPerChunk );
94 67

  
95
        // check we don't go too far off 
68
        /* check we don't go too far off */
96 69
        if (itr->second.pos > mSelection.getEnd()){
97 70
            itr->second.pos = Cursor::kNoPosition;
98 71
        }
......
112 85
void Wave::draw( const DrawInfo& di ){
113 86

  
114 87

  
115
    /* ########### draw the particles ########## */
88
	/* ########### draw the particles ########## */
116 89
#ifdef USE_PARTICLES
117
    mParticleController.draw();
90
	mParticleController.draw();
118 91
#endif
119 92

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

  
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
    }
97
	
98
	const float wavePixelLen =  ( mNumChunks * ( 2 + Chunk::kWidth ) );
99
	/* scale the x-axis for the wave to fit the window */
100
	gl::scale( ((float)di.getWindowWidth() ) / wavePixelLen , 1.0f);
101
	/* draw the chunks */
102
	if (mSelection.isNull()){
103
		/* no selection: all chunks the same color */
104
		gl::color(mColor); 
105
		for (size_t i = 0; i < getSize(); i++){
106
			mChunks[i].draw( di, mChunkBatch );
107
		}
108
	}
136 109
    else{ 
137 110
        // Selection not null 
138
        gl::color(this->mColor); 
111
		gl::color(this->mColor); 
139 112

  
140 113
        // update the array with cursor positions 
141 114
        mCursorsPos.clear();
......
143 116
            mCursorsPos.push_back( cursor.second.pos );
144 117
        }
145 118

  
146
        gl::enableAlphaBlending();
119
		gl::enableAlphaBlending();
147 120

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

  
150 123

  
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);
124
		for (size_t i = 0; i < getSize(); i++){
125
			/* when in selection use selection color */
126
			
127
			if (i == mSelection.getStart()){
128
				/* draw the selection bar with a transparent selection color */
129
				gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
157 130
                mChunks[i].drawBar( di, mChunkBatch );
158 131

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

  
163
            // check if one of the cursors is positioned in this chunk, and draw it white if it is 
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);
136
            // check if one of the cursors is positioned in this chunk  
137
			if (std::find(mCursorsPos.begin(), mCursorsPos.end(),i) != mCursorsPos.end() ){
138
				gl::color(CURSOR_CLR);
139
				mChunks[i].draw( di, mChunkBatch );
140
				gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, selectionAlpha);
141
			}
142
			else{
143
				/* just draw with current color */
144
				mChunks[i].draw( di, mChunkBatch );
145
			}
146
			
147
			/* exit selection: go back to wave color */
148
			if (i == mSelection.getEnd()){
149
				/* draw the selection bar with a transparent selection color */
150
				gl::color(mSelection.getColor().r, mSelection.getColor().g, mSelection.getColor().b, 0.5f);
178 151
                mChunks[i].drawBar( di, mChunkBatch );
179
                /* set the color to the wave */
180
                gl::color(this->mColor);  
181
            }
182
        }
183
        gl::disableAlphaBlending();
184
    }
185
    
152
				/* set the colo to the wave */
153
				gl::color(this->mColor);  
154
			}
155
		}
156
		gl::disableAlphaBlending();
157
	}
158
	
186 159

  
187
    gl::popModelView();
160
	gl::popModelView();
188 161

  
189 162
}
190 163

  
......
203 176

  
204 177
void Wave::Selection::setStart(size_t start)  {
205 178

  
206
    /* deselect the previous */
179
	/* deselect the previous */
207 180
    mWave->mChunks[mSelectionStart].setAsSelectionStart( false );
208
    /* select the next */
181
	/* select the next */
209 182
    mWave->mChunks[start].setAsSelectionStart( true );
210
    
211
    mNull = false;
183
	
184
	mNull = false;
212 185

  
213 186
    size_t size = getSize();
214 187

  
215
    mSelectionStart = start;
188
	mSelectionStart = start;
216 189
    mSelectionEnd = start + size - 1;
217 190
    if ( mSelectionEnd > mWave->getSize() - 1 )
218 191
        mSelectionEnd = mWave->getSize() - 1;
......
233 206
        size = mWave->mNumChunks - mSelectionStart - 1;
234 207
    }
235 208

  
236
    /* deselect the previous */
209
	/* deselect the previous */
237 210
    mWave->mChunks[mSelectionEnd].setAsSelectionEnd( false );
238 211

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

  
243
    mNull = false;
216
	mNull = false;
244 217
}
245 218

  
246 219

  

Also available in: Unified diff