bool NoteItem::shortCut(int k) { switch(k) { case Qt::Key_N: if(MainWindow::s_query.length()) { if(m_rich) { TextBrowser* textBrowser = findChild<TextBrowser *>("contentWidget"); textBrowser->find(MainWindow::s_query); } else { PlainTextBrowser* textBrowser = findChild<PlainTextBrowser *>("contentWidget"); textBrowser->find(MainWindow::s_query); } } return true; case Qt::Key_X: exportFile(); return true; case Qt::Key_Left: case Qt::Key_Right: { NoteList *noteList = qobject_cast<NoteList*>(parentWidget()); NoteItem* item = noteList->getNextNote(this,(k==Qt::Key_Right)?1:-1); if(item) NoteItem::setActiveItem(item); } return true; case Qt::Key_Return: g_mainWindow->editActiveNote(); return true; default: return false; } }
void TrackEditorPattern::paint_multiple_note_events( GUI::Painter& p, int p_row , const NoteList& p_list , bool p_repeat) { /* separate in columns */ std::vector<NoteList> notes_in_column( track->get_visible_columns() ); NoteList::const_iterator I=p_list.begin(); for (;I!=p_list.end();I++) { int col=I->pos.column; ERR_CONTINUE( col < 0 ); ERR_CONTINUE( col >= notes_in_column.size() ); notes_in_column[col].push_back(*I); } /* now draw columns */ for (int i=0;i<notes_in_column.size();i++) { if (notes_in_column[i].empty()) continue; if (notes_in_column[i].size()==1) { paint_note_event(p,p_row,*notes_in_column[i].begin(),p_repeat); } else paint_multiple_nonvisible_events(p,p_row,notes_in_column[i]); } }
Track_Pattern::NoteList Track_Pattern::get_notes_in_range(Tick p_from, Tick p_to) { NoteList res; int block_from; int block_to; // printf("get blocks in range %f-%f:",(float)p_from/TICKS_PER_BEAT,(float)p_to/TICKS_PER_BEAT); if (get_blocks_in_rage( p_from, p_to, &block_from, &block_to )) { // printf(" none!\n"); return res; //emty list, nothing fits! } //printf(" %i\n",(block_to-block_from)+1); for (int i=block_from;i<=block_to;i++) { PatternBlock *b = get_block(i); Tick tick_begin=get_block_pos(i); Tick tick_end=tick_begin+b->get_length()-1; int note_from; int note_to; Tick tick_from=(tick_begin<p_from)?p_from:tick_begin; Tick tick_to=(p_to>tick_end)?tick_end:p_to; // printf("scanning block %i, ticks %f-%f\n",i,(float)tick_from/TICKS_PER_BEAT,(float)tick_to/TICKS_PER_BEAT); if (b->get_notes_in_local_range( tick_from-tick_begin, tick_to-tick_begin, ¬e_from, ¬e_to) ) continue; //couldnt find any note //printf("found %i notes\n",note_to-note_from); for (int j=note_from;j<=note_to;j++) { NoteListElement e; e.note=b->get_note( j ); e.pos=b->get_note_pos( j ); e.pos.tick+=get_block_pos( i ); res.push_back(e); } } return res; }
NoteList zip_to_long_notes(SingleNoteList const &HNL, SingleNoteList const &RNL) { auto Hmap = split_notes_by_key(HNL); auto Rmap = split_notes_by_key(RNL); std::list<std::future<NoteList>> futures; for(auto node : Hmap) futures.push_back( std::async( std::launch::async, zip_key, Hmap[node.first], Rmap[node.first] ) ); NoteList L; while(!futures.empty()) { auto it = futures.begin(); NoteList l = it->get(); L.insert(L.end(), l.begin(), l.end()); futures.erase(it); } return L; }
/*! Connects two lists of notes to a list of long notes. * * This function assumes that all notes being sent into this function * have the same key. * * This function will attempt to fix erroneous long note sequences. * The fixes are based on the following conditions: * - A HOLD note MUST be located before a RELEASE note. * - Both ends of the long notes MUST have identical Sample IDs, except * in the case of BMS's LN_TYPE 1 mode. * - Switching between HOLD notes and NORMAL notes are allowed because * they both make sounds. * - Deletion of RELEASE notes are allowed because they do not make any sound. */ NoteList zip_key(SingleNoteList H, SingleNoteList R) { NoteList L; while(!H.empty()) { if (R.empty()) { clan::Console::write_line("Note [debug] Converting lone HOLD to NORMAL."); L.push_back(*(H.begin())); H.erase(H.begin()); } else { SingleNoteList::iterator h = H.begin(), r = R.begin(); Note_Single *hn = *h, *rn = *r; //// CHECK AND FIX NOTES //////////////////////////// // TODO Put note checking logic into a class. bool errTime = hn->getTime() > rn->getTime(); bool errSmpl = hn->getSampleID() != rn->getSampleID(); if (hn->getTime() == rn->getTime()) { clan::Console::write_line("Note [debug] Bad long note: Instant RELEASE."); clan::Console::write_line(" [---->] Deleting RELEASE."); if (errSmpl) clan::Console::write_line(" [---->] Note: It has mis-matched samples."); R.erase(r); delete rn; continue; } if (errTime) { clan::Console::write_line("Note [debug] Bad long note: Invalid time."); clan::Console::write_line(" [---->] Deleting RELEASE."); if (errSmpl) clan::Console::write_line(" [---->] Note: It has mis-matched samples."); // TODO If the note before `r` is a NORMAL note with the same sample ID, // one may change the type of that NORMAL note to HOLD. But we don't // have access to any NORMAL notes. R.erase(r); delete rn; continue; } if (errSmpl) { clan::Console::write_line("Note [debug] Bad long note: Sound mismatch."); SingleNoteList::iterator t = h; if ((++t) != H.end()) { if ((*t)->getTime() < rn->getTime()) { clan::Console::write_line(" [---->] Converting HOLD to NORMAL since the next hold note can fit."); L.push_back(hn); H.erase(h); continue; } } clan::Console::write_line(" [---->] Deleting RELEASE."); R.erase(r); delete rn; continue; } L.push_back(new Note_Long(*hn, *rn, hn->getVol(), hn->getPan())); H.erase(h); delete hn; R.erase(r); delete rn; } } return L; }
void HumdrumFile::generateNoteList(NoteListArray& notelist, int startLine, int endLine) { HumdrumFile& score = *this; // cout << "start index: " << startLine << "\tstopindex: " << endLine << endl; // int z; // for (z=startLine; z<=endLine; z++) { // cout << "\t" << score[z] << endl; // } if (endLine <= 0) { endLine = score.getNumLines() - 1; } if (startLine > endLine) { int temp = endLine; endLine = startLine; startLine = temp; } // estimate the largest amount necessary: notelist.setSize(score.getNumLines() * score.getMaxTracks() * 10); notelist.setGrowth(score.getNumLines()); notelist.setSize(0); notelist.allowGrowth(1); NoteList currentlist; currentlist.clear(); Array<int> scorelevels; score.analyzeMetricLevel(scorelevels); int firsttime = 1; int i, j, k; int ii, jj; int ccount; static char buffer[1024] = {0}; int pitch; int token; int spine; double beatvalue; double track; double duration; double firstdur; for (i=startLine; i<=endLine; i++) { if (score[i].getType() != E_humrec_data) { // ignore non-note data lines continue; } beatvalue = score.getAbsBeat(i); ii = i; for (j=0; j<score[i].getFieldCount(); j++) { spine = j; if (score[i].getExInterpNum(j) != E_KERN_EXINT) { // ignore non-kern data spines continue; } if (firsttime && strcmp(score[i][j], ".") == 0) { // extract the held over note from a previous point in the score ii = score[i].getDotLine(j); jj = score[i].getDotSpine(j); } else { ii = i; jj = j; } if (strcmp(score[ii][jj], ".") != 0) { // extract all notes in the region of interest, ignoring // tied notes. ccount = score[ii].getTokenCount(jj); track = score[ii].getTrack(jj); for (k=0; k<ccount; k++) { token = k; score[ii].getToken(buffer, jj, k, 128); if (strchr(buffer, 'r') != NULL) { // skip over rests continue; } if (strchr(buffer, '_') != NULL) { // skip over doubly tied notes continue; } if (!firsttime && strchr(buffer, ']') != NULL) { // skip over tied notes at the ends of ties. continue; } // have a note so now extract the metric level and the duration pitch = Convert::kernToBase40(buffer); // cout << "read pitch: " << pitch % 40 << endl; if (pitch < 0) { // ignore rests continue; } duration = score.getTiedDuration(ii, jj, k); firstdur = Convert::kernToDuration(score[ii].getToken(buffer, jj, k)); if (duration == 0.0) { // ignore grace notes and other zero-dur ornaments continue; } currentlist.setLevel(1.0/pow(2.0, scorelevels[ii])); currentlist.setFirstDur(firstdur); currentlist.setDur(duration); currentlist.setPitch(pitch); currentlist.setAbsBeat(beatvalue); currentlist.setLine(i); currentlist.setTrack(track); currentlist.setSpine(spine); currentlist.setToken(token); notelist.append(currentlist); currentlist.clear(); } // end of a chord } } // end of a line firsttime = 0; } // end of the music selection notelist.allowGrowth(0); // cout << "Notes: " << endl; // char xxx[128] = {0}; // for (int z=0; z<notelist.getSize(); z++) { // cout << "\t(" << notelist[z].getPitch() << " - " << // notelist[z].getPitch()%40 << ") " << Convert::base40ToKern(xxx, // ((notelist[z].getPitch()) % 40)+3*40) << endl; // } }
void Note::sync() { NoteList list; list.append(this); m_notes->updateNotes(list); }
void TrackEditorPattern::draw(const GUI::Point& p_pos,const GUI::Size& p_size,const GUI::Rect& p_exposed) { Editor::get_singleton()->set_window_rows( p_size.height / get_row_height() ); GUI::Painter &p=*get_painter(); // p.set_clip_rect(false,p_exposed); //p.set_clip_rect(true,p_exposed); p.draw_fill_rect(GUI::Point(0,0),size,color(COLOR_PATTERN_BG)); paint_frames(p); paint_selection(p,p_exposed.pos.y,p_exposed.pos.y+p_exposed.size.height); int visible_rows=Editor::get_singleton()->get_window_rows(); for (int i=0;i<visible_rows;i++) { Tick from=Editor::get_singleton()->get_row_ticks( Editor::get_singleton()->get_window_offset() + i ); Tick to=from+Editor::get_singleton()->get_ticks_per_row()-1; Tick adjust=0; /* Calculate Repeat, if exists */ bool repeat=false; int blk_idx = track->get_block_at_pos( from ); int prev=track->find_block_at_pos( from ); if (blk_idx<0 && prev>=0 && track->get_block( prev )->is_repeat_enabled()) repeat=true; //printf("row %i, blkidx %i , prev %i, repeat %i\n",i,blk_idx,prev,repeat); /* If repeat, adjust from and to */ if (repeat) { Tick block_from=track->get_block_pos( prev ); Tick block_len=track->get_block( prev )->get_length(); Tick new_tick_from=block_from+(from-block_from)%block_len; adjust=from-new_tick_from; to=new_tick_from+(to-from); from=new_tick_from; } NoteList nl; { int from_block=track->find_block_at_pos(from); int to_block=track->find_block_at_pos(to); for (int b=from_block;b<=to_block;b++) { if (b<0) continue; PatternTrack::PatternBlock *block = static_cast<PatternTrack::PatternBlock*>(track->get_block(b)); Tick block_pos = track->get_block_pos(b); Tick block_len = block->get_length(); if (block_pos+block_len < from ) continue; int note_from,note_to; //printf("tick %i-%i, notes %i-%i\n",from,to,note_from,note_to); if (block->get_notes_in_local_range(from-block_pos,to-block_pos,¬e_from,¬e_to)) { for (int n=note_from;n<=note_to;n++) { NoteListElement nle; nle.pos=block->get_note_pos(n); nle.pos.tick=nle.pos.tick+block_pos-from; nle.note=block->get_note(n); nl.push_back(nle); } } } } /* Then if repeat, adjust positions */ NoteList::iterator I=nl.begin(); if (repeat) { for(;I!=nl.end();I++) { I->pos.tick+=adjust; } } if (!nl.empty()) { paint_multiple_note_events( p,i , nl, repeat ); } //paint_cursor(p,i); } paint_row_lines(p); // printf("focus %i, track %i, row %i (%i-%i)\n",(int)has_focus(),(int)Editor::get_singleton()->get_cursor_track(),(int)Editor::get_singleton()->get_cursor_row(),(int)Editor::get_singleton()->get_window_offset(),(int)(Editor::get_singleton()->get_window_offset()+visible_rows)); if ( has_focus() && Editor::get_singleton()->get_cursor_track()==song->find_track_pos(track) && Editor::get_singleton()->get_cursor_row()>=Editor::get_singleton()->get_window_offset() && Editor::get_singleton()->get_cursor_row()<(Editor::get_singleton()->get_window_offset()+visible_rows)) { /* cursor is here */ paint_cursor( p, Editor::get_singleton()->get_cursor_row()-Editor::get_singleton()->get_window_offset() ); } }
void TrackEditorPattern::paint_multiple_nonvisible_events( GUI::Painter& p, int p_row, const NoteList& p_list) { int font_width=get_font_width(); int rowsize=get_row_size(); int fontofs=(rowsize-get_font_height())/2; int eventofs=p_row*rowsize+fontofs; int notewidth=get_font_width()*3; int columnwidth=get_font_width()*4; NoteList::const_iterator I=p_list.begin(); int howmany=p_list.size(); int maxevents=(rowsize-4)/2; if (howmany>maxevents) howmany=maxevents; int maxsize=(rowsize-4)-(howmany-1); for (int i=0;i<howmany;I++,i++) { NoteListElement note = *I; int xofs=font_width+note.pos.column*columnwidth; int from=i*maxsize/howmany; int to=((i+1)*maxsize/howmany); int eheight = to-from; if (eheight<=0) eheight=1; from+=i; //printf("%i - from %i, height %i\n",i,from,eheight); //GUI::Color col=color(COLOR_PATTERN_FONT); if (note.note.is_note()) { switch( Editor::get_singleton()->get_track_edit_mode() ) { case Editor::EDIT_MODE_FRONT: { GUI::Color bg=GUI::Color(COLOR_PATTERN_NOTE_BG); GUI::Color fg=color(COLOR_PATTERN_FONT); int note_w=get_note_display_column_pos(notewidth,note.note.note); p.draw_fill_rect(GUI::Point(xofs,eventofs+from),GUI::Size(notewidth,eheight),bg); p.draw_fill_rect(GUI::Point(xofs+note_w,eventofs+from),GUI::Size(constant(C_TRACK_EDITOR_VOL_NOTE_BAR_HEIGHT),eheight),fg); } break; case Editor::EDIT_MODE_BACK: { GUI::Color bg=GUI::Color(COLOR_PATTERN_VOLUME_BG); GUI::Color fg=color(COLOR_PATTERN_FONT_VOLUME); int vol_w=(note.note.volume*notewidth)/PatternTrack::Note::MAX_VOLUME; p.draw_fill_rect(GUI::Point(xofs,eventofs+from),GUI::Size(notewidth,eheight),bg); p.draw_fill_rect(GUI::Point(xofs,eventofs+from),GUI::Size(vol_w,eheight),fg); } break; } } else if (note.note.is_note_off()) { GUI::Color col = color(COLOR_PATTERN_SUBBEAT_LINE); p.draw_fill_rect(GUI::Point(xofs,eventofs+from),GUI::Size(notewidth,eheight),col); } else { //printf("WTF!!\n"); } } }