Changeset 2481
- Timestamp:
- 04/02/12 20:17:01 (14 months ago)
- Location:
- trunk
- Files:
-
- 12 modified
-
src/core/include/hydrogen/event_queue.h (modified) (3 diffs)
-
src/core/src/hydrogen.cpp (modified) (89 diffs)
-
src/core/src/midi_action.cpp (modified) (2 diffs)
-
src/gui/src/EventListener.h (modified) (1 diff)
-
src/gui/src/HydrogenApp.cpp (modified) (4 diffs)
-
src/gui/src/MainForm.cpp (modified) (1 diff)
-
src/gui/src/MainForm.h (modified) (1 diff)
-
src/gui/src/PatternEditor/DrumPatternEditor.cpp (modified) (4 diffs)
-
src/gui/src/PatternEditor/DrumPatternEditor.h (modified) (1 diff)
-
src/gui/src/PatternEditor/PianoRollEditor.cpp (modified) (1 diff)
-
src/gui/src/UndoActions.h (modified) (6 diffs)
-
todo_undo_implementation (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/core/include/hydrogen/event_queue.h
r2348 r2481 25 25 26 26 #include <hydrogen/object.h> 27 #include <hydrogen/basics/note.h> 27 28 #include <cassert> 28 29 … … 47 48 EVENT_PROGRESS, 48 49 EVENT_JACK_SESSION, 49 EVENT_PLAYLIST_LOADSONG 50 EVENT_PLAYLIST_LOADSONG, 51 EVENT_UNDO_REDO 50 52 }; 51 53 … … 72 74 Event pop_event(); 73 75 76 struct AddMidiNoteVector 77 { 78 int m_column; //position 79 int m_row; //instrument row 80 int m_pattern; // pattern number 81 int m_length; 82 float f_velocity; 83 float f_pan_L; 84 float f_pan_R; 85 Note::Key nk_noteKeyVal; 86 Note::Octave no_octaveKeyVal; 87 bool b_isMidi; 88 bool b_isInstrumentMode; 89 bool b_noteExist; 90 }; 91 std::vector<AddMidiNoteVector> m_addMidiNoteVector; 92 74 93 private: 75 94 EventQueue(); -
trunk/src/core/src/hydrogen.cpp
r2480 r2481 120 120 AudioOutput *m_pAudioDriver = NULL; ///< Audio output 121 121 QMutex mutex_OutputPointer; ///< Mutex for audio output pointer, allows multiple readers 122 ///< When locking this AND AudioEngine, always lock AudioEngine first.122 ///< When locking this AND AudioEngine, always lock AudioEngine first. 123 123 MidiInput *m_pMidiDriver = NULL; ///< MIDI input 124 124 MidiOutput *m_pMidiDriverOut = NULL; ///< MIDI output … … 126 126 // overload the the > operator of Note objects for priority_queue 127 127 struct compare_pNotes { 128 bool operator() (Note* pNote1, Note* pNote2) {129 return (pNote1->get_humanize_delay()130 + pNote1->get_position() * m_pAudioDriver->m_transport.m_nTickSize)131 >132 (pNote2->get_humanize_delay()133 + pNote2->get_position() * m_pAudioDriver->m_transport.m_nTickSize);134 }128 bool operator() (Note* pNote1, Note* pNote2) { 129 return (pNote1->get_humanize_delay() 130 + pNote1->get_position() * m_pAudioDriver->m_transport.m_nTickSize) 131 > 132 (pNote2->get_humanize_delay() 133 + pNote2->get_position() * m_pAudioDriver->m_transport.m_nTickSize); 134 } 135 135 }; 136 136 137 /// Song Note FIFO137 /// Song Note FIFO 138 138 std::priority_queue<Note*, std::deque<Note*>, compare_pNotes > m_songNoteQueue; 139 139 std::deque<Note*> m_midiNoteQueue; ///< Midi Note FIFO … … 142 142 PatternList* m_pNextPatterns; ///< Next pattern (used only in Pattern mode) 143 143 bool m_bAppendNextPattern; ///< Add the next pattern to the list instead 144 /// of replace.144 /// of replace. 145 145 bool m_bDeleteNextPattern; ///< Delete the next pattern from the list. 146 146 … … 219 219 inline timeval currentTime2() 220 220 { 221 struct timeval now;222 gettimeofday( &now, NULL );223 return now;221 struct timeval now; 222 gettimeofday( &now, NULL ); 223 return now; 224 224 } 225 225 … … 228 228 inline int randomValue( int max ) 229 229 { 230 return rand() % max;230 return rand() % max; 231 231 } 232 232 … … 234 234 inline float getGaussian( float z ) 235 235 { 236 // gaussian distribution -- dimss237 float x1, x2, w;238 do {239 x1 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0;240 x2 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0;241 w = x1 * x1 + x2 * x2;242 } while ( w >= 1.0 );243 244 w = sqrtf( ( -2.0 * logf( w ) ) / w );245 return x1 * w * z + 0.0; // tunable236 // gaussian distribution -- dimss 237 float x1, x2, w; 238 do { 239 x1 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0; 240 x2 = 2.0 * ( ( ( float ) rand() ) / RAND_MAX ) - 1.0; 241 w = x1 * x1 + x2 * x2; 242 } while ( w >= 1.0 ); 243 244 w = sqrtf( ( -2.0 * logf( w ) ) / w ); 245 return x1 * w * z + 0.0; // tunable 246 246 } 247 247 … … 250 250 void audioEngine_raiseError( unsigned nErrorCode ) 251 251 { 252 EventQueue::get_instance()->push_event( EVENT_ERROR, nErrorCode );252 EventQueue::get_instance()->push_event( EVENT_ERROR, nErrorCode ); 253 253 } 254 254 … … 257 257 void updateTickSize() 258 258 { 259 float sampleRate = ( float )m_pAudioDriver->getSampleRate();260 m_pAudioDriver->m_transport.m_nTickSize =261 ( sampleRate * 60.0 / m_pSong->__bpm / m_pSong->__resolution );259 float sampleRate = ( float )m_pAudioDriver->getSampleRate(); 260 m_pAudioDriver->m_transport.m_nTickSize = 261 ( sampleRate * 60.0 / m_pSong->__bpm / m_pSong->__resolution ); 262 262 } 263 263 … … 266 266 void audioEngine_init() 267 267 { 268 ___INFOLOG( "*** Hydrogen audio engine init ***" );269 270 // check current state271 if ( m_audioEngineState != STATE_UNINITIALIZED ) {272 ___ERRORLOG( "Error the audio engine is not in UNINITIALIZED state" );273 AudioEngine::get_instance()->unlock();274 return;275 }276 277 m_pSong = NULL;278 m_pPlayingPatterns = new PatternList();279 m_pNextPatterns = new PatternList();280 m_nSongPos = -1;281 m_nSelectedPatternNumber = 0;282 m_nSelectedInstrumentNumber = 0;283 m_nPatternTickPosition = 0;284 m_pMetronomeInstrument = NULL;285 m_pAudioDriver = NULL;286 287 m_pMainBuffer_L = NULL;288 m_pMainBuffer_R = NULL;289 290 srand( time( NULL ) );291 292 // Create metronome instrument293 QString sMetronomeFilename = Filesystem::click_file();294 m_pMetronomeInstrument =295 new Instrument( METRONOME_INSTR_ID, "metronome" );296 m_pMetronomeInstrument->set_layer(297 new InstrumentLayer( Sample::load( sMetronomeFilename ) ),298 0299 );300 301 // Change the current audio engine state302 m_audioEngineState = STATE_INITIALIZED;268 ___INFOLOG( "*** Hydrogen audio engine init ***" ); 269 270 // check current state 271 if ( m_audioEngineState != STATE_UNINITIALIZED ) { 272 ___ERRORLOG( "Error the audio engine is not in UNINITIALIZED state" ); 273 AudioEngine::get_instance()->unlock(); 274 return; 275 } 276 277 m_pSong = NULL; 278 m_pPlayingPatterns = new PatternList(); 279 m_pNextPatterns = new PatternList(); 280 m_nSongPos = -1; 281 m_nSelectedPatternNumber = 0; 282 m_nSelectedInstrumentNumber = 0; 283 m_nPatternTickPosition = 0; 284 m_pMetronomeInstrument = NULL; 285 m_pAudioDriver = NULL; 286 287 m_pMainBuffer_L = NULL; 288 m_pMainBuffer_R = NULL; 289 290 srand( time( NULL ) ); 291 292 // Create metronome instrument 293 QString sMetronomeFilename = Filesystem::click_file(); 294 m_pMetronomeInstrument = 295 new Instrument( METRONOME_INSTR_ID, "metronome" ); 296 m_pMetronomeInstrument->set_layer( 297 new InstrumentLayer( Sample::load( sMetronomeFilename ) ), 298 0 299 ); 300 301 // Change the current audio engine state 302 m_audioEngineState = STATE_INITIALIZED; 303 303 304 304 #ifdef H2CORE_HAVE_LADSPA 305 Effects::create_instance();305 Effects::create_instance(); 306 306 #endif 307 AudioEngine::create_instance();308 Playlist::create_instance();309 310 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED );307 AudioEngine::create_instance(); 308 Playlist::create_instance(); 309 310 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED ); 311 311 312 312 } … … 316 316 void audioEngine_destroy() 317 317 { 318 // check current state319 if ( m_audioEngineState != STATE_INITIALIZED ) {320 ___ERRORLOG( "Error the audio engine is not in INITIALIZED state" );321 return;322 }323 AudioEngine::get_instance()->get_sampler()->stop_playing_notes();324 325 AudioEngine::get_instance()->lock( RIGHT_HERE );326 ___INFOLOG( "*** Hydrogen audio engine shutdown ***" );327 328 // delete all copied notes in the song notes queue329 while ( !m_songNoteQueue.empty() ) {330 m_songNoteQueue.top()->get_instrument()->dequeue();331 delete m_songNoteQueue.top();332 m_songNoteQueue.pop();333 }334 // delete all copied notes in the midi notes queue335 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) {336 Note *note = m_midiNoteQueue[i];337 delete note;338 note = NULL;339 }340 m_midiNoteQueue.clear();341 342 // change the current audio engine state343 m_audioEngineState = STATE_UNINITIALIZED;344 345 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_UNINITIALIZED );346 347 delete m_pPlayingPatterns;348 m_pPlayingPatterns = NULL;349 350 delete m_pNextPatterns;351 m_pNextPatterns = NULL;352 353 delete m_pMetronomeInstrument;354 m_pMetronomeInstrument = NULL;355 356 AudioEngine::get_instance()->unlock();318 // check current state 319 if ( m_audioEngineState != STATE_INITIALIZED ) { 320 ___ERRORLOG( "Error the audio engine is not in INITIALIZED state" ); 321 return; 322 } 323 AudioEngine::get_instance()->get_sampler()->stop_playing_notes(); 324 325 AudioEngine::get_instance()->lock( RIGHT_HERE ); 326 ___INFOLOG( "*** Hydrogen audio engine shutdown ***" ); 327 328 // delete all copied notes in the song notes queue 329 while ( !m_songNoteQueue.empty() ) { 330 m_songNoteQueue.top()->get_instrument()->dequeue(); 331 delete m_songNoteQueue.top(); 332 m_songNoteQueue.pop(); 333 } 334 // delete all copied notes in the midi notes queue 335 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) { 336 Note *note = m_midiNoteQueue[i]; 337 delete note; 338 note = NULL; 339 } 340 m_midiNoteQueue.clear(); 341 342 // change the current audio engine state 343 m_audioEngineState = STATE_UNINITIALIZED; 344 345 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_UNINITIALIZED ); 346 347 delete m_pPlayingPatterns; 348 m_pPlayingPatterns = NULL; 349 350 delete m_pNextPatterns; 351 m_pNextPatterns = NULL; 352 353 delete m_pMetronomeInstrument; 354 m_pMetronomeInstrument = NULL; 355 356 AudioEngine::get_instance()->unlock(); 357 357 } 358 358 … … 367 367 int audioEngine_start( bool bLockEngine, unsigned nTotalFrames ) 368 368 { 369 if ( bLockEngine ) {370 AudioEngine::get_instance()->lock( RIGHT_HERE );371 }372 373 ___INFOLOG( "[audioEngine_start]" );374 375 // check current state376 if ( m_audioEngineState != STATE_READY ) {377 ___ERRORLOG( "Error the audio engine is not in READY state" );378 if ( bLockEngine ) {379 AudioEngine::get_instance()->unlock();380 }381 return 0; // FIXME!!382 }383 384 m_fMasterPeak_L = 0.0f;385 m_fMasterPeak_R = 0.0f;386 m_pAudioDriver->m_transport.m_nFrames = nTotalFrames; // reset total frames387 m_nSongPos = -1;388 m_nPatternStartTick = -1;389 m_nPatternTickPosition = 0;390 391 // prepare the tickSize for this song392 updateTickSize();393 394 // change the current audio engine state395 m_audioEngineState = STATE_PLAYING;396 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PLAYING );397 398 if ( bLockEngine ) {399 AudioEngine::get_instance()->unlock();400 }401 return 0; // per ora restituisco sempre OK369 if ( bLockEngine ) { 370 AudioEngine::get_instance()->lock( RIGHT_HERE ); 371 } 372 373 ___INFOLOG( "[audioEngine_start]" ); 374 375 // check current state 376 if ( m_audioEngineState != STATE_READY ) { 377 ___ERRORLOG( "Error the audio engine is not in READY state" ); 378 if ( bLockEngine ) { 379 AudioEngine::get_instance()->unlock(); 380 } 381 return 0; // FIXME!! 382 } 383 384 m_fMasterPeak_L = 0.0f; 385 m_fMasterPeak_R = 0.0f; 386 m_pAudioDriver->m_transport.m_nFrames = nTotalFrames; // reset total frames 387 m_nSongPos = -1; 388 m_nPatternStartTick = -1; 389 m_nPatternTickPosition = 0; 390 391 // prepare the tickSize for this song 392 updateTickSize(); 393 394 // change the current audio engine state 395 m_audioEngineState = STATE_PLAYING; 396 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PLAYING ); 397 398 if ( bLockEngine ) { 399 AudioEngine::get_instance()->unlock(); 400 } 401 return 0; // per ora restituisco sempre OK 402 402 } 403 403 … … 407 407 void audioEngine_stop( bool bLockEngine ) 408 408 { 409 if ( bLockEngine ) {410 AudioEngine::get_instance()->lock( RIGHT_HERE );411 }412 ___INFOLOG( "[audioEngine_stop]" );413 414 // check current state415 if ( m_audioEngineState != STATE_PLAYING ) {416 ___ERRORLOG( "Error the audio engine is not in PLAYING state" );417 if ( bLockEngine ) {418 AudioEngine::get_instance()->unlock();419 }420 return;421 }422 423 // change the current audio engine state424 m_audioEngineState = STATE_READY;425 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );426 427 m_fMasterPeak_L = 0.0f;428 m_fMasterPeak_R = 0.0f;429 // m_nPatternTickPosition = 0;430 m_nPatternStartTick = -1;431 432 // delete all copied notes in the song notes queue433 while(!m_songNoteQueue.empty()){434 m_songNoteQueue.top()->get_instrument()->dequeue();435 delete m_songNoteQueue.top();436 m_songNoteQueue.pop();437 }438 /* // delete all copied notes in the playing notes queue439 for (unsigned i = 0; i < m_playingNotesQueue.size(); ++i) {440 Note *note = m_playingNotesQueue[i];441 delete note;442 }443 m_playingNotesQueue.clear();444 */445 446 // delete all copied notes in the midi notes queue447 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) {448 Note *note = m_midiNoteQueue[i];449 delete note;450 }451 m_midiNoteQueue.clear();452 453 if ( bLockEngine ) {454 AudioEngine::get_instance()->unlock();455 }409 if ( bLockEngine ) { 410 AudioEngine::get_instance()->lock( RIGHT_HERE ); 411 } 412 ___INFOLOG( "[audioEngine_stop]" ); 413 414 // check current state 415 if ( m_audioEngineState != STATE_PLAYING ) { 416 ___ERRORLOG( "Error the audio engine is not in PLAYING state" ); 417 if ( bLockEngine ) { 418 AudioEngine::get_instance()->unlock(); 419 } 420 return; 421 } 422 423 // change the current audio engine state 424 m_audioEngineState = STATE_READY; 425 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY ); 426 427 m_fMasterPeak_L = 0.0f; 428 m_fMasterPeak_R = 0.0f; 429 // m_nPatternTickPosition = 0; 430 m_nPatternStartTick = -1; 431 432 // delete all copied notes in the song notes queue 433 while(!m_songNoteQueue.empty()){ 434 m_songNoteQueue.top()->get_instrument()->dequeue(); 435 delete m_songNoteQueue.top(); 436 m_songNoteQueue.pop(); 437 } 438 /* // delete all copied notes in the playing notes queue 439 for (unsigned i = 0; i < m_playingNotesQueue.size(); ++i) { 440 Note *note = m_playingNotesQueue[i]; 441 delete note; 442 } 443 m_playingNotesQueue.clear(); 444 */ 445 446 // delete all copied notes in the midi notes queue 447 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) { 448 Note *note = m_midiNoteQueue[i]; 449 delete note; 450 } 451 m_midiNoteQueue.clear(); 452 453 if ( bLockEngine ) { 454 AudioEngine::get_instance()->unlock(); 455 } 456 456 } 457 457 … … 462 462 { 463 463 464 if ( ( m_audioEngineState == STATE_READY ) || ( m_audioEngineState == STATE_PLAYING ) ) {465 466 float fNewTickSize =467 m_pAudioDriver->getSampleRate() * 60.0468 / m_pSong->__bpm469 / m_pSong->__resolution;470 471 if ( fNewTickSize != m_pAudioDriver->m_transport.m_nTickSize ) {472 // cerco di convertire ...473 float fTickNumber =474 ( float )m_pAudioDriver->m_transport.m_nFrames475 / ( float )m_pAudioDriver->m_transport.m_nTickSize;476 477 m_pAudioDriver->m_transport.m_nTickSize = fNewTickSize;478 479 if ( m_pAudioDriver->m_transport.m_nTickSize == 0 ) {480 return;481 }482 483 ___WARNINGLOG( "Tempo change: Recomputing ticksize and frame position" );484 long long nNewFrames = ( long long )( fTickNumber * fNewTickSize );485 // update frame position486 m_pAudioDriver->m_transport.m_nFrames = nNewFrames;487 464 if ( ( m_audioEngineState == STATE_READY ) || ( m_audioEngineState == STATE_PLAYING ) ) { 465 466 float fNewTickSize = 467 m_pAudioDriver->getSampleRate() * 60.0 468 / m_pSong->__bpm 469 / m_pSong->__resolution; 470 471 if ( fNewTickSize != m_pAudioDriver->m_transport.m_nTickSize ) { 472 // cerco di convertire ... 473 float fTickNumber = 474 ( float )m_pAudioDriver->m_transport.m_nFrames 475 / ( float )m_pAudioDriver->m_transport.m_nTickSize; 476 477 m_pAudioDriver->m_transport.m_nTickSize = fNewTickSize; 478 479 if ( m_pAudioDriver->m_transport.m_nTickSize == 0 ) { 480 return; 481 } 482 483 ___WARNINGLOG( "Tempo change: Recomputing ticksize and frame position" ); 484 long long nNewFrames = ( long long )( fTickNumber * fNewTickSize ); 485 // update frame position 486 m_pAudioDriver->m_transport.m_nFrames = nNewFrames; 487 488 488 #ifdef H2CORE_HAVE_JACK 489 if ( JackOutput::class_name() == m_pAudioDriver->class_name()490 && m_audioEngineState == STATE_PLAYING ) {491 static_cast< JackOutput* >( m_pAudioDriver )492 ->calculateFrameOffset();493 }489 if ( JackOutput::class_name() == m_pAudioDriver->class_name() 490 && m_audioEngineState == STATE_PLAYING ) { 491 static_cast< JackOutput* >( m_pAudioDriver ) 492 ->calculateFrameOffset(); 493 } 494 494 #endif 495 EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1);496 }497 }495 EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1); 496 } 497 } 498 498 } 499 499 500 500 inline void audioEngine_process_playNotes( unsigned long nframes ) 501 501 { 502 unsigned int framepos;503 504 if ( m_audioEngineState == STATE_PLAYING ) {505 framepos = m_pAudioDriver->m_transport.m_nFrames;506 } else {507 // use this to support realtime events when not playing508 framepos = m_nRealtimeFrames;509 }510 511 // reading from m_songNoteQueue512 while ( !m_songNoteQueue.empty() ) {513 Note *pNote = m_songNoteQueue.top();514 515 // verifico se la nota rientra in questo ciclo516 unsigned int noteStartInFrames =517 (int)( pNote->get_position() * m_pAudioDriver->m_transport.m_nTickSize );518 519 // if there is a negative Humanize delay, take into account so520 // we don't miss the time slice. ignore positive delay, or we521 // might end the queue processing prematurely based on NoteQueue522 // placement. the sampler handles positive delay.523 if (pNote->get_humanize_delay() < 0) {524 noteStartInFrames += pNote->get_humanize_delay();525 }526 527 // m_nTotalFrames <= NotePos < m_nTotalFrames + bufferSize528 bool isNoteStart = ( ( noteStartInFrames >= framepos )529 && ( noteStartInFrames < ( framepos + nframes ) ) );530 bool isOldNote = noteStartInFrames < framepos;531 if ( isNoteStart || isOldNote ) {532 // Humanize - Velocity parameter533 if ( m_pSong->get_humanize_velocity_value() != 0 ) {534 float random = m_pSong->get_humanize_velocity_value()535 * getGaussian( 0.2 );536 pNote->set_velocity(537 pNote->get_velocity()538 + ( random539 - ( m_pSong->get_humanize_velocity_value() / 2.0 ) ) 540 );541 if ( pNote->get_velocity() > 1.0 ) {542 pNote->set_velocity( 1.0 );543 } else if ( pNote->get_velocity() < 0.0 ) {544 pNote->set_velocity( 0.0 );545 }546 }547 548 // Random Pitch ;)549 const float fMaxPitchDeviation = 2.0;550 pNote->set_pitch( pNote->get_pitch()551 + ( fMaxPitchDeviation * getGaussian( 0.2 )552 - fMaxPitchDeviation / 2.0 )553 * pNote->get_instrument()->get_random_pitch_factor() );554 555 Instrument * noteInstrument = pNote->get_instrument();556 if ( noteInstrument->is_stop_notes() ){ 557 Note *pOffNote = new Note( noteInstrument,558 0.0,559 0.0,560 0.0,561 0.0,562 -1,563 0 );564 pOffNote->set_note_off( true );565 AudioEngine::get_instance()->get_sampler()->note_on( pOffNote );566 }567 568 AudioEngine::get_instance()->get_sampler()->note_on( pNote );569 570 m_songNoteQueue.pop(); // rimuovo la nota dalla lista di note571 pNote->get_instrument()->dequeue();572 // raise noteOn event573 int nInstrument = m_pSong->get_instrument_list()->index( pNote->get_instrument() );574 EventQueue::get_instance()->push_event( EVENT_NOTEON, nInstrument );575 continue;576 } else {577 // this note will not be played578 break;579 }580 }502 unsigned int framepos; 503 504 if ( m_audioEngineState == STATE_PLAYING ) { 505 framepos = m_pAudioDriver->m_transport.m_nFrames; 506 } else { 507 // use this to support realtime events when not playing 508 framepos = m_nRealtimeFrames; 509 } 510 511 // reading from m_songNoteQueue 512 while ( !m_songNoteQueue.empty() ) { 513 Note *pNote = m_songNoteQueue.top(); 514 515 // verifico se la nota rientra in questo ciclo 516 unsigned int noteStartInFrames = 517 (int)( pNote->get_position() * m_pAudioDriver->m_transport.m_nTickSize ); 518 519 // if there is a negative Humanize delay, take into account so 520 // we don't miss the time slice. ignore positive delay, or we 521 // might end the queue processing prematurely based on NoteQueue 522 // placement. the sampler handles positive delay. 523 if (pNote->get_humanize_delay() < 0) { 524 noteStartInFrames += pNote->get_humanize_delay(); 525 } 526 527 // m_nTotalFrames <= NotePos < m_nTotalFrames + bufferSize 528 bool isNoteStart = ( ( noteStartInFrames >= framepos ) 529 && ( noteStartInFrames < ( framepos + nframes ) ) ); 530 bool isOldNote = noteStartInFrames < framepos; 531 if ( isNoteStart || isOldNote ) { 532 // Humanize - Velocity parameter 533 if ( m_pSong->get_humanize_velocity_value() != 0 ) { 534 float random = m_pSong->get_humanize_velocity_value() 535 * getGaussian( 0.2 ); 536 pNote->set_velocity( 537 pNote->get_velocity() 538 + ( random 539 - ( m_pSong->get_humanize_velocity_value() / 2.0 ) ) 540 ); 541 if ( pNote->get_velocity() > 1.0 ) { 542 pNote->set_velocity( 1.0 ); 543 } else if ( pNote->get_velocity() < 0.0 ) { 544 pNote->set_velocity( 0.0 ); 545 } 546 } 547 548 // Random Pitch ;) 549 const float fMaxPitchDeviation = 2.0; 550 pNote->set_pitch( pNote->get_pitch() 551 + ( fMaxPitchDeviation * getGaussian( 0.2 ) 552 - fMaxPitchDeviation / 2.0 ) 553 * pNote->get_instrument()->get_random_pitch_factor() ); 554 555 Instrument * noteInstrument = pNote->get_instrument(); 556 if ( noteInstrument->is_stop_notes() ){ 557 Note *pOffNote = new Note( noteInstrument, 558 0.0, 559 0.0, 560 0.0, 561 0.0, 562 -1, 563 0 ); 564 pOffNote->set_note_off( true ); 565 AudioEngine::get_instance()->get_sampler()->note_on( pOffNote ); 566 } 567 568 AudioEngine::get_instance()->get_sampler()->note_on( pNote ); 569 570 m_songNoteQueue.pop(); // rimuovo la nota dalla lista di note 571 pNote->get_instrument()->dequeue(); 572 // raise noteOn event 573 int nInstrument = m_pSong->get_instrument_list()->index( pNote->get_instrument() ); 574 EventQueue::get_instance()->push_event( EVENT_NOTEON, nInstrument ); 575 continue; 576 } else { 577 // this note will not be played 578 break; 579 } 580 } 581 581 } 582 582 … … 584 584 void audioEngine_seek( long long nFrames, bool bLoopMode ) 585 585 { 586 if ( m_pAudioDriver->m_transport.m_nFrames == nFrames ) {587 return;588 }589 590 if ( nFrames < 0 ) {591 ___ERRORLOG( "nFrames < 0" );592 }593 594 char tmp[200];595 sprintf( tmp, "seek in %lld (old pos = %d)",596 nFrames,597 ( int )m_pAudioDriver->m_transport.m_nFrames );598 ___INFOLOG( tmp );599 600 m_pAudioDriver->m_transport.m_nFrames = nFrames;601 602 int tickNumber_start = ( unsigned )(603 m_pAudioDriver->m_transport.m_nFrames604 / m_pAudioDriver->m_transport.m_nTickSize );605 // sprintf(tmp, "[audioEngine_seek()] tickNumber_start = %d", tickNumber_start);606 // hydrogenInstance->infoLog(tmp);607 608 bool loop = m_pSong->is_loop_enabled();609 610 if ( bLoopMode ) {611 loop = true;612 }613 614 m_nSongPos = findPatternInTick( tickNumber_start, loop, &m_nPatternStartTick );615 // sprintf(tmp, "[audioEngine_seek()] m_nSongPos = %d", m_nSongPos);616 // hydrogenInstance->infoLog(tmp);617 618 audioEngine_clearNoteQueue();586 if ( m_pAudioDriver->m_transport.m_nFrames == nFrames ) { 587 return; 588 } 589 590 if ( nFrames < 0 ) { 591 ___ERRORLOG( "nFrames < 0" ); 592 } 593 594 char tmp[200]; 595 sprintf( tmp, "seek in %lld (old pos = %d)", 596 nFrames, 597 ( int )m_pAudioDriver->m_transport.m_nFrames ); 598 ___INFOLOG( tmp ); 599 600 m_pAudioDriver->m_transport.m_nFrames = nFrames; 601 602 int tickNumber_start = ( unsigned )( 603 m_pAudioDriver->m_transport.m_nFrames 604 / m_pAudioDriver->m_transport.m_nTickSize ); 605 // sprintf(tmp, "[audioEngine_seek()] tickNumber_start = %d", tickNumber_start); 606 // hydrogenInstance->infoLog(tmp); 607 608 bool loop = m_pSong->is_loop_enabled(); 609 610 if ( bLoopMode ) { 611 loop = true; 612 } 613 614 m_nSongPos = findPatternInTick( tickNumber_start, loop, &m_nPatternStartTick ); 615 // sprintf(tmp, "[audioEngine_seek()] m_nSongPos = %d", m_nSongPos); 616 // hydrogenInstance->infoLog(tmp); 617 618 audioEngine_clearNoteQueue(); 619 619 } 620 620 … … 623 623 inline void audioEngine_process_transport() 624 624 { 625 if ( ( m_audioEngineState == STATE_READY )626 || ( m_audioEngineState == STATE_PLAYING ) ) {627 m_pAudioDriver->updateTransportInfo();628 unsigned long nNewFrames = m_pAudioDriver->m_transport.m_nFrames;629 630 // ??? audioEngine_seek returns IMMEDIATELY631 // when nNewFrames == m_pAudioDriver->m_transport.m_nFrames ???632 // audioEngine_seek( nNewFrames, true );633 634 switch ( m_pAudioDriver->m_transport.m_status ) {635 case TransportInfo::ROLLING:636 637 if ( m_audioEngineState == STATE_READY ) {638 audioEngine_start( false, nNewFrames ); // no engine lock639 }640 641 if ( m_pSong->__bpm != m_pAudioDriver->m_transport.m_nBPM ) {642 ___INFOLOG(643 QString( "song bpm: (%1) gets transport bpm: (%2)" )644 .arg( m_pSong->__bpm )645 .arg( m_pAudioDriver->m_transport.m_nBPM ) );646 647 m_pSong->__bpm = m_pAudioDriver->m_transport.m_nBPM;648 }649 650 m_nRealtimeFrames = m_pAudioDriver->m_transport.m_nFrames;651 break;652 653 654 case TransportInfo::STOPPED:655 if ( m_audioEngineState == STATE_PLAYING ) {656 audioEngine_stop( false ); // no engine lock657 }658 659 if ( m_pSong->__bpm != m_pAudioDriver->m_transport.m_nBPM ) {660 m_pSong->__bpm = m_pAudioDriver->m_transport.m_nBPM;661 }662 663 // go ahead and increment the realtimeframes by buffersize664 // to support our realtime keyboard and midi event timing665 m_nRealtimeFrames += m_nBufferSize;666 break;667 }668 }625 if ( ( m_audioEngineState == STATE_READY ) 626 || ( m_audioEngineState == STATE_PLAYING ) ) { 627 m_pAudioDriver->updateTransportInfo(); 628 unsigned long nNewFrames = m_pAudioDriver->m_transport.m_nFrames; 629 630 // ??? audioEngine_seek returns IMMEDIATELY 631 // when nNewFrames == m_pAudioDriver->m_transport.m_nFrames ??? 632 // audioEngine_seek( nNewFrames, true ); 633 634 switch ( m_pAudioDriver->m_transport.m_status ) { 635 case TransportInfo::ROLLING: 636 637 if ( m_audioEngineState == STATE_READY ) { 638 audioEngine_start( false, nNewFrames ); // no engine lock 639 } 640 641 if ( m_pSong->__bpm != m_pAudioDriver->m_transport.m_nBPM ) { 642 ___INFOLOG( 643 QString( "song bpm: (%1) gets transport bpm: (%2)" ) 644 .arg( m_pSong->__bpm ) 645 .arg( m_pAudioDriver->m_transport.m_nBPM ) ); 646 647 m_pSong->__bpm = m_pAudioDriver->m_transport.m_nBPM; 648 } 649 650 m_nRealtimeFrames = m_pAudioDriver->m_transport.m_nFrames; 651 break; 652 653 654 case TransportInfo::STOPPED: 655 if ( m_audioEngineState == STATE_PLAYING ) { 656 audioEngine_stop( false ); // no engine lock 657 } 658 659 if ( m_pSong->__bpm != m_pAudioDriver->m_transport.m_nBPM ) { 660 m_pSong->__bpm = m_pAudioDriver->m_transport.m_nBPM; 661 } 662 663 // go ahead and increment the realtimeframes by buffersize 664 // to support our realtime keyboard and midi event timing 665 m_nRealtimeFrames += m_nBufferSize; 666 break; 667 } 668 } 669 669 } 670 670 … … 673 673 void audioEngine_clearNoteQueue() 674 674 { 675 //___INFOLOG( "clear notes...");676 677 // delete all copied notes in the song notes queue678 while (!m_songNoteQueue.empty()) {679 m_songNoteQueue.top()->get_instrument()->dequeue();680 delete m_songNoteQueue.top();681 m_songNoteQueue.pop();682 }683 684 AudioEngine::get_instance()->get_sampler()->stop_playing_notes();685 686 // delete all copied notes in the midi notes queue687 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) {688 delete m_midiNoteQueue[i];689 }690 m_midiNoteQueue.clear();675 //___INFOLOG( "clear notes..."); 676 677 // delete all copied notes in the song notes queue 678 while (!m_songNoteQueue.empty()) { 679 m_songNoteQueue.top()->get_instrument()->dequeue(); 680 delete m_songNoteQueue.top(); 681 m_songNoteQueue.pop(); 682 } 683 684 AudioEngine::get_instance()->get_sampler()->stop_playing_notes(); 685 686 // delete all copied notes in the midi notes queue 687 for ( unsigned i = 0; i < m_midiNoteQueue.size(); ++i ) { 688 delete m_midiNoteQueue[i]; 689 } 690 m_midiNoteQueue.clear(); 691 691 692 692 } … … 697 697 inline void audioEngine_process_clearAudioBuffers( uint32_t nFrames ) 698 698 { 699 QMutexLocker mx( &mutex_OutputPointer );700 701 // clear main out Left and Right702 if ( m_pAudioDriver ) {703 m_pMainBuffer_L = m_pAudioDriver->getOut_L();704 m_pMainBuffer_R = m_pAudioDriver->getOut_R();705 } else {706 m_pMainBuffer_L = m_pMainBuffer_R = 0;707 }708 if ( m_pMainBuffer_L ) {709 memset( m_pMainBuffer_L, 0, nFrames * sizeof( float ) );710 }711 if ( m_pMainBuffer_R ) {712 memset( m_pMainBuffer_R, 0, nFrames * sizeof( float ) );713 }699 QMutexLocker mx( &mutex_OutputPointer ); 700 701 // clear main out Left and Right 702 if ( m_pAudioDriver ) { 703 m_pMainBuffer_L = m_pAudioDriver->getOut_L(); 704 m_pMainBuffer_R = m_pAudioDriver->getOut_R(); 705 } else { 706 m_pMainBuffer_L = m_pMainBuffer_R = 0; 707 } 708 if ( m_pMainBuffer_L ) { 709 memset( m_pMainBuffer_L, 0, nFrames * sizeof( float ) ); 710 } 711 if ( m_pMainBuffer_R ) { 712 memset( m_pMainBuffer_R, 0, nFrames * sizeof( float ) ); 713 } 714 714 715 715 #ifdef H2CORE_HAVE_JACK 716 JackOutput* jo = dynamic_cast<JackOutput*>(m_pAudioDriver);717 if( jo && jo->has_track_outs() ) {718 float* buf;719 int k;720 for( k=0 ; k<jo->getNumTracks() ; ++k ) {721 buf = jo->getTrackOut_L(k);722 if( buf ) {723 memset( buf, 0, nFrames * sizeof( float ) );724 }725 buf = jo->getTrackOut_R(k);726 if( buf ) {727 memset( buf, 0, nFrames * sizeof( float ) );728 }729 }730 }716 JackOutput* jo = dynamic_cast<JackOutput*>(m_pAudioDriver); 717 if( jo && jo->has_track_outs() ) { 718 float* buf; 719 int k; 720 for( k=0 ; k<jo->getNumTracks() ; ++k ) { 721 buf = jo->getTrackOut_L(k); 722 if( buf ) { 723 memset( buf, 0, nFrames * sizeof( float ) ); 724 } 725 buf = jo->getTrackOut_R(k); 726 if( buf ) { 727 memset( buf, 0, nFrames * sizeof( float ) ); 728 } 729 } 730 } 731 731 #endif 732 732 733 mx.unlock();733 mx.unlock(); 734 734 735 735 #ifdef H2CORE_HAVE_LADSPA 736 if ( m_audioEngineState >= STATE_READY ) {737 Effects* pEffects = Effects::get_instance();738 for ( unsigned i = 0; i < MAX_FX; ++i ) { // clear FX buffers739 LadspaFX* pFX = pEffects->getLadspaFX( i );740 if ( pFX ) {741 assert( pFX->m_pBuffer_L );742 assert( pFX->m_pBuffer_R );743 memset( pFX->m_pBuffer_L, 0, nFrames * sizeof( float ) );744 memset( pFX->m_pBuffer_R, 0, nFrames * sizeof( float ) );745 }746 }747 }736 if ( m_audioEngineState >= STATE_READY ) { 737 Effects* pEffects = Effects::get_instance(); 738 for ( unsigned i = 0; i < MAX_FX; ++i ) { // clear FX buffers 739 LadspaFX* pFX = pEffects->getLadspaFX( i ); 740 if ( pFX ) { 741 assert( pFX->m_pBuffer_L ); 742 assert( pFX->m_pBuffer_R ); 743 memset( pFX->m_pBuffer_L, 0, nFrames * sizeof( float ) ); 744 memset( pFX->m_pBuffer_R, 0, nFrames * sizeof( float ) ); 745 } 746 } 747 } 748 748 #endif 749 749 } … … 752 752 int audioEngine_process( uint32_t nframes, void* /*arg*/ ) 753 753 { 754 timeval startTimeval = currentTime2();755 756 audioEngine_process_clearAudioBuffers( nframes );757 758 if( m_audioEngineState < STATE_READY) {759 return 0;760 }761 762 763 AudioEngine::get_instance()->lock( RIGHT_HERE );764 765 if( m_audioEngineState < STATE_READY) {766 AudioEngine::get_instance()->unlock();767 return 0;768 }769 770 if ( m_nBufferSize != nframes ) {771 ___INFOLOG(772 QString( "Buffer size changed. Old size = %1, new size = %2" )773 .arg( m_nBufferSize )774 .arg( nframes )775 );776 m_nBufferSize = nframes;777 }778 779 // m_pAudioDriver->bpm updates Song->__bpm. (!!(Calls audioEngine_seek))780 audioEngine_process_transport();781 audioEngine_process_checkBPMChanged(); // m_pSong->__bpm decides tick size782 783 bool sendPatternChange = false;784 // always update note queue.. could come from pattern or realtime input785 // (midi, keyboard)786 int res2 = audioEngine_updateNoteQueue( nframes );787 if ( res2 == -1 ) { // end of song788 ___INFOLOG( "End of song received, calling engine_stop()" );789 AudioEngine::get_instance()->unlock();790 m_pAudioDriver->stop();791 m_pAudioDriver->locate( 0 ); // locate 0, reposition from start of the song792 793 if ( ( m_pAudioDriver->class_name() == DiskWriterDriver::class_name() )794 || ( m_pAudioDriver->class_name() == FakeDriver::class_name() ) ) {795 ___INFOLOG( "End of song." );796 return 1; // kill the audio AudioDriver thread797 }754 timeval startTimeval = currentTime2(); 755 756 audioEngine_process_clearAudioBuffers( nframes ); 757 758 if( m_audioEngineState < STATE_READY) { 759 return 0; 760 } 761 762 763 AudioEngine::get_instance()->lock( RIGHT_HERE ); 764 765 if( m_audioEngineState < STATE_READY) { 766 AudioEngine::get_instance()->unlock(); 767 return 0; 768 } 769 770 if ( m_nBufferSize != nframes ) { 771 ___INFOLOG( 772 QString( "Buffer size changed. Old size = %1, new size = %2" ) 773 .arg( m_nBufferSize ) 774 .arg( nframes ) 775 ); 776 m_nBufferSize = nframes; 777 } 778 779 // m_pAudioDriver->bpm updates Song->__bpm. (!!(Calls audioEngine_seek)) 780 audioEngine_process_transport(); 781 audioEngine_process_checkBPMChanged(); // m_pSong->__bpm decides tick size 782 783 bool sendPatternChange = false; 784 // always update note queue.. could come from pattern or realtime input 785 // (midi, keyboard) 786 int res2 = audioEngine_updateNoteQueue( nframes ); 787 if ( res2 == -1 ) { // end of song 788 ___INFOLOG( "End of song received, calling engine_stop()" ); 789 AudioEngine::get_instance()->unlock(); 790 m_pAudioDriver->stop(); 791 m_pAudioDriver->locate( 0 ); // locate 0, reposition from start of the song 792 793 if ( ( m_pAudioDriver->class_name() == DiskWriterDriver::class_name() ) 794 || ( m_pAudioDriver->class_name() == FakeDriver::class_name() ) ) { 795 ___INFOLOG( "End of song." ); 796 return 1; // kill the audio AudioDriver thread 797 } 798 798 #ifdef H2CORE_HAVE_JACK 799 else if ( m_pAudioDriver->class_name() == JackOutput::class_name() ) {800 // Do something clever :-s ... Jakob Lund801 // Mainly to keep sync with Ardour.802 static_cast<JackOutput*>(m_pAudioDriver)->locateInNCycles( 0 );803 }799 else if ( m_pAudioDriver->class_name() == JackOutput::class_name() ) { 800 // Do something clever :-s ... Jakob Lund 801 // Mainly to keep sync with Ardour. 802 static_cast<JackOutput*>(m_pAudioDriver)->locateInNCycles( 0 ); 803 } 804 804 #endif 805 return 0;806 } else if ( res2 == 2 ) { // send pattern change807 sendPatternChange = true;808 }809 810 // play all notes811 audioEngine_process_playNotes( nframes );812 813 // SAMPLER814 AudioEngine::get_instance()->get_sampler()->process( nframes, m_pSong );815 float* out_L = AudioEngine::get_instance()->get_sampler()->__main_out_L;816 float* out_R = AudioEngine::get_instance()->get_sampler()->__main_out_R;817 for ( unsigned i = 0; i < nframes; ++i ) {818 m_pMainBuffer_L[ i ] += out_L[ i ];819 m_pMainBuffer_R[ i ] += out_R[ i ];820 }821 822 // SYNTH823 AudioEngine::get_instance()->get_synth()->process( nframes );824 out_L = AudioEngine::get_instance()->get_synth()->m_pOut_L;825 out_R = AudioEngine::get_instance()->get_synth()->m_pOut_R;826 for ( unsigned i = 0; i < nframes; ++i ) {827 m_pMainBuffer_L[ i ] += out_L[ i ];828 m_pMainBuffer_R[ i ] += out_R[ i ];829 }830 831 832 timeval renderTime_end = currentTime2();833 834 835 836 timeval ladspaTime_start = renderTime_end;805 return 0; 806 } else if ( res2 == 2 ) { // send pattern change 807 sendPatternChange = true; 808 } 809 810 // play all notes 811 audioEngine_process_playNotes( nframes ); 812 813 // SAMPLER 814 AudioEngine::get_instance()->get_sampler()->process( nframes, m_pSong ); 815 float* out_L = AudioEngine::get_instance()->get_sampler()->__main_out_L; 816 float* out_R = AudioEngine::get_instance()->get_sampler()->__main_out_R; 817 for ( unsigned i = 0; i < nframes; ++i ) { 818 m_pMainBuffer_L[ i ] += out_L[ i ]; 819 m_pMainBuffer_R[ i ] += out_R[ i ]; 820 } 821 822 // SYNTH 823 AudioEngine::get_instance()->get_synth()->process( nframes ); 824 out_L = AudioEngine::get_instance()->get_synth()->m_pOut_L; 825 out_R = AudioEngine::get_instance()->get_synth()->m_pOut_R; 826 for ( unsigned i = 0; i < nframes; ++i ) { 827 m_pMainBuffer_L[ i ] += out_L[ i ]; 828 m_pMainBuffer_R[ i ] += out_R[ i ]; 829 } 830 831 832 timeval renderTime_end = currentTime2(); 833 834 835 836 timeval ladspaTime_start = renderTime_end; 837 837 #ifdef H2CORE_HAVE_LADSPA 838 // Process LADSPA FX839 if ( m_audioEngineState >= STATE_READY ) {840 for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) {841 LadspaFX *pFX = Effects::get_instance()->getLadspaFX( nFX );842 if ( ( pFX ) && ( pFX->isEnabled() ) ) {843 pFX->processFX( nframes );844 float *buf_L = NULL;845 float *buf_R = NULL;846 if ( pFX->getPluginType() == LadspaFX::STEREO_FX ) {847 buf_L = pFX->m_pBuffer_L;848 buf_R = pFX->m_pBuffer_R;849 } else { // MONO FX850 buf_L = pFX->m_pBuffer_L;851 buf_R = buf_L;852 }853 for ( unsigned i = 0; i < nframes; ++i ) {854 m_pMainBuffer_L[ i ] += buf_L[ i ];855 m_pMainBuffer_R[ i ] += buf_R[ i ];856 if ( buf_L[ i ] > m_fFXPeak_L[nFX] )857 m_fFXPeak_L[nFX] = buf_L[ i ];858 if ( buf_R[ i ] > m_fFXPeak_R[nFX] )859 m_fFXPeak_R[nFX] = buf_R[ i ];860 }861 }862 }863 }838 // Process LADSPA FX 839 if ( m_audioEngineState >= STATE_READY ) { 840 for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) { 841 LadspaFX *pFX = Effects::get_instance()->getLadspaFX( nFX ); 842 if ( ( pFX ) && ( pFX->isEnabled() ) ) { 843 pFX->processFX( nframes ); 844 float *buf_L = NULL; 845 float *buf_R = NULL; 846 if ( pFX->getPluginType() == LadspaFX::STEREO_FX ) { 847 buf_L = pFX->m_pBuffer_L; 848 buf_R = pFX->m_pBuffer_R; 849 } else { // MONO FX 850 buf_L = pFX->m_pBuffer_L; 851 buf_R = buf_L; 852 } 853 for ( unsigned i = 0; i < nframes; ++i ) { 854 m_pMainBuffer_L[ i ] += buf_L[ i ]; 855 m_pMainBuffer_R[ i ] += buf_R[ i ]; 856 if ( buf_L[ i ] > m_fFXPeak_L[nFX] ) 857 m_fFXPeak_L[nFX] = buf_L[ i ]; 858 if ( buf_R[ i ] > m_fFXPeak_R[nFX] ) 859 m_fFXPeak_R[nFX] = buf_R[ i ]; 860 } 861 } 862 } 863 } 864 864 #endif 865 timeval ladspaTime_end = currentTime2();866 867 // update master peaks868 float val_L;869 float val_R;870 if ( m_audioEngineState >= STATE_READY ) {871 for ( unsigned i = 0; i < nframes; ++i ) {872 val_L = m_pMainBuffer_L[i];873 val_R = m_pMainBuffer_R[i];874 if ( val_L > m_fMasterPeak_L ) {875 m_fMasterPeak_L = val_L;876 }877 if ( val_R > m_fMasterPeak_R ) {878 m_fMasterPeak_R = val_R;879 }880 }881 }882 883 // update total frames number884 if ( m_audioEngineState == STATE_PLAYING ) {885 m_pAudioDriver->m_transport.m_nFrames += nframes;886 }887 888 // float fRenderTime = (renderTime_end.tv_sec - renderTime_start.tv_sec) * 1000.0 + (renderTime_end.tv_usec - renderTime_start.tv_usec) / 1000.0;889 float fLadspaTime =890 ( ladspaTime_end.tv_sec - ladspaTime_start.tv_sec ) * 1000.0891 + ( ladspaTime_end.tv_usec - ladspaTime_start.tv_usec ) / 1000.0;892 893 timeval finishTimeval = currentTime2();894 m_fProcessTime =895 ( finishTimeval.tv_sec - startTimeval.tv_sec ) * 1000.0896 + ( finishTimeval.tv_usec - startTimeval.tv_usec ) / 1000.0;897 898 float sampleRate = ( float )m_pAudioDriver->getSampleRate();899 m_fMaxProcessTime = 1000.0 / ( sampleRate / nframes );865 timeval ladspaTime_end = currentTime2(); 866 867 // update master peaks 868 float val_L; 869 float val_R; 870 if ( m_audioEngineState >= STATE_READY ) { 871 for ( unsigned i = 0; i < nframes; ++i ) { 872 val_L = m_pMainBuffer_L[i]; 873 val_R = m_pMainBuffer_R[i]; 874 if ( val_L > m_fMasterPeak_L ) { 875 m_fMasterPeak_L = val_L; 876 } 877 if ( val_R > m_fMasterPeak_R ) { 878 m_fMasterPeak_R = val_R; 879 } 880 } 881 } 882 883 // update total frames number 884 if ( m_audioEngineState == STATE_PLAYING ) { 885 m_pAudioDriver->m_transport.m_nFrames += nframes; 886 } 887 888 // float fRenderTime = (renderTime_end.tv_sec - renderTime_start.tv_sec) * 1000.0 + (renderTime_end.tv_usec - renderTime_start.tv_usec) / 1000.0; 889 float fLadspaTime = 890 ( ladspaTime_end.tv_sec - ladspaTime_start.tv_sec ) * 1000.0 891 + ( ladspaTime_end.tv_usec - ladspaTime_start.tv_usec ) / 1000.0; 892 893 timeval finishTimeval = currentTime2(); 894 m_fProcessTime = 895 ( finishTimeval.tv_sec - startTimeval.tv_sec ) * 1000.0 896 + ( finishTimeval.tv_usec - startTimeval.tv_usec ) / 1000.0; 897 898 float sampleRate = ( float )m_pAudioDriver->getSampleRate(); 899 m_fMaxProcessTime = 1000.0 / ( sampleRate / nframes ); 900 900 901 901 #ifdef CONFIG_DEBUG 902 if ( m_fProcessTime > m_fMaxProcessTime ) {903 ___WARNINGLOG( "" );904 ___WARNINGLOG( "----XRUN----" );905 ___WARNINGLOG( QString( "XRUN of %1 msec (%2 > %3)" )902 if ( m_fProcessTime > m_fMaxProcessTime ) { 903 ___WARNINGLOG( "" ); 904 ___WARNINGLOG( "----XRUN----" ); 905 ___WARNINGLOG( QString( "XRUN of %1 msec (%2 > %3)" ) 906 906 .arg( ( m_fProcessTime - m_fMaxProcessTime ) ) 907 907 .arg( m_fProcessTime ).arg( m_fMaxProcessTime ) ); 908 ___WARNINGLOG( QString( "Ladspa process time = %1" ).arg( fLadspaTime ) );909 ___WARNINGLOG( "------------" );910 ___WARNINGLOG( "" );911 // raise xRun event912 EventQueue::get_instance()->push_event( EVENT_XRUN, -1 );913 }908 ___WARNINGLOG( QString( "Ladspa process time = %1" ).arg( fLadspaTime ) ); 909 ___WARNINGLOG( "------------" ); 910 ___WARNINGLOG( "" ); 911 // raise xRun event 912 EventQueue::get_instance()->push_event( EVENT_XRUN, -1 ); 913 } 914 914 #endif 915 915 916 AudioEngine::get_instance()->unlock();917 918 if ( sendPatternChange ) {919 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 );920 }921 922 return 0;916 AudioEngine::get_instance()->unlock(); 917 918 if ( sendPatternChange ) { 919 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 ); 920 } 921 922 return 0; 923 923 } 924 924 … … 929 929 void audioEngine_setupLadspaFX( unsigned nBufferSize ) 930 930 { 931 //___INFOLOG( "buffersize=" + to_string(nBufferSize) );932 933 if ( m_pSong == NULL ) {934 //___INFOLOG( "m_pSong=NULL" );935 return;936 }937 if ( nBufferSize == 0 ) {938 ___ERRORLOG( "nBufferSize=0" );939 return;940 }931 //___INFOLOG( "buffersize=" + to_string(nBufferSize) ); 932 933 if ( m_pSong == NULL ) { 934 //___INFOLOG( "m_pSong=NULL" ); 935 return; 936 } 937 if ( nBufferSize == 0 ) { 938 ___ERRORLOG( "nBufferSize=0" ); 939 return; 940 } 941 941 942 942 #ifdef H2CORE_HAVE_LADSPA 943 for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) {944 LadspaFX *pFX = Effects::get_instance()->getLadspaFX( nFX );945 if ( pFX == NULL ) {946 return;947 }948 949 pFX->deactivate();950 951 // delete[] pFX->m_pBuffer_L;952 // pFX->m_pBuffer_L = NULL;953 // delete[] pFX->m_pBuffer_R;954 // pFX->m_pBuffer_R = NULL;955 // if ( nBufferSize != 0 ) {956 //pFX->m_nBufferSize = nBufferSize;957 //pFX->m_pBuffer_L = new float[ nBufferSize ];958 //pFX->m_pBuffer_R = new float[ nBufferSize ];959 // }960 961 Effects::get_instance()->getLadspaFX( nFX )->connectAudioPorts(962 pFX->m_pBuffer_L,963 pFX->m_pBuffer_R,964 pFX->m_pBuffer_L,965 pFX->m_pBuffer_R966 );967 pFX->activate();968 }943 for ( unsigned nFX = 0; nFX < MAX_FX; ++nFX ) { 944 LadspaFX *pFX = Effects::get_instance()->getLadspaFX( nFX ); 945 if ( pFX == NULL ) { 946 return; 947 } 948 949 pFX->deactivate(); 950 951 // delete[] pFX->m_pBuffer_L; 952 // pFX->m_pBuffer_L = NULL; 953 // delete[] pFX->m_pBuffer_R; 954 // pFX->m_pBuffer_R = NULL; 955 // if ( nBufferSize != 0 ) { 956 //pFX->m_nBufferSize = nBufferSize; 957 //pFX->m_pBuffer_L = new float[ nBufferSize ]; 958 //pFX->m_pBuffer_R = new float[ nBufferSize ]; 959 // } 960 961 Effects::get_instance()->getLadspaFX( nFX )->connectAudioPorts( 962 pFX->m_pBuffer_L, 963 pFX->m_pBuffer_R, 964 pFX->m_pBuffer_L, 965 pFX->m_pBuffer_R 966 ); 967 pFX->activate(); 968 } 969 969 #endif 970 970 } … … 975 975 { 976 976 #ifdef H2CORE_HAVE_JACK 977 // renames jack ports978 if ( m_pSong == NULL ) {979 return;980 }981 if ( m_pAudioDriver->class_name() == JackOutput::class_name() ) {982 static_cast< JackOutput* >( m_pAudioDriver )->makeTrackOutputs( m_pSong );983 }977 // renames jack ports 978 if ( m_pSong == NULL ) { 979 return; 980 } 981 if ( m_pAudioDriver->class_name() == JackOutput::class_name() ) { 982 static_cast< JackOutput* >( m_pAudioDriver )->makeTrackOutputs( m_pSong ); 983 } 984 984 #endif 985 985 } … … 989 989 void audioEngine_setSong( Song *newSong ) 990 990 { 991 ___WARNINGLOG( QString( "Set song: %1" ).arg( newSong->__name ) );992 993 AudioEngine::get_instance()->lock( RIGHT_HERE );994 995 if ( m_audioEngineState == STATE_PLAYING ) {996 m_pAudioDriver->stop();997 audioEngine_stop( false );998 }999 1000 // check current state1001 if ( m_audioEngineState != STATE_PREPARED ) {1002 ___ERRORLOG( "Error the audio engine is not in PREPARED state" );1003 }1004 1005 m_pPlayingPatterns->clear();1006 m_pNextPatterns->clear();1007 1008 EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );1009 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 );1010 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );1011 1012 //sleep( 1 );1013 1014 audioEngine_clearNoteQueue();1015 1016 assert( m_pSong == NULL );1017 m_pSong = newSong;1018 1019 // setup LADSPA FX1020 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );1021 1022 // update ticksize1023 audioEngine_process_checkBPMChanged();1024 1025 // find the first pattern and set as current1026 if ( m_pSong->get_pattern_list()->size() > 0 ) {1027 m_pPlayingPatterns->add( m_pSong->get_pattern_list()->get( 0 ) );1028 }1029 1030 1031 audioEngine_renameJackPorts();1032 1033 m_pAudioDriver->setBpm( m_pSong->__bpm );1034 1035 // change the current audio engine state1036 m_audioEngineState = STATE_READY;1037 1038 m_pAudioDriver->locate( 0 );1039 1040 AudioEngine::get_instance()->unlock();1041 1042 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );991 ___WARNINGLOG( QString( "Set song: %1" ).arg( newSong->__name ) ); 992 993 AudioEngine::get_instance()->lock( RIGHT_HERE ); 994 995 if ( m_audioEngineState == STATE_PLAYING ) { 996 m_pAudioDriver->stop(); 997 audioEngine_stop( false ); 998 } 999 1000 // check current state 1001 if ( m_audioEngineState != STATE_PREPARED ) { 1002 ___ERRORLOG( "Error the audio engine is not in PREPARED state" ); 1003 } 1004 1005 m_pPlayingPatterns->clear(); 1006 m_pNextPatterns->clear(); 1007 1008 EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 ); 1009 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 ); 1010 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 ); 1011 1012 //sleep( 1 ); 1013 1014 audioEngine_clearNoteQueue(); 1015 1016 assert( m_pSong == NULL ); 1017 m_pSong = newSong; 1018 1019 // setup LADSPA FX 1020 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() ); 1021 1022 // update ticksize 1023 audioEngine_process_checkBPMChanged(); 1024 1025 // find the first pattern and set as current 1026 if ( m_pSong->get_pattern_list()->size() > 0 ) { 1027 m_pPlayingPatterns->add( m_pSong->get_pattern_list()->get( 0 ) ); 1028 } 1029 1030 1031 audioEngine_renameJackPorts(); 1032 1033 m_pAudioDriver->setBpm( m_pSong->__bpm ); 1034 1035 // change the current audio engine state 1036 m_audioEngineState = STATE_READY; 1037 1038 m_pAudioDriver->locate( 0 ); 1039 1040 AudioEngine::get_instance()->unlock(); 1041 1042 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY ); 1043 1043 } 1044 1044 … … 1047 1047 void audioEngine_removeSong() 1048 1048 { 1049 AudioEngine::get_instance()->lock( RIGHT_HERE );1050 1051 if ( m_audioEngineState == STATE_PLAYING ) {1052 m_pAudioDriver->stop();1053 audioEngine_stop( false );1054 }1055 1056 // check current state1057 if ( m_audioEngineState != STATE_READY ) {1058 ___ERRORLOG( "Error the audio engine is not in READY state" );1059 AudioEngine::get_instance()->unlock();1060 return;1061 }1062 1063 m_pSong = NULL;1064 m_pPlayingPatterns->clear();1065 m_pNextPatterns->clear();1066 1067 audioEngine_clearNoteQueue();1068 1069 // change the current audio engine state1070 m_audioEngineState = STATE_PREPARED;1071 AudioEngine::get_instance()->unlock();1072 1073 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED );1049 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1050 1051 if ( m_audioEngineState == STATE_PLAYING ) { 1052 m_pAudioDriver->stop(); 1053 audioEngine_stop( false ); 1054 } 1055 1056 // check current state 1057 if ( m_audioEngineState != STATE_READY ) { 1058 ___ERRORLOG( "Error the audio engine is not in READY state" ); 1059 AudioEngine::get_instance()->unlock(); 1060 return; 1061 } 1062 1063 m_pSong = NULL; 1064 m_pPlayingPatterns->clear(); 1065 m_pNextPatterns->clear(); 1066 1067 audioEngine_clearNoteQueue(); 1068 1069 // change the current audio engine state 1070 m_audioEngineState = STATE_PREPARED; 1071 AudioEngine::get_instance()->unlock(); 1072 1073 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED ); 1074 1074 } 1075 1075 … … 1079 1079 inline int audioEngine_updateNoteQueue( unsigned nFrames ) 1080 1080 { 1081 static int nLastTick = -1; 1082 bool bSendPatternChange = false; 1083 int nMaxTimeHumanize = 2000; 1084 int nLeadLagFactor = m_pAudioDriver->m_transport.m_nTickSize * 5; // 5 ticks 1085 1086 unsigned int framepos; 1087 if ( m_audioEngineState == STATE_PLAYING ) { 1088 framepos = m_pAudioDriver->m_transport.m_nFrames; 1089 } else { 1090 // use this to support realtime events when not playing 1091 framepos = m_nRealtimeFrames; 1092 } 1093 1094 int tickNumber_start = 0; 1095 1096 // We need to look ahead in the song for notes with negative offsets 1097 // from LeadLag or Humanize. When starting from the beginning, we prime 1098 // the note queue with notes between 0 and nFrames plus 1099 // lookahead. lookahead should be equal or greater than the 1100 // nLeadLagFactor + nMaxTimeHumanize. 1101 int lookahead = nLeadLagFactor + nMaxTimeHumanize + 1; 1102 m_nLookaheadFrames = lookahead; 1103 if ( framepos == 0 1104 || ( m_audioEngineState == STATE_PLAYING 1105 && m_pSong->get_mode() == Song::SONG_MODE 1106 && m_nSongPos == -1 ) ) { 1107 tickNumber_start = (int)( framepos 1108 / m_pAudioDriver->m_transport.m_nTickSize ); 1109 } 1110 else { 1111 tickNumber_start = (int)( (framepos + lookahead) 1112 / m_pAudioDriver->m_transport.m_nTickSize ); 1113 } 1114 int tickNumber_end = (int)( (framepos + nFrames + lookahead) 1115 / m_pAudioDriver->m_transport.m_nTickSize ); 1116 1117 int tick = tickNumber_start; 1118 1119 // ___WARNINGLOG( "Lookahead: " + to_string( lookahead 1120 // / m_pAudioDriver->m_transport.m_nTickSize ) ); 1121 // get initial timestamp for first tick 1122 gettimeofday( &m_currentTickTime, NULL ); 1123 1124 1125 while ( tick <= tickNumber_end ) { 1126 if ( tick == nLastTick ) { 1127 ++tick; 1128 continue; 1129 } else { 1130 nLastTick = tick; 1131 } 1132 1133 1134 // midi events now get put into the m_songNoteQueue as well, 1135 // based on their timestamp 1136 while ( m_midiNoteQueue.size() > 0 ) { 1137 Note *note = m_midiNoteQueue[0]; 1138 1139 if ( ( int )note->get_position() <= tick ) { 1140 // printf ("tick=%d pos=%d\n", tick, note->getPosition()); 1141 m_midiNoteQueue.pop_front(); 1142 note->get_instrument()->enqueue(); 1143 m_songNoteQueue.push( note ); 1144 } else { 1145 break; 1146 } 1147 } 1148 1149 if ( m_audioEngineState != STATE_PLAYING ) { 1150 // only keep going if we're playing 1151 continue; 1152 } 1153 1154 // if ( m_nPatternStartTick == -1 ) { // for debugging pattern mode :s 1155 // ___WARNINGLOG( "m_nPatternStartTick == -1; tick = " 1156 // + to_string( tick ) ); 1157 // } 1158 1159 1160 // SONG MODE 1161 bool doErase = m_audioEngineState == STATE_PLAYING 1162 && Preferences::get_instance()->getRecordEvents() 1163 && Preferences::get_instance()->getDestructiveRecord() 1164 && Preferences::get_instance()->m_nRecPreDelete == 0; 1165 if ( m_pSong->get_mode() == Song::SONG_MODE ) { 1166 if ( m_pSong->get_pattern_group_vector()->size() == 0 ) { 1167 // there's no song!! 1168 ___ERRORLOG( "no patterns in song." ); 1169 m_pAudioDriver->stop(); 1170 return -1; 1171 } 1172 1173 m_nSongPos = findPatternInTick( tick, 1174 m_pSong->is_loop_enabled(), 1175 &m_nPatternStartTick ); 1176 if ( m_nSongSizeInTicks != 0 ) { 1177 m_nPatternTickPosition = ( tick - m_nPatternStartTick ) 1178 % m_nSongSizeInTicks; 1179 } else { 1180 m_nPatternTickPosition = tick - m_nPatternStartTick; 1181 } 1182 1183 1184 if ( m_nPatternTickPosition == 0 ) { 1185 bSendPatternChange = true; 1186 } 1187 1188 // PatternList *pPatternList = 1189 // (*(m_pSong->getPatternGroupVector()))[m_nSongPos]; 1190 if ( m_nSongPos == -1 ) { 1191 ___INFOLOG( "song pos = -1" ); 1192 if ( m_pSong->is_loop_enabled() == true ) { 1193 m_nSongPos = findPatternInTick( 0, 1194 true, 1195 &m_nPatternStartTick ); 1196 } else { 1197 1198 ___INFOLOG( "End of Song" ); 1199 1200 if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ 1201 Hydrogen::get_instance()->getMidiOutput()->handleQueueAllNoteOff(); 1202 } 1203 1204 return -1; 1205 } 1206 } 1207 PatternList *pPatternList = ( *( m_pSong->get_pattern_group_vector() ) )[m_nSongPos]; 1208 m_pPlayingPatterns->clear(); 1209 for ( int i=0; i< pPatternList->size(); ++i ) { 1210 Pattern* pattern = pPatternList->get(i); 1211 m_pPlayingPatterns->add( pattern ); 1212 pattern->extand_with_flattened_virtual_patterns( m_pPlayingPatterns ); 1213 } 1214 // Set destructive record depending on punch area 1215 doErase = doErase && Preferences::get_instance()->inPunchArea(m_nSongPos); 1216 } 1217 // PATTERN MODE 1218 else if ( m_pSong->get_mode() == Song::PATTERN_MODE ) { 1219 // per ora considero solo il primo pattern, se ce ne 1220 // saranno piu' di uno bisognera' prendere quello piu' 1221 // piccolo 1222 1223 //m_nPatternTickPosition = tick % m_pCurrentPattern->getSize(); 1224 int nPatternSize = MAX_NOTES; 1225 1226 1227 if ( Preferences::get_instance()->patternModePlaysSelected() ) 1228 { 1229 m_pPlayingPatterns->clear(); 1230 Pattern * pattern = m_pSong->get_pattern_list()->get(m_nSelectedPatternNumber); 1231 m_pPlayingPatterns->add( pattern ); 1232 pattern->extand_with_flattened_virtual_patterns( m_pPlayingPatterns ); 1233 } 1234 1235 1236 if ( m_pPlayingPatterns->size() != 0 ) { 1237 Pattern *pFirstPattern = m_pPlayingPatterns->get( 0 ); 1238 nPatternSize = pFirstPattern->get_length(); 1239 } 1240 1241 if ( nPatternSize == 0 ) { 1242 ___ERRORLOG( "nPatternSize == 0" ); 1243 } 1244 1245 if ( ( tick == m_nPatternStartTick + nPatternSize ) 1246 || ( m_nPatternStartTick == -1 ) ) { 1247 if ( m_pNextPatterns->size() > 0 ) { 1248 Pattern * p; 1249 for ( uint i = 0; 1250 i < m_pNextPatterns->size(); 1251 i++ ) { 1252 p = m_pNextPatterns->get( i ); 1253 // ___WARNINGLOG( QString( "Got pattern # %1" ) 1254 // .arg( i + 1 ) ); 1255 // if the pattern isn't playing 1256 // already, start it now. 1257 if ( ( m_pPlayingPatterns->del( p ) ) == NULL ) { 1258 m_pPlayingPatterns->add( p ); 1259 } 1260 } 1261 m_pNextPatterns->clear(); 1262 bSendPatternChange = true; 1263 } 1264 if ( m_nPatternStartTick == -1 ) { 1265 m_nPatternStartTick = tick - (tick % nPatternSize); 1266 // ___WARNINGLOG( "set Pattern Start Tick to " 1267 // + to_string( m_nPatternStartTick ) ); 1268 } else { 1269 m_nPatternStartTick = tick; 1270 } 1271 } 1272 m_nPatternTickPosition = tick - m_nPatternStartTick; 1273 if ( m_nPatternTickPosition > nPatternSize ) { 1274 m_nPatternTickPosition = tick % nPatternSize; 1275 } 1276 } 1277 1278 // metronome 1279 // if ( ( m_nPatternStartTick == tick ) 1280 // || ( ( tick - m_nPatternStartTick ) % 48 == 0 ) ) { 1281 if ( m_nPatternTickPosition % 48 == 0 ) { 1282 float fPitch; 1283 float fVelocity; 1284 // ___INFOLOG( "Beat: " + to_string(m_nPatternTickPosition / 48 + 1) 1285 // + "@ " + to_string( tick ) ); 1286 if ( m_nPatternTickPosition == 0 ) { 1287 fPitch = 3; 1288 fVelocity = 1.0; 1289 EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 ); 1290 } else { 1291 fPitch = 0; 1292 fVelocity = 0.8; 1293 EventQueue::get_instance()->push_event( EVENT_METRONOME, 0 ); 1294 } 1295 if ( Preferences::get_instance()->m_bUseMetronome ) { 1296 m_pMetronomeInstrument->set_volume( 1297 Preferences::get_instance()->m_fMetronomeVolume 1298 ); 1299 Note *pMetronomeNote = new Note( m_pMetronomeInstrument, 1300 tick, 1301 fVelocity, 1302 0.5, 1303 0.5, 1304 -1, 1305 fPitch 1306 ); 1307 m_pMetronomeInstrument->enqueue(); 1308 m_songNoteQueue.push( pMetronomeNote ); 1309 } 1310 } 1311 1312 // update the notes queue 1313 if ( m_pPlayingPatterns->size() != 0 ) { 1314 for ( unsigned nPat = 0 ; 1315 nPat < m_pPlayingPatterns->size() ; 1316 ++nPat ) { 1317 Pattern *pPattern = m_pPlayingPatterns->get( nPat ); 1318 assert( pPattern != NULL ); 1319 Pattern::notes_t* notes = (Pattern::notes_t*)pPattern->get_notes(); 1320 // Delete notes before attempting to play them 1321 if ( doErase ) { 1322 FOREACH_NOTE_IT_BOUND(notes,it,m_nPatternTickPosition) { 1323 Note* pNote = it->second; 1324 assert( pNote != NULL ); 1325 if ( pNote->get_just_recorded() == false ) { 1326 delete pNote; 1327 notes->erase( it ); 1328 } 1329 } 1330 } 1331 1332 // Now play notes 1333 FOREACH_NOTE_CST_IT_BOUND(notes,it,m_nPatternTickPosition) { 1334 Note *pNote = it->second; 1335 if ( pNote ) { 1336 pNote->set_just_recorded( false ); 1337 int nOffset = 0; 1338 1339 // Swing 1340 float fSwingFactor = m_pSong->get_swing_factor(); 1341 1342 if ( ( ( m_nPatternTickPosition % 12 ) == 0 ) 1343 && ( ( m_nPatternTickPosition % 24 ) != 0 ) ) { 1344 // da l'accento al tick 4, 12, 20, 36... 1345 nOffset += ( int )( 1346 6.0 1347 * m_pAudioDriver->m_transport.m_nTickSize 1348 * fSwingFactor 1349 ); 1350 } 1351 1352 // Humanize - Time parameter 1353 if ( m_pSong->get_humanize_time_value() != 0 ) { 1354 nOffset += ( int )( 1355 getGaussian( 0.3 ) 1356 * m_pSong->get_humanize_time_value() 1357 * nMaxTimeHumanize 1358 ); 1359 } 1360 //~ 1361 // Lead or Lag - timing parameter 1362 nOffset += (int) ( pNote->get_lead_lag() 1363 * nLeadLagFactor); 1364 //~ 1365 1366 if((tick == 0) && (nOffset < 0)) { 1367 nOffset = 0; 1368 } 1369 Note *pCopiedNote = new Note( pNote ); 1370 pCopiedNote->set_position( tick ); 1371 1372 // humanize time 1373 pCopiedNote->set_humanize_delay( nOffset ); 1374 pNote->get_instrument()->enqueue(); 1375 m_songNoteQueue.push( pCopiedNote ); 1376 //pCopiedNote->dumpInfo(); 1377 } 1378 } 1379 } 1380 } 1381 ++tick; 1382 } 1383 1384 1385 // audioEngine_process must send the pattern change event after mutex unlock 1386 if ( bSendPatternChange ) { 1387 return 2; 1388 } 1389 return 0; 1081 static int nLastTick = -1; 1082 bool bSendPatternChange = false; 1083 int nMaxTimeHumanize = 2000; 1084 int nLeadLagFactor = m_pAudioDriver->m_transport.m_nTickSize * 5; // 5 ticks 1085 1086 unsigned int framepos; 1087 if ( m_audioEngineState == STATE_PLAYING ) { 1088 framepos = m_pAudioDriver->m_transport.m_nFrames; 1089 } else { 1090 // use this to support realtime events when not playing 1091 framepos = m_nRealtimeFrames; 1092 } 1093 1094 int tickNumber_start = 0; 1095 1096 // We need to look ahead in the song for notes with negative offsets 1097 // from LeadLag or Humanize. When starting from the beginning, we prime 1098 // the note queue with notes between 0 and nFrames plus 1099 // lookahead. lookahead should be equal or greater than the 1100 // nLeadLagFactor + nMaxTimeHumanize. 1101 int lookahead = nLeadLagFactor + nMaxTimeHumanize + 1; 1102 m_nLookaheadFrames = lookahead; 1103 if ( framepos == 0 1104 || ( m_audioEngineState == STATE_PLAYING 1105 && m_pSong->get_mode() == Song::SONG_MODE 1106 && m_nSongPos == -1 ) ) { 1107 tickNumber_start = (int)( framepos 1108 / m_pAudioDriver->m_transport.m_nTickSize ); 1109 } 1110 else { 1111 tickNumber_start = (int)( (framepos + lookahead) 1112 / m_pAudioDriver->m_transport.m_nTickSize ); 1113 } 1114 int tickNumber_end = (int)( (framepos + nFrames + lookahead) 1115 / m_pAudioDriver->m_transport.m_nTickSize ); 1116 1117 int tick = tickNumber_start; 1118 1119 // ___WARNINGLOG( "Lookahead: " + to_string( lookahead 1120 // / m_pAudioDriver->m_transport.m_nTickSize ) ); 1121 // get initial timestamp for first tick 1122 gettimeofday( &m_currentTickTime, NULL ); 1123 1124 1125 while ( tick <= tickNumber_end ) { 1126 if ( tick == nLastTick ) { 1127 ++tick; 1128 continue; 1129 } else { 1130 nLastTick = tick; 1131 } 1132 1133 1134 // midi events now get put into the m_songNoteQueue as well, 1135 // based on their timestamp 1136 while ( m_midiNoteQueue.size() > 0 ) { 1137 Note *note = m_midiNoteQueue[0]; 1138 1139 if ( ( int )note->get_position() <= tick ) { 1140 // printf ("tick=%d pos=%d\n", tick, note->getPosition()); 1141 m_midiNoteQueue.pop_front(); 1142 note->get_instrument()->enqueue(); 1143 m_songNoteQueue.push( note ); 1144 } else { 1145 break; 1146 } 1147 } 1148 1149 if ( m_audioEngineState != STATE_PLAYING ) { 1150 // only keep going if we're playing 1151 continue; 1152 } 1153 1154 // if ( m_nPatternStartTick == -1 ) { // for debugging pattern mode :s 1155 // ___WARNINGLOG( "m_nPatternStartTick == -1; tick = " 1156 // + to_string( tick ) ); 1157 // } 1158 1159 1160 // SONG MODE 1161 bool doErase = m_audioEngineState == STATE_PLAYING 1162 && Preferences::get_instance()->getRecordEvents() 1163 && Preferences::get_instance()->getDestructiveRecord() 1164 && Preferences::get_instance()->m_nRecPreDelete == 0; 1165 if ( m_pSong->get_mode() == Song::SONG_MODE ) { 1166 if ( m_pSong->get_pattern_group_vector()->size() == 0 ) { 1167 // there's no song!! 1168 ___ERRORLOG( "no patterns in song." ); 1169 m_pAudioDriver->stop(); 1170 return -1; 1171 } 1172 1173 m_nSongPos = findPatternInTick( tick, 1174 m_pSong->is_loop_enabled(), 1175 &m_nPatternStartTick ); 1176 if ( m_nSongSizeInTicks != 0 ) { 1177 m_nPatternTickPosition = ( tick - m_nPatternStartTick ) 1178 % m_nSongSizeInTicks; 1179 } else { 1180 m_nPatternTickPosition = tick - m_nPatternStartTick; 1181 } 1182 1183 1184 if ( m_nPatternTickPosition == 0 ) { 1185 bSendPatternChange = true; 1186 } 1187 1188 // PatternList *pPatternList = 1189 // (*(m_pSong->getPatternGroupVector()))[m_nSongPos]; 1190 if ( m_nSongPos == -1 ) { 1191 ___INFOLOG( "song pos = -1" ); 1192 if ( m_pSong->is_loop_enabled() == true ) { 1193 m_nSongPos = findPatternInTick( 0, 1194 true, 1195 &m_nPatternStartTick ); 1196 } else { 1197 1198 ___INFOLOG( "End of Song" ); 1199 1200 if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ 1201 Hydrogen::get_instance()->getMidiOutput()->handleQueueAllNoteOff(); 1202 } 1203 1204 return -1; 1205 } 1206 } 1207 PatternList *pPatternList = ( *( m_pSong->get_pattern_group_vector() ) )[m_nSongPos]; 1208 m_pPlayingPatterns->clear(); 1209 for ( int i=0; i< pPatternList->size(); ++i ) { 1210 Pattern* pattern = pPatternList->get(i); 1211 m_pPlayingPatterns->add( pattern ); 1212 pattern->extand_with_flattened_virtual_patterns( m_pPlayingPatterns ); 1213 } 1214 // Set destructive record depending on punch area 1215 doErase = doErase && Preferences::get_instance()->inPunchArea(m_nSongPos); 1216 } 1217 // PATTERN MODE 1218 else if ( m_pSong->get_mode() == Song::PATTERN_MODE ) { 1219 // per ora considero solo il primo pattern, se ce ne 1220 // saranno piu' di uno bisognera' prendere quello piu' 1221 // piccolo 1222 1223 //m_nPatternTickPosition = tick % m_pCurrentPattern->getSize(); 1224 int nPatternSize = MAX_NOTES; 1225 1226 1227 if ( Preferences::get_instance()->patternModePlaysSelected() ) 1228 { 1229 m_pPlayingPatterns->clear(); 1230 Pattern * pattern = m_pSong->get_pattern_list()->get(m_nSelectedPatternNumber); 1231 m_pPlayingPatterns->add( pattern ); 1232 pattern->extand_with_flattened_virtual_patterns( m_pPlayingPatterns ); 1233 } 1234 1235 1236 if ( m_pPlayingPatterns->size() != 0 ) { 1237 Pattern *pFirstPattern = m_pPlayingPatterns->get( 0 ); 1238 nPatternSize = pFirstPattern->get_length(); 1239 } 1240 1241 if ( nPatternSize == 0 ) { 1242 ___ERRORLOG( "nPatternSize == 0" ); 1243 } 1244 1245 if ( ( tick == m_nPatternStartTick + nPatternSize ) 1246 || ( m_nPatternStartTick == -1 ) ) { 1247 if ( m_pNextPatterns->size() > 0 ) { 1248 Pattern * p; 1249 for ( uint i = 0; 1250 i < m_pNextPatterns->size(); 1251 i++ ) { 1252 p = m_pNextPatterns->get( i ); 1253 // ___WARNINGLOG( QString( "Got pattern # %1" ) 1254 // .arg( i + 1 ) ); 1255 // if the pattern isn't playing 1256 // already, start it now. 1257 if ( ( m_pPlayingPatterns->del( p ) ) == NULL ) { 1258 m_pPlayingPatterns->add( p ); 1259 } 1260 } 1261 m_pNextPatterns->clear(); 1262 bSendPatternChange = true; 1263 } 1264 if ( m_nPatternStartTick == -1 ) { 1265 m_nPatternStartTick = tick - (tick % nPatternSize); 1266 // ___WARNINGLOG( "set Pattern Start Tick to " 1267 // + to_string( m_nPatternStartTick ) ); 1268 } else { 1269 m_nPatternStartTick = tick; 1270 } 1271 } 1272 m_nPatternTickPosition = tick - m_nPatternStartTick; 1273 if ( m_nPatternTickPosition > nPatternSize ) { 1274 m_nPatternTickPosition = tick % nPatternSize; 1275 } 1276 } 1277 1278 // metronome 1279 // if ( ( m_nPatternStartTick == tick ) 1280 // || ( ( tick - m_nPatternStartTick ) % 48 == 0 ) ) { 1281 if ( m_nPatternTickPosition % 48 == 0 ) { 1282 float fPitch; 1283 float fVelocity; 1284 // ___INFOLOG( "Beat: " + to_string(m_nPatternTickPosition / 48 + 1) 1285 // + "@ " + to_string( tick ) ); 1286 if ( m_nPatternTickPosition == 0 ) { 1287 fPitch = 3; 1288 fVelocity = 1.0; 1289 EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 ); 1290 } else { 1291 fPitch = 0; 1292 fVelocity = 0.8; 1293 EventQueue::get_instance()->push_event( EVENT_METRONOME, 0 ); 1294 } 1295 if ( Preferences::get_instance()->m_bUseMetronome ) { 1296 m_pMetronomeInstrument->set_volume( 1297 Preferences::get_instance()->m_fMetronomeVolume 1298 ); 1299 Note *pMetronomeNote = new Note( m_pMetronomeInstrument, 1300 tick, 1301 fVelocity, 1302 0.5, 1303 0.5, 1304 -1, 1305 fPitch 1306 ); 1307 m_pMetronomeInstrument->enqueue(); 1308 m_songNoteQueue.push( pMetronomeNote ); 1309 } 1310 } 1311 1312 // update the notes queue 1313 if ( m_pPlayingPatterns->size() != 0 ) { 1314 for ( unsigned nPat = 0 ; 1315 nPat < m_pPlayingPatterns->size() ; 1316 ++nPat ) { 1317 Pattern *pPattern = m_pPlayingPatterns->get( nPat ); 1318 assert( pPattern != NULL ); 1319 Pattern::notes_t* notes = (Pattern::notes_t*)pPattern->get_notes(); 1320 // Delete notes before attempting to play them 1321 if ( doErase ) { 1322 FOREACH_NOTE_IT_BOUND(notes,it,m_nPatternTickPosition) { 1323 Note* pNote = it->second; 1324 assert( pNote != NULL ); 1325 if ( pNote->get_just_recorded() == false ) { 1326 EventQueue::AddMidiNoteVector noteAction; 1327 noteAction.m_column = pNote->get_position(); 1328 noteAction.m_row = pNote->get_instrument_id(); 1329 noteAction.m_pattern = nPat; 1330 noteAction.f_velocity = pNote->get_velocity(); 1331 noteAction.f_pan_L = pNote->get_pan_l(); 1332 noteAction.f_pan_R = pNote->get_pan_r(); 1333 noteAction.m_length = -1; 1334 noteAction.no_octaveKeyVal = pNote->get_octave(); 1335 noteAction.nk_noteKeyVal = pNote->get_key(); 1336 noteAction.b_isInstrumentMode = false; 1337 noteAction.b_isMidi = false; 1338 noteAction.b_noteExist = false; 1339 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 1340 } 1341 } 1342 } 1343 1344 // Now play notes 1345 FOREACH_NOTE_CST_IT_BOUND(notes,it,m_nPatternTickPosition) { 1346 Note *pNote = it->second; 1347 if ( pNote ) { 1348 pNote->set_just_recorded( false ); 1349 int nOffset = 0; 1350 1351 // Swing 1352 float fSwingFactor = m_pSong->get_swing_factor(); 1353 1354 if ( ( ( m_nPatternTickPosition % 12 ) == 0 ) 1355 && ( ( m_nPatternTickPosition % 24 ) != 0 ) ) { 1356 // da l'accento al tick 4, 12, 20, 36... 1357 nOffset += ( int )( 1358 6.0 1359 * m_pAudioDriver->m_transport.m_nTickSize 1360 * fSwingFactor 1361 ); 1362 } 1363 1364 // Humanize - Time parameter 1365 if ( m_pSong->get_humanize_time_value() != 0 ) { 1366 nOffset += ( int )( 1367 getGaussian( 0.3 ) 1368 * m_pSong->get_humanize_time_value() 1369 * nMaxTimeHumanize 1370 ); 1371 } 1372 //~ 1373 // Lead or Lag - timing parameter 1374 nOffset += (int) ( pNote->get_lead_lag() 1375 * nLeadLagFactor); 1376 //~ 1377 1378 if((tick == 0) && (nOffset < 0)) { 1379 nOffset = 0; 1380 } 1381 Note *pCopiedNote = new Note( pNote ); 1382 pCopiedNote->set_position( tick ); 1383 1384 // humanize time 1385 pCopiedNote->set_humanize_delay( nOffset ); 1386 pNote->get_instrument()->enqueue(); 1387 m_songNoteQueue.push( pCopiedNote ); 1388 //pCopiedNote->dumpInfo(); 1389 } 1390 } 1391 } 1392 } 1393 ++tick; 1394 } 1395 1396 1397 // audioEngine_process must send the pattern change event after mutex unlock 1398 if ( bSendPatternChange ) { 1399 return 2; 1400 } 1401 return 0; 1390 1402 } 1391 1403 … … 1395 1407 inline int findPatternInTick( int nTick, bool bLoopMode, int *pPatternStartTick ) 1396 1408 { 1397 assert( m_pSong );1398 1399 int nTotalTick = 0;1400 m_nSongSizeInTicks = 0;1401 1402 std::vector<PatternList*> *pPatternColumns = m_pSong->get_pattern_group_vector();1403 int nColumns = pPatternColumns->size();1404 1405 int nPatternSize;1406 for ( int i = 0; i < nColumns; ++i ) {1407 PatternList *pColumn = ( *pPatternColumns )[ i ];1408 if ( pColumn->size() != 0 ) {1409 // tengo in considerazione solo il primo pattern. I1410 // pattern nel gruppo devono avere la stessa lunghezza.1411 nPatternSize = pColumn->get( 0 )->get_length();1412 } else {1413 nPatternSize = MAX_NOTES;1414 }1415 1416 if ( ( nTick >= nTotalTick ) && ( nTick < nTotalTick + nPatternSize ) ) {1417 ( *pPatternStartTick ) = nTotalTick;1418 return i;1419 }1420 nTotalTick += nPatternSize;1421 }1422 1423 if ( bLoopMode ) {1424 m_nSongSizeInTicks = nTotalTick;1425 int nLoopTick = 0;1426 if ( m_nSongSizeInTicks != 0 ) {1427 nLoopTick = nTick % m_nSongSizeInTicks;1428 }1429 nTotalTick = 0;1430 for ( int i = 0; i < nColumns; ++i ) {1431 PatternList *pColumn = ( *pPatternColumns )[ i ];1432 if ( pColumn->size() != 0 ) {1433 // tengo in considerazione solo il primo1434 // pattern. I pattern nel gruppo devono avere la1435 // stessa lunghezza.1436 nPatternSize = pColumn->get( 0 )->get_length();1437 } else {1438 nPatternSize = MAX_NOTES;1439 }1440 1441 if ( ( nLoopTick >= nTotalTick )1442 && ( nLoopTick < nTotalTick + nPatternSize ) ) {1443 ( *pPatternStartTick ) = nTotalTick;1444 return i;1445 }1446 nTotalTick += nPatternSize;1447 }1448 }1449 1450 QString err = QString( "[findPatternInTick] tick = %1. No pattern found" ).arg( QString::number(nTick) );1451 ___ERRORLOG( err );1452 return -1;1409 assert( m_pSong ); 1410 1411 int nTotalTick = 0; 1412 m_nSongSizeInTicks = 0; 1413 1414 std::vector<PatternList*> *pPatternColumns = m_pSong->get_pattern_group_vector(); 1415 int nColumns = pPatternColumns->size(); 1416 1417 int nPatternSize; 1418 for ( int i = 0; i < nColumns; ++i ) { 1419 PatternList *pColumn = ( *pPatternColumns )[ i ]; 1420 if ( pColumn->size() != 0 ) { 1421 // tengo in considerazione solo il primo pattern. I 1422 // pattern nel gruppo devono avere la stessa lunghezza. 1423 nPatternSize = pColumn->get( 0 )->get_length(); 1424 } else { 1425 nPatternSize = MAX_NOTES; 1426 } 1427 1428 if ( ( nTick >= nTotalTick ) && ( nTick < nTotalTick + nPatternSize ) ) { 1429 ( *pPatternStartTick ) = nTotalTick; 1430 return i; 1431 } 1432 nTotalTick += nPatternSize; 1433 } 1434 1435 if ( bLoopMode ) { 1436 m_nSongSizeInTicks = nTotalTick; 1437 int nLoopTick = 0; 1438 if ( m_nSongSizeInTicks != 0 ) { 1439 nLoopTick = nTick % m_nSongSizeInTicks; 1440 } 1441 nTotalTick = 0; 1442 for ( int i = 0; i < nColumns; ++i ) { 1443 PatternList *pColumn = ( *pPatternColumns )[ i ]; 1444 if ( pColumn->size() != 0 ) { 1445 // tengo in considerazione solo il primo 1446 // pattern. I pattern nel gruppo devono avere la 1447 // stessa lunghezza. 1448 nPatternSize = pColumn->get( 0 )->get_length(); 1449 } else { 1450 nPatternSize = MAX_NOTES; 1451 } 1452 1453 if ( ( nLoopTick >= nTotalTick ) 1454 && ( nLoopTick < nTotalTick + nPatternSize ) ) { 1455 ( *pPatternStartTick ) = nTotalTick; 1456 return i; 1457 } 1458 nTotalTick += nPatternSize; 1459 } 1460 } 1461 1462 QString err = QString( "[findPatternInTick] tick = %1. No pattern found" ).arg( QString::number(nTick) ); 1463 ___ERRORLOG( err ); 1464 return -1; 1453 1465 } 1454 1466 … … 1457 1469 void audioEngine_noteOn( Note *note ) 1458 1470 { 1459 // check current state1460 if ( ( m_audioEngineState != STATE_READY )1461 && ( m_audioEngineState != STATE_PLAYING ) ) {1462 ___ERRORLOG( "Error the audio engine is not in READY state" );1463 delete note;1464 return;1465 }1466 1467 m_midiNoteQueue.push_back( note );1471 // check current state 1472 if ( ( m_audioEngineState != STATE_READY ) 1473 && ( m_audioEngineState != STATE_PLAYING ) ) { 1474 ___ERRORLOG( "Error the audio engine is not in READY state" ); 1475 delete note; 1476 return; 1477 } 1478 1479 m_midiNoteQueue.push_back( note ); 1468 1480 } 1469 1481 … … 1472 1484 void audioEngine_noteOff( Note *note ) 1473 1485 { 1474 if ( note == NULL ) {1475 ___ERRORLOG( "Error, note == NULL" );1476 }1477 1478 AudioEngine::get_instance()->lock( RIGHT_HERE );1479 1480 // check current state1481 if ( ( m_audioEngineState != STATE_READY )1482 && ( m_audioEngineState != STATE_PLAYING ) ) {1483 ___ERRORLOG( "Error the audio engine is not in READY state" );1484 delete note;1485 AudioEngine::get_instance()->unlock();1486 return;1487 }1486 if ( note == NULL ) { 1487 ___ERRORLOG( "Error, note == NULL" ); 1488 } 1489 1490 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1491 1492 // check current state 1493 if ( ( m_audioEngineState != STATE_READY ) 1494 && ( m_audioEngineState != STATE_PLAYING ) ) { 1495 ___ERRORLOG( "Error the audio engine is not in READY state" ); 1496 delete note; 1497 AudioEngine::get_instance()->unlock(); 1498 return; 1499 } 1488 1500 1489 1501 // AudioEngine::get_instance()->get_sampler()->note_off( note ); 1490 AudioEngine::get_instance()->unlock();1491 delete note;1502 AudioEngine::get_instance()->unlock(); 1503 delete note; 1492 1504 1493 1505 } … … 1503 1515 AudioOutput* createDriver( const QString& sDriver ) 1504 1516 { 1505 ___INFOLOG( QString( "Driver: '%1'" ).arg( sDriver ) );1506 Preferences *pPref = Preferences::get_instance();1507 AudioOutput *pDriver = NULL;1508 1509 if ( sDriver == "Oss" ) {1510 pDriver = new OssDriver( audioEngine_process );1511 if ( pDriver->class_name() == NullDriver::class_name() ) {1512 delete pDriver;1513 pDriver = NULL;1514 }1515 } else if ( sDriver == "Jack" ) {1516 pDriver = new JackOutput( audioEngine_process );1517 if ( pDriver->class_name() == NullDriver::class_name() ) {1518 delete pDriver;1519 pDriver = NULL;1520 } else {1517 ___INFOLOG( QString( "Driver: '%1'" ).arg( sDriver ) ); 1518 Preferences *pPref = Preferences::get_instance(); 1519 AudioOutput *pDriver = NULL; 1520 1521 if ( sDriver == "Oss" ) { 1522 pDriver = new OssDriver( audioEngine_process ); 1523 if ( pDriver->class_name() == NullDriver::class_name() ) { 1524 delete pDriver; 1525 pDriver = NULL; 1526 } 1527 } else if ( sDriver == "Jack" ) { 1528 pDriver = new JackOutput( audioEngine_process ); 1529 if ( pDriver->class_name() == NullDriver::class_name() ) { 1530 delete pDriver; 1531 pDriver = NULL; 1532 } else { 1521 1533 #ifdef H2CORE_HAVE_JACK 1522 static_cast<JackOutput*>(pDriver)->setConnectDefaults(1523 Preferences::get_instance()->m_bJackConnectDefaults1524 );1534 static_cast<JackOutput*>(pDriver)->setConnectDefaults( 1535 Preferences::get_instance()->m_bJackConnectDefaults 1536 ); 1525 1537 #endif 1526 }1527 } else if ( sDriver == "Alsa" ) {1528 pDriver = new AlsaAudioDriver( audioEngine_process );1529 if ( pDriver->class_name() == NullDriver::class_name() ) {1530 delete pDriver;1531 pDriver = NULL;1532 }1533 } else if ( sDriver == "PortAudio" ) {1534 pDriver = new PortAudioDriver( audioEngine_process );1535 if ( pDriver->class_name() == NullDriver::class_name() ) {1536 delete pDriver;1537 pDriver = NULL;1538 }1539 }1540 //#ifdef Q_OS_MACX1541 else if ( sDriver == "CoreAudio" ) {1542 ___INFOLOG( "Creating CoreAudioDriver" );1543 pDriver = new CoreAudioDriver( audioEngine_process );1544 if ( pDriver->class_name() == NullDriver::class_name() ) {1545 delete pDriver;1546 pDriver = NULL;1547 }1548 }1549 //#endif1550 else if ( sDriver == "Fake" ) {1551 ___WARNINGLOG( "*** Using FAKE audio driver ***" );1552 pDriver = new FakeDriver( audioEngine_process );1553 } else {1554 ___ERRORLOG( "Unknown driver " + sDriver );1555 audioEngine_raiseError( Hydrogen::UNKNOWN_DRIVER );1556 }1557 1558 if ( pDriver ) {1559 // initialize the audio driver1560 int res = pDriver->init( pPref->m_nBufferSize );1561 if ( res != 0 ) {1562 ___ERRORLOG( "Error starting audio driver [audioDriver::init()]" );1563 delete pDriver;1564 pDriver = NULL;1565 }1566 }1567 1568 return pDriver;1538 } 1539 } else if ( sDriver == "Alsa" ) { 1540 pDriver = new AlsaAudioDriver( audioEngine_process ); 1541 if ( pDriver->class_name() == NullDriver::class_name() ) { 1542 delete pDriver; 1543 pDriver = NULL; 1544 } 1545 } else if ( sDriver == "PortAudio" ) { 1546 pDriver = new PortAudioDriver( audioEngine_process ); 1547 if ( pDriver->class_name() == NullDriver::class_name() ) { 1548 delete pDriver; 1549 pDriver = NULL; 1550 } 1551 } 1552 //#ifdef Q_OS_MACX 1553 else if ( sDriver == "CoreAudio" ) { 1554 ___INFOLOG( "Creating CoreAudioDriver" ); 1555 pDriver = new CoreAudioDriver( audioEngine_process ); 1556 if ( pDriver->class_name() == NullDriver::class_name() ) { 1557 delete pDriver; 1558 pDriver = NULL; 1559 } 1560 } 1561 //#endif 1562 else if ( sDriver == "Fake" ) { 1563 ___WARNINGLOG( "*** Using FAKE audio driver ***" ); 1564 pDriver = new FakeDriver( audioEngine_process ); 1565 } else { 1566 ___ERRORLOG( "Unknown driver " + sDriver ); 1567 audioEngine_raiseError( Hydrogen::UNKNOWN_DRIVER ); 1568 } 1569 1570 if ( pDriver ) { 1571 // initialize the audio driver 1572 int res = pDriver->init( pPref->m_nBufferSize ); 1573 if ( res != 0 ) { 1574 ___ERRORLOG( "Error starting audio driver [audioDriver::init()]" ); 1575 delete pDriver; 1576 pDriver = NULL; 1577 } 1578 } 1579 1580 return pDriver; 1569 1581 } 1570 1582 … … 1573 1585 void audioEngine_startAudioDrivers() 1574 1586 { 1575 Preferences *preferencesMng = Preferences::get_instance();1576 1577 AudioEngine::get_instance()->lock( RIGHT_HERE );1578 QMutexLocker mx(&mutex_OutputPointer);1579 1580 ___INFOLOG( "[audioEngine_startAudioDrivers]" );1581 1582 // check current state1583 if ( m_audioEngineState != STATE_INITIALIZED ) {1584 ___ERRORLOG( QString( "Error the audio engine is not in INITIALIZED"1587 Preferences *preferencesMng = Preferences::get_instance(); 1588 1589 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1590 QMutexLocker mx(&mutex_OutputPointer); 1591 1592 ___INFOLOG( "[audioEngine_startAudioDrivers]" ); 1593 1594 // check current state 1595 if ( m_audioEngineState != STATE_INITIALIZED ) { 1596 ___ERRORLOG( QString( "Error the audio engine is not in INITIALIZED" 1585 1597 " state. state=%1" ) 1586 1598 .arg( m_audioEngineState ) ); 1587 AudioEngine::get_instance()->unlock();1588 return;1589 }1590 1591 if ( m_pAudioDriver ) { // check if the audio m_pAudioDriver is still alive1592 ___ERRORLOG( "The audio driver is still alive" );1593 }1594 if ( m_pMidiDriver ) { // check if midi driver is still alive1595 ___ERRORLOG( "The MIDI driver is still active" );1596 }1597 1598 1599 QString sAudioDriver = preferencesMng->m_sAudioDriver;1600 // sAudioDriver = "Auto";1601 if ( sAudioDriver == "Auto" ) {1602 if ( ( m_pAudioDriver = createDriver( "Jack" ) ) == NULL ) {1603 if ( ( m_pAudioDriver = createDriver( "Alsa" ) ) == NULL ) {1604 if ( ( m_pAudioDriver = createDriver( "CoreAudio" ) ) == NULL ) {1605 if ( ( m_pAudioDriver = createDriver( "PortAudio" ) ) == NULL ) {1606 if ( ( m_pAudioDriver = createDriver( "Oss" ) ) == NULL ) {1607 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );1608 ___ERRORLOG( "Error starting audio driver" );1609 ___ERRORLOG( "Using the NULL output audio driver" );1610 1611 // use the NULL output driver1612 m_pAudioDriver = new NullDriver( audioEngine_process );1613 m_pAudioDriver->init( 0 );1614 }1615 }1616 }1617 }1618 }1619 } else {1620 m_pAudioDriver = createDriver( sAudioDriver );1621 if ( m_pAudioDriver == NULL ) {1622 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );1623 ___ERRORLOG( "Error starting audio driver" );1624 ___ERRORLOG( "Using the NULL output audio driver" );1625 1626 // use the NULL output driver1627 m_pAudioDriver = new NullDriver( audioEngine_process );1628 m_pAudioDriver->init( 0 );1629 }1630 }1631 1632 if ( preferencesMng->m_sMidiDriver == "ALSA" ) {1599 AudioEngine::get_instance()->unlock(); 1600 return; 1601 } 1602 1603 if ( m_pAudioDriver ) { // check if the audio m_pAudioDriver is still alive 1604 ___ERRORLOG( "The audio driver is still alive" ); 1605 } 1606 if ( m_pMidiDriver ) { // check if midi driver is still alive 1607 ___ERRORLOG( "The MIDI driver is still active" ); 1608 } 1609 1610 1611 QString sAudioDriver = preferencesMng->m_sAudioDriver; 1612 // sAudioDriver = "Auto"; 1613 if ( sAudioDriver == "Auto" ) { 1614 if ( ( m_pAudioDriver = createDriver( "Jack" ) ) == NULL ) { 1615 if ( ( m_pAudioDriver = createDriver( "Alsa" ) ) == NULL ) { 1616 if ( ( m_pAudioDriver = createDriver( "CoreAudio" ) ) == NULL ) { 1617 if ( ( m_pAudioDriver = createDriver( "PortAudio" ) ) == NULL ) { 1618 if ( ( m_pAudioDriver = createDriver( "Oss" ) ) == NULL ) { 1619 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER ); 1620 ___ERRORLOG( "Error starting audio driver" ); 1621 ___ERRORLOG( "Using the NULL output audio driver" ); 1622 1623 // use the NULL output driver 1624 m_pAudioDriver = new NullDriver( audioEngine_process ); 1625 m_pAudioDriver->init( 0 ); 1626 } 1627 } 1628 } 1629 } 1630 } 1631 } else { 1632 m_pAudioDriver = createDriver( sAudioDriver ); 1633 if ( m_pAudioDriver == NULL ) { 1634 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER ); 1635 ___ERRORLOG( "Error starting audio driver" ); 1636 ___ERRORLOG( "Using the NULL output audio driver" ); 1637 1638 // use the NULL output driver 1639 m_pAudioDriver = new NullDriver( audioEngine_process ); 1640 m_pAudioDriver->init( 0 ); 1641 } 1642 } 1643 1644 if ( preferencesMng->m_sMidiDriver == "ALSA" ) { 1633 1645 #ifdef H2CORE_HAVE_ALSA 1634 // Create MIDI driver1635 AlsaMidiDriver *alsaMidiDriver = new AlsaMidiDriver();1636 m_pMidiDriverOut = alsaMidiDriver;1637 m_pMidiDriver = alsaMidiDriver;1638 m_pMidiDriver->open();1639 m_pMidiDriver->setActive( true );1646 // Create MIDI driver 1647 AlsaMidiDriver *alsaMidiDriver = new AlsaMidiDriver(); 1648 m_pMidiDriverOut = alsaMidiDriver; 1649 m_pMidiDriver = alsaMidiDriver; 1650 m_pMidiDriver->open(); 1651 m_pMidiDriver->setActive( true ); 1640 1652 #endif 1641 } else if ( preferencesMng->m_sMidiDriver == "PortMidi" ) {1653 } else if ( preferencesMng->m_sMidiDriver == "PortMidi" ) { 1642 1654 #ifdef H2CORE_HAVE_PORTMIDI 1643 m_pMidiDriver = new PortMidiDriver();1644 m_pMidiDriver->open();1645 m_pMidiDriver->setActive( true );1655 m_pMidiDriver = new PortMidiDriver(); 1656 m_pMidiDriver->open(); 1657 m_pMidiDriver->setActive( true ); 1646 1658 #endif 1647 } else if ( preferencesMng->m_sMidiDriver == "CoreMidi" ) {1659 } else if ( preferencesMng->m_sMidiDriver == "CoreMidi" ) { 1648 1660 #ifdef H2CORE_HAVE_COREMIDI 1649 m_pMidiDriver = new CoreMidiDriver();1650 m_pMidiDriver->open();1651 m_pMidiDriver->setActive( true );1661 m_pMidiDriver = new CoreMidiDriver(); 1662 m_pMidiDriver->open(); 1663 m_pMidiDriver->setActive( true ); 1652 1664 #endif 1653 } else if ( preferencesMng->m_sMidiDriver == "JackMidi" ) {1665 } else if ( preferencesMng->m_sMidiDriver == "JackMidi" ) { 1654 1666 #ifdef H2CORE_HAVE_JACK 1655 JackMidiDriver *jackMidiDriver = new JackMidiDriver();1656 m_pMidiDriverOut = jackMidiDriver;1657 m_pMidiDriver = jackMidiDriver;1658 m_pMidiDriver->open();1659 m_pMidiDriver->setActive( true );1667 JackMidiDriver *jackMidiDriver = new JackMidiDriver(); 1668 m_pMidiDriverOut = jackMidiDriver; 1669 m_pMidiDriver = jackMidiDriver; 1670 m_pMidiDriver->open(); 1671 m_pMidiDriver->setActive( true ); 1660 1672 #endif 1661 }1662 1663 // change the current audio engine state1664 if ( m_pSong == NULL ) {1665 m_audioEngineState = STATE_PREPARED;1666 } else {1667 m_audioEngineState = STATE_READY;1668 }1669 1670 1671 if ( m_pSong ) {1672 m_pAudioDriver->setBpm( m_pSong->__bpm );1673 }1674 1675 if ( m_audioEngineState == STATE_PREPARED ) {1676 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED );1677 } else if ( m_audioEngineState == STATE_READY ) {1678 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY );1679 }1680 1681 // Unlocking earlier might execute the jack process() callback before we1682 // are fully initialized.1683 mx.unlock();1684 AudioEngine::get_instance()->unlock();1685 1686 if ( m_pAudioDriver ) {1687 int res = m_pAudioDriver->connect();1688 if ( res != 0 ) {1689 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER );1690 ___ERRORLOG( "Error starting audio driver [audioDriver::connect()]" );1691 ___ERRORLOG( "Using the NULL output audio driver" );1692 1693 mx.relock();1694 delete m_pAudioDriver;1695 m_pAudioDriver = new NullDriver( audioEngine_process );1696 mx.unlock();1697 m_pAudioDriver->init( 0 );1698 m_pAudioDriver->connect();1699 }1700 1701 if ( ( m_pMainBuffer_L = m_pAudioDriver->getOut_L() ) == NULL ) {1702 ___ERRORLOG( "m_pMainBuffer_L == NULL" );1703 }1704 if ( ( m_pMainBuffer_R = m_pAudioDriver->getOut_R() ) == NULL ) {1705 ___ERRORLOG( "m_pMainBuffer_R == NULL" );1706 }1673 } 1674 1675 // change the current audio engine state 1676 if ( m_pSong == NULL ) { 1677 m_audioEngineState = STATE_PREPARED; 1678 } else { 1679 m_audioEngineState = STATE_READY; 1680 } 1681 1682 1683 if ( m_pSong ) { 1684 m_pAudioDriver->setBpm( m_pSong->__bpm ); 1685 } 1686 1687 if ( m_audioEngineState == STATE_PREPARED ) { 1688 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_PREPARED ); 1689 } else if ( m_audioEngineState == STATE_READY ) { 1690 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_READY ); 1691 } 1692 1693 // Unlocking earlier might execute the jack process() callback before we 1694 // are fully initialized. 1695 mx.unlock(); 1696 AudioEngine::get_instance()->unlock(); 1697 1698 if ( m_pAudioDriver ) { 1699 int res = m_pAudioDriver->connect(); 1700 if ( res != 0 ) { 1701 audioEngine_raiseError( Hydrogen::ERROR_STARTING_DRIVER ); 1702 ___ERRORLOG( "Error starting audio driver [audioDriver::connect()]" ); 1703 ___ERRORLOG( "Using the NULL output audio driver" ); 1704 1705 mx.relock(); 1706 delete m_pAudioDriver; 1707 m_pAudioDriver = new NullDriver( audioEngine_process ); 1708 mx.unlock(); 1709 m_pAudioDriver->init( 0 ); 1710 m_pAudioDriver->connect(); 1711 } 1712 1713 if ( ( m_pMainBuffer_L = m_pAudioDriver->getOut_L() ) == NULL ) { 1714 ___ERRORLOG( "m_pMainBuffer_L == NULL" ); 1715 } 1716 if ( ( m_pMainBuffer_R = m_pAudioDriver->getOut_R() ) == NULL ) { 1717 ___ERRORLOG( "m_pMainBuffer_R == NULL" ); 1718 } 1707 1719 1708 1720 #ifdef H2CORE_HAVE_JACK 1709 audioEngine_renameJackPorts();1721 audioEngine_renameJackPorts(); 1710 1722 #endif 1711 1723 1712 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );1713 }1724 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() ); 1725 } 1714 1726 1715 1727 … … 1721 1733 void audioEngine_stopAudioDrivers() 1722 1734 { 1723 ___INFOLOG( "[audioEngine_stopAudioDrivers]" );1724 1725 // check current state1726 if ( m_audioEngineState == STATE_PLAYING ) {1727 audioEngine_stop();1728 }1729 1730 if ( ( m_audioEngineState != STATE_PREPARED )1731 && ( m_audioEngineState != STATE_READY ) ) {1732 ___ERRORLOG( QString( "Error: the audio engine is not in PREPARED"1735 ___INFOLOG( "[audioEngine_stopAudioDrivers]" ); 1736 1737 // check current state 1738 if ( m_audioEngineState == STATE_PLAYING ) { 1739 audioEngine_stop(); 1740 } 1741 1742 if ( ( m_audioEngineState != STATE_PREPARED ) 1743 && ( m_audioEngineState != STATE_READY ) ) { 1744 ___ERRORLOG( QString( "Error: the audio engine is not in PREPARED" 1733 1745 " or READY state. state=%1" ) 1734 1746 .arg( m_audioEngineState ) ); 1735 return;1736 }1737 1738 // change the current audio engine state1739 m_audioEngineState = STATE_INITIALIZED;1740 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED );1741 1742 AudioEngine::get_instance()->lock( RIGHT_HERE );1743 1744 // delete MIDI driver1745 if ( m_pMidiDriver ) {1746 m_pMidiDriver->close();1747 delete m_pMidiDriver;1748 m_pMidiDriver = NULL;1749 m_pMidiDriverOut = NULL;1750 }1751 1752 // delete audio driver1753 if ( m_pAudioDriver ) {1754 m_pAudioDriver->disconnect();1755 QMutexLocker mx( &mutex_OutputPointer );1756 delete m_pAudioDriver;1757 m_pAudioDriver = NULL;1758 mx.unlock();1759 }1760 1761 AudioEngine::get_instance()->unlock();1747 return; 1748 } 1749 1750 // change the current audio engine state 1751 m_audioEngineState = STATE_INITIALIZED; 1752 EventQueue::get_instance()->push_event( EVENT_STATE, STATE_INITIALIZED ); 1753 1754 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1755 1756 // delete MIDI driver 1757 if ( m_pMidiDriver ) { 1758 m_pMidiDriver->close(); 1759 delete m_pMidiDriver; 1760 m_pMidiDriver = NULL; 1761 m_pMidiDriverOut = NULL; 1762 } 1763 1764 // delete audio driver 1765 if ( m_pAudioDriver ) { 1766 m_pAudioDriver->disconnect(); 1767 QMutexLocker mx( &mutex_OutputPointer ); 1768 delete m_pAudioDriver; 1769 m_pAudioDriver = NULL; 1770 mx.unlock(); 1771 } 1772 1773 AudioEngine::get_instance()->unlock(); 1762 1774 } 1763 1775 … … 1767 1779 void audioEngine_restartAudioDrivers() 1768 1780 { 1769 audioEngine_stopAudioDrivers();1770 audioEngine_startAudioDrivers();1781 audioEngine_stopAudioDrivers(); 1782 audioEngine_startAudioDrivers(); 1771 1783 } 1772 1784 … … 1787 1799 1788 1800 Hydrogen::Hydrogen() 1789 : Object( __class_name )1790 { 1791 if ( __instance ) {1792 ERRORLOG( "Hydrogen audio engine is already running" );1793 throw H2Exception( "Hydrogen audio engine is already running" );1794 }1795 1796 INFOLOG( "[Hydrogen]" );1797 1798 hydrogenInstance = this;1799 // __instance = this;1800 audioEngine_init();1801 // Prevent double creation caused by calls from MIDI thread1802 __instance = this; 1803 audioEngine_startAudioDrivers();1804 for(int i = 0; i<128; i++){1805 m_nInstrumentLookupTable[i] = i;1806 }1801 : Object( __class_name ) 1802 { 1803 if ( __instance ) { 1804 ERRORLOG( "Hydrogen audio engine is already running" ); 1805 throw H2Exception( "Hydrogen audio engine is already running" ); 1806 } 1807 1808 INFOLOG( "[Hydrogen]" ); 1809 1810 hydrogenInstance = this; 1811 // __instance = this; 1812 audioEngine_init(); 1813 // Prevent double creation caused by calls from MIDI thread 1814 __instance = this; 1815 audioEngine_startAudioDrivers(); 1816 for(int i = 0; i<128; i++){ 1817 m_nInstrumentLookupTable[i] = i; 1818 } 1807 1819 1808 1820 } … … 1812 1824 Hydrogen::~Hydrogen() 1813 1825 { 1814 INFOLOG( "[~Hydrogen]" );1815 if ( m_audioEngineState == STATE_PLAYING ) {1816 audioEngine_stop();1817 }1818 removeSong();1819 audioEngine_stopAudioDrivers();1820 audioEngine_destroy();1821 __kill_instruments();1822 __instance = NULL;1826 INFOLOG( "[~Hydrogen]" ); 1827 if ( m_audioEngineState == STATE_PLAYING ) { 1828 audioEngine_stop(); 1829 } 1830 removeSong(); 1831 audioEngine_stopAudioDrivers(); 1832 audioEngine_destroy(); 1833 __kill_instruments(); 1834 __instance = NULL; 1823 1835 } 1824 1836 … … 1827 1839 void Hydrogen::create_instance() 1828 1840 { 1829 // Create all the other instances that we need1830 // ....and in the right order1831 Logger::create_instance();1832 MidiMap::create_instance();1833 Preferences::create_instance();1834 EventQueue::create_instance();1835 MidiActionManager::create_instance();1836 1837 if( __instance == 0 ) {1838 __instance = new Hydrogen;1839 }1840 1841 // See audioEngine_init() for:1842 // AudioEngine::create_instance();1843 // Effects::create_instance();1844 // Playlist::create_instance();1841 // Create all the other instances that we need 1842 // ....and in the right order 1843 Logger::create_instance(); 1844 MidiMap::create_instance(); 1845 Preferences::create_instance(); 1846 EventQueue::create_instance(); 1847 MidiActionManager::create_instance(); 1848 1849 if( __instance == 0 ) { 1850 __instance = new Hydrogen; 1851 } 1852 1853 // See audioEngine_init() for: 1854 // AudioEngine::create_instance(); 1855 // Effects::create_instance(); 1856 // Playlist::create_instance(); 1845 1857 } 1846 1858 … … 1848 1860 void Hydrogen::sequencer_play() 1849 1861 { 1850 getSong()->get_pattern_list()->set_to_old();1851 m_pAudioDriver->play();1862 getSong()->get_pattern_list()->set_to_old(); 1863 m_pAudioDriver->play(); 1852 1864 } 1853 1865 … … 1857 1869 void Hydrogen::sequencer_stop() 1858 1870 { 1859 if( Hydrogen::get_instance()->getMidiOutput() != NULL ){1860 Hydrogen::get_instance()->getMidiOutput()->handleQueueAllNoteOff();1861 }1862 1863 m_pAudioDriver->stop();1864 Preferences::get_instance()->setRecordEvents(false);1871 if( Hydrogen::get_instance()->getMidiOutput() != NULL ){ 1872 Hydrogen::get_instance()->getMidiOutput()->handleQueueAllNoteOff(); 1873 } 1874 1875 m_pAudioDriver->stop(); 1876 Preferences::get_instance()->setRecordEvents(false); 1865 1877 } 1866 1878 … … 1869 1881 void Hydrogen::setSong( Song *pSong ) 1870 1882 { 1871 audioEngine_setSong( pSong );1883 audioEngine_setSong( pSong ); 1872 1884 } 1873 1885 … … 1876 1888 void Hydrogen::removeSong() 1877 1889 { 1878 audioEngine_removeSong();1890 audioEngine_removeSong(); 1879 1891 } 1880 1892 … … 1883 1895 Song* Hydrogen::getSong() 1884 1896 { 1885 return m_pSong;1897 return m_pSong; 1886 1898 } 1887 1899 … … 1890 1902 void Hydrogen::midi_noteOn( Note *note ) 1891 1903 { 1892 audioEngine_noteOn( note );1904 audioEngine_noteOn( note ); 1893 1905 } 1894 1906 … … 1904 1916 int msg1 ) 1905 1917 { 1906 UNUSED( pitch ); 1907 1908 Preferences *pref = Preferences::get_instance(); 1909 unsigned int realcolumn = 0; 1910 unsigned res = pref->getPatternEditorGridResolution(); 1911 int nBase = pref->isPatternEditorUsingTriplets() ? 3 : 4; 1912 int scalar = ( 4 * MAX_NOTES ) / ( res * nBase ); 1913 bool hearnote = forcePlay; 1914 1915 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1916 1917 1918 Song *song = getSong(); 1919 if ( !pref->__playselectedinstrument ){ 1920 if ( instrument >= ( int )song->get_instrument_list()->size() ) { 1921 // unused instrument 1922 AudioEngine::get_instance()->unlock(); 1923 return; 1924 } 1925 } 1926 1927 // Get current partern and column, compensating for "lookahead" if required 1928 Pattern* currentPattern = NULL; 1929 unsigned int column = 0; 1930 unsigned int lookaheadTicks = m_nLookaheadFrames / m_pAudioDriver->m_transport.m_nTickSize; 1931 bool doRecord = pref->getRecordEvents(); 1932 if ( m_pSong->get_mode() == Song::SONG_MODE && doRecord && 1933 m_audioEngineState == STATE_PLAYING ) { 1934 1935 // Recording + song playback mode + actually playing 1936 PatternList *pPatternList = m_pSong->get_pattern_list(); 1937 int ipattern = getPatternPos(); // playlist index 1938 if ( ipattern < 0 || ipattern >= (int) pPatternList->size() ) { 1939 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1940 return; 1941 } 1942 // Locate column -- may need to jump back in the pattern list 1943 column = getTickPosition(); 1944 while ( column < lookaheadTicks ) { 1945 ipattern -= 1; 1946 if ( ipattern < 0 || ipattern >= (int) pPatternList->size() ) { 1947 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1948 return; 1949 } 1950 // Convert from playlist index to actual pattern index 1951 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector(); 1952 for ( int i = 0; i <= ipattern; ++i ) { 1953 PatternList *pColumn = ( *pColumns )[i]; 1954 currentPattern = pColumn->get( 0 ); 1955 } 1956 column = column + currentPattern->get_length(); 1957 // WARNINGLOG( "Undoing lookahead: corrected (" + to_string( ipattern+1 ) + 1958 // "," + to_string( (int) ( column - currentPattern->get_length() ) - 1959 // (int) lookaheadTicks ) + ") -> (" + to_string(ipattern) + 1960 // "," + to_string( (int) column - (int) lookaheadTicks ) + ")." ); 1961 } 1962 column -= lookaheadTicks; 1963 // Convert from playlist index to actual pattern index (if not already done above) 1964 if ( currentPattern == NULL ) { 1965 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector(); 1966 for ( int i = 0; i <= ipattern; ++i ) { 1967 PatternList *pColumn = ( *pColumns )[i]; 1968 currentPattern = pColumn->get( 0 ); 1969 } 1970 } 1971 1972 // Cancel recording if punch area disagrees 1973 doRecord = pref->inPunchArea( ipattern ); 1974 1975 } else { 1976 1977 // Not song-record mode 1978 PatternList *pPatternList = m_pSong->get_pattern_list(); 1979 if ( ( m_nSelectedPatternNumber != -1 ) 1980 && ( m_nSelectedPatternNumber < ( int )pPatternList->size() ) ) { 1981 currentPattern = pPatternList->get( m_nSelectedPatternNumber ); 1982 } 1983 if( currentPattern == NULL ){ 1984 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1985 return; 1986 } 1987 // Locate column -- may need to wrap around end of pattern 1988 column = getTickPosition(); 1989 if ( column >= lookaheadTicks ) { 1990 column -= lookaheadTicks; 1991 } else { 1992 lookaheadTicks %= currentPattern->get_length(); 1993 column = (column + currentPattern->get_length() - lookaheadTicks) 1994 % currentPattern->get_length(); 1995 } 1996 1997 } 1998 1999 realcolumn = getRealtimeTickPosition(); 2000 2001 if ( pref->getQuantizeEvents() ) { 2002 // quantize it to scale 2003 unsigned qcolumn = ( unsigned )::round( column / ( double )scalar ) * scalar; 2004 2005 //we have to make sure that no beat is added on the last displayed note in a bar 2006 //for example: if the pattern has 4 beats, the editor displays 5 beats, so we should avoid adding beats an note 5. 2007 if ( qcolumn == currentPattern->get_length() ) qcolumn = 0; 2008 column = qcolumn; 2009 } 2010 2011 2012 unsigned position = column; 2013 m_naddrealtimenotetickposition = column; 2014 2015 2016 Instrument *instrRef = 0; 2017 if ( song ) { 2018 instrRef = song->get_instrument_list()->get( m_nInstrumentLookupTable[ instrument ] );//getlookuptable index = instrument+36, ziel wert = der entprechende wert -36 2019 } 2020 2021 if ( currentPattern && ( getState() == STATE_PLAYING ) ) { 2022 2023 if( doRecord && pref->getDestructiveRecord() && pref->m_nRecPreDelete>0 ) { 2024 // Delete notes around current note if option toggled 2025 2026 int postdelete = 0; 2027 int predelete = 0; 2028 int prefpredelete = pref->m_nRecPreDelete-1; 2029 int prefpostdelete = pref->m_nRecPostDelete; 2030 int length = currentPattern->get_length(); 2031 bool fp = false; 2032 postdelete = column; 2033 2034 switch (prefpredelete) { 2035 case 0: predelete = length ; postdelete = 0; fp = true; break; 2036 case 1: predelete = length ; fp = true; break; 2037 case 2: predelete = length / 2; fp = true; break; 2038 case 3: predelete = length / 4; fp = true; break; 2039 case 4: predelete = length / 8; fp = true; break; 2040 case 5: predelete = length / 16; fp = true; break; 2041 case 6: predelete = length / 32; fp = true; break; 2042 case 7: predelete = length / 64; fp = true; break; 2043 case 8: predelete = length / 64; break; 2044 case 9: predelete = length / 32; break; 2045 case 10: predelete = length / 16; break; 2046 case 11: predelete = length / 8; break; 2047 case 12: predelete = length / 4; break; 2048 case 13: predelete = length / 2; break; 2049 case 14: predelete = length; break; 2050 case 15: break; 2051 default : predelete = 1; break; 2052 } 2053 2054 if(!fp ){ 2055 switch (prefpostdelete) { 2056 case 0: postdelete = column; break; 2057 case 1: postdelete -= length / 64; break; 2058 case 2: postdelete -= length / 32; break; 2059 case 3: postdelete -= length / 16; break; 2060 case 4: postdelete -= length / 8; break; 2061 case 5: postdelete -= length / 4; break; 2062 case 6: postdelete -= length / 2; break; 2063 case 7: postdelete -= length ; break; 2064 default : postdelete = column; break; 2065 } 2066 if (postdelete<0) postdelete = 0; 2067 2068 } 2069 2070 Pattern::notes_t* notes = (Pattern::notes_t*)currentPattern->get_notes(); 2071 FOREACH_NOTE_IT_BEGIN_END(notes,it) { 2072 Note *pNote = it->second; 2073 assert( pNote ); 2074 2075 if( pref->__playselectedinstrument ){//fix me 2076 if( song->get_instrument_list()->get( getSelectedInstrumentNumber()) == pNote->get_instrument() ){ 2077 if(prefpredelete>=1 && prefpredelete <=14 ) 2078 pNote->set_just_recorded( false ); 2079 if( (prefpredelete == 15) && (pNote->get_just_recorded() == false)){ 2080 delete pNote; 2081 notes->erase( it ); 2082 continue; 2083 } 2084 if( ( pNote->get_just_recorded() == false ) && (static_cast<int>( pNote->get_position() ) >= postdelete && pNote->get_position() < column + predelete +1 )){ 2085 delete pNote; 2086 notes->erase( it ); 2087 } 2088 } 2089 continue; 2090 } 2091 2092 if ( !fp && pNote->get_instrument() != instrRef ) { 2093 continue; 2094 } 2095 2096 if(prefpredelete>=1 && prefpredelete <=14 ) 2097 pNote->set_just_recorded( false ); 2098 2099 if( (prefpredelete == 15) && (pNote->get_just_recorded() == false)){ 2100 delete pNote; 2101 notes->erase( it ); 2102 continue; 2103 } 2104 2105 if( ( pNote->get_just_recorded() == false ) && ( static_cast<int>( pNote->get_position() ) >= postdelete && pNote->get_position() <column + predelete +1 )){ 2106 delete pNote; 2107 notes->erase( it ); 2108 } 2109 2110 } 2111 } 2112 assert( currentPattern != NULL ); 2113 2114 bool bNoteAlreadyExist = false; 2115 Note *pNoteOld = NULL; 2116 for ( unsigned nNote = 0 ; 2117 nNote < currentPattern->get_length() ; 2118 nNote++ ) { 2119 const Pattern::notes_t* notes = currentPattern->get_notes(); 2120 FOREACH_NOTE_CST_IT_BOUND(notes,it,nNote) { 2121 pNoteOld = it->second; 2122 if ( pNoteOld!=NULL ) { 2123 if ( pNoteOld->get_instrument() == instrRef 2124 && nNote==column ) { 2125 bNoteAlreadyExist = true; 2126 break; 2127 } 2128 } 2129 } 2130 } 2131 2132 if ( bNoteAlreadyExist ) { 2133 // in this case, we'll leave the note alone 2134 // hear note only if not playing too 2135 if ( pref->getHearNewNotes() 2136 && getState() == STATE_READY ) { 2137 hearnote = true; 2138 } 2139 // Update velocity and flag as just recorded 2140 if ( doRecord ) { 2141 pNoteOld->set_velocity( velocity ); 2142 pNoteOld->set_just_recorded( true ); 2143 } 2144 } else if ( !doRecord ) { 2145 if ( pref->getHearNewNotes() 2146 && ( getState() == STATE_READY 2147 || getState() == STATE_PLAYING ) ) { 2148 hearnote = true; 2149 } 2150 } else { 2151 if ( !pref->__playselectedinstrument ){ 2152 // create the new note 2153 Note *note = new Note( instrRef, 2154 position, 2155 velocity, 2156 pan_L, 2157 pan_R, 2158 -1, 2159 0 ); 2160 currentPattern->insert_note( note, column ); 2161 2162 // hear note if its not in the future 2163 if ( pref->getHearNewNotes() 2164 && position <= getTickPosition() ) { 2165 hearnote = true; 2166 } 2167 2168 note->set_just_recorded( true ); 2169 song->__is_modified = true; 2170 2171 EventQueue::get_instance()->push_event( EVENT_PATTERN_MODIFIED, -1 ); 2172 } 2173 else if ( pref->__playselectedinstrument ){ 2174 2175 Note *note = new Note( song->get_instrument_list()->get( getSelectedInstrumentNumber()), 2176 position, 2177 velocity, 2178 pan_L, 2179 pan_R, 2180 -1, 2181 0 ); 2182 2183 int divider = msg1 / 12; 2184 Note::Octave octave = (Note::Octave)(divider -3); 2185 Note::Key notehigh = (Note::Key)(msg1 - (12 * divider)); 2186 note->set_midi_info( notehigh, octave, msg1 ); 2187 2188 currentPattern->insert_note( note, column ); 2189 2190 // hear note if its not in the future 2191 if ( pref->getHearNewNotes() 2192 && position <= getTickPosition() ) { 2193 hearnote = true; 2194 } 2195 2196 note->set_just_recorded( true ); 2197 song->__is_modified = true; 2198 2199 EventQueue::get_instance()->push_event( EVENT_PATTERN_MODIFIED, -1 ); 2200 } 2201 } 2202 } else if ( pref->getHearNewNotes() ) { 2203 hearnote = true; 2204 } 2205 2206 if ( !pref->__playselectedinstrument ){ 2207 if ( hearnote && instrRef ) { 2208 Note *note2 = new Note( instrRef, 2209 realcolumn, 2210 velocity, 2211 pan_L, 2212 pan_R, 2213 -1, 2214 0 ); 2215 midi_noteOn( note2 ); 2216 } 2217 }else 2218 { 2219 if ( hearnote ) { 2220 Note *note2 = new Note( song->get_instrument_list()->get( getSelectedInstrumentNumber()), 2221 realcolumn, 2222 velocity, 2223 pan_L, 2224 pan_R, 2225 -1, 2226 0 ); 2227 2228 int divider = msg1 / 12; 2229 Note::Octave octave = (Note::Octave)(divider -3); 2230 Note::Key notehigh = (Note::Key)(msg1 - (12 * divider)); 2231 2232 //ERRORLOG( QString( "octave: %1, note: %2, instrument %3" ).arg( octave ).arg(notehigh).arg(instrument)); 2233 note2->set_midi_info( notehigh, octave, msg1 ); 2234 midi_noteOn( note2 ); 2235 } 2236 2237 } 2238 2239 2240 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1918 UNUSED( pitch ); 1919 1920 Preferences *pref = Preferences::get_instance(); 1921 unsigned int realcolumn = 0; 1922 unsigned res = pref->getPatternEditorGridResolution(); 1923 int nBase = pref->isPatternEditorUsingTriplets() ? 3 : 4; 1924 int scalar = ( 4 * MAX_NOTES ) / ( res * nBase ); 1925 bool hearnote = forcePlay; 1926 int currentPatternNumber; 1927 1928 AudioEngine::get_instance()->lock( RIGHT_HERE ); 1929 1930 1931 Song *song = getSong(); 1932 if ( !pref->__playselectedinstrument ){ 1933 if ( instrument >= ( int )song->get_instrument_list()->size() ) { 1934 // unused instrument 1935 AudioEngine::get_instance()->unlock(); 1936 return; 1937 } 1938 } 1939 1940 // Get current partern and column, compensating for "lookahead" if required 1941 Pattern* currentPattern = NULL; 1942 unsigned int column = 0; 1943 unsigned int lookaheadTicks = m_nLookaheadFrames / m_pAudioDriver->m_transport.m_nTickSize; 1944 bool doRecord = pref->getRecordEvents(); 1945 if ( m_pSong->get_mode() == Song::SONG_MODE && doRecord && 1946 m_audioEngineState == STATE_PLAYING ) { 1947 1948 // Recording + song playback mode + actually playing 1949 PatternList *pPatternList = m_pSong->get_pattern_list(); 1950 int ipattern = getPatternPos(); // playlist index 1951 if ( ipattern < 0 || ipattern >= (int) pPatternList->size() ) { 1952 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1953 return; 1954 } 1955 // Locate column -- may need to jump back in the pattern list 1956 column = getTickPosition(); 1957 while ( column < lookaheadTicks ) { 1958 ipattern -= 1; 1959 if ( ipattern < 0 || ipattern >= (int) pPatternList->size() ) { 1960 AudioEngine::get_instance()->unlock(); // unlock the audio engine 1961 return; 1962 } 1963 // Convert from playlist index to actual pattern index 1964 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector(); 1965 for ( int i = 0; i <= ipattern; ++i ) { 1966 PatternList *pColumn = ( *pColumns )[i]; 1967 currentPattern = pColumn->get( 0 ); 1968 currentPatternNumber = i; 1969 } 1970 column = column + currentPattern->get_length(); 1971 // WARNINGLOG( "Undoing lookahead: corrected (" + to_string( ipattern+1 ) + 1972 // "," + to_string( (int) ( column - currentPattern->get_length() ) - 1973 // (int) lookaheadTicks ) + ") -> (" + to_string(ipattern) + 1974 // "," + to_string( (int) column - (int) lookaheadTicks ) + ")." ); 1975 } 1976 column -= lookaheadTicks; 1977 // Convert from playlist index to actual pattern index (if not already done above) 1978 if ( currentPattern == NULL ) { 1979 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector(); 1980 for ( int i = 0; i <= ipattern; ++i ) { 1981 PatternList *pColumn = ( *pColumns )[i]; 1982 currentPattern = pColumn->get( 0 ); 1983 currentPatternNumber = i; 1984 } 1985 } 1986 1987 // Cancel recording if punch area disagrees 1988 doRecord = pref->inPunchArea( ipattern ); 1989 1990 } else { 1991 1992 // Not song-record mode 1993 PatternList *pPatternList = m_pSong->get_pattern_list(); 1994 if ( ( m_nSelectedPatternNumber != -1 ) 1995 && ( m_nSelectedPatternNumber < ( int )pPatternList->size() ) ) { 1996 currentPattern = pPatternList->get( m_nSelectedPatternNumber ); 1997 currentPatternNumber = m_nSelectedPatternNumber; 1998 } 1999 if( currentPattern == NULL ){ 2000 AudioEngine::get_instance()->unlock(); // unlock the audio engine 2001 return; 2002 } 2003 // Locate column -- may need to wrap around end of pattern 2004 column = getTickPosition(); 2005 if ( column >= lookaheadTicks ) { 2006 column -= lookaheadTicks; 2007 } else { 2008 lookaheadTicks %= currentPattern->get_length(); 2009 column = (column + currentPattern->get_length() - lookaheadTicks) 2010 % currentPattern->get_length(); 2011 } 2012 2013 } 2014 2015 realcolumn = getRealtimeTickPosition(); 2016 2017 if ( pref->getQuantizeEvents() ) { 2018 // quantize it to scale 2019 unsigned qcolumn = ( unsigned )::round( column / ( double )scalar ) * scalar; 2020 2021 //we have to make sure that no beat is added on the last displayed note in a bar 2022 //for example: if the pattern has 4 beats, the editor displays 5 beats, so we should avoid adding beats an note 5. 2023 if ( qcolumn == currentPattern->get_length() ) qcolumn = 0; 2024 column = qcolumn; 2025 } 2026 2027 2028 unsigned position = column; 2029 m_naddrealtimenotetickposition = column; 2030 2031 2032 Instrument *instrRef = 0; 2033 if ( song ) { 2034 instrRef = song->get_instrument_list()->get( m_nInstrumentLookupTable[ instrument ] );//getlookuptable index = instrument+36, ziel wert = der entprechende wert -36 2035 } 2036 2037 if ( currentPattern && ( getState() == STATE_PLAYING ) ) { 2038 2039 if( doRecord && pref->getDestructiveRecord() && pref->m_nRecPreDelete>0 ) { 2040 // Delete notes around current note if option toggled 2041 2042 int postdelete = 0; 2043 int predelete = 0; 2044 int prefpredelete = pref->m_nRecPreDelete-1; 2045 int prefpostdelete = pref->m_nRecPostDelete; 2046 int length = currentPattern->get_length(); 2047 bool fp = false; 2048 postdelete = column; 2049 2050 switch (prefpredelete) { 2051 case 0: predelete = length ; postdelete = 0; fp = true; break; 2052 case 1: predelete = length ; fp = true; break; 2053 case 2: predelete = length / 2; fp = true; break; 2054 case 3: predelete = length / 4; fp = true; break; 2055 case 4: predelete = length / 8; fp = true; break; 2056 case 5: predelete = length / 16; fp = true; break; 2057 case 6: predelete = length / 32; fp = true; break; 2058 case 7: predelete = length / 64; fp = true; break; 2059 case 8: predelete = length / 64; break; 2060 case 9: predelete = length / 32; break; 2061 case 10: predelete = length / 16; break; 2062 case 11: predelete = length / 8; break; 2063 case 12: predelete = length / 4; break; 2064 case 13: predelete = length / 2; break; 2065 case 14: predelete = length; break; 2066 case 15: break; 2067 default : predelete = 1; break; 2068 } 2069 2070 if(!fp ){ 2071 switch (prefpostdelete) { 2072 case 0: postdelete = column; break; 2073 case 1: postdelete -= length / 64; break; 2074 case 2: postdelete -= length / 32; break; 2075 case 3: postdelete -= length / 16; break; 2076 case 4: postdelete -= length / 8; break; 2077 case 5: postdelete -= length / 4; break; 2078 case 6: postdelete -= length / 2; break; 2079 case 7: postdelete -= length ; break; 2080 default : postdelete = column; break; 2081 } 2082 if (postdelete<0) postdelete = 0; 2083 2084 } 2085 2086 Pattern::notes_t* notes = (Pattern::notes_t*)currentPattern->get_notes(); 2087 FOREACH_NOTE_IT_BEGIN_END(notes,it) { 2088 Note *pNote = it->second; 2089 assert( pNote ); 2090 int currentPosition = pNote->get_position(); 2091 2092 if( pref->__playselectedinstrument ){//fix me 2093 if( song->get_instrument_list()->get( getSelectedInstrumentNumber()) == pNote->get_instrument() ){ 2094 if(prefpredelete>=1 && prefpredelete <=14 ) 2095 pNote->set_just_recorded( false ); 2096 if( (prefpredelete == 15) && (pNote->get_just_recorded() == false)){ 2097 bool replaceExisting = false; 2098 if(column == currentPosition) 2099 replaceExisting = true; 2100 EventQueue::AddMidiNoteVector noteAction; 2101 noteAction.m_column = currentPosition; 2102 noteAction.m_row = pNote->get_instrument_id();//getSelectedInstrumentNumber(); 2103 noteAction.m_pattern = currentPatternNumber; 2104 noteAction.f_velocity = velocity; 2105 noteAction.f_pan_L = pan_L; 2106 noteAction.f_pan_R = pan_R; 2107 noteAction.m_length = -1; 2108 2109 int divider = msg1 / 12; 2110 noteAction.no_octaveKeyVal = (Note::Octave)(divider -3); 2111 noteAction.nk_noteKeyVal = (Note::Key)(msg1 - (12 * divider)); 2112 noteAction.b_isInstrumentMode = replaceExisting; 2113 noteAction.b_isMidi = true; 2114 noteAction.b_noteExist = replaceExisting; 2115 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2116 continue; 2117 } 2118 if( ( pNote->get_just_recorded() == false ) && (static_cast<int>( pNote->get_position() ) >= postdelete && pNote->get_position() < column + predelete +1 )){ 2119 bool replaceExisting = false; 2120 if(column == currentPosition) 2121 replaceExisting = true; 2122 EventQueue::AddMidiNoteVector noteAction; 2123 noteAction.m_column = currentPosition; 2124 noteAction.m_row = pNote->get_instrument_id();//getSelectedInstrumentNumber(); 2125 noteAction.m_pattern = currentPatternNumber; 2126 noteAction.f_velocity = velocity; 2127 noteAction.f_pan_L = pan_L; 2128 noteAction.f_pan_R = pan_R; 2129 noteAction.m_length = -1; 2130 2131 int divider = msg1 / 12; 2132 noteAction.no_octaveKeyVal = (Note::Octave)(divider -3); 2133 noteAction.nk_noteKeyVal = (Note::Key)(msg1 - (12 * divider)); 2134 noteAction.b_isInstrumentMode = replaceExisting; 2135 noteAction.b_isMidi = true; 2136 noteAction.b_noteExist = replaceExisting; 2137 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2138 } 2139 } 2140 continue; 2141 } 2142 2143 if ( !fp && pNote->get_instrument() != instrRef ) { 2144 continue; 2145 } 2146 2147 if(prefpredelete>=1 && prefpredelete <=14 ) 2148 pNote->set_just_recorded( false ); 2149 2150 if( (prefpredelete == 15) && (pNote->get_just_recorded() == false)){ 2151 2152 bool replaceExisting = false; 2153 if(column == currentPosition) 2154 replaceExisting = true; 2155 EventQueue::AddMidiNoteVector noteAction; 2156 noteAction.m_column = currentPosition; 2157 noteAction.m_row = pNote->get_instrument_id();//m_nInstrumentLookupTable[ instrument ]; 2158 noteAction.m_pattern = currentPatternNumber; 2159 noteAction.f_velocity = velocity; 2160 noteAction.f_pan_L = pan_L; 2161 noteAction.f_pan_R = pan_R; 2162 noteAction.m_length = -1; 2163 noteAction.no_octaveKeyVal = (Note::Octave)0; 2164 noteAction.nk_noteKeyVal = (Note::Key)0; 2165 noteAction.b_isInstrumentMode = false; 2166 noteAction.b_isMidi = false; 2167 noteAction.b_noteExist = replaceExisting; 2168 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2169 continue; 2170 } 2171 2172 if( ( pNote->get_just_recorded() == false ) && ( static_cast<int>( pNote->get_position() ) >= postdelete && pNote->get_position() <column + predelete +1 )){ 2173 bool replaceExisting = false; 2174 if(column == currentPosition) 2175 replaceExisting = true; 2176 EventQueue::AddMidiNoteVector noteAction; 2177 noteAction.m_column = currentPosition; 2178 noteAction.m_row = pNote->get_instrument_id();//m_nInstrumentLookupTable[ instrument ]; 2179 noteAction.m_pattern = currentPatternNumber; 2180 noteAction.f_velocity = velocity; 2181 noteAction.f_pan_L = pan_L; 2182 noteAction.f_pan_R = pan_R; 2183 noteAction.m_length = -1; 2184 noteAction.no_octaveKeyVal = (Note::Octave)0; 2185 noteAction.nk_noteKeyVal = (Note::Key)0; 2186 noteAction.b_isInstrumentMode = false; 2187 noteAction.b_isMidi = false; 2188 noteAction.b_noteExist = replaceExisting; 2189 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2190 } 2191 } 2192 } 2193 assert( currentPattern != NULL ); 2194 if( doRecord ){ 2195 bool bNoteAlreadyExist = false; 2196 Note::Key myKey = (Note::Key)0; 2197 Note::Octave myOctave = (Note::Octave)0; 2198 2199 if(pref->__playselectedinstrument){ 2200 instrRef = song->get_instrument_list()->get( getSelectedInstrumentNumber() ); 2201 int divider = msg1 / 12; 2202 myKey = (Note::Key)(msg1 - (12 * divider)); 2203 myOctave = (Note::Octave)(divider -3); 2204 } 2205 else 2206 { 2207 instrRef = song->get_instrument_list()->get( m_nInstrumentLookupTable[ instrument ] ); 2208 } 2209 2210 Note* pNoteold = currentPattern->find_note( column, -1, instrRef, myKey, myOctave ); 2211 if( pNoteold ) { 2212 bNoteAlreadyExist = true; 2213 } 2214 if ( !pref->__playselectedinstrument ){ 2215 2216 EventQueue::AddMidiNoteVector noteAction; 2217 noteAction.m_column = column; 2218 noteAction.m_row = m_nInstrumentLookupTable[ instrument ]; 2219 noteAction.m_pattern = currentPatternNumber; 2220 noteAction.f_velocity = velocity; 2221 noteAction.f_pan_L = pan_L; 2222 noteAction.f_pan_R = pan_R; 2223 noteAction.m_length = -1; 2224 noteAction.no_octaveKeyVal = (Note::Octave)0; 2225 noteAction.nk_noteKeyVal = (Note::Key)0; 2226 noteAction.b_isInstrumentMode = false; 2227 noteAction.b_isMidi = true; 2228 noteAction.b_noteExist = bNoteAlreadyExist; 2229 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2230 2231 // hear note if its not in the future 2232 if ( pref->getHearNewNotes() 2233 && position <= getTickPosition() ) { 2234 hearnote = true; 2235 } 2236 } 2237 else if ( pref->__playselectedinstrument ){ 2238 2239 EventQueue::AddMidiNoteVector noteAction; 2240 noteAction.m_column = column; 2241 noteAction.m_row = getSelectedInstrumentNumber(); 2242 noteAction.m_pattern = currentPatternNumber; 2243 noteAction.f_velocity = velocity; 2244 noteAction.f_pan_L = pan_L; 2245 noteAction.f_pan_R = pan_R; 2246 noteAction.m_length = -1; 2247 2248 int divider = msg1 / 12; 2249 noteAction.no_octaveKeyVal = (Note::Octave)(divider -3); 2250 noteAction.nk_noteKeyVal = (Note::Key)(msg1 - (12 * divider)); 2251 noteAction.b_isInstrumentMode = true; 2252 noteAction.b_isMidi = true; 2253 noteAction.b_noteExist = bNoteAlreadyExist; 2254 EventQueue::get_instance()->m_addMidiNoteVector.push_back(noteAction); 2255 2256 // hear note if its not in the future 2257 if ( pref->getHearNewNotes() 2258 && position <= getTickPosition() ) { 2259 hearnote = true; 2260 } 2261 } 2262 } 2263 } else if ( pref->getHearNewNotes() ) { 2264 hearnote = true; 2265 } 2266 2267 if ( !pref->__playselectedinstrument ){ 2268 if ( hearnote && instrRef ) { 2269 Note *note2 = new Note( instrRef, 2270 realcolumn, 2271 velocity, 2272 pan_L, 2273 pan_R, 2274 -1, 2275 0 ); 2276 midi_noteOn( note2 ); 2277 } 2278 }else 2279 { 2280 if ( hearnote ) { 2281 Note *note2 = new Note( song->get_instrument_list()->get( getSelectedInstrumentNumber()), 2282 realcolumn, 2283 velocity, 2284 pan_L, 2285 pan_R, 2286 -1, 2287 0 ); 2288 2289 int divider = msg1 / 12; 2290 Note::Octave octave = (Note::Octave)(divider -3); 2291 Note::Key notehigh = (Note::Key)(msg1 - (12 * divider)); 2292 2293 //ERRORLOG( QString( "octave: %1, note: %2, instrument %3" ).arg( octave ).arg(notehigh).arg(instrument)); 2294 note2->set_midi_info( notehigh, octave, msg1 ); 2295 midi_noteOn( note2 ); 2296 } 2297 2298 } 2299 2300 2301 AudioEngine::get_instance()->unlock(); // unlock the audio engine 2241 2302 } 2242 2303 … … 2245 2306 float Hydrogen::getMasterPeak_L() 2246 2307 { 2247 return m_fMasterPeak_L;2308 return m_fMasterPeak_L; 2248 2309 } 2249 2310 … … 2252 2313 float Hydrogen::getMasterPeak_R() 2253 2314 { 2254 return m_fMasterPeak_R;2315 return m_fMasterPeak_R; 2255 2316 } 2256 2317 … … 2259 2320 unsigned long Hydrogen::getTickPosition() 2260 2321 { 2261 return m_nPatternTickPosition;2322 return m_nPatternTickPosition; 2262 2323 } 2263 2324 … … 2266 2327 unsigned long Hydrogen::getRealtimeTickPosition() 2267 2328 { 2268 //unsigned long initTick = audioEngine_getTickPosition();2269 unsigned int initTick = ( unsigned int )( m_nRealtimeFrames2270 / m_pAudioDriver->m_transport.m_nTickSize );2271 unsigned long retTick;2272 2273 struct timeval currtime;2274 struct timeval deltatime;2275 2276 double sampleRate = ( double ) m_pAudioDriver->getSampleRate();2277 gettimeofday ( &currtime, NULL );2278 2279 timersub( &currtime, &m_currentTickTime, &deltatime );2280 2281 // add a buffers worth for jitter resistance2282 double deltaSec =2283 ( double ) deltatime.tv_sec2284 + ( deltatime.tv_usec / 1000000.0 )2285 + ( m_pAudioDriver->getBufferSize() / ( double )sampleRate );2286 2287 retTick = ( unsigned long ) ( ( sampleRate2288 / ( double ) m_pAudioDriver->m_transport.m_nTickSize )2289 * deltaSec );2290 2291 retTick = initTick + retTick;2292 2293 return retTick;2329 //unsigned long initTick = audioEngine_getTickPosition(); 2330 unsigned int initTick = ( unsigned int )( m_nRealtimeFrames 2331 / m_pAudioDriver->m_transport.m_nTickSize ); 2332 unsigned long retTick; 2333 2334 struct timeval currtime; 2335 struct timeval deltatime; 2336 2337 double sampleRate = ( double ) m_pAudioDriver->getSampleRate(); 2338 gettimeofday ( &currtime, NULL ); 2339 2340 timersub( &currtime, &m_currentTickTime, &deltatime ); 2341 2342 // add a buffers worth for jitter resistance 2343 double deltaSec = 2344 ( double ) deltatime.tv_sec 2345 + ( deltatime.tv_usec / 1000000.0 ) 2346 + ( m_pAudioDriver->getBufferSize() / ( double )sampleRate ); 2347 2348 retTick = ( unsigned long ) ( ( sampleRate 2349 / ( double ) m_pAudioDriver->m_transport.m_nTickSize ) 2350 * deltaSec ); 2351 2352 retTick = initTick + retTick; 2353 2354 return retTick; 2294 2355 } 2295 2356 … … 2298 2359 PatternList* Hydrogen::getCurrentPatternList() 2299 2360 { 2300 return m_pPlayingPatterns;2361 return m_pPlayingPatterns; 2301 2362 } 2302 2363 2303 2364 PatternList * Hydrogen::getNextPatterns() 2304 2365 { 2305 return m_pNextPatterns;2366 return m_pNextPatterns; 2306 2367 } 2307 2368 … … 2309 2370 void Hydrogen::sequencer_setNextPattern( int pos, bool appendPattern, bool deletePattern ) 2310 2371 { 2311 m_bAppendNextPattern = appendPattern;2312 m_bDeleteNextPattern = deletePattern;2313 2314 AudioEngine::get_instance()->lock( RIGHT_HERE );2315 2316 if ( m_pSong && m_pSong->get_mode() == Song::PATTERN_MODE ) {2317 PatternList *patternList = m_pSong->get_pattern_list();2318 Pattern * p = patternList->get( pos );2319 if ( ( pos >= 0 ) && ( pos < ( int )patternList->size() ) ) {2320 // if p is already on the next pattern list, delete it.2321 if ( m_pNextPatterns->del( p ) == NULL ) {2322 // WARNINGLOG( "Adding to nextPatterns" );2323 m_pNextPatterns->add( p );2324 }/* else {2372 m_bAppendNextPattern = appendPattern; 2373 m_bDeleteNextPattern = deletePattern; 2374 2375 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2376 2377 if ( m_pSong && m_pSong->get_mode() == Song::PATTERN_MODE ) { 2378 PatternList *patternList = m_pSong->get_pattern_list(); 2379 Pattern * p = patternList->get( pos ); 2380 if ( ( pos >= 0 ) && ( pos < ( int )patternList->size() ) ) { 2381 // if p is already on the next pattern list, delete it. 2382 if ( m_pNextPatterns->del( p ) == NULL ) { 2383 // WARNINGLOG( "Adding to nextPatterns" ); 2384 m_pNextPatterns->add( p ); 2385 }/* else { 2325 2386 // WARNINGLOG( "Removing " + to_string(pos) ); 2326 }*/2327 } else {2328 ERRORLOG( QString( "pos not in patternList range. pos=%1 "2329 "patternListSize=%2" )2330 .arg( pos )2331 .arg( patternList->size() ) );2332 m_pNextPatterns->clear();2333 }2334 } else {2335 ERRORLOG( "can't set next pattern in song mode" );2336 m_pNextPatterns->clear();2337 }2338 2339 AudioEngine::get_instance()->unlock();2387 }*/ 2388 } else { 2389 ERRORLOG( QString( "pos not in patternList range. pos=%1 " 2390 "patternListSize=%2" ) 2391 .arg( pos ) 2392 .arg( patternList->size() ) ); 2393 m_pNextPatterns->clear(); 2394 } 2395 } else { 2396 ERRORLOG( "can't set next pattern in song mode" ); 2397 m_pNextPatterns->clear(); 2398 } 2399 2400 AudioEngine::get_instance()->unlock(); 2340 2401 } 2341 2402 … … 2344 2405 int Hydrogen::getPatternPos() 2345 2406 { 2346 return m_nSongPos;2407 return m_nSongPos; 2347 2408 } 2348 2409 … … 2351 2412 void Hydrogen::restartDrivers() 2352 2413 { 2353 audioEngine_restartAudioDrivers();2414 audioEngine_restartAudioDrivers(); 2354 2415 } 2355 2416 … … 2358 2419 void Hydrogen::startExportSong( const QString& filename, int rate, int depth ) 2359 2420 { 2360 if ( getState() == STATE_PLAYING ) {2361 sequencer_stop();2362 }2363 AudioEngine::get_instance()->get_sampler()->stop_playing_notes();2364 Preferences *pPref = Preferences::get_instance();2365 2366 m_oldEngineMode = m_pSong->get_mode();2367 m_bOldLoopEnabled = m_pSong->is_loop_enabled();2368 2369 m_pSong->set_mode( Song::SONG_MODE );2370 m_pSong->set_loop_enabled( true );2371 // unsigned nSamplerate = m_pAudioDriver->getSampleRate();2372 unsigned nSamplerate = (unsigned)rate;2373 // stop all audio drivers2374 audioEngine_stopAudioDrivers();2375 2376 /*2377 FIXME: Questo codice fa davvero schifo....2378 */2379 2380 2381 m_pAudioDriver = new DiskWriterDriver( audioEngine_process, nSamplerate, filename, depth);2382 2383 2384 // reset2385 m_pAudioDriver->m_transport.m_nFrames = 0; // reset total frames2386 //m_pAudioDriver->setBpm( m_pSong->__bpm );2387 m_nSongPos = 0;2388 m_nPatternTickPosition = 0;2389 m_audioEngineState = STATE_PLAYING;2390 m_nPatternStartTick = -1;2391 2392 int res = m_pAudioDriver->init( pPref->m_nBufferSize );2393 if ( res != 0 ) {2394 ERRORLOG( "Error starting disk writer driver "2395 "[DiskWriterDriver::init()]" );2396 }2397 2398 m_pMainBuffer_L = m_pAudioDriver->getOut_L();2399 m_pMainBuffer_R = m_pAudioDriver->getOut_R();2400 2401 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );2402 2403 audioEngine_seek( 0, false );2404 2405 res = m_pAudioDriver->connect();2406 if ( res != 0 ) {2407 ERRORLOG( "Error starting disk writer driver "2408 "[DiskWriterDriver::connect()]" );2409 }2421 if ( getState() == STATE_PLAYING ) { 2422 sequencer_stop(); 2423 } 2424 AudioEngine::get_instance()->get_sampler()->stop_playing_notes(); 2425 Preferences *pPref = Preferences::get_instance(); 2426 2427 m_oldEngineMode = m_pSong->get_mode(); 2428 m_bOldLoopEnabled = m_pSong->is_loop_enabled(); 2429 2430 m_pSong->set_mode( Song::SONG_MODE ); 2431 m_pSong->set_loop_enabled( true ); 2432 // unsigned nSamplerate = m_pAudioDriver->getSampleRate(); 2433 unsigned nSamplerate = (unsigned)rate; 2434 // stop all audio drivers 2435 audioEngine_stopAudioDrivers(); 2436 2437 /* 2438 FIXME: Questo codice fa davvero schifo.... 2439 */ 2440 2441 2442 m_pAudioDriver = new DiskWriterDriver( audioEngine_process, nSamplerate, filename, depth); 2443 2444 2445 // reset 2446 m_pAudioDriver->m_transport.m_nFrames = 0; // reset total frames 2447 //m_pAudioDriver->setBpm( m_pSong->__bpm ); 2448 m_nSongPos = 0; 2449 m_nPatternTickPosition = 0; 2450 m_audioEngineState = STATE_PLAYING; 2451 m_nPatternStartTick = -1; 2452 2453 int res = m_pAudioDriver->init( pPref->m_nBufferSize ); 2454 if ( res != 0 ) { 2455 ERRORLOG( "Error starting disk writer driver " 2456 "[DiskWriterDriver::init()]" ); 2457 } 2458 2459 m_pMainBuffer_L = m_pAudioDriver->getOut_L(); 2460 m_pMainBuffer_R = m_pAudioDriver->getOut_R(); 2461 2462 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() ); 2463 2464 audioEngine_seek( 0, false ); 2465 2466 res = m_pAudioDriver->connect(); 2467 if ( res != 0 ) { 2468 ERRORLOG( "Error starting disk writer driver " 2469 "[DiskWriterDriver::connect()]" ); 2470 } 2410 2471 } 2411 2472 2412 2473 void Hydrogen::stopExportSong( bool reconnectOldDriver ) 2413 2474 { 2414 if ( m_pAudioDriver->class_name() != DiskWriterDriver::class_name() ) {2415 return;2416 }2417 2418 // audioEngine_stopAudioDrivers();2419 m_pAudioDriver->disconnect();2420 2421 m_audioEngineState = STATE_INITIALIZED;2422 delete m_pAudioDriver;2423 m_pAudioDriver = NULL;2424 2425 m_pMainBuffer_L = NULL;2426 m_pMainBuffer_R = NULL;2427 2428 m_pSong->set_mode( m_oldEngineMode );2429 m_pSong->set_loop_enabled( m_bOldLoopEnabled );2430 2431 m_nSongPos = -1;2432 m_nPatternTickPosition = 0;2433 2434 if(!reconnectOldDriver) return;2435 2436 audioEngine_startAudioDrivers();2437 2438 if ( m_pAudioDriver ) {2439 m_pAudioDriver->setBpm( m_pSong->__bpm );2440 } else {2441 ERRORLOG( "m_pAudioDriver = NULL" );2442 }2475 if ( m_pAudioDriver->class_name() != DiskWriterDriver::class_name() ) { 2476 return; 2477 } 2478 2479 // audioEngine_stopAudioDrivers(); 2480 m_pAudioDriver->disconnect(); 2481 2482 m_audioEngineState = STATE_INITIALIZED; 2483 delete m_pAudioDriver; 2484 m_pAudioDriver = NULL; 2485 2486 m_pMainBuffer_L = NULL; 2487 m_pMainBuffer_R = NULL; 2488 2489 m_pSong->set_mode( m_oldEngineMode ); 2490 m_pSong->set_loop_enabled( m_bOldLoopEnabled ); 2491 2492 m_nSongPos = -1; 2493 m_nPatternTickPosition = 0; 2494 2495 if(!reconnectOldDriver) return; 2496 2497 audioEngine_startAudioDrivers(); 2498 2499 if ( m_pAudioDriver ) { 2500 m_pAudioDriver->setBpm( m_pSong->__bpm ); 2501 } else { 2502 ERRORLOG( "m_pAudioDriver = NULL" ); 2503 } 2443 2504 } 2444 2505 … … 2447 2508 AudioOutput* Hydrogen::getAudioOutput() 2448 2509 { 2449 return m_pAudioDriver;2510 return m_pAudioDriver; 2450 2511 } 2451 2512 … … 2455 2516 MidiInput* Hydrogen::getMidiInput() 2456 2517 { 2457 return m_pMidiDriver;2518 return m_pMidiDriver; 2458 2519 } 2459 2520 2460 2521 MidiOutput* Hydrogen::getMidiOutput() 2461 2522 { 2462 return m_pMidiDriverOut;2523 return m_pMidiDriverOut; 2463 2524 } 2464 2525 … … 2467 2528 void Hydrogen::setMasterPeak_L( float value ) 2468 2529 { 2469 m_fMasterPeak_L = value;2530 m_fMasterPeak_L = value; 2470 2531 } 2471 2532 … … 2474 2535 void Hydrogen::setMasterPeak_R( float value ) 2475 2536 { 2476 m_fMasterPeak_R = value;2537 m_fMasterPeak_R = value; 2477 2538 } 2478 2539 … … 2481 2542 int Hydrogen::getState() 2482 2543 { 2483 return m_audioEngineState;2544 return m_audioEngineState; 2484 2545 } 2485 2546 … … 2488 2549 void Hydrogen::setCurrentPatternList( PatternList *pPatternList ) 2489 2550 { 2490 AudioEngine::get_instance()->lock( RIGHT_HERE );2491 m_pPlayingPatterns = pPatternList;2492 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 );2493 AudioEngine::get_instance()->unlock();2551 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2552 m_pPlayingPatterns = pPatternList; 2553 EventQueue::get_instance()->push_event( EVENT_PATTERN_CHANGED, -1 ); 2554 AudioEngine::get_instance()->unlock(); 2494 2555 } 2495 2556 … … 2498 2559 float Hydrogen::getProcessTime() 2499 2560 { 2500 return m_fProcessTime;2561 return m_fProcessTime; 2501 2562 } 2502 2563 … … 2505 2566 float Hydrogen::getMaxProcessTime() 2506 2567 { 2507 return m_fMaxProcessTime;2568 return m_fMaxProcessTime; 2508 2569 } 2509 2570 … … 2512 2573 int Hydrogen::loadDrumkit( Drumkit *drumkitInfo ) 2513 2574 { 2514 int old_ae_state = m_audioEngineState;2515 if( m_audioEngineState >= STATE_READY ) {2516 m_audioEngineState = STATE_PREPARED;2517 }2518 2519 INFOLOG( drumkitInfo->get_name() );2520 m_currentDrumkit = drumkitInfo->get_name();2521 LocalFileMng fileMng;2522 QString sDrumkitPath = Filesystem::drumkit_path_search( drumkitInfo->get_name() );2523 2524 2525 //current instrument list2526 InstrumentList *songInstrList = m_pSong->get_instrument_list();2527 2528 //new instrument list2529 InstrumentList *pDrumkitInstrList = drumkitInfo->get_instruments();2530 2531 /*2532 If the old drumkit is bigger then the new drumkit,2533 delete all instruments with a bigger pos then2534 pDrumkitInstrList->size(). Otherwise the instruments2535 from our old instrumentlist with2536 pos > pDrumkitInstrList->size() stay in the2537 new instrumentlist2538 2539 wolke: info!2540 this has moved to the end of this function2541 because we get lost objects in memory2542 now: 2543 1. the new drumkit will loaded2544 2. all not used instruments will complete deleted 2545 2546 old funktion:2547 while ( pDrumkitInstrList->size() < songInstrList->size() )2548 {2549 songInstrList->del(songInstrList->size() - 1);2550 }2551 */2552 2553 //needed for the new delete function2554 int instrumentDiff = songInstrList->size() - pDrumkitInstrList->size();2555 2556 for ( unsigned nInstr = 0; nInstr < pDrumkitInstrList->size(); ++nInstr ) {2557 Instrument *pInstr = NULL;2558 if ( nInstr < songInstrList->size() ) {2559 //instrument exists already2560 pInstr = songInstrList->get( nInstr );2561 assert( pInstr );2562 } else {2563 pInstr = new Instrument();2564 // The instrument isn't playing yet; no need for locking2565 // :-) - Jakob Lund. AudioEngine::get_instance()->lock(2566 // "Hydrogen::loadDrumkit" );2567 songInstrList->add( pInstr );2568 // AudioEngine::get_instance()->unlock();2569 }2570 2571 Instrument *pNewInstr = pDrumkitInstrList->get( nInstr );2572 assert( pNewInstr );2573 INFOLOG( QString( "Loading instrument (%1 of %2) [%3]" )2574 .arg( nInstr )2575 .arg( pDrumkitInstrList->size() )2576 .arg( pNewInstr->get_name() ) );2577 2578 // creo i nuovi layer in base al nuovo strumento2579 // Moved code from here right into the Instrument class - Jakob Lund.2580 pInstr->load_from( drumkitInfo, pNewInstr );2581 }2582 2583 2584 //wolke: new delete funktion2585 if ( instrumentDiff >=0 ){2586 for ( int i = 0; i < instrumentDiff ; i++ ){2587 removeInstrument(2588 m_pSong->get_instrument_list()->size() - 1,2589 true2590 );2591 }2592 }2593 2594 #ifdef H2CORE_HAVE_JACK2595 AudioEngine::get_instance()->lock( RIGHT_HERE );2596 renameJackPorts();2597 AudioEngine::get_instance()->unlock();2598 #endif2599 2600 m_audioEngineState = old_ae_state;2601 2602 return 0; //ok2575 int old_ae_state = m_audioEngineState; 2576 if( m_audioEngineState >= STATE_READY ) { 2577 m_audioEngineState = STATE_PREPARED; 2578 } 2579 2580 INFOLOG( drumkitInfo->get_name() ); 2581 m_currentDrumkit = drumkitInfo->get_name(); 2582 LocalFileMng fileMng; 2583 QString sDrumkitPath = Filesystem::drumkit_path_search( drumkitInfo->get_name() ); 2584 2585 2586 //current instrument list 2587 InstrumentList *songInstrList = m_pSong->get_instrument_list(); 2588 2589 //new instrument list 2590 InstrumentList *pDrumkitInstrList = drumkitInfo->get_instruments(); 2591 2592 /* 2593 If the old drumkit is bigger then the new drumkit, 2594 delete all instruments with a bigger pos then 2595 pDrumkitInstrList->size(). Otherwise the instruments 2596 from our old instrumentlist with 2597 pos > pDrumkitInstrList->size() stay in the 2598 new instrumentlist 2599 2600 wolke: info! 2601 this has moved to the end of this function 2602 because we get lost objects in memory 2603 now: 2604 1. the new drumkit will loaded 2605 2. all not used instruments will complete deleted 2606 2607 old funktion: 2608 while ( pDrumkitInstrList->size() < songInstrList->size() ) 2609 { 2610 songInstrList->del(songInstrList->size() - 1); 2611 } 2612 */ 2613 2614 //needed for the new delete function 2615 int instrumentDiff = songInstrList->size() - pDrumkitInstrList->size(); 2616 2617 for ( unsigned nInstr = 0; nInstr < pDrumkitInstrList->size(); ++nInstr ) { 2618 Instrument *pInstr = NULL; 2619 if ( nInstr < songInstrList->size() ) { 2620 //instrument exists already 2621 pInstr = songInstrList->get( nInstr ); 2622 assert( pInstr ); 2623 } else { 2624 pInstr = new Instrument(); 2625 // The instrument isn't playing yet; no need for locking 2626 // :-) - Jakob Lund. AudioEngine::get_instance()->lock( 2627 // "Hydrogen::loadDrumkit" ); 2628 songInstrList->add( pInstr ); 2629 // AudioEngine::get_instance()->unlock(); 2630 } 2631 2632 Instrument *pNewInstr = pDrumkitInstrList->get( nInstr ); 2633 assert( pNewInstr ); 2634 INFOLOG( QString( "Loading instrument (%1 of %2) [%3]" ) 2635 .arg( nInstr ) 2636 .arg( pDrumkitInstrList->size() ) 2637 .arg( pNewInstr->get_name() ) ); 2638 2639 // creo i nuovi layer in base al nuovo strumento 2640 // Moved code from here right into the Instrument class - Jakob Lund. 2641 pInstr->load_from( drumkitInfo, pNewInstr ); 2642 } 2643 2644 2645 //wolke: new delete funktion 2646 if ( instrumentDiff >=0 ){ 2647 for ( int i = 0; i < instrumentDiff ; i++ ){ 2648 removeInstrument( 2649 m_pSong->get_instrument_list()->size() - 1, 2650 true 2651 ); 2652 } 2653 } 2654 2655 #ifdef H2CORE_HAVE_JACK 2656 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2657 renameJackPorts(); 2658 AudioEngine::get_instance()->unlock(); 2659 #endif 2660 2661 m_audioEngineState = old_ae_state; 2662 2663 return 0; //ok 2603 2664 } 2604 2665 … … 2608 2669 void Hydrogen::removeInstrument( int instrumentnumber, bool conditional ) 2609 2670 { 2610 Instrument *pInstr = m_pSong->get_instrument_list()->get( instrumentnumber );2611 2612 2613 PatternList* pPatternList = getSong()->get_pattern_list();2614 2615 if ( conditional ) {2616 // new! this check if a pattern has an active note if there is an note2617 //inside the pattern the intrument would not be deleted2618 for ( int nPattern = 0 ;2619 nPattern < (int)pPatternList->size() ;2620 ++nPattern ) {2621 if( pPatternList2622 ->get( nPattern )2623 ->references( pInstr ) ) {2624 return;2625 }2626 }2627 } else {2628 getSong()->purge_instrument( pInstr );2629 }2630 2631 Song *pSong = getSong();2632 InstrumentList* pList = pSong->get_instrument_list();2633 if(pList->size()==1){2634 AudioEngine::get_instance()->lock( RIGHT_HERE );2635 Instrument* pInstr = pList->get( 0 );2636 pInstr->set_name( (QString( "Instrument 1" )) );2637 // remove all layers2638 for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {2639 InstrumentLayer* pLayer = pInstr->get_layer( nLayer );2640 delete pLayer;2641 pInstr->set_layer( NULL, nLayer );2642 } 2643 AudioEngine::get_instance()->unlock();2644 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );2645 INFOLOG("clear last instrument to empty instrument 1 instead delete the last instrument");2646 return;2647 }2648 2649 // if the instrument was the last on the instruments list, select the2650 // next-last2651 if ( instrumentnumber2652 >= (int)getSong()->get_instrument_list()->size() - 1 ) {2653 Hydrogen::get_instance()2654 ->setSelectedInstrumentNumber(2655 std::max(0, instrumentnumber - 1)2656 );2657 }2658 // delete the instrument from the instruments list2659 AudioEngine::get_instance()->lock( RIGHT_HERE );2660 getSong()->get_instrument_list()->del( instrumentnumber );2661 getSong()->__is_modified = true;2662 AudioEngine::get_instance()->unlock();2663 2664 // At this point the instrument has been removed from both the2665 // instrument list and every pattern in the song. Hence there's no way2666 // (NOTE) to play on that instrument, and once all notes have stopped2667 // playing it will be save to delete.2668 // the ugly name is just for debugging...2669 QString xxx_name = QString( "XXX_%1" ) . arg( pInstr->get_name() );2670 pInstr->set_name( xxx_name );2671 __instrument_death_row.push_back( pInstr );2672 __kill_instruments(); // checks if there are still notes.2673 2674 // this will force a GUI update.2675 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );2671 Instrument *pInstr = m_pSong->get_instrument_list()->get( instrumentnumber ); 2672 2673 2674 PatternList* pPatternList = getSong()->get_pattern_list(); 2675 2676 if ( conditional ) { 2677 // new! this check if a pattern has an active note if there is an note 2678 //inside the pattern the intrument would not be deleted 2679 for ( int nPattern = 0 ; 2680 nPattern < (int)pPatternList->size() ; 2681 ++nPattern ) { 2682 if( pPatternList 2683 ->get( nPattern ) 2684 ->references( pInstr ) ) { 2685 return; 2686 } 2687 } 2688 } else { 2689 getSong()->purge_instrument( pInstr ); 2690 } 2691 2692 Song *pSong = getSong(); 2693 InstrumentList* pList = pSong->get_instrument_list(); 2694 if(pList->size()==1){ 2695 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2696 Instrument* pInstr = pList->get( 0 ); 2697 pInstr->set_name( (QString( "Instrument 1" )) ); 2698 // remove all layers 2699 for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) { 2700 InstrumentLayer* pLayer = pInstr->get_layer( nLayer ); 2701 delete pLayer; 2702 pInstr->set_layer( NULL, nLayer ); 2703 } 2704 AudioEngine::get_instance()->unlock(); 2705 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 ); 2706 INFOLOG("clear last instrument to empty instrument 1 instead delete the last instrument"); 2707 return; 2708 } 2709 2710 // if the instrument was the last on the instruments list, select the 2711 // next-last 2712 if ( instrumentnumber 2713 >= (int)getSong()->get_instrument_list()->size() - 1 ) { 2714 Hydrogen::get_instance() 2715 ->setSelectedInstrumentNumber( 2716 std::max(0, instrumentnumber - 1) 2717 ); 2718 } 2719 // delete the instrument from the instruments list 2720 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2721 getSong()->get_instrument_list()->del( instrumentnumber ); 2722 getSong()->__is_modified = true; 2723 AudioEngine::get_instance()->unlock(); 2724 2725 // At this point the instrument has been removed from both the 2726 // instrument list and every pattern in the song. Hence there's no way 2727 // (NOTE) to play on that instrument, and once all notes have stopped 2728 // playing it will be save to delete. 2729 // the ugly name is just for debugging... 2730 QString xxx_name = QString( "XXX_%1" ) . arg( pInstr->get_name() ); 2731 pInstr->set_name( xxx_name ); 2732 __instrument_death_row.push_back( pInstr ); 2733 __kill_instruments(); // checks if there are still notes. 2734 2735 // this will force a GUI update. 2736 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 ); 2676 2737 } 2677 2738 … … 2679 2740 void Hydrogen::raiseError( unsigned nErrorCode ) 2680 2741 { 2681 audioEngine_raiseError( nErrorCode );2742 audioEngine_raiseError( nErrorCode ); 2682 2743 } 2683 2744 … … 2685 2746 unsigned long Hydrogen::getTotalFrames() 2686 2747 { 2687 return m_pAudioDriver->m_transport.m_nFrames;2748 return m_pAudioDriver->m_transport.m_nFrames; 2688 2749 } 2689 2750 2690 2751 unsigned long Hydrogen::getRealtimeFrames() 2691 2752 { 2692 return m_nRealtimeFrames;2753 return m_nRealtimeFrames; 2693 2754 } 2694 2755 … … 2701 2762 long Hydrogen::getTickForPosition( int pos ) 2702 2763 { 2703 int nPatternGroups = m_pSong->get_pattern_group_vector()->size();2704 if( nPatternGroups == 0 ) return -1; 2705 2706 if ( pos >= nPatternGroups ) {2707 if ( m_pSong->is_loop_enabled() ) {2708 pos = pos % nPatternGroups;2709 } else {2710 WARNINGLOG( QString( "patternPos > nPatternGroups. pos:"2711 " %1, nPatternGroups: %2")2712 .arg( pos )2713 .arg( nPatternGroups ) );2714 return -1;2715 }2716 }2717 2718 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector();2719 long totalTick = 0;2720 int nPatternSize;2721 Pattern *pPattern = NULL;2722 for ( int i = 0; i < pos; ++i ) {2723 PatternList *pColumn = ( *pColumns )[ i ];2724 // prendo solo il primo. I pattern nel gruppo devono avere la2725 // stessa lunghezza2726 pPattern = pColumn->get( 0 );2727 if ( pPattern ) {2728 nPatternSize = pPattern->get_length();2729 } else {2730 nPatternSize = MAX_NOTES;2731 }2732 2733 totalTick += nPatternSize;2734 }2735 return totalTick;2764 int nPatternGroups = m_pSong->get_pattern_group_vector()->size(); 2765 if( nPatternGroups == 0 ) return -1; 2766 2767 if ( pos >= nPatternGroups ) { 2768 if ( m_pSong->is_loop_enabled() ) { 2769 pos = pos % nPatternGroups; 2770 } else { 2771 WARNINGLOG( QString( "patternPos > nPatternGroups. pos:" 2772 " %1, nPatternGroups: %2") 2773 .arg( pos ) 2774 .arg( nPatternGroups ) ); 2775 return -1; 2776 } 2777 } 2778 2779 std::vector<PatternList*> *pColumns = m_pSong->get_pattern_group_vector(); 2780 long totalTick = 0; 2781 int nPatternSize; 2782 Pattern *pPattern = NULL; 2783 for ( int i = 0; i < pos; ++i ) { 2784 PatternList *pColumn = ( *pColumns )[ i ]; 2785 // prendo solo il primo. I pattern nel gruppo devono avere la 2786 // stessa lunghezza 2787 pPattern = pColumn->get( 0 ); 2788 if ( pPattern ) { 2789 nPatternSize = pPattern->get_length(); 2790 } else { 2791 nPatternSize = MAX_NOTES; 2792 } 2793 2794 totalTick += nPatternSize; 2795 } 2796 return totalTick; 2736 2797 } 2737 2798 … … 2739 2800 void Hydrogen::setPatternPos( int pos ) 2740 2801 { 2741 if ( pos < -1 )2742 pos = -1;2743 AudioEngine::get_instance()->lock( RIGHT_HERE );2744 EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 );2745 long totalTick = getTickForPosition( pos );2746 if ( totalTick < 0 ) {2747 AudioEngine::get_instance()->unlock();2748 return;2749 }2750 2751 if ( getState() != STATE_PLAYING ) {2752 // find pattern immediately when not playing2753 // int dummy;2754 // m_nSongPos = findPatternInTick( totalTick,2755 // m_pSong->is_loop_enabled(),2756 // &dummy );2757 m_nSongPos = pos;2758 m_nPatternTickPosition = 0;2759 }2760 m_pAudioDriver->locate(2761 ( int ) ( totalTick * m_pAudioDriver->m_transport.m_nTickSize )2762 );2763 2764 AudioEngine::get_instance()->unlock();2802 if ( pos < -1 ) 2803 pos = -1; 2804 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2805 EventQueue::get_instance()->push_event( EVENT_METRONOME, 1 ); 2806 long totalTick = getTickForPosition( pos ); 2807 if ( totalTick < 0 ) { 2808 AudioEngine::get_instance()->unlock(); 2809 return; 2810 } 2811 2812 if ( getState() != STATE_PLAYING ) { 2813 // find pattern immediately when not playing 2814 // int dummy; 2815 // m_nSongPos = findPatternInTick( totalTick, 2816 // m_pSong->is_loop_enabled(), 2817 // &dummy ); 2818 m_nSongPos = pos; 2819 m_nPatternTickPosition = 0; 2820 } 2821 m_pAudioDriver->locate( 2822 ( int ) ( totalTick * m_pAudioDriver->m_transport.m_nTickSize ) 2823 ); 2824 2825 AudioEngine::get_instance()->unlock(); 2765 2826 } 2766 2827 … … 2771 2832 { 2772 2833 #ifdef H2CORE_HAVE_LADSPA 2773 ( *fL ) = m_fFXPeak_L[nFX];2774 ( *fR ) = m_fFXPeak_R[nFX];2834 ( *fL ) = m_fFXPeak_L[nFX]; 2835 ( *fR ) = m_fFXPeak_R[nFX]; 2775 2836 #else 2776 ( *fL ) = 0;2777 ( *fR ) = 0;2837 ( *fL ) = 0; 2838 ( *fR ) = 0; 2778 2839 #endif 2779 2840 } … … 2784 2845 { 2785 2846 #ifdef H2CORE_HAVE_LADSPA 2786 m_fFXPeak_L[nFX] = fL;2787 m_fFXPeak_R[nFX] = fR;2847 m_fFXPeak_L[nFX] = fL; 2848 m_fFXPeak_R[nFX] = fR; 2788 2849 #endif 2789 2850 } … … 2793 2854 { 2794 2855 #ifndef WIN32 2795 INFOLOG( "tap tempo" );2796 static timeval oldTimeVal;2797 2798 struct timeval now;2799 gettimeofday(&now, NULL);2800 2801 float fInterval =2802 (now.tv_sec - oldTimeVal.tv_sec) * 1000.02803 + (now.tv_usec - oldTimeVal.tv_usec) / 1000.0;2804 2805 oldTimeVal = now;2806 2807 if ( fInterval < 1000.0 ) {2808 setTapTempo( fInterval );2809 }2856 INFOLOG( "tap tempo" ); 2857 static timeval oldTimeVal; 2858 2859 struct timeval now; 2860 gettimeofday(&now, NULL); 2861 2862 float fInterval = 2863 (now.tv_sec - oldTimeVal.tv_sec) * 1000.0 2864 + (now.tv_usec - oldTimeVal.tv_usec) / 1000.0; 2865 2866 oldTimeVal = now; 2867 2868 if ( fInterval < 1000.0 ) { 2869 setTapTempo( fInterval ); 2870 } 2810 2871 #endif 2811 2872 } … … 2814 2875 { 2815 2876 2816 // infoLog( "set tap tempo" );2817 static float fOldBpm1 = -1;2818 static float fOldBpm2 = -1;2819 static float fOldBpm3 = -1;2820 static float fOldBpm4 = -1;2821 static float fOldBpm5 = -1;2822 static float fOldBpm6 = -1;2823 static float fOldBpm7 = -1;2824 static float fOldBpm8 = -1;2825 2826 float fBPM = 60000.0 / fInterval;2827 2828 if ( fabs( fOldBpm1 - fBPM ) > 20 ) { // troppa differenza, niente media2829 fOldBpm1 = fBPM;2830 fOldBpm2 = fBPM;2831 fOldBpm3 = fBPM;2832 fOldBpm4 = fBPM;2833 fOldBpm5 = fBPM;2834 fOldBpm6 = fBPM;2835 fOldBpm7 = fBPM;2836 fOldBpm8 = fBPM;2837 }2838 2839 if ( fOldBpm1 == -1 ) {2840 fOldBpm1 = fBPM;2841 fOldBpm2 = fBPM;2842 fOldBpm3 = fBPM;2843 fOldBpm4 = fBPM;2844 fOldBpm5 = fBPM;2845 fOldBpm6 = fBPM;2846 fOldBpm7 = fBPM;2847 fOldBpm8 = fBPM;2848 }2849 2850 fBPM = ( fBPM + fOldBpm1 + fOldBpm2 + fOldBpm3 + fOldBpm4 + fOldBpm52851 + fOldBpm6 + fOldBpm7 + fOldBpm8 ) / 9.0;2852 2853 2854 INFOLOG( QString( "avg BPM = %1" ).arg( fBPM ) );2855 fOldBpm8 = fOldBpm7;2856 fOldBpm7 = fOldBpm6;2857 fOldBpm6 = fOldBpm5;2858 fOldBpm5 = fOldBpm4;2859 fOldBpm4 = fOldBpm3;2860 fOldBpm3 = fOldBpm2;2861 fOldBpm2 = fOldBpm1;2862 fOldBpm1 = fBPM;2863 2864 AudioEngine::get_instance()->lock( RIGHT_HERE );2865 2866 // m_pAudioDriver->setBpm( fBPM );2867 // m_pSong->setBpm( fBPM );2868 2869 setBPM( fBPM );2870 2871 AudioEngine::get_instance()->unlock();2877 // infoLog( "set tap tempo" ); 2878 static float fOldBpm1 = -1; 2879 static float fOldBpm2 = -1; 2880 static float fOldBpm3 = -1; 2881 static float fOldBpm4 = -1; 2882 static float fOldBpm5 = -1; 2883 static float fOldBpm6 = -1; 2884 static float fOldBpm7 = -1; 2885 static float fOldBpm8 = -1; 2886 2887 float fBPM = 60000.0 / fInterval; 2888 2889 if ( fabs( fOldBpm1 - fBPM ) > 20 ) { // troppa differenza, niente media 2890 fOldBpm1 = fBPM; 2891 fOldBpm2 = fBPM; 2892 fOldBpm3 = fBPM; 2893 fOldBpm4 = fBPM; 2894 fOldBpm5 = fBPM; 2895 fOldBpm6 = fBPM; 2896 fOldBpm7 = fBPM; 2897 fOldBpm8 = fBPM; 2898 } 2899 2900 if ( fOldBpm1 == -1 ) { 2901 fOldBpm1 = fBPM; 2902 fOldBpm2 = fBPM; 2903 fOldBpm3 = fBPM; 2904 fOldBpm4 = fBPM; 2905 fOldBpm5 = fBPM; 2906 fOldBpm6 = fBPM; 2907 fOldBpm7 = fBPM; 2908 fOldBpm8 = fBPM; 2909 } 2910 2911 fBPM = ( fBPM + fOldBpm1 + fOldBpm2 + fOldBpm3 + fOldBpm4 + fOldBpm5 2912 + fOldBpm6 + fOldBpm7 + fOldBpm8 ) / 9.0; 2913 2914 2915 INFOLOG( QString( "avg BPM = %1" ).arg( fBPM ) ); 2916 fOldBpm8 = fOldBpm7; 2917 fOldBpm7 = fOldBpm6; 2918 fOldBpm6 = fOldBpm5; 2919 fOldBpm5 = fOldBpm4; 2920 fOldBpm4 = fOldBpm3; 2921 fOldBpm3 = fOldBpm2; 2922 fOldBpm2 = fOldBpm1; 2923 fOldBpm1 = fBPM; 2924 2925 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2926 2927 // m_pAudioDriver->setBpm( fBPM ); 2928 // m_pSong->setBpm( fBPM ); 2929 2930 setBPM( fBPM ); 2931 2932 AudioEngine::get_instance()->unlock(); 2872 2933 } 2873 2934 … … 2876 2937 void Hydrogen::setBPM( float fBPM ) 2877 2938 { 2878 if ( m_pAudioDriver && m_pSong ) {2879 m_pAudioDriver->setBpm( fBPM );2880 m_pSong->__bpm = fBPM;2881 m_nNewBpmJTM = fBPM;2882 // audioEngine_process_checkBPMChanged();2883 }2939 if ( m_pAudioDriver && m_pSong ) { 2940 m_pAudioDriver->setBpm( fBPM ); 2941 m_pSong->__bpm = fBPM; 2942 m_nNewBpmJTM = fBPM; 2943 // audioEngine_process_checkBPMChanged(); 2944 } 2884 2945 } 2885 2946 … … 2888 2949 void Hydrogen::restartLadspaFX() 2889 2950 { 2890 if ( m_pAudioDriver ) {2891 AudioEngine::get_instance()->lock( RIGHT_HERE );2892 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() );2893 AudioEngine::get_instance()->unlock();2894 } else {2895 ERRORLOG( "m_pAudioDriver = NULL" );2896 }2951 if ( m_pAudioDriver ) { 2952 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2953 audioEngine_setupLadspaFX( m_pAudioDriver->getBufferSize() ); 2954 AudioEngine::get_instance()->unlock(); 2955 } else { 2956 ERRORLOG( "m_pAudioDriver = NULL" ); 2957 } 2897 2958 } 2898 2959 … … 2901 2962 int Hydrogen::getSelectedPatternNumber() 2902 2963 { 2903 return m_nSelectedPatternNumber;2964 return m_nSelectedPatternNumber; 2904 2965 } 2905 2966 … … 2907 2968 void Hydrogen::setSelectedPatternNumberWithoutGuiEvent( int nPat ) 2908 2969 { 2909 if ( nPat == m_nSelectedPatternNumber2910 || ( nPat + 1 > m_pSong->get_pattern_list()->size() ) )2911 return;2912 2913 if ( Preferences::get_instance()->patternModePlaysSelected() ) {2914 AudioEngine::get_instance()->lock( RIGHT_HERE );2915 2916 m_nSelectedPatternNumber = nPat;2917 AudioEngine::get_instance()->unlock();2918 } else {2919 m_nSelectedPatternNumber = nPat;2920 }2970 if ( nPat == m_nSelectedPatternNumber 2971 || ( nPat + 1 > m_pSong->get_pattern_list()->size() ) ) 2972 return; 2973 2974 if ( Preferences::get_instance()->patternModePlaysSelected() ) { 2975 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2976 2977 m_nSelectedPatternNumber = nPat; 2978 AudioEngine::get_instance()->unlock(); 2979 } else { 2980 m_nSelectedPatternNumber = nPat; 2981 } 2921 2982 } 2922 2983 2923 2984 void Hydrogen::setSelectedPatternNumber( int nPat ) 2924 2985 { 2925 // FIXME: controllare se e' valido..2926 if ( nPat == m_nSelectedPatternNumber ) return;2927 2928 2929 if ( Preferences::get_instance()->patternModePlaysSelected() ) {2930 AudioEngine::get_instance()->lock( RIGHT_HERE );2931 2932 m_nSelectedPatternNumber = nPat;2933 AudioEngine::get_instance()->unlock();2934 } else {2935 m_nSelectedPatternNumber = nPat;2936 }2937 2938 EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );2986 // FIXME: controllare se e' valido.. 2987 if ( nPat == m_nSelectedPatternNumber ) return; 2988 2989 2990 if ( Preferences::get_instance()->patternModePlaysSelected() ) { 2991 AudioEngine::get_instance()->lock( RIGHT_HERE ); 2992 2993 m_nSelectedPatternNumber = nPat; 2994 AudioEngine::get_instance()->unlock(); 2995 } else { 2996 m_nSelectedPatternNumber = nPat; 2997 } 2998 2999 EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 ); 2939 3000 } 2940 3001 … … 2943 3004 int Hydrogen::getSelectedInstrumentNumber() 2944 3005 { 2945 return m_nSelectedInstrumentNumber;3006 return m_nSelectedInstrumentNumber; 2946 3007 } 2947 3008 … … 2950 3011 void Hydrogen::setSelectedInstrumentNumber( int nInstrument ) 2951 3012 { 2952 if ( m_nSelectedInstrumentNumber == nInstrument ) return;2953 2954 m_nSelectedInstrumentNumber = nInstrument;2955 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );3013 if ( m_nSelectedInstrumentNumber == nInstrument ) return; 3014 3015 m_nSelectedInstrumentNumber = nInstrument; 3016 EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 ); 2956 3017 } 2957 3018 … … 2960 3021 void Hydrogen::renameJackPorts() 2961 3022 { 2962 if( Preferences::get_instance()->m_bJackTrackOuts == true ){2963 audioEngine_renameJackPorts();2964 }3023 if( Preferences::get_instance()->m_bJackTrackOuts == true ){ 3024 audioEngine_renameJackPorts(); 3025 } 2965 3026 } 2966 3027 #endif … … 2971 3032 void Hydrogen::setbeatsToCount( int beatstocount) 2972 3033 { 2973 m_nbeatsToCount = beatstocount;3034 m_nbeatsToCount = beatstocount; 2974 3035 } 2975 3036 … … 2977 3038 int Hydrogen::getbeatsToCount() 2978 3039 { 2979 return m_nbeatsToCount;3040 return m_nbeatsToCount; 2980 3041 } 2981 3042 … … 2983 3044 void Hydrogen::setNoteLength( float notelength) 2984 3045 { 2985 m_ntaktoMeterCompute = notelength;3046 m_ntaktoMeterCompute = notelength; 2986 3047 } 2987 3048 … … 2990 3051 float Hydrogen::getNoteLength()