📄 musicxmlexporter.cpp
字号:
std::string s; s += c; while (num / 52 > 0) { s += c; num /= 52; } return s;}boolMusicXmlExporter::write(){ Composition *composition = &m_doc->getComposition(); std::ofstream str(m_fileName.c_str(), std::ios::out); if (!str) { std::cerr << "MusicXmlExporter::write() - can't write file " << m_fileName << std::endl; return false; } // XML header information str << "<?xml version=\"1.0\"?>" << std::endl; str << "<!DOCTYPE score-partwise PUBLIC \"-//Recordare//DTD MusicXML 1.1 Partwise//EN\" \"http://www.musicxml.org/dtds/partwise.dtd\">" << std::endl; // MusicXml header information str << "<score-partwise>" << std::endl; str << "\t<work> <work-title>" << XmlExportable::encode(m_fileName) << "</work-title></work> " << std::endl; // Movement, etc. info goes here str << "\t<identification> " << std::endl; if (composition->getCopyrightNote() != "") { str << "\t\t<rights>" << XmlExportable::encode(composition->getCopyrightNote()) << "</rights>" << std::endl; } str << "\t\t<encoding>" << std::endl; // Incomplete: Insert date! // str << "\t\t\t<encoding-date>" << << "</encoding-date>" << std::endl; str << "\t\t\t<software>Rosegarden v" VERSION "</software>" << std::endl; str << "\t\t</encoding>" << std::endl; str << "\t</identification> " << std::endl; // MIDI information str << "\t<part-list>" << std::endl; Composition::trackcontainer& tracks = composition->getTracks(); int trackNo = 0; timeT lastNoteTime = -1; for (Composition::trackiterator i = tracks.begin(); i != tracks.end(); ++i) { // Incomplete: What about all the other Midi stuff? // Incomplete: (Future) GUI to set labels if they're not already Instrument * trackInstrument = (&m_doc->getStudio())->getInstrumentById((*i).second->getInstrument()); str << "\t\t<score-part id=\"" << numToId((*i).first) << "\">" << std::endl; str << "\t\t\t<part-name>" << XmlExportable::encode((*i).second->getLabel()) << "</part-name>" << std::endl; if (trackInstrument) {/* Removing this stuff for now. It doesn't work, because the ids are are expected to be non-numeric names that refer to elements elsewhere that define the actual instruments. I think. str << "\t\t\t<score-instrument id=\"" << trackInstrument->getName() << "\">" << std::endl; str << "\t\t\t\t<instrument-name>" << trackInstrument->getType() << "</instrument-name>" << std::endl; str << "\t\t\t</score-instrument>" << std::endl; str << "\t\t\t<midi-instrument id=\"" << trackInstrument->getName() << "\">" << std::endl; str << "\t\t\t\t<midi-channel>" << ((unsigned int)trackInstrument->getMidiChannel() + 1) << "</midi-channel>" << std::endl; if (trackInstrument->sendsProgramChange()) { str << "\t\t\t\t<midi-program>" << ((unsigned int)trackInstrument->getProgramChange() + 1) << "</midi-program>" << std::endl; } str << "\t\t\t</midi-instrument>" << std::endl;*/ } str << "\t\t</score-part>" << std::endl; emit setProgress(int(double(trackNo++) / double(tracks.size()) * 20.0)); rgapp->refreshGUI(50); } // end track iterator str << "\t</part-list>" << std::endl; // Notes! // Write out all segments for each Track trackNo = 0; for (Composition::trackiterator j = tracks.begin(); j != tracks.end(); ++j) { bool startedPart = false; // Code courtesy docs/code/iterators.txt CompositionTimeSliceAdapter::TrackSet trackSet; // Incomplete: get the track info for each track (i.e. this should // be in an iterator loop) into the track set trackSet.insert((*j).first); CompositionTimeSliceAdapter adapter(composition, trackSet); int oldMeasureNumber = -1; bool startedAttributes = false; Rosegarden::Key key; Clef clef; AccidentalTable accTable(key, clef); TimeSignature prevTimeSignature; bool timeSigPending = false; bool keyPending = false; bool clefPending = false; for (CompositionTimeSliceAdapter::iterator k = adapter.begin(); k != adapter.end(); ++k) { Event *event = *k; timeT absoluteTime = event->getNotationAbsoluteTime(); if (!startedPart) { str << "\t<part id=\"" << numToId((*j).first) << "\">" << std::endl; startedPart = true; } // Open a new measure if necessary // Incomplete: How does MusicXML handle non-contiguous measures? int measureNumber = composition->getBarNumber(absoluteTime); TimeSignature timeSignature = composition->getTimeSignatureAt(absoluteTime); if (measureNumber != oldMeasureNumber) { if (startedAttributes) { // rather bizarrely, MusicXML appears to require // key, time, clef in that order if (keyPending) { writeKey(key, str); keyPending = false; } if (timeSigPending) { writeTime(prevTimeSignature, str); timeSigPending = false; } if (clefPending) { writeClef(clef, str); clefPending = false; } str << "\t\t\t</attributes>" << std::endl; startedAttributes = false; } while (measureNumber > oldMeasureNumber) { bool first = (oldMeasureNumber < 0); if (!first) { if (startedAttributes) { str << "\t\t\t</attributes>" << std::endl; } str << "\t\t</measure>\n" << std::endl; } ++oldMeasureNumber; str << "\t\t<measure number=\"" << (oldMeasureNumber + 1) << "\">" << std::endl; if (first) { str << "\t\t\t<attributes>" << std::endl; // Divisions is divisions of crotchet (quarter-note) on which all // note-lengths are based str << "\t\t\t\t<divisions>" << Note(Note::Crotchet).getDuration() << "</divisions>" << std::endl; startedAttributes = true; timeSigPending = true; } } accTable = AccidentalTable(key, clef); } oldMeasureNumber = measureNumber; if (timeSignature != prevTimeSignature) { prevTimeSignature = timeSignature; timeSigPending = true; if (!startedAttributes) { str << "\t\t\t<attributes>" << std::endl; startedAttributes = true; } } // process event if (event->isa(Rosegarden::Key::EventType)) { if (!startedAttributes) { str << "\t\t\t<attributes>" << std::endl; startedAttributes = true; } key = Rosegarden::Key(*event); keyPending = true; accTable = AccidentalTable(key, clef); } else if (event->isa(Clef::EventType)) { if (!startedAttributes) { str << "\t\t\t<attributes>" << std::endl; startedAttributes = true; } clef = Clef(*event); clefPending = true; accTable = AccidentalTable(key, clef); } else if (event->isa(Note::EventRestType) || event->isa(Note::EventType)) { if (startedAttributes) { if (keyPending) { writeKey(key, str); keyPending = false; } if (timeSigPending) { writeTime(prevTimeSignature, str); timeSigPending = false; } if (clefPending) { writeClef(clef, str); clefPending = false; } str << "\t\t\t</attributes>" << std::endl; startedAttributes = false; } writeNote(event, lastNoteTime, accTable, clef, key, str); if (event->isa(Note::EventType)) { lastNoteTime = event->getNotationAbsoluteTime(); } else if (event->isa(Note::EventRestType)) { lastNoteTime = -1; } } } if (startedPart) { if (startedAttributes) { if (keyPending) { writeKey(key, str); keyPending = false; } if (timeSigPending) { writeTime(prevTimeSignature, str); timeSigPending = false; } if (clefPending) { writeClef(clef, str); clefPending = false; } str << "\t\t\t</attributes>" << std::endl; startedAttributes = false; } str << "\t\t</measure>" << std::endl; str << "\t</part>" << std::endl; } emit setProgress(20 + int(double(trackNo++) / double(tracks.size()) * 80.0)); rgapp->refreshGUI(50); } str << "</score-partwise>" << std::endl; str.close(); return true;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -