Example #1
0
void RT_schedule_LPBs_newblock(struct SeqTrack *seqtrack,
                               const struct SeqBlock *seqblock,
                               const Place start_place)
{
  LPB_Iterator *iterator = &seqtrack->lpb_iterator;

  // Null out all fields, except num_beats_played_so_far.
  double num_beats_played_so_far = iterator->num_beats_played_so_far + iterator->num_beats_between_place1_and_place2;
  memset(iterator, 0, sizeof(LPB_Iterator));
  iterator->num_beats_played_so_far = num_beats_played_so_far;
  
  const struct Blocks *block = seqblock->block;

  const struct LPBs *lpb = block->lpbs;

  if (lpb==NULL) {

    set_iterator_data2(iterator, block, PlaceFirstPos, root->lpb, NULL);
    
  } else if (PlaceGreaterThan(&lpb->l.p, &start_place)){

    set_iterator_data2(iterator, block, PlaceFirstPos, root->lpb, lpb);      
    schedule_next_LPB(seqtrack, seqblock, lpb);
    
  } else {
    
    const struct LPBs *next_lpb = NextLPB(lpb);
    
    // spool forward to the 'lpb' that is used by 'start_place'
    //
    while(next_lpb != NULL){
      if (PlaceGreaterThan(&next_lpb->l.p, &start_place))
        break;
      
      lpb = next_lpb;
      next_lpb = NextLPB(lpb);
    }
    
    set_iterator_data(iterator, block, lpb);
    
    if (next_lpb != NULL)
      schedule_next_LPB(seqtrack, seqblock, next_lpb);
    
  }

  
  R_ASSERT(iterator->lpb_value != 0);  
}
Example #2
0
void ListAddElement3_a(
	void *voidlistroot,
	struct ListHeader3 *element
){
	struct ListHeaderPointer3 *listroot=voidlistroot;
	struct ListHeader3 *prev=NULL;
	struct ListHeader3 *temp=listroot->root;

	if(element==NULL) return;

	while(temp!=NULL){
		if(PlaceGreaterThan(&temp->p,&element->p)) break;
		prev=temp;
		temp=temp->next;
	}

	if(prev==NULL){
                R_ASSERT_RETURN_IF_FALSE(element!=NULL);
		element->next=listroot->root;
		listroot->root=element;
	}else{
                R_ASSERT_RETURN_IF_FALSE(element!=NULL);
		element->next=prev->next;
		prev->next=element;
	}
}
Example #3
0
/**************************************************************
  FUNCTION
    Set the _end attributes for note 'note'.
    Finds next note to stop at, or block length.
**************************************************************/
void SetEndAttributes(
	const struct Blocks *block,
	const struct Tracks *track,
	struct Notes *note
){
	Place *place;
	Place *p1=NULL,*p2=NULL;

        bool endSetEarlier = PlaceGreaterThan(&note->end, &note->l.p);
        Place *earliest = endSetEarlier ? &note->end : &note->l.p;

        struct ListHeader3 *nextnote=note->l.next;
        while(nextnote!=NULL){
          if(PlaceGreaterThan(&nextnote->p, earliest)){
            p1 = &nextnote->p;
            break;
          }
          nextnote=nextnote->next;
        }

        struct ListHeader3 *stop= &track->stops->l;
        while(stop!=NULL){
          if(PlaceGreaterThan(&stop->p, earliest)){
            p2 = &stop->p;
            break;
          }
          stop=stop->next;
        }

	place=PlaceMin(p1,p2);

	if(place!=NULL){
		note->end.line=place->line;
		note->end.counter=place->counter;
		note->end.dividor=place->dividor;
	}else{
        	PlaceSetLastPos(block, &note->end);
        	note->noend=1;
	}

        ValidatePlace(&note->end);
}
Example #4
0
void TRACK_make_monophonic_destructively(struct Tracks *track){
  struct Tracker_Windows *window = root->song->tracker_windows;
  struct WBlocks *wblock = window->wblock;

  struct Notes *note = track->notes;

  bool have_made_undo = false;
  
  while(note!=NULL){
    struct Notes *next = NextNote(note);
    if (next==NULL)
      break;

    if (PlaceGreaterThan(&note->end, &next->l.p)){

      PLAYER_lock();{

        if (PlaceEqual(&note->l.p, &next->l.p)) {

          ListRemoveElement3(&track->notes, &next->l);                           

        } else {

          PlaceCopy(&note->end, &next->l.p);
          note = next;

        }

      }PLAYER_unlock();

      if (have_made_undo==false){      
        ADD_UNDO(Notes(window,
                       wblock->block,
                       track,
                       wblock->curr_realline
                       )
                 );

        have_made_undo = true;
      }

    } else {

      note = next;

    }

  }

  if (have_made_undo==false)
    GFX_Message(NULL, "Track is already monophonic");
  else
    window->must_redraw = true;
}
Example #5
0
/**********************************************************************
  FUNCTION
    Set the end attributes of all notes that previously was stopped
    at position 'placement' to the next stop wherever that may be.
**********************************************************************/
void LengthenNotesTo(
	struct Blocks *block,
	struct Tracks *track,
	Place *placement
){
	struct Notes *note=track->notes;
	while(note!=NULL){
		if(PlaceGreaterThan(&note->l.p,placement)) break;
		if(PlaceEqual(&note->end,placement))
			SetEndAttributes(block,track,note);
		note=NextNote(note);
	}
}
Example #6
0
/* Nearly the same, except that it cuts first one that is placed _after_ 'place' */
void CutListAt_a(void *listroot,Place *place){
	struct ListHeaderPointer3 *root=(struct ListHeaderPointer3 *)listroot;
	struct ListHeader3 *element=root->root;

	if(element==NULL) return;

	if(PlaceGreaterThan(&element->p,place)){
		root->root=NULL;
		return;
	}

	for(;element!=NULL;element=element->next){
		if(
			element->next!=NULL &&
			PlaceGreaterThan(&element->next->p,place)
		){
			element->next=NULL;
			break;
		}
	}
	
}
Example #7
0
/**********************************************************************
  FUNCTION
    Set the end attributes of all notes that previously was stopped
    at position 'old_placement' to 'new_placement'.
**********************************************************************/
void ReplaceNoteEnds(
	struct Blocks *block,
	struct Tracks *track,
	Place *old_placement,
        Place *new_placement,
        int polyphony_num
){
	struct Notes *note=track->notes;
	while(note!=NULL){
          if (note->polyphony_num == polyphony_num) {
            if(PlaceGreaterThan(&note->l.p,old_placement)) break;
            if(PlaceEqual(&note->end,old_placement)) {
              note->end = *new_placement;
              NOTE_validate(block, track, note);
            }
          }
          note=NextNote(note);
	}
}
Example #8
0
void RT_schedule_Signature_newblock(struct SeqTrack *seqtrack,
                                    const struct SeqBlock *seqblock,
                                    const Place start_place)
{

  Signature_Iterator *iterator = &seqtrack->signature_iterator;
  memset(iterator, 0, sizeof(Signature_Iterator));
  iterator->signature_value = root->signature;
  //printf("   SIG Init %d/%d\n",iterator->signature_value.numerator, iterator->signature_value.denominator);
  
  const struct Blocks *block = seqblock->block;
    
  const struct Signatures *next_signature = block->signatures;

  if(next_signature==NULL)
    return;

  // spool forward to the 'signature' that is used by 'start_place'
  //
  while(PlaceGreaterThan(&start_place, &next_signature->l.p)){
    iterator->signature_value = next_signature->signature;
    //printf("   SIG Init %d/%d\n",iterator->signature_value.numerator, iterator->signature_value.denominator);
    next_signature = NextSignature(next_signature);
    if (next_signature==NULL)
      return;
  }

  iterator->next_signature = next_signature;
  
  {
    int num_args = 1;
    union SuperType args[num_args];
    args[0].const_pointer = seqblock;
    
    int64_t time = get_seqblock_place_time(seqblock, next_signature->l.p);
    
    SCHEDULER_add_event(seqtrack, time, RT_scheduled_Signature, &args[0], num_args, SCHEDULER_SIGNATURE_PRIORITY);
  }
}
Example #9
0
/**************************************************************
  FUNCTION
    Stops all notes before line+(counter/dividor) at
    line+(counter/dividor, if they last that long.
**************************************************************/
void StopAllNotesAtPlace(
                         struct Blocks *block,
                         struct Tracks *track,
                         Place *placement
){
  if (PLAYER_current_thread_has_lock()==false && is_playing()==true){
    RError("StopAllNotesAtPlace. PLAYER_current_thread_has_lock(): %d, is_playing(): %d", PLAYER_current_thread_has_lock()==false, is_playing()==true);
  }
          
	struct Notes *temp;

	temp=track->notes;

	while(temp!=NULL && PlaceLessThan(&temp->l.p,placement)){
		if(PlaceGreaterThan(&temp->end,placement)){
			CutListAt(&temp->velocities,placement);
			CutListAt(&temp->pitches,placement);
			PlaceCopy(&temp->end,placement);
                        NOTE_validate(block, track, temp);
		}
		temp=NextNote(temp);
	}
}
Example #10
0
void TRACK_split_into_monophonic_tracks(struct Tracker_Windows *window, struct WBlocks *wblock, struct WTracks *wtrack){
  
  PlayStop(); // This function is too chaotic. Don't bother pausing player.

  vector_t notesvector = {0};
  
  struct Tracks *track = wtrack->track;

  struct Notes *notes = track->notes;
  struct Notes *notes_nexttrack = NULL;

  bool have_made_undo = false;

  if (NOTES_sorted_by_pitch_questionmark(track->notes)==false) {
    ADD_UNDO(Block_CurrPos(window));    
    have_made_undo = true;
    notes = NOTES_sort_by_pitch(notes);
  }
  
  while(notes != NULL){

    struct Notes *notes_root = notes;
    
    while(notes != NULL) {

      struct Notes *next = NextNote(notes);
      if (next==NULL)
        break;

      if (PlaceGreaterThan(&notes->end, &next->l.p)){

        if (have_made_undo==false) {
            have_made_undo=true;
        }
        
        ListRemoveElement3(&notes, &next->l);                           
        ListAddElement3_a(&notes_nexttrack, &next->l);

      } else
        notes = next;
    }

    VECTOR_push_back(&notesvector, notes_root);

    notes = notes_nexttrack;
    notes_nexttrack = NULL;
  }

  if (have_made_undo==false){
    GFX_Message(NULL, "Track is already monophonic");
    return;
  }

  int num_tracks = notesvector.num_elements;

  track->notes = NULL;

  struct WTracks *wtrack_copy = CB_CopyTrack(wblock,wtrack);
  VECTOR_clean(&wtrack_copy->track->fxs);

  InsertTracks(window, wblock, wtrack->l.num+1, num_tracks-1);

  printf("Vector length: %d\n",num_tracks);
  int i;
  for(i=0;i<num_tracks;i++){
    struct Notes *notes = notesvector.elements[i];
    printf("  %d: %d\n", i, ListFindNumElements3(&notes->l));
    while(notes != NULL){
      printf("    %s\n",NotesTexts3[(int)notes->note]);
      notes = NextNote(notes);
    }
    
    struct WTracks *towtrack = ListFindElement1(&wblock->wtracks->l, wtrack->l.num+i);
    
    if (i>0)
      co_CB_PasteTrack(wblock, wtrack_copy, towtrack);

    towtrack->track->notes = notesvector.elements[i];
  }

  window->must_redraw = true;
}
Example #11
0
static const struct NodeLine *create_nodelines(
                                        const struct Tracker_Windows *window,
                                        const struct WBlocks *wblock,
                                        const struct ListHeader3 *list,                                  
                                        float (*get_x)(const struct WBlocks *wblock, const struct ListHeader3 *element, int *logtype), // should return a value between 0 and 1.
                                        const struct ListHeader3 *last_element // may be null. may also contain more than one element.
                                        )
{
  struct NodeLine *nodelines = NULL;

  R_ASSERT(list != NULL);
  R_ASSERT(list->next != NULL || last_element!=NULL);

  if (last_element!=NULL){
    const Place *start = &list->p;
    const Place *end = &last_element->p;
    R_ASSERT(PlaceGreaterThan(end, start));
  }
  
  // 1. Create straight forward nodelines from the list
  {
    float reallineF = 0.0f;
    struct NodeLine *nodelines_last = NULL;

    while(list != NULL){
      struct NodeLine *nodeline = (struct NodeLine *)talloc(sizeof(struct NodeLine));

      nodeline->x1 = get_x(wblock, list, &nodeline->logtype);
      reallineF = FindReallineForF(wblock, reallineF, &list->p);
      nodeline->y1 = get_realline_y(window, reallineF);
      nodeline->element1 = list;
      nodeline->is_node = true;

      if(nodelines_last==NULL)
        nodelines = nodelines_last = nodeline;
      else {
        nodelines_last->next = nodeline;
        nodelines_last = nodeline;
      }

      list = list->next;
      if (list==NULL) {
        list = last_element;
        last_element = NULL;
      }
    }
  }


  // 2. Insert x2, y2 and element2 attributes, and remove last element.
  {
    R_ASSERT_RETURN_IF_FALSE2(nodelines!=NULL, NULL); // shouldn't be possible, but I got a crash report that indicates that this might have happened.
    R_ASSERT_RETURN_IF_FALSE2(nodelines->next!=NULL, NULL); // shouldn't be possible either, but more likely than the line above.

    struct NodeLine *ns = nodelines;
    struct NodeLine *next = ns->next;
    
    for(;;){
      ns->x2 = ns->logtype==LOGTYPE_HOLD ? ns->x1 : next->x1;
      ns->y2 = next->y1;

      if (ns->y2 < ns->y1) {
        RWarning("y2 < y1: %f < %f",ns->y2,ns->y1);
        ns->y2 = ns->y1;
      }

      ns->element2 = next->element1;
      if(next->next==NULL)
        break;
      ns = next;
      next = next->next;
    }
    ns->next = NULL; // Cut the last element
  }


  // 3. Insert all non-node break-points. (caused by realline level changes)
  {
    struct LocalZooms **reallines=wblock->reallines;
    int curr_level = reallines[0]->level;
    int realline;
    float reallineF = 0.0f;
    
    for(realline = 1; realline < wblock->num_reallines ; realline++) {
          
      struct LocalZooms *localzoom = reallines[realline];
      
      if (localzoom->level != curr_level){
        reallineF = FindReallineForF(wblock, reallineF, &localzoom->l.p);
        insert_nonnode_nodeline(nodelines, &localzoom->l, get_realline_y(window, reallineF));
        curr_level = localzoom->level;
      }
    }
  }


  return nodelines;
}
Example #12
0
static void set_legal_start_and_end_pos(const struct Blocks *block, struct Tracks *track, struct Notes *note){
  Place *start = &note->l.p;
  Place *end = &note->end;
  Place endplace;

  PlaceSetLastPos(block,&endplace);
  
  if(PlaceGreaterOrEqual(start,&endplace)) {
    RError("note is placed after block end. start: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&note->end));
    set_new_position(track, note, PlaceCreate(block->num_lines - 2, 0, 1), NULL);
    start = &note->l.p;
  }
  
  if (start->line < 0) {
    RError("note is placed before block start. start: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&note->end));
    set_new_position(track, note, PlaceCreate(0,1,1), NULL);
    start = &note->l.p;
  }
  
  if(PlaceGreaterThan(end,&endplace)) {
    RError("note end is placed after block end. start: %f, end: %f. block end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&note->end), GetfloatFromPlace(&endplace));
    set_new_position(track, note, NULL, &endplace);
    end = &note->end;
  }

  if (note->velocities != NULL) {
    {
      struct Velocities *first_velocity = note->velocities;
      if(PlaceGreaterThan(start, &first_velocity->l.p)){
        RError("note start is placed after first velocity. start: %f, first: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&first_velocity->l.p), GetfloatFromPlace(&note->end));
        float e = p_float(first_velocity->l.p);
        e -= 0.01;
        e = R_MAX(0.0, e);
        Place new_start;
        Float2Placement(e, &new_start);
        set_new_position(track, note, &new_start, NULL);
        start = &note->l.p;
      }
    }

    struct Velocities *last_velocity = (struct Velocities*)ListLast3(&note->velocities->l);
    if(PlaceLessThan(end, &last_velocity->l.p)){
      RError("note end is placed before last velocity. start: %f, last: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&last_velocity->l.p), GetfloatFromPlace(&note->end));
      float e = p_float(last_velocity->l.p);
      e += 0.01;
      Place new_end;
      Float2Placement(e, &new_end);
      set_new_position(track, note, NULL, &new_end);
      end = &note->end;
    }

  }
  
  if (note->pitches != NULL) {
    {
      struct Pitches *first_pitch = note->pitches;
      if(PlaceGreaterThan(start, &first_pitch->l.p)){
        RError("note start is placed after first pitch. start: %f, first: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&first_pitch->l.p), GetfloatFromPlace(&note->end));
        float e = p_float(first_pitch->l.p);
        e -= 0.01;
        e = R_MAX(0.0, e);
        Place new_start;
        Float2Placement(e, &new_start);
        set_new_position(track, note, &new_start, NULL);
        start = &note->l.p;
      }
    }
    
    struct Pitches *last_pitch = (struct Pitches*)ListLast3(&note->pitches->l);
    if(PlaceLessThan(end, &last_pitch->l.p)){
      RError("note end is placed before last pitch. start: %f, last: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&last_pitch->l.p), GetfloatFromPlace(&note->end));
      float e = p_float(last_pitch->l.p);
      e += 0.01;
      Place new_end;
      Float2Placement(e, &new_end);
      set_new_position(track, note, NULL, &new_end);
      end = &note->end;
    }
  }
  
  if(PlaceLessOrEqual(end,start)) {
    RError("note end is placed before (or on) note start. start: %f, end: %f", GetfloatFromPlace(&note->l.p), GetfloatFromPlace(&note->end));
    float e = p_float(*start);
    e += 0.01;
    Place new_end;
    Float2Placement(e, &new_end);
    set_new_position(track, note, NULL, &new_end);
  }

}