예제 #1
0
void NoteEntryAction::mousePress(Staff* staff, int bar, const QPointF& pos)
{
    Clef* clef = staff->lastClefChange(bar);

    Voice* voice = staff->part()->voice(m_tool->voice());
    VoiceBar* vb = voice->bar(bar);

    // find element before which to insert the chord
    int before = 0;
    for (int i = 0; i < vb->elementCount(); i++) {
        VoiceElement* e = vb->element(i);
        if (e->x() >= pos.x()) break;
        before++;
    }

    int line = staff->line(pos.y());
    int pitch = 0, accidentals = 0;
    if (clef && !m_isRest) {
        pitch = clef->lineToPitch(line);
        // get correct accidentals for note
        KeySignature* ks = staff->lastKeySignatureChange(bar);
        if (ks) accidentals = ks->accidentals(pitch);
        for (int i = 0; i < before; i++) {
            Chord* c = dynamic_cast<Chord*>(vb->element(i));
            if (!c) continue;
            for (int n = 0; n < c->noteCount(); n++) {
                if (c->note(n)->pitch() == pitch) {
                    accidentals = c->note(n)->accidentals();
                }
            }
        }
    }

    Chord* join = NULL;
    if (before > 0) join = dynamic_cast<Chord*>(vb->element(before-1));
    if (join && join->x() + join->width() >= pos.x()) {
        if (clef && !m_isRest) {
            m_tool->addCommand(new AddNoteCommand(m_tool->shape(), join, staff, m_duration, pitch, accidentals));
        } else {
            m_tool->addCommand(new MakeRestCommand(m_tool->shape(), join));
        }
    } else {
        if (clef && !m_isRest) {
            m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, before, pitch, accidentals));
        } else {
            m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, before));
        }
    }
}
예제 #2
0
    void testNoteAccidentals()
    {
        Sheet* sheet = new Sheet();
        Bar* bar = sheet->addBar();
        Part* part = sheet->addPart("part");
        Voice* voice = part->addVoice();
        Staff* staff = part->addStaff();
        VoiceBar* vb = bar->voice(voice);

        for (int a = -2; a <= 2; a++) {
            Chord* c = new Chord(QuarterNote);
            c->addNote(staff, 0, a);
            vb->addElement(c);
        }

        validateOutput(sheet, "noteaccidentals.xml");
        delete sheet;
    }
예제 #3
0
    void testNotePitch()
    {
        Sheet* sheet = new Sheet();
        Bar* bar = sheet->addBar();
        Part* part = sheet->addPart("part");
        Voice* voice = part->addVoice();
        Staff* staff = part->addStaff();
        VoiceBar* vb = bar->voice(voice);

        for (int p = -20; p <= 20; p++) {
            Chord* c = new Chord(QuarterNote);
            c->addNote(staff, p);
            vb->addElement(c);
        }

        validateOutput(sheet, "notepitch.xml");
        delete sheet;
    }
예제 #4
0
void NoteEntryAction::renderKeyboardPreview(QPainter& painter, const MusicCursor& cursor)
{
    Staff* staff = cursor.staff();
    Part* part = staff->part();
    Sheet* sheet = part->sheet();
    Bar* bar = sheet->bar(cursor.bar());
    QPointF p = bar->position() + QPointF(0, staff->top());
    Voice* voice = cursor.staff()->part()->voice(cursor.voice());
    VoiceBar* vb = voice->bar(bar);

    if (cursor.element() >= vb->elementCount()) {
        // cursor is past last element in bar, position of cursor is
        // halfway between last element and end of bar
        if (vb->elementCount() == 0) {
            // unless entire voicebar is still empty
            p.rx() += 15.0;
        } else {
            VoiceElement* ve = vb->element(vb->elementCount()-1);
            p.rx() += (ve->x() + bar->size()) / 2;
        }
    } else {
        // cursor is on an element, get the position of that element
        p.rx() += vb->element(cursor.element())->x();
    }

    p.ry() += (cursor.staff()->lineCount() - 1)* cursor.staff()->lineSpacing();
    p.ry() -= cursor.staff()->lineSpacing() * cursor.line() / 2;

    m_tool->shape()->renderer()->renderNote(painter, m_duration < QuarterNote ? QuarterNote : m_duration, p, 0, Qt::magenta);
}
예제 #5
0
    void testNoteDurations()
    {
        Sheet* sheet = new Sheet();
        Bar* bar = sheet->addBar();
        Part* part = sheet->addPart("part");
        Voice* voice = part->addVoice();
        Staff* staff = part->addStaff();
        VoiceBar* vb = bar->voice(voice);

        for (Duration d = HundredTwentyEighthNote; d <= BreveNote; d = (Duration)(d + 1)) {
            Chord* c = new Chord(d);
            c->addNote(staff, 0);
            vb->addElement(c);
        }
        for (int i = 1; i < 4; i++) {
            Chord* c = new Chord(QuarterNote, i);
            c->addNote(staff, 0);
            vb->addElement(c);
        }

        validateOutput(sheet, "notedurations.xml");
        delete sheet;
    }
예제 #6
0
void NoteEntryAction::keyPress(QKeyEvent* event, const MusicCursor& cursor)
{
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
        Staff* staff = cursor.staff();
        //Part* part = staff->part();
        //Sheet* sheet = part->sheet();
        //Bar* bar = sheet->bar(cursor.bar());
        Clef* clef = staff->lastClefChange(cursor.bar());
        int line = cursor.line();
        int pitch = 0, accidentals = 0;
        VoiceBar* vb = cursor.voiceBar();
        if (clef) {
            pitch = clef->lineToPitch(line);
            // get correct accidentals for note
            KeySignature* ks = staff->lastKeySignatureChange(cursor.bar());
            if (ks) accidentals = ks->accidentals(pitch);
            for (int i = 0; i < cursor.element(); i++) {
                Chord* c = dynamic_cast<Chord*>(vb->element(i));
                if (!c) continue;
                for (int n = 0; n < c->noteCount(); n++) {
                    if (c->note(n)->pitch() == pitch) {
                        accidentals = c->note(n)->accidentals();
                    }
                }
            }
        }

        Chord* join = 0;
        if (cursor.element() < vb->elementCount()) join = dynamic_cast<Chord*>(vb->element(cursor.element()));
        if (event->modifiers() & Qt::ShiftModifier || !join) {
            m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, cursor.element(), pitch, accidentals));
        } else {
            m_tool->addCommand(new AddNoteCommand(m_tool->shape(), join, staff, join->duration(), pitch, accidentals));
        }
        event->accept();
    }
}
void AbstractNoteMusicAction::mousePress(Staff* staff, int barIdx, const QPointF& pos)
{
    Part* part = staff->part();
    Sheet* sheet = part->sheet();
    Bar* bar = sheet->bar(barIdx);
    
    Clef* clef = staff->lastClefChange(barIdx, 0);
    
    // loop over all noteheads
    qreal closestDist = 1e9;
    Note* closestNote = 0;
    Chord* chord = 0;
    
    // outer loop, loop over all voices
    for (int v = 0; v < part->voiceCount(); v++) {
        Voice* voice = part->voice(v);
        VoiceBar* vb = voice->bar(bar);
        
        // next loop over all chords
        for (int e = 0; e < vb->elementCount(); e++) {
            Chord* c = dynamic_cast<Chord*>(vb->element(e));
            if (!c) continue;
            
            qreal centerX = c->x() + (c->width() / 2);
            
            // check if it is a rest
            if (c->noteCount() == 0) {
                qreal centerY = c->y() + (c->height() / 2);
                qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y()));
                if (dist < closestDist) {
                    closestDist = dist;
                    closestNote = NULL;
                    chord = c;
                }
            }
            
            // lastly loop over all noteheads
            for (int n = 0; n < c->noteCount(); n++) {
                Note* note = c->note(n);
                if (note->staff() != staff) continue;
                
                int line = clef->pitchToLine(note->pitch());
                qreal centerY = line * staff->lineSpacing() / 2;
                
                qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y()));
                if (dist < closestDist) {
                    closestDist = dist;
                    closestNote = note;
                    chord = c;
                }
            }
        }
    }
    
    StaffElement* se = 0;
    for (int e = 0; e < bar->staffElementCount(staff); e++) {
        StaffElement* elem = bar->staffElement(staff, e);
        qreal centerX = elem->x() + (elem->width() / 2);
        qreal centerY = elem->y() + (elem->height() / 2);
        qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y()));
        if (dist < closestDist) {
            se = elem;
            closestDist = dist;
        }
    }
    
    if (se) {
        mousePress(se, closestDist, pos);
    } else {
        mousePress(chord, closestNote, closestDist, pos);
    }
}
예제 #8
0
static void writePart(KoXmlWriter& w, int id, Part* part)
{
    w.startElement("music:part");
    w.addAttribute("id", QString("P%1").arg(id));

    for (int i = 0; i < part->sheet()->barCount(); i++) {
        Bar* bar = part->sheet()->bar(i);
        
        w.startElement("music:measure");
        w.addAttribute("number", i+1);

        bool inAttributes = false;
        if (i == 0) {
            w.startElement("music:attributes");
            w.startElement("music:divisions");
            w.addTextNode(QString::number(QuarterLength));
            w.endElement(); // music:divisions
            inAttributes = true;
        }

        for (int st = 0; st < part->staffCount(); st++) {
            Staff* staff = part->staff(st);
            for (int e = 0; e < bar->staffElementCount(staff); e++) {
                StaffElement* se = bar->staffElement(staff, e);
                
                KeySignature* ks = dynamic_cast<KeySignature*>(se);
                if (ks) {
                    if (!inAttributes) {
                        w.startElement("music:attributes");
                        inAttributes = true;
                    }
                    writeKeySignature(w, ks, part);
                }
            }
        }
        for (int st = 0; st < part->staffCount(); st++) {
            Staff* staff = part->staff(st);
            for (int e = 0; e < bar->staffElementCount(staff); e++) {
                StaffElement* se = bar->staffElement(staff, e);
                
                TimeSignature* ts = dynamic_cast<TimeSignature*>(se);
                if (ts) {
                    if (!inAttributes) {
                        w.startElement("music:attributes");
                        inAttributes = true;
                    }
                    writeTimeSignature(w, ts, part);
                }
            }
        }

        if (i == 0 && part->staffCount() != 1) {
            w.startElement("music:staves");
            w.addTextNode(QString::number(part->staffCount()));
            w.endElement(); // music:staves
        }            
            
        for (int st = 0; st < part->staffCount(); st++) {
            Staff* staff = part->staff(st);
            for (int e = 0; e < bar->staffElementCount(staff); e++) {
                StaffElement* se = bar->staffElement(staff, e);
                
                Clef* c = dynamic_cast<Clef*>(se);
                if (c) {
                    if (!inAttributes) {
                        w.startElement("music:attributes");
                        inAttributes = true;
                    }
                    writeClef(w, c, part);
                }
            }
        }

        if (inAttributes) {
            w.endElement(); // music:attributes
        }

        int curTime = 0;
        for (int voice = 0; voice < part->voiceCount(); voice++) {
            if (curTime != 0) {
                w.startElement("music:backup");
                w.startElement("music:duration");
                w.addTextNode(QString::number(curTime));
                w.endElement(); // music:duration
                w.endElement(); // music:backup
            }

            Voice* v = part->voice(voice);
            VoiceBar* vb = part->sheet()->bar(i)->voice(v);
            for (int e = 0; e < vb->elementCount(); e++) {
                VoiceElement* ve = vb->element(e);
                curTime += ve->length();

                Chord* c =  dynamic_cast<Chord*>(ve);
                if(c) writeChord(w, c, v, part, i);
            }
        }
        w.endElement(); // music:measure
    }

    w.endElement(); // music:part
}
예제 #9
0
static void writeChord(KoXmlWriter& w, Chord* chord, Voice* voice, Part* part, int bar)
{
    if (!chord->noteCount()) {
        w.startElement("music:note");

        w.startElement("music:rest");
        w.endElement();  // music:rest

        w.startElement("music:duration");
        w.addTextNode(QString::number(chord->length()));
        w.endElement(); // music:duration
        
        w.startElement("music:voice");
        w.addTextNode(QString::number(part->indexOfVoice(voice) + 1));
        w.endElement(); // music:voice
        
        w.startElement("music:type");
        w.addTextNode(durationToString(chord->duration()));
        w.endElement(); // music:type
        
        for (int i = 0; i < chord->dots(); i++) {
            w.startElement("music:dot");
            w.endElement(); // music:dot
        }
        
        if (part->staffCount() > 1) {
            // only write staff info when more than one staff exists
            Staff* s = chord->staff();
            w.startElement("music:staff");
            w.addTextNode(QString::number(part->indexOfStaff(s) + 1));
            w.endElement();  //music:staff
        }
        w.endElement(); // music:note
    } else for (int n = 0; n < chord->noteCount(); n++) {
        Staff* staff = chord->note(n)->staff();
        w.startElement("music:note");
        
        if (n > 0) {
            w.startElement("music:chord");
            w.endElement(); // music:chord
        }

        w.startElement("music:pitch");
        w.startElement("music:step");
        int pitch = chord->note(n)->pitch();
        char note = 'A' + ((((pitch + 2) % 7) + 7) % 7);
        w.addTextNode(QString(note));
        w.endElement(); // music:step

        if (chord->note(n)->accidentals()) {
            w.startElement("music:alter");
            w.addTextNode(QString::number(chord->note(n)->accidentals()));
            w.endElement(); // music:alter
        }
        
        w.startElement("music:octave");
        w.addTextNode(QString::number((pitch + 4*7) / 7)); // first add, than divide to get proper rounding
        w.endElement(); // music:octave
        w.endElement(); // music:pitch
        w.startElement("music:duration");
        w.addTextNode(QString::number(chord->length()));
        w.endElement(); // music:duration
        
        w.startElement("music:voice");
        w.addTextNode(QString::number(part->indexOfVoice(voice) + 1));
        w.endElement(); // music:voice
        
        w.startElement("music:type");
        w.addTextNode(durationToString(chord->duration()));
        w.endElement(); // music:type
        
        for (int i = 0; i < chord->dots(); i++) {
            w.startElement("music:dot");
            w.endElement(); // music:dot
        }
        
        int activeAccidentals = 0;
        KeySignature* ks = staff->lastKeySignatureChange(bar);
        if (ks) activeAccidentals = ks->accidentals(chord->note(n)->pitch());
        VoiceBar* vb = chord->voiceBar();
        // next check the bar for the last previous note in the same voice with the same pitch
        for (int e = 0; e < vb->elementCount(); e++) {
            Chord* c = dynamic_cast<Chord*>(vb->element(e));
            if (!c) continue;
            if (c == chord) break;
            for (int nid = 0; nid < c->noteCount(); nid++) {
                Note* note = c->note(nid);
                if (note->staff() != staff) continue;
                if (note->pitch() == chord->note(n)->pitch()) {
                    activeAccidentals = note->accidentals();
                }
            }
        }
        
        if (chord->note(n)->accidentals() != activeAccidentals) {
            w.startElement("music:accidental");
            switch (chord->note(n)->accidentals()) {
                case -2: w.addTextNode("flat-flat"); break;
                case -1: w.addTextNode("flat"); break;
                case  0: w.addTextNode("natural"); break;
                case  1: w.addTextNode("sharp"); break;
                case  2: w.addTextNode("double-sharp"); break;
            }
            w.endElement(); // music:accidental
        }
        
        if (part->staffCount() > 1) {
            // only write staff info when more than one staff exists
            Staff* s = chord->note(n)->staff();
            w.startElement("music:staff");
            w.addTextNode(QString::number(part->indexOfStaff(s) + 1));
            w.endElement();  //music:staff
        }
        w.endElement(); // music:note
    }
}