Audio track velocity editing in the sequencer.
This commit is contained in:
parent
b46d4f09bb
commit
896a7907d3
10 changed files with 292 additions and 6 deletions
|
|
@ -1214,6 +1214,69 @@ int main(int argc, char **argv)
|
|||
unlink("/tmp/xtc-workspace.xtc"); window.do_callback();
|
||||
}
|
||||
reset();
|
||||
{
|
||||
MainWindow window(false,""); window.show(); auto *s=timeline(&window);
|
||||
char wave[4096]; CHECK(realpath("examples/projects/original-pluck.wav",wave));
|
||||
CHECK(window.create_track(false)==XTC_OK && window.import_audio(wave)==XTC_OK);
|
||||
uint64_t track=s->selected_track(); CHECK(s->expand_track(track,true));
|
||||
CHECK(s->set_zoom(96)==XTC_OK && s->grid(960)==XTC_OK);
|
||||
float base_l[256]{},base_r[256]{},edited_l[256]{},edited_r[256]{};
|
||||
xtc_audio_plan *plan=nullptr;
|
||||
CHECK(xtc_audio_plan_create(s->project(),48000,&plan)==XTC_OK);
|
||||
CHECK(xtc_audio_plan_render_stereo(plan,1000,base_l,base_r,256)==XTC_OK); xtc_audio_plan_destroy(plan);
|
||||
// An arbitrary off-grid position, with no MIDI notes, creates an audio level point.
|
||||
int px=s->header_width()+37, top=28+56;
|
||||
gesture(s,px,top+65,0,-15); // 2x gain at tick 370.
|
||||
size_t count=0; xtc_project_automation_count(s->project(),&count); CHECK(count==1);
|
||||
xtc_automation_point point{}; xtc_project_get_automation(s->project(),0,&point);
|
||||
CHECK(point.track_id==track && point.tick==370 && point.parameter==XTC_AUTOMATION_GAIN && point.value==2.0f && !point.step);
|
||||
CHECK(xtc_audio_plan_create(s->project(),48000,&plan)==XTC_OK);
|
||||
CHECK(xtc_audio_plan_render_stereo(plan,1000,edited_l,edited_r,256)==XTC_OK); xtc_audio_plan_destroy(plan);
|
||||
for(int i=0;i<256;++i) CHECK(std::fabs(edited_l[i]-base_l[i]*2)<1e-5f && std::fabs(edited_r[i]-base_r[i]*2)<1e-5f);
|
||||
CHECK(window.undo(false)==XTC_OK); xtc_project_automation_count(s->project(),&count); CHECK(count==0);
|
||||
CHECK(window.undo(true)==XTC_OK && s->track_expanded(track));
|
||||
gesture(s,px,top+50,0,500); // Existing point clamps to silence.
|
||||
xtc_project_get_automation(s->project(),0,&point); CHECK(point.tick==370 && point.value==0);
|
||||
gesture(s,px,top+80,0,-500); // Existing point clamps to 400%.
|
||||
xtc_project_get_automation(s->project(),0,&point); CHECK(point.value==4);
|
||||
gesture(s,s->header_width()+61,top+65,0,0);
|
||||
xtc_project_automation_count(s->project(),&count); CHECK(count==2);
|
||||
// A pre-existing Hold point keeps its interpolation mode when dragged.
|
||||
xtc_project_get_automation(s->project(),1,&point); point.step=1;
|
||||
CHECK(xtc_project_set_automation(s->project(),&point)==XTC_OK);
|
||||
gesture(s,s->header_width()+61,top+65,0,-15);
|
||||
xtc_project_get_automation(s->project(),1,&point); CHECK(point.tick==610 && point.value==2 && point.step==1);
|
||||
// Escape cancels a point at another arbitrary position.
|
||||
int ox=Fl::e_x,oy=Fl::e_y,ok=Fl::e_keysym;
|
||||
Fl::e_x=s->x()+s->header_width()+91; Fl::e_y=s->y()+top+50;
|
||||
Fl::e_keysym=FL_Button+FL_LEFT_MOUSE; CHECK(s->handle(FL_PUSH)==1);
|
||||
Fl::e_y+=10; CHECK(s->handle(FL_DRAG)==1);
|
||||
Fl::e_keysym=FL_Escape; CHECK(s->handle(FL_KEYDOWN)==1);
|
||||
xtc_project_automation_count(s->project(),&count); CHECK(count==2);
|
||||
CHECK(window.save_project("/tmp/xtc-audio-velocity.xtc")==XTC_OK);
|
||||
CHECK(window.new_project()==XTC_OK && window.open_project("/tmp/xtc-audio-velocity.xtc")==XTC_OK);
|
||||
CHECK(s->expand_track(track,true));
|
||||
xtc_project_get_automation(s->project(),0,&point); CHECK(point.value==4 && point.tick==370);
|
||||
CHECK(s->set_zoom(96)==XTC_OK);
|
||||
// Delete a point with the real right mouse gesture; undo restores it.
|
||||
Fl::e_x=s->x()+px; Fl::e_y=s->y()+top+20;
|
||||
Fl::e_keysym=FL_Button+FL_RIGHT_MOUSE; CHECK(s->handle(FL_PUSH)==1);
|
||||
Fl::e_x=ox; Fl::e_y=oy; Fl::e_keysym=ok;
|
||||
xtc_project_automation_count(s->project(),&count); CHECK(count==1);
|
||||
CHECK(window.undo(false)==XTC_OK); xtc_project_automation_count(s->project(),&count); CHECK(count==2);
|
||||
// Pinned headers and horizontal scrolling still map to timeline positions.
|
||||
auto *scroll=dynamic_cast<Fl_Scroll *>(s->parent()); CHECK(scroll);
|
||||
scroll->scroll_to(80,0); pump();
|
||||
int screen_x=s->header_left()+s->header_width()+100;
|
||||
uint64_t expected=static_cast<uint64_t>(screen_x-s->x()-s->header_width())*960/static_cast<unsigned int>(s->zoom_level());
|
||||
gesture(s,screen_x-s->x(),top+50,0,0);
|
||||
xtc_project_automation_count(s->project(),&count); CHECK(count==3);
|
||||
bool found=false;
|
||||
for(size_t i=0;i<count;++i) {xtc_project_get_automation(s->project(),i,&point); if(point.tick==expected && point.value==2) found=true;}
|
||||
CHECK(found);
|
||||
unlink("/tmp/xtc-audio-velocity.xtc"); window.do_callback();
|
||||
}
|
||||
reset();
|
||||
{
|
||||
MainWindow window(false,""); window.show(); auto *s=timeline(&window);
|
||||
CHECK(window.create_track(true)==XTC_OK);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue