Пример #1
0
float Automation::get_tick_val(Tick p_tick) {
	
	int block=get_block_idx_at_pos( p_tick );
	
	if (block<0) {
		/* Check Repeat */
		int prev_block=get_prev_block_from_idx( p_tick );
		if (prev_block<0 || !get_block( prev_block )->is_repeat_active() )
			return -1.0;
		
		// adjust block and tick
		block=prev_block;
		Tick block_pos=get_block_pos( block );
		p_tick=(p_tick - block_pos) % get_block( block )->get_length();
		p_tick+=block_pos;
		
	}
	
	AutomationBlock * b=(AutomationBlock*)BlockList::get_block(block); //cant use dynamic cast here, too slow, sorry there are other checks :(
	
	Tick block_tick=p_tick-get_block_pos(block);
	
	float res=b->get_data()->get_tick_val(block_tick);
	//printf("for tick p_tick %g , val is %g\n",(float)p_tick/(float)TICKS_PER_BEAT,res);
	return res;
	
	
	
	
}
void Track_Pattern::track_block_pre_process(int p_frames,int p_block, Tick p_offset,Tick p_total, Tick p_from, Tick p_to) {

	EventBuffer &event_buffer=get_event_buffer();
	
	Tick block_pos=get_block_pos(p_block);
	Tick tick_from_local=p_from;
	Tick tick_to_local=p_to;
	if (tick_from_local<0)
		tick_from_local=0;
	if (tick_to_local<0)
		tick_to_local=0;
		
	Position pos_from_local(tick_from_local,0);
	Position pos_to_local(tick_to_local,MAX_COLUMNS);
		
	Pattern *pd=get_block(p_block)->get_pattern();
	int from_idx;
	int to_idx;
	if (!pd->data.find_values_in_range(pos_from_local,pos_to_local,&from_idx,&to_idx)) {
			//printf("ticks %i to %i have indexes %i to %i\n",(int)tick_from_local,(int)tick_to_local,from_idx,to_idx);
		
		for (int i=from_idx;i<=to_idx;i++) {
								
			Tick tick=pd->data.get_index_pos(i).tick;
			if (tick<tick_from_local)
				continue;
			if (tick>tick_to_local)
				break;
			int col=pd->data.get_index_pos(i).column;
			if (col<0 || col>=MAX_COLUMNS)
				continue; //wont play what is not visible
			int frame=(p_offset+tick)*(p_total)/(Tick)p_frames;
				
				//printf("something at %i, in index %i (%i to %i) out of %i\n",(int)tick,i,from_idx,to_idx,pd->data.get_stream_size());
			Note n = pd->data.get_index_value(i);
				
			if (n.is_note()) {
					
					
				add_noteon_event_to_buffer(n.note,n.volume,col,event_buffer,frame);
					
			} else if (n.is_note_off() && data.last_note[col].is_note()) {
					
					//printf("AT %i - note off\n",(int)tick_to);
					
				Event e;
				SET_EVENT_MIDI(e,EventMidi::MIDI_NOTE_OFF,0,data.last_note[col].note,0);
				e.frame_offset=frame; //off te
				event_buffer.push_event(e);
				data.last_note[col]=n;
			}
		}
	}
	
	
}
Track_Pattern::NoteList Track_Pattern::get_notes_in_range(Tick p_from, Tick p_to) {
	
	NoteList res;
	int block_from;
	int block_to;
//	printf("get blocks in range %f-%f:",(float)p_from/TICKS_PER_BEAT,(float)p_to/TICKS_PER_BEAT);
	if (get_blocks_in_rage( p_from, p_to, &block_from, &block_to )) {
//		printf(" none!\n");
		return res; //emty list, nothing fits!
	}
	//printf(" %i\n",(block_to-block_from)+1);
	
	for (int i=block_from;i<=block_to;i++) {
		
		PatternBlock *b = get_block(i);
		Tick tick_begin=get_block_pos(i);
		Tick tick_end=tick_begin+b->get_length()-1;
		int note_from;
		int note_to;
		Tick tick_from=(tick_begin<p_from)?p_from:tick_begin;
		Tick tick_to=(p_to>tick_end)?tick_end:p_to;
				
//		printf("scanning block %i, ticks %f-%f\n",i,(float)tick_from/TICKS_PER_BEAT,(float)tick_to/TICKS_PER_BEAT);
		
		if (b->get_notes_in_local_range( tick_from-tick_begin, tick_to-tick_begin, &note_from, &note_to) )
			continue; //couldnt find any note
		//printf("found %i notes\n",note_to-note_from);
		
		for (int j=note_from;j<=note_to;j++) {
			
			NoteListElement e;
			e.note=b->get_note( j );
			e.pos=b->get_note_pos( j );
			e.pos.tick+=get_block_pos( i );
			res.push_back(e);
		}
	}
	
	
	return res;
}
Пример #4
0
 optional<signed_block> block_log::read_block_by_num(uint32_t block_num) const {
     try {
         optional<signed_block> b;
         uint64_t pos = get_block_pos(block_num);
         if (pos != npos) {
             b = read_block(pos).first;
             FC_ASSERT(b->block_num() ==
                       block_num, "Wrong block was read from block log.", ("returned", b->block_num())("expected", block_num));
         }
         return b;
     }
     FC_LOG_AND_RETHROW()
 }
Track_Pattern::Note Track_Pattern::get_note(const Position& p_pos) {
		
	int pb_idx = get_block_idx_at_pos( p_pos.tick );
	ERR_FAIL_COND_V(pb_idx==-1,Note());
	PatternBlock *bp=get_block(pb_idx);
	ERR_FAIL_COND_V(bp==NULL,Note());
	
	Position rel_pos( p_pos.tick-get_block_pos(pb_idx) , p_pos.column );
	
	int tick_idx = bp->get_pattern()->data.get_exact_index(rel_pos);
	if (tick_idx==INVALID_STREAM_INDEX)
		return Note(); //return empty note, as pos in tick does not exist */
	
	return bp->get_pattern()->data.get_index_value(tick_idx);

}
void Track_Pattern::set_note(const Position& p_pos,const Note& p_note) {
	
	int pb_idx = get_block_idx_at_pos( p_pos.tick );
	ERR_FAIL_COND(pb_idx==-1);
	PatternBlock *bp=get_block(pb_idx);
	ERR_FAIL_COND(bp==NULL);
	
	Position rel_pos( p_pos.tick-get_block_pos(pb_idx) , p_pos.column );

	if (p_note.is_empty()) { //sets an empty note, delete it */
		int tick_idx = bp->get_pattern()->data.get_exact_index( rel_pos );
		if (tick_idx==INVALID_STREAM_INDEX) {
			return; /* nothing to erase */
		}   

		bp->get_pattern()->data.erase_index(tick_idx);

	} else { /* just insert-overwrite wathever you can find */

		bp->get_pattern()->data.insert( rel_pos, p_note);
	
	}

}
void Track_Pattern::track_pre_process(int p_frames) {
	/* I HATE THIS FUNCTION */
	
	EventBuffer &event_buffer=get_event_buffer();
	
	//add the edit events (if any) at offset 0
	for (int i=0;i<data.edit_event_buffer.get_event_count();i++) {
		
		Event e=*data.edit_event_buffer.get_event(i);
		e.frame_offset=0;
		event_buffer.push_event(e);
	}
	data.edit_event_buffer.clear();

	
	if (get_song_playback()->get_status()!=SongPlayback::STATUS_PLAY) {
		
		data.old_tick_to=-1;
		return; //nothing much to do
	}
	int block_count=get_block_count();
	if (block_count==0) {
		data.old_tick_to=-1;
		return; //nuthin' to do
	}
	
	/* Up to where we are going to process. */
	Tick tick_to=get_swinged_tick( get_song_playback()->get_current_tick_to() );
		
	Tick tick_from; //from where we process
	
	if (data.old_tick_to==-1 || tick_to<data.old_tick_to || abs(tick_to-data.old_tick_to)>TICKS_PER_BEAT)
		// if previous processing pos is invalid, or position changed
		tick_from=get_song_playback()->get_current_tick_from();
	else
		
		tick_from=data.old_tick_to+1;
	
	
	if (tick_from>tick_to) //we already processed up to this tick
		return; //nothing to do
	
	data.old_tick_to=tick_to;
	
	int block_idx=get_prev_block_from_idx(tick_from);
	//printf("PAT: from %i to %i\n",(int)tick_from,(int)tick_to);
	
	if (block_idx==-1) {
		
		block_idx=0;
	}
	
	while (block_idx<block_count && (get_block_pos(block_idx)<=tick_to) ) {
		
		/* process block */
		Tick block_pos=get_block_pos(block_idx);
		Tick block_len=get_block(block_idx)->get_length();
		Tick block_end=block_pos+block_len;
		
		/* If not inside the block, dont even bother */
		if (tick_from<block_end)
			track_block_pre_process( p_frames, block_idx, 0, tick_to-tick_from, tick_from-block_pos, tick_to-block_pos );
		
		/* Check if this has repeat, and has to be computed! */
		if (get_block(block_idx)->is_repeat_active() && tick_to>=block_end) {
			
			Tick rep_tick_from=tick_from;
			Tick rep_tick_to=tick_to;
			Tick rep_ofs=0;
			
			/* Wrap tick to repeat-able-space*/
			if (block_idx<(block_count-1) && tick_to>=get_block_pos(block_idx+1)) {
				
				rep_tick_to=get_block_pos(block_idx+1)-1;
			}
			
			if (tick_from<block_end) {
				rep_tick_from=block_end;
				rep_ofs=block_end-tick_from;
			}
			
			/* convert to local to block positions */
			
			rep_tick_from-=block_pos;
			rep_tick_to-=block_pos;
			
			if (rep_tick_from<=rep_tick_to) { //can do bussiness 
			
				int from_at_idx=rep_tick_from/block_len;
				int to_at_idx=rep_tick_to/block_len;
				
				/* convert to inside block positions  */
				
				rep_tick_from=rep_tick_from%block_len;
				rep_tick_to=rep_tick_to%block_len;
				
				/* process all blocks that need repeat! */
				for (int i=from_at_idx;i<=to_at_idx;i++) {
					
					Tick from_local=0;
					Tick to_local=block_len-1;
												
					// adjust depending on begin and end
					if (i==from_at_idx)
						from_local=rep_tick_from;
					
					if (i==to_at_idx)
						to_local=rep_tick_to;
					
//					printf("%i Repeat at %i, %i - inside %i\n",i-from_at_idx,(int)from_local,(int)to_local,(int)block_len);
					track_block_pre_process( p_frames, block_idx, rep_ofs, tick_to-tick_from, from_local, to_local );
					
					rep_ofs+=block_len-from_local;
				}
			}
		}
		
		/* 
		Tick tick_from_local=tick_from-block_pos;
		Tick tick_to_local=tick_to-block_pos;
		if (tick_from_local<0)
			tick_from_local=0;
		if (tick_to_local<0)
			tick_to_local=0;
		
		Position pos_from_local(tick_from_local,0);
		Position pos_to_local(tick_to_local,MAX_COLUMNS);
		
		Pattern *pd=get_block(block_idx)->get_pattern();
		int from_idx;
		int to_idx;
		if (!pd->data.find_values_in_range(pos_from_local,pos_to_local,&from_idx,&to_idx)) {
			//printf("ticks %i to %i have indexes %i to %i\n",(int)tick_from_local,(int)tick_to_local,from_idx,to_idx);
		
			for (int i=from_idx;i<=to_idx;i++) {
								
				Tick tick=pd->data.get_index_pos(i).tick;
				if (tick<tick_from_local)
					continue;
				if (tick>tick_to_local)
					break;
				int col=pd->data.get_index_pos(i).column;
				if (col<0 || col>=MAX_COLUMNS)
					continue; //wont play what is not visible
				int frame=tick*(tick_to-tick_from)/(Tick)p_frames;
				
				//printf("something at %i, in index %i (%i to %i) out of %i\n",(int)tick,i,from_idx,to_idx,pd->data.get_stream_size());
				Note n = pd->data.get_index_value(i);
				
				if (n.is_note()) {
					
					
					add_noteon_event_to_buffer(n.note,n.volume,col,event_buffer,frame);
					
				} else if (n.is_note_off() && data.last_note[col].is_note()) {
					
					//printf("AT %i - note off\n",(int)tick_to);
					
					Event e;
					SET_EVENT_MIDI(e,EventMidi::MIDI_NOTE_OFF,0,data.last_note[col].note,0);
					e.frame_offset=frame; //off te
					event_buffer.push_event(e);
					data.last_note[col]=n;
				}
			}
		} */

		
		
		/* Process note OFFs at end of block */
		
		/* Is there a reason for this?
		Tick block_len=get_block(block_idx)->get_length();
		if (tick_from_local<=block_len && tick_to_local>=block_len) {
			
			int frame=block_len*(tick_to_local-tick_from_local)/(Tick)p_frames;
			
			for (int i=0;i<MAX_COLUMNS;i++) {
				
				if (data.last_note[i].is_note()) {
					
					//printf("AT %i - note off\n",(int)tick_to);
					
					Event e;
					SET_EVENT_MIDI(e,EventMidi::MIDI_NOTE_OFF,0,data.last_note[i].note,0);
					e.frame_offset=frame; //off te
					event_buffer.push_event(e);
					data.last_note[i]=Note(Note::NOTE_OFF);
				}				
			}
		}
		
		*/
		block_idx++;
	}
	
	
	
}