struct Notes *FindNextNoteOnSameSubtrack(struct Notes *note){ int polyphony_num = note->polyphony_num; note = NextNote(note); while(note!=NULL){ if (note->polyphony_num==polyphony_num) return note; else note = NextNote(note); } return NULL; }
void Glissando_CurrPos(struct Tracker_Windows *window){ struct WBlocks *wblock=window->wblock; struct WTracks *wtrack=wblock->wtrack; struct Notes *note=wtrack->track->notes; struct Notes *nextnote; int realline = wblock->curr_realline; const Place *p=&wblock->reallines[realline]->l.p; while(note!=NULL){ nextnote=NextNote(note); if(nextnote==NULL) return; if(PlaceIsBetween2(p,¬e->l.p,&nextnote->l.p)){ ADD_UNDO(Notes(window, wblock->block, wtrack->track, realline)); Glissando(wblock,wtrack,note); /* UpdateAndClearSomeTrackReallinesAndGfxWTracks( window, wblock, wtrack->l.num, wtrack->l.num ); */ return; } note=nextnote; } }
float TRACK_get_max_pitch(const struct Tracks *track){ float max_pitch = -1; int num_pitches = 0; { struct Notes *note = track->notes; while(note!=NULL){ max_pitch = R_MAX(note->note, max_pitch); num_pitches ++; struct Pitches *pitch = note->pitches; while(pitch != NULL){ max_pitch = R_MAX(pitch->note, max_pitch); num_pitches ++; pitch = NextPitch(pitch); } note = NextNote(note); } } if (num_pitches==0) return -1; else return max_pitch; }
static void Scroll_play_down3( struct WBlocks *wblock, const Place *p1, const Place *p2 ){ struct Tracks *track = wblock->block->tracks; while(track != NULL){ struct Patch *patch=track->patch; if (patch != NULL){ struct Notes *note = track->notes; while(note != NULL){ if (PlaceIsBetween2(¬e->l.p, p1, p2)) PATCH_play_note(patch, note->note, note->id, VELOCITY_get(note->velocity), TRACK_get_pan(track)); if (PlaceIsBetween2(¬e->end, p1, p2)) PATCH_stop_note(patch, note->note, note->id); note = NextNote(note); } } track = NextTrack(track); } }
void Invert_notes( struct Notes *note, Place *p1, Place *p2, bool firsttime, int last ){ int next=0; if(note==NULL) return; if(PlaceGreaterOrEqual(¬e->l.p,p1)){ if(PlaceGreaterOrEqual(¬e->l.p,p2)) return; next=note->note; if(firsttime==false){ note->note=R_MAX(1,R_MIN(127,2*last-note->note)); }else{ firsttime=false; } } Invert_notes(NextNote(note),p1,p2,firsttime,next); }
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(¬e->end, &next->l.p)){ PLAYER_lock();{ if (PlaceEqual(¬e->l.p, &next->l.p)) { ListRemoveElement3(&track->notes, &next->l); } else { PlaceCopy(¬e->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; }
struct Notes *FindPrevNoteOnSameSubTrack(struct Tracks *track, struct Notes *note){ struct Notes *notes = track->notes; struct Notes *prev = NULL; while(notes != note){ if (notes->polyphony_num == note->polyphony_num) prev = notes; notes = NextNote(notes); } return prev; }
void TransposeTrack( struct Tracks *track, int trans ){ struct Notes *note=track->notes; while(note!=NULL){ Transpose_note(note, trans); note=NextNote(note); } }
bool NOTES_sorted_by_pitch_questionmark(struct Notes *notes){ while(notes != NULL){ struct Notes *next = NextNote(notes); if (next==NULL) return true; if (PlaceEqual(¬es->l.p, &next->l.p)) if (notes->note > next->note) return false; notes = next; } return true; }
struct Notes *FindNextNote( struct Tracks *track, Place *placement ) { struct Notes *note = track->notes; while(note != NULL) { if (PlaceGreaterOrEqual(¬e->l.p, placement)) break; note = NextNote(note); } return note; }
struct Notes *FindNote( struct Tracks *track, Place *placement ) { struct Notes *note = track->notes; while(note != NULL) { if (PlaceIsBetween2(placement, ¬e->l.p, ¬e->end)) break; note = NextNote(note); } return note; }
/********************************************************************** 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(¬e->l.p,placement)) break; if(PlaceEqual(¬e->end,placement)) SetEndAttributes(block,track,note); note=NextNote(note); } }
void PEQ_FindNextNote(struct PEventQueue *peq){ struct Notes *note=NextNote(peq->note); if(note!=NULL){ peq->note=note; PC_InsertElement2_a(peq,0,¬e->l.p); InitPEQendnote(peq->block,peq->track,note,0); InitPEQvelocities(peq->block,peq->track,note,0); InitPEQpitches(peq->block,peq->track,note,0); }else{ PEQ_FindNextNoteAddPlayPos(peq); } }
void AddPitchElements( struct Tracker_Windows *window, struct WBlocks *wblock, struct WTracks *wtrack ){ float min_pitch = 10000.0f; float max_pitch = -10000.0f; TRACK_get_min_and_max_pitches(wtrack->track,&min_pitch, &max_pitch); struct Notes *note=wtrack->track->notes; while(note!=NULL){ struct Pitches *pitch=note->pitches; int realline = 0; while(pitch!=NULL){ realline=FindRealLineFor(wblock,R_MAX(pitch->Tline,realline),&pitch->l.p); int subrealline=FindSubRealLine(window,wblock,realline,&pitch->l.p); InsertTRLElementS( wtrack, note, realline, TRE_THISPITCHLINES,0, (float)subrealline,(float)subrealline,0.0f,(float)(wtrack->fxwidth-2), pitch ); if (wtrack->trackreallines[realline].note!=0) { wtrack->trackreallines[realline].note=NOTE_MUL; wtrack->trackreallines[realline].dasnote=NULL; } else { wtrack->trackreallines[realline].note=pitch->note; wtrack->trackreallines[realline].daspitch=pitch; } pitch=NextPitch(pitch); } #if !USE_OPENGL UpdateWPitches(window, wblock, wtrack, note, min_pitch, max_pitch); #endif note=NextNote(note); } }
static void Scroll_play_down3( struct WBlocks *wblock, const Place *p1, const Place *p2 ){ struct Tracks *track = wblock->block->tracks; while(track != NULL){ if (track->onoff==1){ struct Patch *patch=track->patch; if (patch != NULL){ struct Notes *note = track->notes; while(note != NULL){ if (PlaceIsBetween2(¬e->l.p, p1, p2)) PATCH_play_note(patch, create_note_t(NULL, note->id, note->note, VELOCITY_get(note->velocity), TRACK_get_pan(track), ATOMIC_GET(track->midi_channel), 0) ); if (PlaceIsBetween2(¬e->end, p1, p2)) PATCH_stop_note(patch, create_note_t(NULL, note->id, note->note, 0, TRACK_get_pan(track), ATOMIC_GET(track->midi_channel), 0 ) ); note = NextNote(note); } } } track = NextTrack(track); } }
void CopyRange_notes( struct Notes **tonote, struct Notes *fromnote, Place *p1, Place *p2 ){ struct Notes *note; if(fromnote==NULL){ return; } if(PlaceLessThan(&fromnote->l.p,p1)){ CopyRange_notes(tonote,NextNote(fromnote),p1,p2); return; } if(PlaceGreaterOrEqual(&fromnote->l.p,p2)){ return; } note=CopyNote(fromnote); note->pitches = NULL; note->velocities = NULL; NOTE_init(note); PlaceSub(¬e->l.p,p1); PlaceSub(¬e->end,p1); ListAddElement3(tonote,¬e->l); CopyRange_velocities(¬e->velocities,fromnote->velocities,p1,p2); CopyRange_pitches(¬e->pitches,fromnote->pitches,p1,p2); CopyRange_notes(tonote,NextNote(fromnote),p1,p2); }
bool TRACK_get_min_and_max_pitches(const struct Tracks *track, float *ret_min_pitch, float *ret_max_pitch){ float min_pitch = 10000.0f; float max_pitch = -10000.0f; int num_pitches = 0; // find min_pitch and max_pitch { struct Notes *note = track->notes; while(note!=NULL){ min_pitch = R_MIN(note->note, min_pitch); max_pitch = R_MAX(note->note, max_pitch); num_pitches ++; struct Pitches *pitch = note->pitches; while(pitch != NULL){ min_pitch = R_MIN(pitch->note, min_pitch); max_pitch = R_MAX(pitch->note, max_pitch); num_pitches ++; pitch = NextPitch(pitch); } note = NextNote(note); } float pitch_range = max_pitch - min_pitch; min_pitch = min_pitch - pitch_range/8.0f; if(min_pitch < 0) min_pitch = 0; max_pitch = max_pitch + pitch_range/8.0f; if(max_pitch >127) max_pitch = 127; } if(min_pitch == 10000.0f) return false; else { if (num_pitches>3) { *ret_min_pitch = min_pitch; *ret_max_pitch = max_pitch; } else { *ret_min_pitch = 0; *ret_max_pitch = 128; } return true; } }
/**************************************************************** FUNCTION Building up all from the ground, is what really happens. ****************************************************************/ void UpdateTrackReallines( struct Tracker_Windows *window, struct WBlocks *wblock, struct WTracks *wtrack ){ #if 0 SetNum_Vel(wtrack); #endif /* if(wtrack->num_vel>(wtrack->fxwidth/(window->fontwidth*2))){ wtrack->fxwidth=window->fontwidth*wtrack->num_vel*2; if(window->wblock==wblock){ UpdateAllWTracksCoordinates(window,wblock); UpdateFXNodeLines(window,wblock,wtrack); window->must_redraw = true; } } */ NewTrackRealLines(wblock,wtrack); struct Notes *note=wtrack->track->notes; while(note!=NULL){ AddTrackReallineNote(window,wblock,wtrack,note); note=NextNote(note); } InsertStartTREElements(wtrack); OrganizeThisNoteLines(window,wblock,wtrack); AddStopsElements(window,wblock,wtrack); AddPitchElements(window,wblock,wtrack); #if !USE_OPENGL create_peaks(window,wblock,wtrack); #endif #if 0 if(window->curr_track==wtrack->l.num) if(window->curr_track_sub >= wtrack->num_vel) window->curr_track_sub=wtrack->num_vel-1; #endif }
void Transpose_notes( struct Notes *note, Place *p1, Place *p2, int trans ){ if(note==NULL) return; if(PlaceGreaterOrEqual(¬e->l.p,p1)){ if(PlaceGreaterOrEqual(¬e->l.p,p2)) return; Transpose_note(note,trans); } Transpose_notes(NextNote(note),p1,p2,trans); }
static float FindNextPitch(struct PEventQueue *peq){ struct Notes *next_note = NextNote(peq->note); if(next_note!=NULL) return next_note->note; else { const struct Blocks *block; struct Tracks *track; struct Notes *note; int playlistaddpos=0; if (PC_GetNextNoteAfterCurrentBlock(peq->track->l.num, &playlistaddpos, ¬e, &track, &block) == false) return -1.0f; return note->note; } }
/********************************************************************** 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(¬e->l.p,old_placement)) break; if(PlaceEqual(¬e->end,old_placement)) { note->end = *new_placement; NOTE_validate(block, track, note); } } note=NextNote(note); } }
struct Notes *FindNoteOnSubTrack( const struct WTracks *wtrack, int subtrack, Place *placement ){ SetNotePolyphonyAttributes(wtrack->track); struct Notes *note = wtrack->track->notes; while (note != NULL) { if(PlaceIsBetween2(placement,¬e->l.p,¬e->end)) if (NOTE_subtrack(wtrack, note)==subtrack) return note; note = NextNote(note); } return NULL; }
vector_t *get_all_ranged_notes(struct WBlocks *wblock){ vector_t *v=talloc(sizeof(vector_t)); struct WTracks *wtrack = wblock->wtracks; while(wtrack!=NULL){ struct Tracks *track = wtrack->track; if(is_track_ranged(wblock,wtrack)){ struct Notes *note = track->notes; while(note!=NULL){ if(isPlaceRanged(wblock,¬e->l.p)) VECTOR_push_back(v, note); note=NextNote(note); } } wtrack=NextWTrack(wtrack); } return v; }
// Also sets the track->polyphony attribute. void SetNotePolyphonyAttributes(struct Tracks *track){ last_free_polyphony_num = 0; // reset if (end_places==NULL) end_places = (Place**)V_calloc(end_places_size,sizeof(Place*)); // Using calloc since this memory is only used temporarily in here, so it's not necessary for the GC to know about it in any way. track->polyphony = 1; struct Notes *note = track->notes; while(note != NULL){ int polyphony_num = FindFirstFreePolyphony_num(¬e->l.p); note->polyphony_num = polyphony_num; if (polyphony_num+1 > track->polyphony) track->polyphony = polyphony_num+1; end_places[polyphony_num] = ¬e->end; note = NextNote(note); } }
void CutRange_notes( struct Notes **tonote, struct Notes *fromnote, Place *p1, Place *p2 ){ struct Notes *next; if(fromnote==NULL) return; next=NextNote(fromnote); if(PlaceLessThan(&fromnote->l.p,p1)){ CutRange_notes(tonote,next,p1,p2); return; } if(PlaceGreaterOrEqual(&fromnote->l.p,p2)) return; ListRemoveElement3(tonote,&fromnote->l); CutRange_notes(tonote,next,p1,p2); }
static void InitPEQnotesBlock( PEQ_UsedTracks **UsedTracks, const struct Blocks *block, const Place *p, int playlistaddpos ){ PEQ_UsedTracks *peq_usedtrack; struct Notes *note; struct Tracks *track=block->tracks; while(track!=NULL){ if( ListFindElement1_r0(*UsedTracks,track->l.num) == NULL ){ note=track->notes; if(note!=NULL){ while(PlaceLessThan(¬e->l.p,p)){ note=NextNote(note); if(note==NULL) break; } if(note!=NULL){ peq_usedtrack=talloc(sizeof(PEQ_UsedTracks)); peq_usedtrack->num=track->l.num; ListAddElement1(UsedTracks,peq_usedtrack); InitPEQnote(block,track,note,playlistaddpos); } else{ //PEQ_FindNextNoteAddPlayPos(peq); } } } track=NextTrack(track); } }
// Returns a pointer to an array of vectors (one vector for each realline), not a pointer to a vector. vector_t *TRS_get(const struct WBlocks *wblock, const struct WTracks *wtrack){ int num_reallines = wblock->num_reallines; vector_t *trs = talloc(sizeof(vector_t) * num_reallines); struct Notes *note = wtrack->track->notes; while(note!=NULL){ add_note(wblock, trs, note); note = NextNote(note); } struct Stops *stop = wtrack->track->stops; while(stop!=NULL){ add_stop(wblock, trs, stop); stop = NextStop(stop); } spread_trackreallines(wblock, trs); // if (wtrack->l.num==0) // TRS_print(wblock,trs); return trs; }
static void SetNum_Vel_rec( struct WTracks *wtrack, struct FindNum_Velstruct **velroot, struct Notes *note ){ struct FindNum_Velstruct temp_start; struct FindNum_Velstruct temp_end; if(note==NULL){ SetNum_Vel_set(wtrack,velroot); return; } PlaceCopy(&temp_start.l.p,¬e->l.p); temp_start.startstop=1; ListAddElement3_a(velroot,&temp_start.l); PlaceCopy(&temp_end.l.p,¬e->end); temp_end.startstop= -1; ListAddElement3(velroot,&temp_end.l); SetNum_Vel_rec(wtrack,velroot,NextNote(note)); }
/************************************************************** 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); } }
static struct Notes *sort_notes_by_pitch_a_little_bit(struct Notes *notes){ struct Notes *ret = notes; struct Notes *note_to_place_after = NULL; while(notes != NULL){ struct Notes *next = NextNote(notes); R_ASSERT_RETURN_IF_FALSE2(next!=NULL, NULL); if (PlaceEqual(¬es->l.p, &next->l.p)) if (notes->note > next->note) { note_to_place_after = notes; break; } notes = next; } ListRemoveElement3(&ret, ¬e_to_place_after->l); ListAddElement3_a(&ret, ¬e_to_place_after->l); return ret; }