Ejemplo n.º 1
0
// 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);
}
Ejemplo n.º 2
0
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;
	}