maiacore 1.10.1
Music analisys library
score.h
1#pragma once
2
3#include <initializer_list>
4#include <map>
5#include <string>
6#include <vector>
7
8#include "SQLiteCpp/SQLiteCpp.h"
9#include "maiacore/chord.h"
10#include "maiacore/constants.h"
11#include "maiacore/key.h"
12#include "maiacore/measure.h"
13#include "maiacore/note.h"
14#include "maiacore/part.h"
15#include "nlohmann/json.hpp"
16#include "pugi/pugixml.hpp"
17
25class Score {
26 private:
27 std::string _title;
28 std::string _composerName;
29 std::vector<Part> _part;
30 std::string _filePath;
31 std::string _fileName;
32
33 pugi::xml_document _doc;
34 int _numParts;
35 int _numMeasures;
36 int _numNotes;
37 bool _isValidXML;
38 bool _haveTypeTag;
39 bool _isLoadedXML;
40 std::vector<Chord> _stackedChords;
41 int _lcmDivisionsPerQuarterNote;
42 bool _haveAnacrusisMeasure;
43
47 struct NoteEvent {
48 std::string partName;
49 int measureIdx;
50 int staveIdx;
51 int noteIdx;
52 const std::string keyName;
53 const Note* notePtr;
54 };
55
56 mutable std::vector<NoteEvent> _cachedNoteEvents;
57 mutable bool _isNoteEventsCached = false;
62 std::vector<NoteEvent> collectNoteEvents() const;
63
64 mutable std::vector<std::vector<NoteEvent>> _cachedNoteEventsPerPart;
65 mutable bool _isNoteEventsPerPartCached = false;
70 std::vector<std::vector<NoteEvent>> collectNoteEventsPerPart() const;
71
77 void removeDuplicatePatterns(std::vector<std::vector<Note>>* patterns) const;
78
79 typedef struct noteData_st {
80 float currentTimeValue = 0.0f;
81 const Note* notePtr = nullptr;
82 float floatBeatStartTime = 0.0f;
83 float floatBeatEndTime = 0.0f;
84 } NoteData;
85
86 typedef struct chordData_st {
87 std::vector<NoteData> noteData;
88 const Measure* measurePtr = nullptr;
89 bool isHomophonicChord = true;
90 float beatEndTimeHigherLimit = 0.0f;
91 float beatStartTimeLowerLimit = 1000.0f;
92 float chordQuarterDuration = 0.0f;
93 } ChordData;
94
100 void loadXMLFile(const std::string& filePath);
101
108 std::vector<std::tuple<int, float, Key, Chord, bool>> getChordsPerEachNoteEvent(
109 SQLite::Database& db, const bool includeDuplicates);
110
111 public:
117 explicit Score(const std::initializer_list<std::string>& partsName, const int numMeasures = 20);
118
124 explicit Score(const std::vector<std::string>& partsName, const int numMeasures = 20);
125
131 explicit Score(const std::string& filePath);
132
136 Score(Score&&) = default;
137
142
147 void clear();
148
155 void addPart(const std::string& partName, const int numStaves = 1);
156
161 void removePart(const int partId);
162
167 void addMeasure(const int numMeasures);
168
174 void removeMeasure(const int measureStart, const int measureEnd);
175
181 Part& getPart(const int partId);
182
188 Part& getPart(const std::string& partName);
189
194 int getNumParts() const;
195
200 int getNumMeasures() const;
201
206 int getNumNotes() const;
207
212 const std::vector<std::string> getPartsNames() const;
213
218 std::string getTitle() const;
219
224 void setTitle(const std::string& scoreTitle);
225
230 std::string getComposerName() const;
231
236 void setComposerName(const std::string& composerName);
237
245 void setKeySignature(const int fifthCicle, const bool isMajorMode = true, const int measureId = 0);
246
252 void setKeySignature(const std::string& key, const int measureId = 0);
253
261 void setTimeSignature(const int timeUpper, const int timeLower, const int measureId = -1);
262
269 void setMetronomeMark(int bpm, const RhythmFigure duration = RhythmFigure::QUARTER, int measureStart = 0);
270
277 const std::string toXML(const int identSize = 2) const;
278
284 const std::string toJSON() const;
285
292 void toFile(std::string fileName, bool compressedXML = false, const int identSize = 2) const;
293
298 void info() const;
299
309 std::function<void(Part* part, Measure* measure, int staveId, Note* note)> callback,
310 int measureStart = 0, int measureEnd = -1, std::vector<std::string> partNames = {});
311
316 bool isValid(void) const;
317
322 std::string getFilePath() const;
323
328 std::string getFileName() const;
329
334 bool haveTypeTag(void) const;
335
352 bool getNote(const int part, const int measure, const int note, std::string& pitch,
353 std::string& step, int& octave, int& duration, int& voice, std::string& type,
354 std::string& steam, int& staff) const;
355
366 bool getNote(const int part, const int measure, const int note, std::string& pitch,
367 std::string& step, int& octave) const;
368
377 bool getNote(const int part, const int measure, const int note, std::string& pitch) const;
378
382 void printPartNames() const;
383
389 int xPathCountNodes(const std::string& xPath) const;
390
396 const std::string getPartName(const int partId) const;
397
404 bool getPartIndex(const std::string& partName, int* index) const;
405
411
425 void getNoteNodeData(const pugi::xml_node& node, std::string& partName, int& measure,
426 std::string& pitch, std::string& pitchClass, std::string& alterSymbol,
427 int& alterValue, int& octave, std::string& type, float& duration) const;
428
434 void setRepeat(int measureStart, int measureEnd = -1);
435
491 nlohmann::json instrumentFragmentation(nlohmann::json config = nlohmann::json());
492
493 // /**
494 // * @brief Returns the vertical (stacked) chords of the score, with configurable filters.
495 // * @details Extracts chords considering parts, measures, min/max duration, duplicates, etc.
496 // * @param config JSON object with configuration parameters.
497 // * @return Vector of tuples: {measure number, time, key, chord, homophony}.
498 // */
499 // std::vector<std::tuple<int, float, Key, Chord, bool>> getChords(nlohmann::json config = {});
500
505 Score(const Score& other) {
506 _title = other._title;
507 _composerName = other._composerName;
508 _filePath = other._filePath;
509 _fileName = other._fileName;
510 _part = other._part;
511 _numParts = other._numParts;
512 _numMeasures = other._numMeasures;
513 _numNotes = other._numNotes;
514 _isValidXML = other._isValidXML;
515 _haveTypeTag = other._haveTypeTag;
516 _isLoadedXML = other._isLoadedXML;
517 _lcmDivisionsPerQuarterNote = other._lcmDivisionsPerQuarterNote;
518 _stackedChords = other._stackedChords;
519 _haveAnacrusisMeasure = other._haveAnacrusisMeasure;
520
521 // Deep copy of XML document
522 _doc.reset(other._doc);
523
524 // Invalidate caches - they will be rebuilt when needed
525 _isNoteEventsCached = false;
526 _isNoteEventsPerPartCached = false;
527 _cachedNoteEvents.clear();
528 _cachedNoteEventsPerPart.clear();
529 }
530
536 Score& operator=(const Score& other) {
537 if (this == &other) return *this;
538
539 _title = other._title;
540 _composerName = other._composerName;
541 _filePath = other._filePath;
542 _fileName = other._fileName;
543 _part = other._part;
544 _numParts = other._numParts;
545 _numMeasures = other._numMeasures;
546 _numNotes = other._numNotes;
547 _isValidXML = other._isValidXML;
548 _haveTypeTag = other._haveTypeTag;
549 _isLoadedXML = other._isLoadedXML;
550 _lcmDivisionsPerQuarterNote = other._lcmDivisionsPerQuarterNote;
551 _stackedChords = other._stackedChords;
552 _haveAnacrusisMeasure = other._haveAnacrusisMeasure;
553
554 // Deep copy of XML document
555 _doc.reset(other._doc);
556
557 // Invalidate caches - they will be rebuilt when needed
558 _isNoteEventsCached = false;
559 _isNoteEventsPerPartCached = false;
560 _cachedNoteEvents.clear();
561 _cachedNoteEventsPerPart.clear();
562
563 return *this;
564 }
565
566 // ====== MELODIC PATTERN ANALYSIS ======
567
572 typedef std::tuple<std::string, int, int, std::string, std::string, std::vector<std::string>, std::vector<float>, std::vector<float>,
573 float, float, float> MelodyPatternRow;
577 typedef std::vector<MelodyPatternRow> MelodyPatternTable;
578
631 const std::vector<Note>& melodyPattern, const float totalIntervalsSimilarityThreshold = 0.5,
632 const float totalRhythmSimilarityThreshold = 0.5,
633 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
634 intervalsSimilarityCallback = nullptr,
635 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
636 rhythmSimilarityCallback = nullptr,
637 const std::function<float(const std::vector<float>&)> totalIntervalSimilarityCallback =
638 nullptr,
639 const std::function<float(const std::vector<float>&)> totalRhythmSimilarityCallback =
640 nullptr,
641 const std::function<float(float, float)> totalSimilarityCallback = nullptr) const;
642
656 std::vector<MelodyPatternTable> findMelodyPattern(
657 const std::vector<std::vector<Note>>& melodyPatterns, const float totalIntervalsSimilarityThreshold = 0.5,
658 const float totalRhythmSimilarityThreshold = 0.5,
659 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
660 intervalsSimilarityCallback = nullptr,
661 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
662 rhythmSimilarityCallback = nullptr,
663 const std::function<float(const std::vector<float>&)> totalIntervalSimilarityCallback =
664 nullptr,
665 const std::function<float(const std::vector<float>&)> totalRhythmSimilarityCallback =
666 nullptr,
667 const std::function<float(float, float)> totalSimilarityCallback = nullptr) const;
668
682 std::vector<MelodyPatternTable> findAnyMelodyPattern(const int patternNumNotes = 5,
683 const float totalIntervalsSimilarityThreshold = 1.0f,
684 const float totalRhythmSimilarityThreshold = 1.0f,
685 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
686 intervalsSimilarityCallback = nullptr,
687 const std::function<std::vector<float>(const std::vector<Note>&, const std::vector<Note>&)>
688 rhythmSimilarityCallback = nullptr,
689 const std::function<float(const std::vector<float>&)> totalIntervalSimilarityCallback =
690 nullptr,
691 const std::function<float(const std::vector<float>&)> totalRhythmSimilarityCallback =
692 nullptr,
693 const std::function<float(float, float)> totalSimilarityCallback = nullptr) const;
694
755 std::vector<std::tuple<int, float, Key, Chord, bool>> getChords(nlohmann::json config = {});
756};
Represents a musical measure (bar) within a score, containing notes, staves, key/time signatures,...
Definition: measure.h:23
Represents a musical note, including pitch, duration, articulation, and MusicXML-related attributes.
Definition: note.h:19
Represents a musical part (instrument or voice) in a score, containing measures, staves,...
Definition: part.h:17
Represents a complete musical score, including metadata, parts, measures, and notes.
Definition: score.h:25
void forEachNote(std::function< void(Part *part, Measure *measure, int staveId, Note *note)> callback, int measureStart=0, int measureEnd=-1, std::vector< std::string > partNames={})
Iterates over all notes in the score, applying a callback function.
Score(const std::initializer_list< std::string > &partsName, const int numMeasures=20)
Constructs a new blank Score object with specified part names and initial measure count.
int getNumParts() const
Returns the number of parts (instruments/voices) in the score.
int getNumNotes() const
Returns the total number of notes in the score.
void addPart(const std::string &partName, const int numStaves=1)
Adds a new part (instrument/voice) to the score.
void clear()
Clears all content from the score, removing parts, measures, and metadata.
Part & getPart(const std::string &partName)
Returns a reference to a part by its name.
const std::vector< std::string > getPartsNames() const
Returns a vector with the names of all parts/instruments.
void getNoteNodeData(const pugi::xml_node &node, std::string &partName, int &measure, std::string &pitch, std::string &pitchClass, std::string &alterSymbol, int &alterValue, int &octave, std::string &type, float &duration) const
Retrieves detailed information from a note XML node.
MelodyPatternTable findMelodyPattern(const std::vector< Note > &melodyPattern, const float totalIntervalsSimilarityThreshold=0.5, const float totalRhythmSimilarityThreshold=0.5, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> intervalsSimilarityCallback=nullptr, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> rhythmSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalIntervalSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalRhythmSimilarityCallback=nullptr, const std::function< float(float, float)> totalSimilarityCallback=nullptr) const
Searches for a melodic pattern throughout the score, returning detailed results.
void setTimeSignature(const int timeUpper, const int timeLower, const int measureId=-1)
Sets the time signature for all or part of the measures.
void printPartNames() const
Prints the names of all parts/instruments in the score to the terminal.
bool isValid(void) const
Returns true if the score is valid (MusicXML loaded correctly).
void toFile(std::string fileName, bool compressedXML=false, const int identSize=2) const
Saves the score to a file in XML or compressed MXL format.
Score(const Score &other)
Copy constructor for Score.
Definition: score.h:505
~Score()
Destructor. Releases resources associated with the score.
int getNumMeasures() const
Returns the number of measures in the score.
void removePart(const int partId)
Removes a part from the score by its index.
void info() const
Prints summary information about the score to the log.
Part & getPart(const int partId)
Returns a reference to a part by its index.
std::tuple< std::string, int, int, std::string, std::string, std::vector< std::string >, std::vector< float >, std::vector< float >, float, float, float > MelodyPatternRow
Table row type for melodic pattern search results.
Definition: score.h:573
std::string getTitle() const
Returns the title of the score.
void setRepeat(int measureStart, int measureEnd=-1)
Sets repeat barlines for a range of measures.
std::vector< MelodyPatternTable > findMelodyPattern(const std::vector< std::vector< Note > > &melodyPatterns, const float totalIntervalsSimilarityThreshold=0.5, const float totalRhythmSimilarityThreshold=0.5, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> intervalsSimilarityCallback=nullptr, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> rhythmSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalIntervalSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalRhythmSimilarityCallback=nullptr, const std::function< float(float, float)> totalSimilarityCallback=nullptr) const
Searches for multiple melodic patterns in the score, returning a table for each pattern.
nlohmann::json instrumentFragmentation(nlohmann::json config=nlohmann::json())
Analyzes instrumental fragmentation patterns across the score timeline.
void setKeySignature(const int fifthCicle, const bool isMajorMode=true, const int measureId=0)
Sets the key signature for all parts at a specific measure.
void setKeySignature(const std::string &key, const int measureId=0)
Sets the key signature using the key name (e.g., "C", "Gm").
bool getNote(const int part, const int measure, const int note, std::string &pitch, std::string &step, int &octave, int &duration, int &voice, std::string &type, std::string &steam, int &staff) const
Retrieves detailed information about a specific note in the score.
void removeMeasure(const int measureStart, const int measureEnd)
Removes a range of measures from all parts in the score.
bool getNote(const int part, const int measure, const int note, std::string &pitch, std::string &step, int &octave) const
Retrieves basic information about a specific note (pitch, step, octave).
Score & operator=(const Score &other)
Assignment operator for Score.
Definition: score.h:536
const std::string toJSON() const
Exports the score to JSON format.
std::vector< std::tuple< int, float, Key, Chord, bool > > getChords(nlohmann::json config={})
Extracts vertical chord structures from the score with configurable analysis parameters.
std::vector< MelodyPatternRow > MelodyPatternTable
Table type for melodic pattern search results.
Definition: score.h:577
std::string getFilePath() const
Returns the file path of the loaded MusicXML file.
int xPathCountNodes(const std::string &xPath) const
Counts the number of XML nodes matching a given XPath expression.
bool haveTypeTag(void) const
Returns true if the MusicXML file contains <type> tags for notes.
const std::string toXML(const int identSize=2) const
Exports the score to MusicXML format.
bool haveAnacrusisMeasure() const
Returns true if the score contains an anacrusis (pickup) measure.
bool getPartIndex(const std::string &partName, int *index) const
Gets the index of a part by its name.
Score(Score &&)=default
Move constructor for Score.
Score(const std::vector< std::string > &partsName, const int numMeasures=20)
Constructs a new blank Score object with specified part names and initial measure count.
bool getNote(const int part, const int measure, const int note, std::string &pitch) const
Retrieves only the pitch of a specific note.
std::vector< MelodyPatternTable > findAnyMelodyPattern(const int patternNumNotes=5, const float totalIntervalsSimilarityThreshold=1.0f, const float totalRhythmSimilarityThreshold=1.0f, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> intervalsSimilarityCallback=nullptr, const std::function< std::vector< float >(const std::vector< Note > &, const std::vector< Note > &)> rhythmSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalIntervalSimilarityCallback=nullptr, const std::function< float(const std::vector< float > &)> totalRhythmSimilarityCallback=nullptr, const std::function< float(float, float)> totalSimilarityCallback=nullptr) const
Finds all possible melodic patterns of a given length in the score.
void setTitle(const std::string &scoreTitle)
Sets the title of the score.
void setMetronomeMark(int bpm, const RhythmFigure duration=RhythmFigure::QUARTER, int measureStart=0)
Sets the metronome mark (BPM) for a specific measure.
std::string getComposerName() const
Returns the composer's name.
void addMeasure(const int numMeasures)
Adds a specified number of measures to all parts in the score.
std::string getFileName() const
Returns the file name of the loaded MusicXML file.
const std::string getPartName(const int partId) const
Returns the name of a part by its index.
void setComposerName(const std::string &composerName)
Sets the composer's name.
Score(const std::string &filePath)
Constructs a new Score object by loading a MusicXML file.