f@5
|
1 /*
|
f@5
|
2
|
f@5
|
3 Copyright (C) 2016 Queen Mary University of London
|
f@5
|
4 Author: Fiore Martin
|
f@5
|
5
|
f@5
|
6 This file is part of Collidoscope.
|
f@5
|
7
|
f@5
|
8 Collidoscope is free software: you can redistribute it and/or modify
|
f@5
|
9 it under the terms of the GNU General Public License as published by
|
f@5
|
10 the Free Software Foundation, either version 3 of the License, or
|
f@5
|
11 (at your option) any later version.
|
f@5
|
12
|
f@5
|
13 This program is distributed in the hope that it will be useful,
|
f@5
|
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@5
|
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@5
|
16 GNU General Public License for more details.
|
f@5
|
17
|
f@5
|
18 You should have received a copy of the GNU General Public License
|
f@5
|
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@5
|
20 */
|
f@5
|
21
|
f@6
|
22
|
f@0
|
23 #include "cinder/app/App.h"
|
f@0
|
24 #include "cinder/app/RendererGl.h"
|
f@0
|
25 #include "cinder/gl/gl.h"
|
f@0
|
26 #include "cinder/Exception.h"
|
f@6
|
27 #include <stdexcept>
|
f@0
|
28
|
f@0
|
29
|
f@0
|
30 #include "Config.h"
|
f@0
|
31 #include "Wave.h"
|
f@0
|
32 #include "DrawInfo.h"
|
f@0
|
33 #include "Log.h"
|
f@0
|
34 #include "AudioEngine.h"
|
f@0
|
35 #include "Oscilloscope.h"
|
f@0
|
36 #include "Messages.h"
|
f@0
|
37 #include "MIDI.h"
|
f@0
|
38
|
f@0
|
39 using namespace ci;
|
f@0
|
40 using namespace ci::app;
|
f@0
|
41
|
f@0
|
42 using namespace std;
|
f@0
|
43
|
f@0
|
44
|
f@0
|
45 class CollidoscopeApp : public App {
|
f@0
|
46 public:
|
f@0
|
47
|
f@5
|
48 void setup() override;
|
f@0
|
49 void setupGraphics();
|
f@0
|
50
|
f@6
|
51 /** Receives MIDI command messages from MIDI thread */
|
f@0
|
52 void receiveCommands();
|
f@6
|
53 /** Prints command line usage */
|
f@6
|
54 void usage();
|
f@0
|
55
|
f@5
|
56 void keyDown( KeyEvent event ) override;
|
f@5
|
57 void update() override;
|
f@5
|
58 void draw() override;
|
f@0
|
59 void resize() override;
|
f@0
|
60
|
f@5
|
61 Config mConfig;
|
f@0
|
62 collidoscope::MIDI mMIDI;
|
f@0
|
63 AudioEngine mAudioEngine;
|
f@5
|
64
|
f@0
|
65 array< shared_ptr< Wave >, NUM_WAVES > mWaves;
|
f@0
|
66 array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos;
|
f@0
|
67 array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes;
|
f@0
|
68 // buffers to read the wave messages as a new wave gets recorded
|
f@0
|
69 array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers;
|
f@0
|
70 array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers;
|
f@0
|
71
|
f@0
|
72 double mSecondsPerChunk;
|
f@0
|
73
|
f@0
|
74 ~CollidoscopeApp();
|
f@0
|
75
|
f@0
|
76 };
|
f@0
|
77
|
f@0
|
78
|
f@0
|
79 void CollidoscopeApp::setup()
|
f@0
|
80 {
|
f@0
|
81 hideCursor();
|
f@0
|
82 /* setup is logged: setup steps and errors */
|
f@0
|
83
|
f@0
|
84 /*try {
|
f@0
|
85 mConfig.loadFromFile( "./collidoscope_config.xml" );
|
f@0
|
86 }
|
f@0
|
87 catch ( const Exception &e ){
|
f@0
|
88 logError( string("Exception loading config from file:") + e.what() );
|
f@0
|
89 }*/
|
f@0
|
90
|
f@0
|
91 // setup buffers to read messages from audio thread
|
f@0
|
92 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
93 mRecordWaveMessageBuffers[i] = new RecordWaveMsg[mConfig.getNumChunks()];
|
f@0
|
94 mCursorTriggerMessagesBuffers[i].reserve( mConfig.getCursorTriggerMessageBufSize() );
|
f@0
|
95 }
|
f@0
|
96
|
f@0
|
97 mAudioEngine.setup( mConfig );
|
f@0
|
98
|
f@0
|
99 setupGraphics();
|
f@0
|
100
|
f@0
|
101 mSecondsPerChunk = mConfig.getWaveLen() / mConfig.getNumChunks();
|
f@0
|
102
|
f@0
|
103 try {
|
f@0
|
104 mMIDI.setup( mConfig );
|
f@0
|
105 }
|
f@0
|
106 catch ( const collidoscope::MIDIException &e ){
|
f@0
|
107 logError( string( "Exception opening MIDI input device: " ) + e.getMessage() );
|
f@0
|
108 }
|
f@0
|
109
|
f@0
|
110 }
|
f@0
|
111
|
f@0
|
112 void CollidoscopeApp::setupGraphics()
|
f@0
|
113 {
|
f@0
|
114 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
115
|
f@0
|
116 mDrawInfos[i] = make_shared< DrawInfo >( i );
|
f@0
|
117 mWaves[i] = make_shared< Wave >(mConfig.getNumChunks(), mConfig.getWaveSelectionColor(i) );
|
f@0
|
118 mOscilloscopes[i] = make_shared< Oscilloscope >( mAudioEngine.getAudioOutputBuffer( i ).getNumFrames() / mConfig.getOscilloscopeNumPointsDivider() );
|
f@0
|
119
|
f@0
|
120 }
|
f@0
|
121 }
|
f@0
|
122
|
f@0
|
123 void CollidoscopeApp::keyDown( KeyEvent event )
|
f@0
|
124 {
|
f@0
|
125 char c = event.getChar();
|
f@0
|
126
|
f@0
|
127 switch (c){
|
f@0
|
128 case 'r' :
|
f@0
|
129 mAudioEngine.record( 0 );
|
f@0
|
130 break;
|
f@0
|
131
|
f@0
|
132 case 'w': {
|
f@6
|
133
|
f@0
|
134 mWaves[0]->getSelection().setSize(mWaves[0]->getSelection().getSize() + 1);
|
f@0
|
135
|
f@0
|
136 size_t numSelectionChunks = mWaves[0]->getSelection().getSize();
|
f@0
|
137 // how many samples in one selection ?
|
f@0
|
138 size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
139
|
f@0
|
140 mAudioEngine.setSelectionSize(0, selectionSize);
|
f@0
|
141 };
|
f@0
|
142 break;
|
f@0
|
143
|
f@0
|
144 case 'e': {
|
f@0
|
145 mWaves[1]->getSelection().setSize(mWaves[1]->getSelection().getSize() + 1);
|
f@0
|
146
|
f@0
|
147 size_t numSelectionChunks = mWaves[1]->getSelection().getSize();
|
f@0
|
148 // how many samples in one selection ?
|
f@0
|
149 size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
150
|
f@0
|
151 mAudioEngine.setSelectionSize(1, selectionSize);
|
f@0
|
152 };
|
f@0
|
153 break;
|
f@0
|
154
|
f@0
|
155 case 's': {
|
f@0
|
156
|
f@0
|
157 mWaves[0]->getSelection().setSize( mWaves[0]->getSelection().getSize() - 1 );
|
f@0
|
158
|
f@0
|
159 size_t selectionSize = mWaves[0]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
160 mAudioEngine.setSelectionSize( 0, selectionSize );
|
f@0
|
161 };
|
f@0
|
162 break;
|
f@0
|
163
|
f@0
|
164 case 'd': {
|
f@0
|
165
|
f@0
|
166 for( size_t waveIdx = 0; waveIdx < NUM_WAVES; waveIdx++){
|
f@0
|
167 size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@0
|
168 mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 );
|
f@0
|
169
|
f@0
|
170 selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@0
|
171 mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
172 }
|
f@0
|
173 };
|
f@0
|
174
|
f@0
|
175 break;
|
f@0
|
176
|
f@0
|
177 case 'a': {
|
f@0
|
178 size_t selectionStart = mWaves[0]->getSelection().getStart();
|
f@0
|
179
|
f@0
|
180 if ( selectionStart == 0 )
|
f@0
|
181 return;
|
f@0
|
182
|
f@0
|
183 mWaves[0]->getSelection().setStart( selectionStart - 1 );
|
f@0
|
184
|
f@0
|
185 selectionStart = mWaves[0]->getSelection().getStart();
|
f@0
|
186
|
f@0
|
187 mAudioEngine.setSelectionStart( 0, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
188 };
|
f@0
|
189 break;
|
f@0
|
190
|
f@0
|
191
|
f@0
|
192 case 'p':
|
f@0
|
193
|
f@0
|
194 mWaves[0]->setCursorPos( 4, mWaves[0]->getSelection().getStart(), *mDrawInfos[0] ) ;
|
f@0
|
195 break;
|
f@0
|
196
|
f@0
|
197 case 'f':
|
f@0
|
198 setFullScreen( !isFullScreen() );
|
f@0
|
199 break;
|
f@0
|
200
|
f@0
|
201 case ' ': {
|
f@0
|
202 static bool isOn = false;
|
f@0
|
203 isOn = !isOn;
|
f@0
|
204 if ( isOn ){
|
f@0
|
205 mAudioEngine.loopOn( 0 );
|
f@0
|
206 mAudioEngine.loopOn( 1 );
|
f@0
|
207 }
|
f@0
|
208 else{
|
f@0
|
209 mAudioEngine.loopOff( 0 );
|
f@0
|
210 mAudioEngine.loopOff( 1 );
|
f@0
|
211 }
|
f@0
|
212 };
|
f@0
|
213 break;
|
f@0
|
214
|
f@5
|
215 case 'm' :
|
f@5
|
216 mAudioEngine.setGrainDurationCoeff(0, 8);
|
f@5
|
217 break;
|
f@0
|
218
|
f@0
|
219 case 'n': {
|
f@0
|
220 mAudioEngine.setGrainDurationCoeff( 0, 1 );
|
f@0
|
221 };
|
f@0
|
222 break;
|
f@0
|
223
|
f@0
|
224 case '9': {
|
f@0
|
225 int c = mWaves[0]->getSelection().getParticleSpread();
|
f@0
|
226 if ( c == 1 )
|
f@0
|
227 return;
|
f@0
|
228 else
|
f@0
|
229 c -= 1;
|
f@0
|
230
|
f@0
|
231 mAudioEngine.setGrainDurationCoeff( 0, c );
|
f@0
|
232 mWaves[0]->getSelection().setParticleSpread( float( c ) );
|
f@0
|
233 mAudioEngine.setGrainDurationCoeff( 1, c );
|
f@0
|
234 mWaves[1]->getSelection().setParticleSpread( float( c ) );
|
f@0
|
235 }; break;
|
f@0
|
236
|
f@0
|
237 case '0': {
|
f@0
|
238 int c = mWaves[0]->getSelection().getParticleSpread();
|
f@0
|
239 if ( c == 8 )
|
f@0
|
240 return;
|
f@0
|
241 else
|
f@0
|
242 c += 1;
|
f@0
|
243
|
f@0
|
244 mAudioEngine.setGrainDurationCoeff( 0, c );
|
f@0
|
245 mWaves[0]->getSelection().setParticleSpread( float( c ) );
|
f@0
|
246 }; break;
|
f@0
|
247
|
f@0
|
248 }
|
f@0
|
249
|
f@0
|
250 }
|
f@0
|
251
|
f@0
|
252 void CollidoscopeApp::update()
|
f@0
|
253 {
|
f@0
|
254 // check incoming commands
|
f@0
|
255 receiveCommands();
|
f@0
|
256
|
f@0
|
257 // check new wave chunks from recorder buffer
|
f@0
|
258 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
259 size_t availableRead = mAudioEngine.getRecordWaveAvailable( i );
|
f@0
|
260 mAudioEngine.readRecordWave( i, mRecordWaveMessageBuffers[i], availableRead );
|
f@0
|
261
|
f@0
|
262 for ( size_t msgIndex = 0; msgIndex < availableRead; msgIndex++ ){
|
f@0
|
263 const RecordWaveMsg & msg = mRecordWaveMessageBuffers[i][msgIndex];
|
f@0
|
264
|
f@0
|
265 if ( msg.cmd == Command::WAVE_CHUNK ){
|
f@0
|
266 mWaves[i]->setChunk( msg.index, msg.arg1, msg.arg2 );
|
f@0
|
267 }
|
f@0
|
268 else if ( msg.cmd == Command::WAVE_START ){
|
f@0
|
269 mWaves[i]->reset( true ); // reset only chunks but leave selection
|
f@0
|
270 }
|
f@0
|
271
|
f@0
|
272 }
|
f@0
|
273 }
|
f@0
|
274
|
f@0
|
275 // check if new cursors have been triggered
|
f@0
|
276 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
277
|
f@0
|
278 mAudioEngine.checkCursorTriggers( i, mCursorTriggerMessagesBuffers[i] );
|
f@0
|
279 for ( auto & trigger : mCursorTriggerMessagesBuffers[i] ){
|
f@0
|
280 const int nodeID = trigger.synthID;
|
f@0
|
281
|
f@0
|
282 switch ( trigger.cmd ){
|
f@0
|
283
|
f@0
|
284 case Command::TRIGGER_UPDATE: {
|
f@0
|
285 mWaves[i]->setCursorPos( nodeID, mWaves[i]->getSelection().getStart(), *mDrawInfos[i] );
|
f@0
|
286 };
|
f@0
|
287 break;
|
f@0
|
288
|
f@0
|
289 case Command::TRIGGER_END: {
|
f@0
|
290 mWaves[i]->removeCursor( nodeID );
|
f@0
|
291 };
|
f@0
|
292 break;
|
f@0
|
293
|
f@0
|
294 }
|
f@0
|
295
|
f@0
|
296 }
|
f@0
|
297 mCursorTriggerMessagesBuffers[i].clear();
|
f@0
|
298 }
|
f@0
|
299
|
f@0
|
300 // update cursors
|
f@0
|
301 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
302 mWaves[i]->update( mSecondsPerChunk, *mDrawInfos[i] );
|
f@0
|
303 }
|
f@0
|
304
|
f@0
|
305 // update oscilloscope
|
f@0
|
306
|
f@0
|
307 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
308 const audio::Buffer &audioOutBuffer = mAudioEngine.getAudioOutputBuffer( i );
|
f@0
|
309 // one oscilloscope sample
|
f@0
|
310
|
f@0
|
311 for ( size_t j = 0; j < mOscilloscopes[i]->getNumPoints(); j++ ){
|
f@0
|
312 mOscilloscopes[i]->setPoint( j, audioOutBuffer.getData()[j], *mDrawInfos[i] );
|
f@0
|
313 }
|
f@0
|
314 }
|
f@0
|
315
|
f@0
|
316
|
f@0
|
317
|
f@0
|
318 }
|
f@0
|
319
|
f@0
|
320 void CollidoscopeApp::draw()
|
f@0
|
321 {
|
f@5
|
322 gl::clear( Color( 0, 0, 0 ) );
|
f@0
|
323
|
f@0
|
324 for ( int i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
325 if ( i == 1 ){
|
f@0
|
326 /* for the upper wave flip the x over the center of the screen which is
|
f@0
|
327 the composition of rotate on the y-axis and translate by -screenwidth*/
|
f@0
|
328 gl::pushModelMatrix();
|
f@0
|
329 gl::rotate( float(M_PI), ci::vec3( 0, 1, 0 ) );
|
f@0
|
330 gl::translate( float( -getWindowWidth() ), 0.0f );
|
f@0
|
331 mOscilloscopes[i]->draw();
|
f@0
|
332 mWaves[i]->draw( *mDrawInfos[i] );
|
f@0
|
333 gl::popModelMatrix();
|
f@0
|
334 }
|
f@0
|
335 else{
|
f@0
|
336
|
f@0
|
337 mOscilloscopes[i]->draw();
|
f@0
|
338 mWaves[i]->draw( *mDrawInfos[i] );
|
f@0
|
339 }
|
f@0
|
340 }
|
f@0
|
341 }
|
f@0
|
342
|
f@0
|
343 void CollidoscopeApp::resize()
|
f@0
|
344 {
|
f@0
|
345 App::resize();
|
f@0
|
346
|
f@0
|
347 for ( int i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
348 // reset the drawing information with the new windows size and same shrink factor
|
f@0
|
349 mDrawInfos[i]->reset( getWindow()->getBounds(), 3.0f / 5.0f );
|
f@0
|
350
|
f@0
|
351 /* reset the oscilloscope points to zero */
|
f@0
|
352 for ( int j = 0; j < mOscilloscopes[i]->getNumPoints(); j++ ){
|
f@0
|
353 mOscilloscopes[i]->setPoint(j, 0.0f, *mDrawInfos[i] );
|
f@0
|
354 }
|
f@0
|
355 }
|
f@0
|
356 }
|
f@0
|
357
|
f@0
|
358
|
f@0
|
359
|
f@0
|
360 void CollidoscopeApp::receiveCommands()
|
f@0
|
361 {
|
f@0
|
362 // check new midi messages
|
f@0
|
363 static std::vector<collidoscope::MIDIMessage> midiMessages;
|
f@0
|
364 mMIDI.checkMessages( midiMessages );
|
f@0
|
365
|
f@0
|
366
|
f@0
|
367 for ( auto &m : midiMessages ){
|
f@0
|
368
|
f@0
|
369 const size_t waveIdx = mConfig.getWaveForMIDIChannel( m.getChannel() );
|
f@0
|
370 if ( waveIdx >= NUM_WAVES )
|
f@0
|
371 continue;
|
f@0
|
372
|
f@0
|
373 if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eNoteOn ){
|
f@0
|
374 int midiNote = m.getData_1();
|
f@0
|
375 mAudioEngine.noteOn( waveIdx, midiNote );
|
f@0
|
376 }
|
f@0
|
377 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eNoteOff ){
|
f@0
|
378 int midiNote = m.getData_1();
|
f@0
|
379 mAudioEngine.noteOff( waveIdx, midiNote );
|
f@0
|
380 }
|
f@0
|
381 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::ePitchBend ){
|
f@0
|
382 const uint16_t MSB = m.getData_2() << 7;
|
f@0
|
383 uint16_t value = m.getData_1(); // LSB
|
f@0
|
384
|
f@0
|
385 value |= MSB;
|
f@0
|
386
|
f@0
|
387
|
f@0
|
388 // value ranges from 0 to 1050. check boundaries in case sensor gives bad values
|
f@0
|
389 if ( value > 149 ){ // FIXME pareametrizer
|
f@0
|
390 continue;
|
f@0
|
391 }
|
f@0
|
392
|
f@0
|
393 size_t startChunk = value;
|
f@0
|
394
|
f@0
|
395 const size_t selectionSizeBeforeStartUpdate = mWaves[waveIdx]->getSelection().getSize();
|
f@0
|
396 mWaves[waveIdx]->getSelection().setStart( startChunk );
|
f@0
|
397
|
f@0
|
398 mAudioEngine.setSelectionStart( waveIdx, startChunk * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
399
|
f@0
|
400 const size_t newSelectionSize = mWaves[waveIdx]->getSelection().getSize();
|
f@0
|
401 if ( selectionSizeBeforeStartUpdate != newSelectionSize ){
|
f@0
|
402 mAudioEngine.setSelectionSize( waveIdx, newSelectionSize * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
403 }
|
f@0
|
404
|
f@0
|
405
|
f@0
|
406 }
|
f@0
|
407 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eControlChange ){
|
f@0
|
408
|
f@0
|
409 switch ( m.getData_1() ){ //controller number
|
f@0
|
410 case 1: { // selection size
|
f@0
|
411 const size_t midiVal = m.getData_2();
|
f@0
|
412 size_t numSelectionChunks = ci::lmap<size_t>( midiVal, 0, 127, 1, mConfig.getMaxSelectionNumChunks() );
|
f@0
|
413
|
f@0
|
414 mWaves[waveIdx]->getSelection().setSize( numSelectionChunks );
|
f@0
|
415
|
f@0
|
416 // how many samples in one selection ?
|
f@5
|
417 size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
418 mAudioEngine.setSelectionSize( waveIdx, selectionSize );
|
f@0
|
419
|
f@0
|
420 };
|
f@0
|
421 break;
|
f@0
|
422
|
f@0
|
423 case 4: { // loop on off
|
f@0
|
424 unsigned char midiVal = m.getData_2();
|
f@0
|
425
|
f@0
|
426 if ( midiVal > 0 )
|
f@0
|
427 mAudioEngine.loopOn( waveIdx );
|
f@0
|
428 else
|
f@0
|
429 mAudioEngine.loopOff( waveIdx );
|
f@0
|
430 };
|
f@0
|
431 break;
|
f@0
|
432
|
f@0
|
433 case 5: // trigger record
|
f@0
|
434 mAudioEngine.record( waveIdx );
|
f@0
|
435 break;
|
f@0
|
436
|
f@0
|
437 case 2: { // duration
|
f@0
|
438 const double midiVal = m.getData_2(); // 0-127
|
f@0
|
439 const double coeff = ci::lmap<double>( midiVal, 0.0, 127, 1.0, mConfig.getMaxGrainDurationCoeff() );
|
f@0
|
440 mAudioEngine.setGrainDurationCoeff( waveIdx, coeff );
|
f@0
|
441 mWaves[waveIdx]->getSelection().setParticleSpread( float( coeff ) );
|
f@0
|
442 };
|
f@0
|
443 break;
|
f@0
|
444
|
f@0
|
445 case 7: { // filter
|
f@0
|
446 const double midiVal = m.getData_2(); // 0-127
|
f@0
|
447 const double minCutoff = mConfig.getMinFilterCutoffFreq();
|
f@0
|
448 const double maxCutoff = mConfig.getMaxFilterCutoffFreq();
|
f@0
|
449 const double cutoff = pow( maxCutoff / 200., midiVal / 127.0 ) * minCutoff;
|
f@0
|
450 mAudioEngine.setFilterCutoff( waveIdx, cutoff );
|
f@0
|
451 const float alpha = ci::lmap<double>( midiVal, 0.0f, 127.0f, 0.f, 1.f );
|
f@0
|
452 mWaves[waveIdx]->setselectionAlpha( alpha );
|
f@0
|
453 };
|
f@0
|
454 break;
|
f@0
|
455
|
f@0
|
456
|
f@0
|
457
|
f@0
|
458 }
|
f@0
|
459 }
|
f@0
|
460 }
|
f@0
|
461
|
f@0
|
462 midiMessages.clear();
|
f@0
|
463 }
|
f@0
|
464
|
f@0
|
465
|
f@0
|
466
|
f@0
|
467 CollidoscopeApp::~CollidoscopeApp()
|
f@0
|
468 {
|
f@0
|
469 for ( int chan = 0; chan < NUM_WAVES; chan++ ){
|
f@0
|
470 /* delete the array for wave messages from audio thread */
|
f@0
|
471 delete[] mRecordWaveMessageBuffers[chan];
|
f@0
|
472 }
|
f@0
|
473 }
|
f@0
|
474
|
f@6
|
475
|
f@0
|
476 CINDER_APP( CollidoscopeApp, RendererGl, [] ( App::Settings *settings) {
|
f@6
|
477
|
f@6
|
478 const std::vector< string > args = settings->getCommandLineArgs();
|
f@6
|
479
|
f@6
|
480 int width = 0;
|
f@6
|
481 int height = 0;
|
f@6
|
482
|
f@6
|
483 try {
|
f@6
|
484 if( args.size() != 3 )
|
f@6
|
485 throw std::invalid_argument("");
|
f@6
|
486
|
f@6
|
487 width = std::stoi( args[1] );
|
f@6
|
488 height = std::stoi( args[2] );
|
f@6
|
489
|
f@6
|
490 }
|
f@6
|
491 catch( std::invalid_argument & e ){
|
f@6
|
492 console() << "Error: invalid arguments" << std::endl;
|
f@6
|
493 console() << "Usage: ./Collidoscope window_width window_height" << std::endl;
|
f@6
|
494 console() << "For example: ./Collidoscope 1024 768 " << std::endl;
|
f@6
|
495
|
f@6
|
496 settings->setShouldQuit( true );
|
f@6
|
497 return;
|
f@6
|
498 }
|
f@6
|
499
|
f@6
|
500 settings->setWindowSize( width, height );
|
f@6
|
501 settings->setMultiTouchEnabled( false );
|
f@6
|
502 settings->disableFrameRate();
|
f@0
|
503
|
f@0
|
504 } )
|