Exemple #1
0
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, &note_from, &note_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;
}
Exemple #4
0
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;
}
Exemple #5
0
/*! 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;
}
Exemple #6
0
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,&note_from,&note_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");
		}
	}
}