From 79f53afff1d249fb568bcf266bdb4ac8fe9b6521 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Wed, 20 Apr 2011 18:01:24 +0000 Subject: added quant-len-toolbar heavy changes in the quantisation-setting-stuff: changed from hardcoded to user-settable. i hope i haven't broken anything. --- muse2/muse/midiedit/scoreedit.cpp | 200 +++++++++++++++++++++++++------------- muse2/muse/midiedit/scoreedit.h | 30 +++++- 2 files changed, 156 insertions(+), 74 deletions(-) diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 1b2e0458..6d6b1879 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -75,17 +75,25 @@ QString IntToQStr(int i); -//TODO: all das unten richtig machen! -#define TICKS_PER_WHOLE (config.division*4) -#define SONG_LENGTH (song->len()) -#define quant_max 3 //whole, half, quarter = 0,1,2 -#define quant_max_fraction (1 << quant_max) //whole, half, quarter= 1,2,4 -#define FLO_QUANT (TICKS_PER_WHOLE/quant_max_fraction) -//FLO_QUANT = how many ticks has a single quantisation area? + +//PIXELS_PER_NOTEPOS must be greater or equal to 3*NOTE_XLEN + 2*NOTE_SHIFT +//because if tick 0 is at x=0: the notes can be shifted by NOTE_SHIFT. +//additionally, they can be moved by NOTE_XLEN (collision avoiding) +//then, they have their own width, which is NOTE_XLEN/2 into the x>0-area +//the same thing applies to the x<0-area + +// OOO +// | +// ^actual calculated x, without shifting or moving +// ^ and +// ^ : moved note (by XLEN) +// additionally, a shift is possible +// total_width = shift + move + note_xlen + move + shift, where move==note_xlen +// total_width = 2*shift + 3*note_xlen +// if total_width is greater than px_per_notepos, there will be collisions! -//TODO: quant_max richtig setzen! @@ -191,6 +199,54 @@ ScoreEdit::ScoreEdit(PartList* pl, QWidget* parent, const char* name, unsigned i transport_toolbar->setObjectName("transport"); transport_toolbar->addActions(transportAction->actions()); + QToolBar* quant_len_toolbar = addToolBar(tr("Quant'n'length")); + quant_len_toolbar->setObjectName("Quant'n'length"); + quant_len_toolbar->addWidget(new QLabel(tr("Note length:"), quant_len_toolbar)); + QActionGroup* len_actions=new QActionGroup(this); + QAction* n1_action = quant_len_toolbar->addAction("1", menu_mapper, SLOT(map())); + QAction* n2_action = quant_len_toolbar->addAction("2", menu_mapper, SLOT(map())); + QAction* n4_action = quant_len_toolbar->addAction("4", menu_mapper, SLOT(map())); + QAction* n8_action = quant_len_toolbar->addAction("8", menu_mapper, SLOT(map())); + QAction* n16_action = quant_len_toolbar->addAction("16", menu_mapper, SLOT(map())); + QAction* n32_action = quant_len_toolbar->addAction("32", menu_mapper, SLOT(map())); + QAction* nlast_action = quant_len_toolbar->addAction(tr("last"), menu_mapper, SLOT(map())); + menu_mapper->setMapping(n1_action, CMD_NOTELEN_1); + menu_mapper->setMapping(n2_action, CMD_NOTELEN_2); + menu_mapper->setMapping(n4_action, CMD_NOTELEN_4); + menu_mapper->setMapping(n8_action, CMD_NOTELEN_8); + menu_mapper->setMapping(n16_action, CMD_NOTELEN_16); + menu_mapper->setMapping(n32_action, CMD_NOTELEN_32); + menu_mapper->setMapping(nlast_action, CMD_NOTELEN_LAST); + n1_action->setCheckable(true); + n2_action->setCheckable(true); + n4_action->setCheckable(true); + n8_action->setCheckable(true); + n16_action->setCheckable(true); + n32_action->setCheckable(true); + nlast_action->setCheckable(true); + len_actions->addAction(n1_action); + len_actions->addAction(n2_action); + len_actions->addAction(n4_action); + len_actions->addAction(n8_action); + len_actions->addAction(n16_action); + len_actions->addAction(n32_action); + len_actions->addAction(nlast_action); + + nlast_action->setChecked(true); + menu_command(CMD_NOTELEN_LAST); + + quant_len_toolbar->addSeparator(); + quant_len_toolbar->addWidget(new QLabel(tr("Quantisation:"), quant_len_toolbar)); + QComboBox* quant_combobox = new QComboBox(this); + quant_combobox->addItem("2"); // if you add or remove items from + quant_combobox->addItem("4"); // here, also change quant_mapper[] + quant_combobox->addItem("8"); // in ScoreCanvas::set_quant()! + quant_combobox->addItem("16"); + quant_combobox->addItem("32"); + connect(quant_combobox, SIGNAL(currentIndexChanged(int)), score_canvas, SLOT(set_quant(int))); + quant_len_toolbar->addWidget(quant_combobox); + quant_combobox->setCurrentIndex(2); + QMenu* settings_menu = menuBar()->addMenu(tr("&Settings")); @@ -230,7 +286,7 @@ ScoreEdit::ScoreEdit(PartList* pl, QWidget* parent, const char* name, unsigned i -/* TODO FINDMICHJETZT +/* FINDMICHJETZT addToolBarBreak(); info = new NoteInfo(this); addToolBar(info); @@ -360,7 +416,7 @@ void ScoreEdit::menu_command(int cmd) void ScoreCanvas::add_staves(PartList* pl, bool all_in_one) { - staff_t staff; + staff_t staff(this); if (all_in_one) { @@ -431,6 +487,10 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent, last_len=384; new_len=-1; + + set_quant(2); //this is actually unneccessary, as while + //initalizing the quant_combobox, this gets + //called again. but for safety... dragging_staff=false; @@ -522,7 +582,7 @@ void ScoreCanvas::set_staffmode(list::iterator it, staff_mode_t mode) it->clef=BASS; it->split_note=SPLIT_NOTE; - staves.insert(it, staff_t(GRAND_TOP, VIOLIN, it->parts, it->split_note)); + staves.insert(it, staff_t(this, GRAND_TOP, VIOLIN, it->parts, it->split_note)); break; default: @@ -775,16 +835,16 @@ bool operator< (const note_pos_t& a, const note_pos_t& b) -int flo_quantize(int tick) +int flo_quantize(int tick, int quant_ticks) { //TODO quantizing must be done with the proper functions! - return int(nearbyint((float)tick / FLO_QUANT))*FLO_QUANT; + return int(nearbyint((float)tick / quant_ticks))*quant_ticks; } -int flo_quantize_floor(int tick) +int flo_quantize_floor(int tick, int quant_ticks) { //TODO quantizing must be done with the proper functions, see above - return int(tick / FLO_QUANT) * FLO_QUANT; + return int(tick / quant_ticks) * quant_ticks; } @@ -825,8 +885,8 @@ void staff_t::create_appropriate_eventlist(const set& parts) (type==NORMAL) ) ) { unsigned begin, end; - begin=flo_quantize(event.tick()+part->tick()); - end=flo_quantize(event.endTick()+part->tick()); + begin=flo_quantize(event.tick()+part->tick(), parent->quant_ticks()); + end=flo_quantize(event.endTick()+part->tick(), parent->quant_ticks()); cout <<"inserting note on at "< parse_note_len(int len_ticks, int begin_tick, vector& foo, if (len_now) //the above failed or allow_dots=false { - for (int i=0; i<=quant_max; i++) + for (int i=0; i<=quant_power2; i++) { int tmp=calc_len(i,0); if (tmp <= len_now) @@ -1178,26 +1236,7 @@ list parse_note_len(int len_ticks, int begin_tick, vector& foo, #define YLEN 10 #define NOTE_SHIFT 3 -#define PIXELS_PER_WHOLE (320) //how many px are between two wholes? -#define PIXELS_PER_NOTEPOS (PIXELS_PER_WHOLE/quant_max_fraction) //how many px are between the smallest drawn beats? - -//PIXELS_PER_NOTEPOS must be greater or equal to 3*NOTE_XLEN + 2*NOTE_SHIFT -//because if tick 0 is at x=0: the notes can be shifted by NOTE_SHIFT. -//additionally, they can be moved by NOTE_XLEN (collision avoiding) -//then, they have their own width, which is NOTE_XLEN/2 into the x>0-area -//the same thing applies to the x<0-area - -// OOO -// | -// ^actual calculated x, without shifting or moving -// ^ and -// ^ : moved note (by XLEN) -// additionally, a shift is possible -// total_width = shift + move + note_xlen + move + shift, where move==note_xlen -// total_width = 2*shift + 3*note_xlen -// if total_width is greater than px_per_notepos, there will be collisions! -#define NOTE_MOVE_X (PIXELS_PER_NOTEPOS/2) #define REST_AUSWEICH_X 10 #define DOT_XDIST 6 #define DOT_XBEGIN 10 @@ -1226,8 +1265,6 @@ list parse_note_len(int len_ticks, int begin_tick, vector& foo, #define KEYCHANGE_ACC_RIGHTDIST 0 -#define stdmap std::map - #define no_notepos note_pos_t() #define TIE_DIST 5 @@ -1312,7 +1349,7 @@ void staff_t::create_itemlist() { if (lastevent==last_measure) //there was no note? { - unsigned tmppos=(last_measure+t-FLO_QUANT)/2; + unsigned tmppos=(last_measure+t-parent->quant_ticks())/2; cout << "\tend-of-measure: this was an empty measure. inserting rest in between at t="< lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,DOTTED_RESTS,UNSPLIT_RESTS); + list lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,parent->quant_power2(),DOTTED_RESTS,UNSPLIT_RESTS); unsigned tmppos=lastevent; for (list::iterator x=lens.begin(); x!=lens.end(); x++) { @@ -1353,7 +1390,7 @@ void staff_t::create_itemlist() // no need to check if the rest crosses measure boundaries; // it can't. - list lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,DOTTED_RESTS,UNSPLIT_RESTS); + list lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,parent->quant_power2(),DOTTED_RESTS,UNSPLIT_RESTS); unsigned tmppos=lastevent; for (list::iterator x=lens.begin(); x!=lens.end(); x++) { @@ -1394,7 +1431,7 @@ void staff_t::create_itemlist() eventlist.insert(pair(t+len, FloEvent(t+len,pitch, velo,0,FloEvent::NOTE_OFF,it->second.source_part, it->second.source_event))); } - list lens=parse_note_len(tmplen,t-last_measure,emphasize_list,true,true); + list lens=parse_note_len(tmplen,t-last_measure,emphasize_list,parent->quant_power2(),true,true); unsigned tmppos=t; int n_lens=lens.size(); int count=0; @@ -1789,7 +1826,7 @@ group_them_again: itemlist[t].insert( FloItem(FloItem::NOTE_END,tmp.pos,0,0) ); - list lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,true,true); + list lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,parent->quant_power2(),true,true); unsigned tmppos=t; int n_lens=lens.size(); int count=0; @@ -1834,7 +1871,7 @@ group_them_again: itemlist[t].insert( FloItem(FloItem::NOTE_END,tmp.pos,0,0) ); - list lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,true,true); + list lens=parse_note_len(len_ticks_remaining,t-last_measure,emphasize_list,parent->quant_power2(),true,true); unsigned tmppos=t; int n_lens=lens.size(); int count=0; @@ -1912,13 +1949,13 @@ void staff_t::calc_item_pos() { for (set::iterator it=it2->second.begin(); it!=it2->second.end();it++) { - it->x=it2->first * PIXELS_PER_WHOLE/TICKS_PER_WHOLE +pos_add; + it->x=it2->first * parent->pixels_per_whole()/TICKS_PER_WHOLE +pos_add; //if this changes, also change the line(s) with YLEN (but not all). don't change it. it->y=2*YLEN - (it->pos.height-2)*YLEN/2; if (it->type==FloItem::NOTE) { - it->x+=NOTE_MOVE_X + it->shift*NOTE_SHIFT; + it->x+=parent->note_x_indent() + it->shift*NOTE_SHIFT; switch (it->len) { @@ -1965,7 +2002,7 @@ void staff_t::calc_item_pos() case 4: it->pix=pix_r16; break; } - it->x+=NOTE_MOVE_X + (it->ausweich ? REST_AUSWEICH_X : 0); //AUSWEICH_X + it->x+=parent->note_x_indent() + (it->ausweich ? REST_AUSWEICH_X : 0); //AUSWEICH_X } else if (it->type==FloItem::BAR) { @@ -2532,7 +2569,7 @@ list calc_accidentials(key_enum key, clef_t clef, key_enum next_key) int ScoreCanvas::tick_to_x(int t) { - int x=t*PIXELS_PER_WHOLE/TICKS_PER_WHOLE; + int x=t*pixels_per_whole()/TICKS_PER_WHOLE; for (std::map::iterator it=pos_add_list.begin(); it!=pos_add_list.end() && it->first<=t; it++) x+=it->second; @@ -2554,7 +2591,7 @@ int ScoreCanvas::calc_posadd(int t) //will be a problem, because a tick is pretty small int ScoreCanvas::x_to_tick(int x) { - int t=TICKS_PER_WHOLE * x/PIXELS_PER_WHOLE; + int t=TICKS_PER_WHOLE * x/pixels_per_whole(); int min_t=0; cout << "t="<msgDeleteEvent(dragged_event, dragged_event_part, false, false, false); } else { - last_len=flo_quantize(dragged_event.lenTick()); + last_len=flo_quantize(dragged_event.lenTick(), quant_ticks()); } } @@ -2832,7 +2869,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) int x=event->x()+x_pos-x_left; - int tick=flo_quantize_floor(x_to_tick(x)); + int tick=flo_quantize_floor(x_to_tick(x), quant_ticks()); if (mouse_operation==NO_OP) { @@ -2889,7 +2926,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) break; case LENGTH: - tick+=FLO_QUANT; + tick+=quant_ticks(); if (dragged_event.tick()+dragged_event.lenTick() + dragged_event_part->tick() != unsigned(tick)) { Event tmp=dragged_event.clone(); @@ -3135,8 +3172,15 @@ void ScoreCanvas::menu_command(int cmd) { switch (cmd) { - case CMD_COLOR_BLACK: coloring_mode=COLOR_MODE_BLACK; redraw(); break; - case CMD_COLOR_PART: coloring_mode=COLOR_MODE_PART; redraw(); break; + case CMD_COLOR_BLACK: coloring_mode=COLOR_MODE_BLACK; redraw(); break; + case CMD_COLOR_PART: coloring_mode=COLOR_MODE_PART; redraw(); break; + case CMD_NOTELEN_1: new_len=TICKS_PER_WHOLE/ 1; break; + case CMD_NOTELEN_2: new_len=TICKS_PER_WHOLE/ 2; break; + case CMD_NOTELEN_4: new_len=TICKS_PER_WHOLE/ 4; break; + case CMD_NOTELEN_8: new_len=TICKS_PER_WHOLE/ 8; break; + case CMD_NOTELEN_16: new_len=TICKS_PER_WHOLE/16; break; + case CMD_NOTELEN_32: new_len=TICKS_PER_WHOLE/32; break; + case CMD_NOTELEN_LAST: new_len=-1; break; default: cout << "ILLEGAL FUNCTION CALL: ScoreCanvas::menu_command called with unknown command ("<=0) && (valtoolbar] * o velocity/release-velo for already existing notes * - do this by right-click -> some dialog shows up? diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 078d7969..c3ba246c 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -44,8 +44,15 @@ using std::string; +#define TICKS_PER_WHOLE (config.division*4) +#define SONG_LENGTH (song->len()) + + + enum {CMD_COLOR_BLACK, CMD_COLOR_VELO, CMD_COLOR_PART, - CMD_SET_NAME}; + CMD_SET_NAME, + CMD_NOTELEN_1, CMD_NOTELEN_2, CMD_NOTELEN_4, CMD_NOTELEN_8, + CMD_NOTELEN_16, CMD_NOTELEN_32, CMD_NOTELEN_LAST }; class ScoreCanvas; @@ -429,23 +436,27 @@ struct staff_t clef_t clef; int split_note; + ScoreCanvas* parent; + void create_appropriate_eventlist(const set& parts); void create_itemlist(); void process_itemlist(); void calc_item_pos(); - staff_t() + staff_t(ScoreCanvas* parent_) { type=NORMAL; clef=VIOLIN; + parent=parent_; } - staff_t (staff_type_t type_, clef_t clef_, set parts_, int split_note_=0) + staff_t (ScoreCanvas* parent_, staff_type_t type_, clef_t clef_, set parts_, int split_note_=0) { type=type_; clef=clef_; split_note=split_note_; parts=parts_; + parent=parent_; } }; @@ -454,7 +465,7 @@ note_pos_t note_pos_(int note, key_enum key); note_pos_t note_pos (unsigned note, key_enum key, clef_t clef); int calc_len(int l, int d); -list parse_note_len(int len_ticks, int begin_tick, vector& foo, bool allow_dots=true, bool allow_normal=true); +list parse_note_len(int len_ticks, int begin_tick, vector& foo, int quant_power2, bool allow_dots=true, bool allow_normal=true); int clef_height(clef_t clef); @@ -518,8 +529,10 @@ class ScoreCanvas : public View void set_staffmode(list::iterator it, staff_mode_t mode); void remove_staff(list::iterator it); void merge_staves(list::iterator dest, list::iterator src); - + + // member variables --------------------------------------------------- + int _quant_power2; std::map pos_add_list; @@ -604,6 +617,7 @@ class ScoreCanvas : public View void heartbeat_timer_event(); void set_tool(int); + void set_quant(int); void menu_command(int); void preamble_keysig_slot(bool); void preamble_timesig_slot(bool); @@ -635,6 +649,12 @@ class ScoreCanvas : public View int canvas_height(); int viewport_width(); int viewport_height(); + + int quant_power2() { return _quant_power2; } + int quant_len() { return (1<<_quant_power2); } + int quant_ticks() { return TICKS_PER_WHOLE / (1<<_quant_power2); } + int pixels_per_whole() { return 320; } //TODO FINDMICHJETZT + int note_x_indent() { return pixels_per_whole()/quant_len()/2; } }; int calc_measure_len(const list& nums, int denom); -- cgit v1.2.3