Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,164 @@ if (asserts.isTiedNote(noteVariation)) {
}
```

### End-to-end Example

This example renders MusicXML for a single measure with an image of a single measure with a C/4 whole note.

![image of a single measure with a C/4 whole note](https://github.com/user-attachments/assets/7480ec5e-2aac-4653-86e3-2717ecfca8c2)

You can validate the MusicXML on https://vexml.dev.

```ts
const musicXml = MusicXML.createPartwise();

musicXml
.getRoot()
.setPartList(
new elements.PartList({
contents: [
new Array<elements.PartGroup>(),
new elements.ScorePart({
attributes: { id: 'P1' },
contents: [
null, // elements.Identification
new Array<elements.PartLink>(),
new elements.PartName({ contents: ['Part 1'] }),
null, // elements.PartNameDisplay
null, // elements.PartAbbreviation
null, // elements.PartAbbreviationDisplay
new Array<elements.Group>(),
new Array<elements.ScoreInstrument>(),
new Array<elements.Player>(),
new Array<elements.MidiDevice | elements.MidiInstrument>(),
],
}),
new Array<elements.PartGroup | elements.ScorePart>(),
],
})
)
.setParts([
new elements.PartPartwise({
attributes: { id: 'P1' },
}).setMeasures([
new elements.MeasurePartwise({
attributes: { number: '1' },
contents: [
[
new elements.Attributes({
attributes: { divisions: 1 },
contents: [
null, // elements.Footnote
null, // elements.Level
null, // elements.Divisions
new Array<elements.Key>(),
new Array<elements.Time>(
new elements.Time({
contents: [
[
[
[
new elements.Beats({
contents: ['4'],
}),
new elements.BeatType({
contents: ['4'],
}),
],
],
null,
],
],
})
),
null, // elements.Staves
null, // elements.PartSymbol
null, // elements.Instruments
new Array<elements.Clef>(),
new Array<elements.StaffDetails>(),
new Array<elements.Transpose>(),
new Array<elements.Directive>(),
new Array<elements.MeasureStyle>(),
],
}),
new elements.Note({
contents: [
[
null, // elements.TiedNote
new elements.Pitch({
contents: [
new elements.Step({
contents: ['C'],
}),
null, // elements.Alter
new elements.Octave({
contents: [4],
}),
],
}),
new elements.Duration({
contents: [4],
}),
[], // elements.Tie,
],
new Array<elements.Instrument>(),
null, // elements.Footnote
null, // elements.Level
null, // elements.Voice
null, // elements.Type
new Array<elements.Dot>(),
null, // elements.Accidental
null, // elements.TimeModification
null, // elements.Stem
null, // elements.Notehead
null, // elements.NoteheadText
null, // elements.Staff
[], // elements.Beam
new Array<elements.Notations>(),
new Array<elements.Lyric>(),
null, // elements.Play
null, // elements.Listen
],
}),
],
],
}),
]),
]);

console.log(musicXml.serialize());
```

which logs the following MusicXML:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<score-partwise version="4.0">
<part-list>
<score-part id="P1">
<part-name>Part 1</part-name>
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
</attributes>
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
</note>
</measure>
</part>
</score-partwise>
```

## 💻 Development

### Prerequisites
Expand Down
144 changes: 144 additions & 0 deletions src/MusicXML.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,150 @@ describe('MusicXML', () => {
expect(note.getStaff()).not.toBeNull();
expect(note.getStaff()!.getValue()).toBe(4);
});

it('creates a document with a single measure and a single note', () => {
const musicXml = MusicXML.createPartwise();

musicXml
.getRoot()
.setPartList(
new elements.PartList({
contents: [
new Array<elements.PartGroup>(),
new elements.ScorePart({
attributes: { id: 'P1' },
contents: [
null, // elements.Identification
new Array<elements.PartLink>(),
new elements.PartName({ contents: ['Part 1'] }),
null, // elements.PartNameDisplay
null, // elements.PartAbbreviation
null, // elements.PartAbbreviationDisplay
new Array<elements.Group>(),
new Array<elements.ScoreInstrument>(),
new Array<elements.Player>(),
new Array<elements.MidiDevice | elements.MidiInstrument>(),
],
}),
new Array<elements.PartGroup | elements.ScorePart>(),
],
})
)
.setParts([
new elements.PartPartwise({
attributes: { id: 'P1' },
}).setMeasures([
new elements.MeasurePartwise({
attributes: { number: '1' },
contents: [
[
new elements.Attributes({
attributes: { divisions: 1 },
contents: [
null, // elements.Footnote
null, // elements.Level
null, // elements.Divisions
new Array<elements.Key>(),
new Array<elements.Time>(
new elements.Time({
contents: [
[
[
[
new elements.Beats({
contents: ['4'],
}),
new elements.BeatType({
contents: ['4'],
}),
],
],
null,
],
],
})
),
null, // elements.Staves
null, // elements.PartSymbol
null, // elements.Instruments
new Array<elements.Clef>(),
new Array<elements.StaffDetails>(),
new Array<elements.Transpose>(),
new Array<elements.Directive>(),
new Array<elements.MeasureStyle>(),
],
}),
new elements.Note({
contents: [
[
null, // elements.TiedNote
new elements.Pitch({
contents: [
new elements.Step({
contents: ['C'],
}),
null, // elements.Alter
new elements.Octave({
contents: [4],
}),
],
}),
new elements.Duration({
contents: [4],
}),
[], // elements.Tie,
],
new Array<elements.Instrument>(),
null, // elements.Footnote
null, // elements.Level
null, // elements.Voice
null, // elements.Type
new Array<elements.Dot>(),
null, // elements.Accidental
null, // elements.TimeModification
null, // elements.Stem
null, // elements.Notehead
null, // elements.NoteheadText
null, // elements.Staff
[], // elements.Beam
new Array<elements.Notations>(),
new Array<elements.Lyric>(),
null, // elements.Play
null, // elements.Listen
],
}),
],
],
}),
]),
]);

expect(musicXml.serialize()).toBe(`<?xml version="1.0" encoding="UTF-8"?>
<score-partwise version="4.0">
<part-list>
<score-part id="P1">
<part-name>Part 1</part-name>
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<time>
<beats>4</beats>
<beat-type>4</beat-type>
</time>
</attributes>
<note>
<pitch>
<step>C</step>
<octave>4</octave>
</pitch>
<duration>4</duration>
</note>
</measure>
</part>
</score-partwise>`);
});
});

describe('parse', () => {
Expand Down
Loading