static double get_num_beats(const struct SeqTrack *seqtrack, const struct SeqBlock *seqblock, LPB_Iterator *iterator, int audioframes_to_add, const char *from_where, bool *curr_num_beats_is_valid){ struct Blocks *block = seqblock->block; double time = seqtrack->start_time - seqblock->time; #if DEBUG_BUGS R_ASSERT_NON_RELEASE(time > -(RADIUM_BLOCKSIZE*ATOMIC_DOUBLE_GET(block->reltempo))); #endif if (time < 0) // Happens when switching between two seqblocks at a non-audio block alignment (i.e. delta time > 0). To avoid this minor inaccuracy, it seems necessary to break the use of constant 64 frame audio block sizes, so it's probably not worth it. time = 0; double time_to_add = (double)audioframes_to_add * ATOMIC_DOUBLE_GET(block->reltempo); #if DEBUG_BUGS printf("Get num_beats. from_where: %s, time: %f, time_to_add: %f, pc->start_time_f: %f, stime2place: %f\n", from_where, time, time_to_add, ATOMIC_DOUBLE_GET(seqtrack->start_time_f), STime2Place_f(block, time+time_to_add) ); #endif if (time+time_to_add > getBlockSTimeLength(block)) // can happen when switching block *curr_num_beats_is_valid = false; return iterator->num_beats_played_so_far + scale_double(STime2Place_f(block, time+time_to_add), iterator->place1_f, iterator->place2_f, 0.0, iterator->num_beats_between_place1_and_place2 ); }
void FX_min_max_have_changed_for_patch(struct Patch *patch, NInt fxnum, float old_min, float old_max, float new_min, float new_max){ struct Blocks *block = root->song->blocks; while(block!=NULL){ struct Tracks *track = block->tracks; while(track!=NULL){ if (track->patch == patch) { struct FXs *fxs=track->fxs; while(fxs!=NULL){ if (fxs->l.num == fxnum) { struct FX *fx = fxs->fx; int fx_min = fx->min; int fx_max = fx->max; struct FXNodeLines *fxnode = fxs->fxnodelines; Undo_FXs(root->song->tracker_windows, block, track, 0); while(fxnode != NULL) { double real_val = scale_double(fxnode->val, fx_min, fx_max, old_min, old_max); fxnode->val = scale_double(real_val, new_min, new_max, fx_min, fx_max); fxnode = NextFXNodeLine(fxnode); } block->is_dirty=true; } fxs = NextFX(fxs); } } track = NextTrack(track); } block = NextBlock(block); } }
static void add_fxtext(const struct WBlocks *wblock, FXText_trss &fxtexts, const struct FX *fx, struct FXNodeLines *fxnodeline){ int realline = FindRealLineFor(wblock, 0, &fxnodeline->l.p); FXText_trs &v = fxtexts[realline]; FXText fxtext = {0}; fxtext.p = fxnodeline->l.p; fxtext.fx = fx; fxtext.fxnodeline = fxnodeline; fxtext.value = round(scale_double(fxnodeline->val, fx->min, fx->max, 0, 0x100)); if (fxtext.value==0x100) fxtext.value=0xff; fxtext.logtype = fxnodeline->logtype; TRS_INSERT_PLACE(v, fxtext); }
bool FXTEXT_keypress(struct Tracker_Windows *window, struct WBlocks *wblock, struct WTracks *wtrack, int realline, Place *place, int key){ struct FXs *fxs; int subsubtrack = FXTEXT_subsubtrack(window, wtrack, &fxs); if (subsubtrack==-1) return false; struct FX *fx = fxs->fx; //printf("FXmin: %d, fxmax: %d\n",fx->min, fx->max); const FXText_trss &fxtexts = FXTEXTS_get(wblock, wtrack, fxs); const FXText_trs &fxtext = fxtexts[realline]; // if (fxtext->num_elements == 0 && val==0) // return true; ADD_UNDO(FXs(window, wblock->block, wtrack->track, wblock->curr_realline)); if (fxtext.size() > 1){ // MORE THAN ONE ELEMENT if (key == EVENT_DEL){ for (auto vt : fxtext) { if (VECTOR_is_in_vector(&wtrack->track->fxs, fxs) && isInList3(&fxs->fxnodelines->l, &vt.fxnodeline->l)) // We might have removed all nodes already (see line below) DeleteFxNodeLine(window, wtrack, fxs, vt.fxnodeline); // In this line, two nodes are removed if there's only two left. } } else { Undo_CancelLastUndo(); } } else if (fxtext.size() == 0){ // NO ELEMENTS if (fx == NULL){ fprintf(stderr, "Can this happen?\n"); Undo_CancelLastUndo(); } else { data_as_text_t dat = DAT_get_newvalue(subsubtrack, key, round(scale_double(0x80, 0, 0x100, fx->min, fx->max)), fx->min, fx->max, true); if (dat.value > fx->max) dat.value = fx->max; if (dat.is_valid==false) return false; int pos = AddFXNodeLine(window, wblock, wtrack, fxs, dat.value, place); struct FXNodeLines *fxnodeline = (struct FXNodeLines*)ListFindElement1_num(&fxs->fxnodelines->l, pos); fxnodeline->logtype = dat.logtype; } } else { // ONE ELEMENT const FXText &vt = fxtext.at(0); struct FXNodeLines *fxnodeline = vt.fxnodeline; if (key == EVENT_DEL) { if (subsubtrack == 2) fxnodeline->logtype = LOGTYPE_LINEAR; else DeleteFxNodeLine(window, wtrack, fxs, fxnodeline); } else { data_as_text_t dat = DAT_get_overwrite(vt.value, vt.logtype, subsubtrack, key, fx->min, fx->max, true, true); printf("fx->min: %x, fx->max: %x, vt.value: %x, dat.value: %x\n",fx->min,fx->max,vt.value,dat.value); if (dat.is_valid==false) return false; fxnodeline->val = dat.value; fxnodeline->logtype = dat.logtype; } } return true; }
static double Place2STime_from_times2( const struct STimes *times, double fp ) { int line1 = (int)fp; int line2 = line1+1; const struct STimes *stime= ×[line1]; // printf("P2ST, block: %x, stime: %x, line: %d\n",block,stime,line); double time1=stime->time; double time2=times[line2].time; double fp1 = line1; double fp2 = fp1+1.0; if (fabs(fp1 - fp) < 0.0000001) return time1; const struct STimeChanges *stc = stime->timechanges; if(stc!=NULL){ double orgfp2 = fp2; struct STimeChanges *next=NextSTimeChange(stc); while(next!=NULL){ double maybe_new_fp2 = GetDoubleFromPlace(&next->l.p); if (maybe_new_fp2 >= fp) { fp2=maybe_new_fp2; time2=next->time; break; } stc=next; next=NextSTimeChange(next); } fp1=GetDoubleFromPlace(&stc->l.p); time1=stc->time; if(stc->tempo1!=0.0f){ double tempo=stc->tempo1 * ( RelTempo2RealRelTempo( (double) ( stc->rel + (stc->deltarel*(fp-fp1)/(2*(fp2-fp1))) // i.e. stc->rel + scale(fp, fp1, fp2, 0, stc->deltarel / 2.0f), )) ); return (double) ( time1 + ( pc->pfreq*60*(fp-fp1)/tempo ) ); } if(next!=NULL){ time2=next->time; }else{ fp2=orgfp2; } } return scale_double(fp, fp1, fp2, time1, time2); }
static double STime2Place2( const struct STimes *times, double correct_time, int num_tries_left, double low_result, double high_result, STime low_time, STime high_time ) { double maybe_result; if (num_tries_left==NUM_STIME2PLACE2_TRIES) maybe_result = scale_double(correct_time, low_time, high_time, low_result, high_result); // usually correct else maybe_result = (high_result+low_result) / 2.0f; /* printf("%d: %d %d (delta: %d) (%f, %f, %f)\n", num_tries_left, (int)low_time, (int)high_time, (int)(high_time-low_time), low_result, maybe_result, high_result ); */ if (num_tries_left==0) return maybe_result; double maybe_time = Place2STime_from_times2(times, maybe_result); if ( fabs(maybe_time-correct_time) < 1.0) return maybe_result; else if (maybe_time > correct_time) return STime2Place2(times, correct_time, num_tries_left-1, low_result, maybe_result, low_time, maybe_time ); else return STime2Place2(times, correct_time, num_tries_left-1, maybe_result, high_result, maybe_time, high_time ); }
static float get_velocity_x(const struct WBlocks *wblock, const struct ListHeader3 *element, int *logtype){ struct Velocities *velocity = (struct Velocities*)element; *logtype = velocity->logtype; return scale_double(velocity->velocity, 0, MAX_VELOCITY, subtrack_x1, subtrack_x2); }