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