// perche' viene passata anche la canzone? E' davvero necessaria? void Sampler::process( uint32_t nFrames, Song* pSong ) { //infoLog( "[process]" ); AudioOutput* audio_output = Hydrogen::get_instance()->getAudioOutput(); assert( audio_output ); memset( __main_out_L, 0, nFrames * sizeof( float ) ); memset( __main_out_R, 0, nFrames * sizeof( float ) ); // Track output queues are zeroed by // audioEngine_process_clearAudioBuffers() // Max notes limit int m_nMaxNotes = Preferences::get_instance()->m_nMaxNotes; while ( ( int )__playing_notes_queue.size() > m_nMaxNotes ) { Note *oldNote = __playing_notes_queue[ 0 ]; __playing_notes_queue.erase( __playing_notes_queue.begin() ); oldNote->get_instrument()->dequeue(); delete oldNote; // FIXME: send note-off instead of removing the note from the list? } for (std::vector<DrumkitComponent*>::iterator it = pSong->get_components()->begin() ; it != pSong->get_components()->end(); ++it) { DrumkitComponent* component = *it; component->reset_outs(nFrames); } // eseguo tutte le note nella lista di note in esecuzione unsigned i = 0; Note* pNote; while ( i < __playing_notes_queue.size() ) { pNote = __playing_notes_queue[ i ]; // recupero una nuova nota if ( __render_note( pNote, nFrames, pSong ) ) { // la nota e' finita __playing_notes_queue.erase( __playing_notes_queue.begin() + i ); pNote->get_instrument()->dequeue(); __queuedNoteOffs.push_back( pNote ); // delete pNote; // pNote = NULL; } else { ++i; // carico la prox nota } } //Queue midi note off messages for notes that have a length specified for them while ( !__queuedNoteOffs.empty() ) { pNote = __queuedNoteOffs[0]; MidiOutput* midiOut = Hydrogen::get_instance()->getMidiOutput(); if( midiOut != NULL ){ midiOut->handleQueueNoteOff( pNote->get_instrument()->get_midi_out_channel(), pNote->get_midi_key(), pNote->get_midi_velocity() ); } __queuedNoteOffs.erase( __queuedNoteOffs.begin() ); if( pNote != NULL) delete pNote; pNote = NULL; }//while processPlaybackTrack(nFrames); }
void SMFWriter::save( const QString& sFilename, Song *pSong ) { INFOLOG( "save" ); const int DRUM_CHANNEL = 9; vector<SMFEvent*> eventList; SMF smf; // Standard MIDI format 1 files should have the first track being the tempo map // which is a track that contains global meta events only. SMFTrack *pTrack0 = new SMFTrack(); pTrack0->addEvent( new SMFCopyRightNoticeMetaEvent( pSong->__author , 0 ) ); pTrack0->addEvent( new SMFTrackNameMetaEvent( pSong->__name , 0 ) ); pTrack0->addEvent( new SMFSetTempoMetaEvent( pSong->__bpm , 0 ) ); pTrack0->addEvent( new SMFTimeSignatureMetaEvent( 4 , 4 , 24 , 8 , 0 ) ); smf.addTrack( pTrack0 ); // Standard MIDI Format 1 files should have note events in tracks =>2 SMFTrack *pTrack1 = new SMFTrack(); smf.addTrack( pTrack1 ); AutomationPath *vp = pSong->get_velocity_automation_path(); InstrumentList *iList = pSong->get_instrument_list(); // ogni pattern sara' una diversa traccia int nTick = 1; for ( unsigned nPatternList = 0 ; nPatternList < pSong->get_pattern_group_vector()->size() ; nPatternList++ ) { // infoLog( "[save] pattern list pos: " + toString( nPatternList ) ); PatternList *pPatternList = ( *(pSong->get_pattern_group_vector()) )[ nPatternList ]; int nStartTicks = nTick; int nMaxPatternLength = 0; for ( unsigned nPattern = 0 ; nPattern < pPatternList->size() ; nPattern++ ) { Pattern *pPattern = pPatternList->get( nPattern ); // infoLog( " |-> pattern: " + pPattern->getName() ); if ( ( int )pPattern->get_length() > nMaxPatternLength ) { nMaxPatternLength = pPattern->get_length(); } for ( unsigned nNote = 0; nNote < pPattern->get_length(); nNote++ ) { const Pattern::notes_t* notes = pPattern->get_notes(); FOREACH_NOTE_CST_IT_BOUND(notes,it,nNote) { Note *pNote = it->second; if ( pNote ) { float rnd = (float)rand()/(float)RAND_MAX; if ( pNote->get_probability() < rnd ) { continue; } float fPos = nPatternList + (float)nNote/(float)nMaxPatternLength; float velocity_adjustment = vp->get_value(fPos); int nVelocity = (int)( 127.0 * pNote->get_velocity() * velocity_adjustment ); int nInstr = iList->index(pNote->get_instrument()); Instrument *pInstr = pNote->get_instrument(); int nPitch = pNote->get_midi_key(); eventList.push_back( new SMFNoteOnEvent( nStartTicks + nNote, DRUM_CHANNEL, nPitch, nVelocity ) ); int nLength = 12; if ( pNote->get_length() != -1 ) { nLength = pNote->get_length(); } eventList.push_back( new SMFNoteOffEvent( nStartTicks + nNote + nLength, DRUM_CHANNEL, nPitch, nVelocity ) ); } } } } nTick += nMaxPatternLength; }