Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
5898 lines (5111 sloc) 251 KB
//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sat Aug 8 12:24:49 PDT 2015
// Last Modified: Wed Apr 10 14:43:08 EDT 2019
// Filename: humlib.h
// URL: https://github.com/craigsapp/humlib/blob/master/include/humlib.h
// Syntax: C++11
// vim: ts=3
//
// Description: Include file for humlib library.
//
/*
Copyright (c) 2015, 2016, 2017, 2018 Craig Stuart Sapp
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _HUMLIB_H_INCLUDED
#define _HUMLIB_H_INCLUDED
#include <stdarg.h>
#include <string.h>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstring>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <locale>
#include <map>
#include <regex>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::ends;
using std::ifstream;
using std::invalid_argument;
using std::istream;
using std::istreambuf_iterator;
using std::list;
using std::map;
using std::ostream;
using std::pair;
using std::regex;
using std::set;
using std::string;
using std::stringstream;
using std::to_string;
using std::vector;
#ifdef USING_URI
#include <sys/types.h> /* socket, connect */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* htons */
#include <netdb.h> /* gethostbyname */
#include <unistd.h> /* read, write */
#include <string.h> /* memcpy */
#include <sstream>
#endif
#include "pugiconfig.hpp"
#include "pugixml.hpp"
using pugi::xml_node;
using pugi::xml_attribute;
using pugi::xml_document;
using pugi::xpath_node;
namespace hum {
class Convert;
class HumNum;
class HumAddress;
class HumdrumToken;
typedef HumdrumToken* HTp;
class HumdrumLine;
class HumdrumFileBase;
class HumdrumFileStructure;
class HumdrumFileContent;
class HumdrumFile;
class GridVoice;
class HumParameter : public std::string {
public:
HumParameter(void);
HumParameter(const std::string& str);
HumdrumToken* origin;
};
typedef std::map<std::string, std::map<std::string, std::map<std::string, HumParameter> > > MapNNKV;
typedef std::map<std::string, std::map<std::string, HumParameter> > MapNKV;
typedef std::map<std::string, HumParameter> MapKV;
class HumHash {
public:
HumHash (void);
~HumHash ();
std::string getValue (const std::string& key) const;
std::string getValue (const std::string& ns2,
const std::string& key) const;
std::string getValue (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
HTp getValueHTp (const std::string& key) const;
HTp getValueHTp (const std::string& ns2,
const std::string& key) const;
HTp getValueHTp (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
int getValueInt (const std::string& key) const;
int getValueInt (const std::string& ns2,
const std::string& key) const;
int getValueInt (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
HumNum getValueFraction (const std::string& key) const;
HumNum getValueFraction (const std::string& ns2,
const std::string& key) const;
HumNum getValueFraction (const std::string& ns1, const std::string& ns2,
const std::string& key)const ;
double getValueFloat (const std::string& key)const ;
double getValueFloat (const std::string& ns2,
const std::string& key) const;
double getValueFloat (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
bool getValueBool (const std::string& key) const;
bool getValueBool (const std::string& ns2,
const std::string& key) const;
bool getValueBool (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
void setValue (const std::string& key,
const std::string& value);
void setValue (const std::string& ns2,
const std::string& key,
const std::string& value);
void setValue (const std::string& ns1,
const std::string& ns2,
const std::string& key,
const std::string& value);
void setValue (const std::string& key,
const char* value);
void setValue (const std::string& ns2,
const std::string& key,
const char* value);
void setValue (const std::string& ns1,
const std::string& ns2,
const std::string& key,
const char* value);
void setValue (const std::string& key, int value);
void setValue (const std::string& ns2, const std::string& key,
int value);
void setValue (const std::string& ns1, const std::string& ns2,
const std::string& key, int value);
void setValue (const std::string& key, HTp value);
void setValue (const std::string& ns2, const std::string& key,
HTp value);
void setValue (const std::string& ns1, const std::string& ns2,
const std::string& key, HTp value);
void setValue (const std::string& key, HumNum value);
void setValue (const std::string& ns2, const std::string& key,
HumNum value);
void setValue (const std::string& ns1, const std::string& ns2,
const std::string& key, HumNum value);
void setValue (const std::string& key, double value);
void setValue (const std::string& ns2, const std::string& key,
double value);
void setValue (const std::string& ns1, const std::string& ns2,
const std::string& key, double value);
bool isDefined (const std::string& key) const;
bool isDefined (const std::string& ns2,
const std::string& key) const;
bool isDefined (const std::string& ns1, const std::string& ns2,
const std::string& key) const;
void deleteValue (const std::string& key);
void deleteValue (const std::string& ns2, const std::string& key);
void deleteValue (const std::string& ns1, const std::string& ns2,
const std::string& key);
std::vector<std::string> getKeys (void) const;
std::vector<std::string> getKeys (const std::string& ns) const;
std::vector<std::string> getKeys (const std::string& ns1,
const std::string& ns2) const;
bool hasParameters (void) const;
bool hasParameters (const std::string& ns) const;
bool hasParameters (const std::string& ns1,
const std::string& ns2) const;
int getParameterCount (void) const;
int getParameterCount (const std::string& ns) const;
int getParameterCount (const std::string& ns1,
const std::string& ns2) const;
void setPrefix (const std::string& value);
std::string getPrefix (void) const;
std::ostream& printXml (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlAsGlobal (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
void setOrigin (const std::string& key,
HumdrumToken* tok);
void setOrigin (const std::string& key,
HumdrumToken& tok);
void setOrigin (const std::string& ns2, const std::string& key,
HumdrumToken* tok);
void setOrigin (const std::string& ns2, const std::string& key,
HumdrumToken& tok);
void setOrigin (const std::string& ns1, const std::string& ns2,
const std::string& parameter,
HumdrumToken* tok);
void setOrigin (const std::string& ns1, const std::string& ns2,
const std::string& parameter,
HumdrumToken& tok);
HumdrumToken* getOrigin (const std::string& key) const;
HumdrumToken* getOrigin (const std::string& ns2,
const std::string& key) const;
HumdrumToken* getOrigin (const std::string& ns1,
const std::string& ns2,
const std::string& parameter) const;
protected:
void initializeParameters (void);
std::vector<std::string> getKeyList (const std::string& keys) const;
private:
MapNNKV* parameters;
std::string prefix;
friend std::ostream& operator<<(std::ostream& out, const HumHash& hash);
};
class HumNum {
public:
HumNum (void);
HumNum (int value);
HumNum (int numerator, int denominator);
HumNum (const HumNum& rat);
HumNum (const std::string& ratstring);
HumNum (const char* ratstring);
~HumNum ();
bool isNegative (void) const;
bool isPositive (void) const;
bool isZero (void) const;
bool isNonZero (void) const;
bool isNonNegative (void) const;
bool isNonPositive (void) const;
bool isInfinite (void) const;
bool isFinite (void) const;
bool isNaN (void) const;
bool isInteger (void) const;
bool isPowerOfTwo (void) const;
double getFloat (void) const;
double toFloat (void) const { return getFloat(); }
int getInteger (double round = 0.0) const;
int toInteger (double round = 0.0) const {
return getInteger(round); }
int getNumerator (void) const;
int getDenominator (void) const;
HumNum getRemainder (void) const;
void setValue (int numerator);
void setValue (int numerator, int denominator);
void setValue (const std::string& ratstring);
void setValue (const char* ratstring);
void invert (void);
HumNum getAbs (void) const;
HumNum& makeAbs (void);
HumNum& operator= (const HumNum& value);
HumNum& operator= (int value);
HumNum& operator+= (const HumNum& value);
HumNum& operator+= (int value);
HumNum& operator-= (const HumNum& value);
HumNum& operator-= (int value);
HumNum& operator*= (const HumNum& value);
HumNum& operator*= (int value);
HumNum& operator/= (const HumNum& value);
HumNum& operator/= (int value);
HumNum operator- (void) const;
HumNum operator+ (const HumNum& value) const;
HumNum operator+ (int value) const;
HumNum operator- (const HumNum& value) const;
HumNum operator- (int value) const;
HumNum operator* (const HumNum& value) const;
HumNum operator* (int value) const;
HumNum operator/ (const HumNum& value) const;
HumNum operator/ (int value) const;
bool operator== (const HumNum& value) const;
bool operator== (double value) const;
bool operator== (int value) const;
bool operator!= (const HumNum& value) const;
bool operator!= (double value) const;
bool operator!= (int value) const;
bool operator< (const HumNum& value) const;
bool operator< (double value) const;
bool operator< (int value) const;
bool operator<= (const HumNum& value) const;
bool operator<= (double value) const;
bool operator<= (int value) const;
bool operator> (const HumNum& value) const;
bool operator> (double value) const;
bool operator> (int value) const;
bool operator>= (const HumNum& value) const;
bool operator>= (double value) const;
bool operator>= (int value) const;
std::ostream& printFraction (std::ostream& = std::cout) const;
std::ostream& printMixedFraction (std::ostream& out = std::cout,
std::string separator = "_") const;
std::ostream& printList (std::ostream& out) const;
protected:
void reduce (void);
int gcdIterative (int a, int b);
int gcdRecursive (int a, int b);
private:
int top;
int bot;
};
std::ostream& operator<<(std::ostream& out, const HumNum& number);
template <typename A>
std::ostream& operator<<(std::ostream& out, const std::vector<A>& v);
class HumRegex {
public:
HumRegex (void);
HumRegex (const std::string& exp,
const std::string& options = "");
~HumRegex ();
// setting persistent options for regular expression contruction
void setIgnoreCase (void);
bool getIgnoreCase (void);
void unsetIgnoreCase (void);
// setting persistent search/match options
void setGlobal (void);
bool getGlobal (void);
void unsetGlobal (void);
// replacing
std::string& replaceDestructive (std::string& input, const std::string& replacement,
const std::string& exp);
std::string& replaceDestructive (std::string& input, const std::string& replacement,
const std::string& exp,
const std::string& options);
std::string replaceCopy (const std::string& input,
const std::string& replacement,
const std::string& exp);
std::string replaceCopy (const std::string& input,
const std::string& replacement,
const std::string& exp,
const std::string& options);
std::string& replaceDestructive (std::string* input, const std::string& replacement,
const std::string& exp);
std::string& replaceDestructive (std::string* input, const std::string& replacement,
const std::string& exp,
const std::string& options);
std::string replaceCopy (std::string* input, const std::string& replacement,
const std::string& exp);
std::string replaceCopy (std::string* input, const std::string& replacement,
const std::string& exp,
const std::string& options);
std::string& tr (std::string& input, const std::string& from,
const std::string& to);
// matching (full-string match)
bool match (const std::string& input, const std::string& exp);
bool match (const std::string& input, const std::string& exp,
const std::string& options);
bool match (const std::string* input, const std::string& exp);
bool match (const std::string* input, const std::string& exp,
const std::string& options);
// searching
// http://www.cplusplus.com/reference/regex/regex_search
int search (const std::string& input, const std::string& exp);
int search (const std::string& input, const std::string& exp,
const std::string& options);
int search (const std::string& input, int startindex,
const std::string& exp);
int search (const std::string& input, int startindex,
const std::string& exp,
const std::string& options);
int search (std::string* input, const std::string& exp);
int search (std::string* input, const std::string& exp,
const std::string& options);
int search (std::string* input, int startindex,
const std::string& exp);
int search (std::string* input, int startindex,
const std::string& exp,
const std::string& options);
int getMatchCount (void);
std::string getMatch (int index);
int getMatchInt (int index);
double getMatchDouble (int index);
std::string getPrefix (void);
std::string getSuffix (void);
int getMatchStartIndex (int index = 0);
int getMatchEndIndex (int index = 0);
int getMatchLength (int index = 0);
// token lists:
bool split (std::vector<std::string>& entries,
const std::string& buffer,
const std::string& separator);
protected:
std::regex_constants::syntax_option_type
getTemporaryRegexFlags(const std::string& sflags);
std::regex_constants::match_flag_type
getTemporarySearchFlags(const std::string& sflags);
private:
// m_regex: stores the regular expression to use as a default.
//
// http://en.cppreference.com/w/cpp/regex/basic_regex
// .assign(string) == set the regular expression.
// operator= == set the regular expression.
// .flags() == return syntax_option_type used to construct.
std::regex m_regex;
// m_matches: stores the matches from a search:
//
// http://en.cppreference.com/w/cpp/regex/match_results
// .empty() == check if match was successful.
// .size() == number of matches.
// .length(i) == return length of a submatch.
// .position(i) == return start index of submatch in search string.
// .str(i) == return string of submatch.
// operator[i] == return submatch.
// .prefix
// .suffix
// .begin() == start of submatch list.
// .end() == end of submatch list.
std::smatch m_matches;
// m_regexflags: store default settings for regex processing
// http://en.cppreference.com/w/cpp/regex/syntax_option_type
// http://en.cppreference.com/w/cpp/regex/basic_regex
// /usr/local/Cellar/gcc49/4.9.3/include/c++/4.9.3/bits/regex_constants.h
//
// Options (in the namespace std::regex_constants):
// icase == Ignore case.
// nosubs == Don't collect submatches.
// optimize == Make matching faster, but construction slower.
// collate == locale character ranges.
// multiline == C++17 only.
//
// Only one of the following can be given. EMCAScript will be
// used by default if none specified.
// EMCAScript == Use EMCAScript regex syntax.
// basic == Use basic POSIX syntax.
// extended == Use extended POSIX syntax.
// awk == Use awk POSIX syntax.
// grep == Use grep POSIX syntax.
// egrep == Use egrep POSIX syntax.
std::regex_constants::syntax_option_type m_regexflags;
// m_flags: store default settings for regex processing
// http://www.cplusplus.com/reference/regex/regex_search
// match_default == clear all options.
// match_not_bol == not beginning of line.
// match_not_eol == not end of line.
// match_not_bow == not beginning of word for \b.
// match_not_eow == not end of word for \b.
// match_any == any match acceptable if more than 1 possible..
// match_not_null == empty sequence does note match.
// match_continuous ==
// match_prev_avail ==
// format_default == same as match_default.
std::regex_constants::match_flag_type m_searchflags;
};
enum signifier_type {
signifier_unknown,
signifier_link,
signifier_above,
signifier_below
};
class HumSignifier {
public:
HumSignifier (void);
HumSignifier (const std::string& rdfline);
~HumSignifier ();
bool parseSignifier (const std::string& rdfline);
void clear (void);
std::string getSignifier (void);
std::string getDefinition (void);
std::string getParameter (const std::string& key);
bool isKernLink (void);
bool isKernAbove (void);
bool isKernBelow (void);
private:
std::string m_exinterp;
std::string m_signifier;
std::string m_definition;
int m_sigtype = signifier_type::signifier_unknown;
std::map<std::string, std::string> m_parameters;
};
class HumSignifiers {
public:
HumSignifiers (void);
~HumSignifiers ();
void clear (void);
bool addSignifier (const std::string& rdfline);
bool hasKernLinkSignifier (void);
std::string getKernLinkSignifier (void);
bool hasKernAboveSignifier (void);
std::string getKernAboveSignifier (void);
bool hasKernBelowSignifier (void);
std::string getKernBelowSignifier (void);
int getSignifierCount(void);
HumSignifier* getSignifier(int index);
private:
std::vector<HumSignifier*> m_signifiers;
int m_kernLinkIndex = -1;
int m_kernAboveIndex = -1;
int m_kernBelowIndex = -1;
};
class HumdrumLine;
class HumdrumToken;
class HumAddress {
public:
HumAddress (void);
HumAddress (HumAddress& address);
~HumAddress ();
HumAddress& operator= (const HumAddress& address);
int getLineIndex (void) const;
int getLineNumber (void) const;
int getFieldIndex (void) const;
const HumdrumToken& getDataType (void) const;
const std::string& getSpineInfo (void) const;
int getTrack (void) const;
int getSubtrack (void) const;
int getSubtrackCount (void) const;
std::string getTrackString (std::string separator = ".") const;
HumdrumLine* getLine (void) const;
HumdrumLine* getOwner (void) const { return getLine(); }
bool hasOwner (void) const;
protected:
void setOwner (HumdrumLine* aLine);
void setFieldIndex (int fieldlindex);
void setSpineInfo (const std::string& spineinfo);
void setTrack (int aTrack, int aSubtrack);
void setTrack (int aTrack);
void setSubtrack (int aSubtrack);
void setSubtrackCount (int aSubtrack);
private:
// fieldindex: This is the index of the token in the HumdrumLine
// which owns this token.
int m_fieldindex;
// spining: This is the spine position of the token. A simple spine
// position is an integer, starting with "1" for the first spine
// of the file (left-most spine). When the spine splits, "(#)a"
// is wrapped around the left-subspine's spine info, and "(#)b"
// around the right-subspine's info. Merged spines will add a space
// between the two or more merged spines information, such as
// "(#)a (#)b" for two sub-spines merged into a single spine again.
// But in this case there is a spine info simplification which will
// convert "(#)a (#)b" into "#" where # is the original spine number.
// Other more complicated mergers may be simplified in the future.
std::string m_spining;
// track: This is the track number of the spine. It is the first
// number found in the spineinfo string.
int m_track;
// subtrack: This is the subtrack number for the spine. When a spine
// is not split, it will be 0, if the spine has been split with *^,
// then the left-subspine will be in subtrack 1 and the right-spine
// will be subtrack 2. If subspines are exchanged with *x, then their
// subtrack assignments will also change.
int m_subtrack;
// subtrackcount: The number of currently active subtracks tokens
// on the owning HumdrumLine (in the same track). The subtrack range
// is from 1 (if there is only a primary spine), to a larger number.
// if subtrackcount is 0, then the variable is not set, or there are
// no tokens in the track (such as for global comments).
int m_subtrackcount;
// owner: This is the line which manages the given token.
HumdrumLine* m_owner;
friend class HumdrumToken;
friend class HumdrumLine;
friend class HumdrumFile;
};
class HumParamSet {
public:
HumParamSet (void);
HumParamSet (const std::string& token);
HumParamSet (HTp token);
~HumParamSet ();
const std::string& getNamespace1 (void);
const std::string& getNamespace2 (void);
std::string getNamespace (void);
void setNamespace1 (const std::string& name);
void setNamespace2 (const std::string& name);
void setNamespace (const std::string& name);
void setNamespace (const std::string& name1, const std::string& name2);
void clear (void);
int getCount (void);
const std::string& getParameterName (int index);
const std::string& getParameterValue (int index);
int addParameter (const std::string& name, const std::string& value);
int setParameter (const std::string& name, const std::string& value);
void readString (const std::string& text);
std::ostream& printXml (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
private:
std::string m_ns1;
std::string m_ns2;
std::vector<std::pair<std::string, std::string>> m_parameters;
};
std::ostream& operator<<(std::ostream& out, HumParamSet* hps);
std::ostream& operator<<(std::ostream& out, HumParamSet& hps);
class _HumInstrument {
public:
_HumInstrument (void) { humdrum = ""; name = ""; gm = 0; }
~_HumInstrument () { humdrum = ""; name = ""; gm = 0; }
std::string humdrum;
std::string name;
int gm;
};
class HumInstrument {
public:
HumInstrument (void);
HumInstrument (const std::string& Hname);
~HumInstrument ();
std::string getName (void);
std::string getName (const std::string& Hname);
std::string getHumdrum (void);
int getGM (void);
int getGM (const std::string& Hname);
void setHumdrum (const std::string& Hname);
int setGM (const std::string& Hname, int aValue);
private:
int index;
static std::vector<_HumInstrument> data;
static int classcount;
protected:
void initialize (void);
void afi (const char* humdrum_name, int midinum,
const char* EN_name);
int find (const std::string& Hname);
void sortData (void);
static int data_compare_by_humdrum_name(const void* a, const void* b);
};
///////////////////////////////////////////////////////////////////////////
//
// General MIDI instrument definitions
//
#define CH_1 0
#define CH_2 1
#define CH_3 2
#define CH_4 3
#define CH_5 4
#define CH_6 5
#define CH_7 6
#define CH_8 7
#define CH_9 8
#define CH_10 9
#define CH_11 10
#define CH_12 11
#define CH_13 12
#define CH_14 13
#define CH_15 14
#define CH_16 15
#define GM_PIANO(X) (0+(X))
#define GM_ACOUSTIC_GRAND_PIANO (0)
#define GM_BRIGHT_ACOUSTIC_PIANO (1)
#define GM_ELECTRIC_GRAND_PIANO (1)
#define GM_HONKYTONK_PIANO (2)
#define GM_HONKY_TONK_PIANO (3)
#define GM_ELECTRIC_PIANO_1 (4)
#define GM_ELECTRIC_PIANO_2 (5)
#define GM_HARPSICHORD (6)
#define GM_CLAVI (7)
#define GM_CHROMATIC(X) (8+(X))
#define GM_CELESTA (8)
#define GM_GLOCKENSPIEL (9)
#define GM_MUSIC_BOX (10)
#define GM_VIBRAPHONE (11)
#define GM_MARIMBA (12)
#define GM_XYLOPHONE (13)
#define GM_TUBULAR_BELLS (14)
#define GM_DULCIMER (15)
#define GM_ORGAN(X) (16+(X))
#define GM_DRAWBAR_ORGAN (16)
#define GM_PERCUSSIVE_ORGAN (17)
#define GM_ROCK_ORGAN (18)
#define GM_CHURCH_ORGAN (19)
#define GM_REED_ORGAN (20)
#define GM_ACCORDION (21)
#define GM_HARMONICA (22)
#define GM_TANGO_ACCORDION (23)
#define GM_GUITAR(X) (24+(X))
#define GM_ACOUSTIC_GUITAR_NYLON (24)
#define GM_ACOUSTIC_GUITAR_STEEL (25)
#define GM_ELECTRIC_GUITAR_JAZZ (26)
#define GM_ELECTRIC_GUITAR_CLEAN (27)
#define GM_ELECTRIC_GUITAR_MUTED (28)
#define GM_OVERDRIVEN_GUITAR (29)
#define GM_DISTORTION_GUITAR (30)
#define GM_GUITAR_HARMONICS (31)
#define GM_BASS(X) (32+(X))
#define GM_ACOUSTIC_BASS (32)
#define GM_ELECTRIC_BASS_FINGER (33)
#define GM_ELECTRIC_BASS_PICK (34)
#define GM_FRETLESS_BASS (35)
#define GM_SLAP_BASS_1 (36)
#define GM_SLAP_BASS_2 (37)
#define GM_SYNTH_BASS_1 (38)
#define GM_SYNTH_BASS_2 (39)
#define GM_STRINGS(X) (40+(X))
#define GM_VIOLIN (40)
#define GM_VIOLA (41)
#define GM_CELLO (42)
#define GM_CONTRABASS (43)
#define GM_TREMOLO_STRINGS (44)
#define GM_PIZZACATO_STRINGS (45)
#define GM_ORCHESTRAL_HARP (46)
#define GM_TIMPANI (47)
#define GM_ENSEMBLE(X) (48+(X))
#define GM_STRING_ENSEMBLE_1 (48)
#define GM_STRING_ENSEMBLE_2 (49)
#define GM_SYNTHSTRINGS_1 (50)
#define GM_SYNTHSTRINGS_2 (51)
#define GM_CHOIR_AAHS (52)
#define GM_VOICE_OOHS (53)
#define GM_SYNTH_VOICE (54)
#define GM_ORCHESTRA_HIT (55)
#define GM_BRASS(X) (56+(X))
#define GM_TRUMPET (56)
#define GM_TROMBONE (57)
#define GM_TUBA (58)
#define GM_MUTED_TRUMPED (59)
#define GM_FRENCH_HORN (60)
#define GM_BRASS_SECTION (61)
#define GM_SYNTHBRASS_1 (62)
#define GM_SYNTHBRASS_2 (63)
#define GM_REED(X) (64+(X))
#define GM_SOPRANO_SAX (64)
#define GM_ALTO_SAX (65)
#define GM_TENOR_SAX (66)
#define GM_BARITONE_SAX (67)
#define GM_OBOE (68)
#define GM_ENGLISH_HORN (69)
#define GM_BASSOON (70)
#define GM_CLARINET (71)
#define GM_PIPE(X) (72+(X))
#define GM_PICCOLO (72)
#define GM_FLUTE (73)
#define GM_RECORDER (74)
#define GM_PAN_FLUTE (75)
#define GM_BLOWN_BOTTLE (76)
#define GM_SHAKUHACHI (77)
#define GM_WHISTLE (78)
#define GM_OCARINA (79)
#define GM_LEAD(X) (80+(X))
#define GM_LEAD_SQUARE (80)
#define GM_LEAD_SAWTOOTH (81)
#define GM_LEAD_CALLIOPE (82)
#define GM_LEAD_CHIFF (83)
#define GM_LEAD_CHARANG (84)
#define GM_LEAD_VOICE (85)
#define GM_LEAD_FIFTHS (86)
#define GM_LEAD_BASS (87)
#define GM_PAD(X) (88+(X))
#define GM_PAD_NEW_AGE (88)
#define GM_PAD_WARM (89)
#define GM_PAD_POLYSYNTH (90)
#define GM_PAD_CHOIR (91)
#define GM_PAD_BOWED (92)
#define GM_PAD_METALLIC (93)
#define GM_PAD_HALO (94)
#define GM_PAD_SWEEP (95)
#define GM_FX(X) (96+(X))
#define GM_FX_TRAIN (96)
#define GM_FX_SOUNDTRACK (97)
#define GM_FX_CRYSTAL (98)
#define GM_FX_ATMOSPHERE (99)
#define GM_FX_BRIGHTNESS (100)
#define GM_FX_GOBLINS (101)
#define GM_FX_ECHOES (102)
#define GM_FX_SCI_FI (103)
#define GM_ETHNIC(X) (104+(X))
#define GM_SITAR (104)
#define GM_BANJO (105)
#define GM_SHAMISEN (106)
#define GM_KOTO (107)
#define GM_KALIMBA (108)
#define GM_BAGPIPE (109)
#define GM_FIDDLE (110)
#define GM_SHANAI (111)
#define GM_PERCUSSION(X) (112+(X))
#define GM_TINKLE_BELL (112)
#define GM_AGOGO (113)
#define GM_STEEL_DRUMS (114)
#define GM_WOODBLOCKS (115)
#define GM_TAIKO_DRUM (116)
#define GM_MELODIC_DRUM (117)
#define GM_SYNTH_DRUM (118)
#define GM_REVERSE_CYMBAL (119)
#define GM_SOUNDEFFECT(X) (120+(X))
#define GM_GUITAR_FRET_NOISE (120)
#define GM_BREATH_NOISE (121)
#define GM_SEASHORE (122)
#define GM_BIRD_TWEET (123)
#define GM_TELEPHONE_RING (124)
#define GM_HELICOPTER (125)
#define GM_APPLAUSE (126)
#define GM_GUNSHOT (127)
//
// Percussion instruments on channel 10
//
#define GM_ACOUSTIC_BASS_DRUM (35)
#define GM_BASS_DRUM_1 (36)
#define GM_SIDE_STICK (37)
#define GM_ACOUSTIC_SNARE (38)
#define GM_HAND_CLAP (39)
#define GM_ELECTRIC_SNARE (40)
#define GM_LOW_FLOOR_TOM (41)
#define GM_CLOSED_HI_HAT (42)
#define GM_HIGH_FLOOR_TOM (43)
#define GM_PEDAL_HI_HAT (44)
#define GM_LOW_TOM (45)
#define GM_OPEN_HI_HAT (46)
#define GM_LOW_MID_TOM (47)
#define GM_HIGH_MID_TOM (48)
#define GM_CRASH_CYMBAL_1 (49)
#define GM_HIGH_TOM (50)
#define GM_RIDE_CYMBAL_1 (51)
#define GM_CHINESE_CYMBAL (52)
#define GM_RIDE_BELL (53)
#define GM_TAMBOURINE (54)
#define GM_SPLASH_CYMBAL (55)
#define GM_COWBELL (56)
#define GM_CRASH_CYMBAL_2 (57)
#define GM_VIBRASLAP (58)
#define GM_RIDE_CYMBAL_2 (59)
#define GM_HI_BONGO (60)
#define GM_LOW_BONGO (61)
#define GM_MUTE_HI_CONGA (62)
#define GM_OPEN_HI_CONGA (63)
#define GM_LOW_CONGA (64)
#define GM_HIGH_TIMBALE (65)
#define GM_LOW_TIMBALE (66)
#define GM_HIGH_AGOGO (67)
#define GM_LOW_AGOGO (68)
#define GM_CABASA (69)
#define GM_MARACAS (70)
#define GM_SHORT_WHISTLE (71)
#define GM_LONG_WHISTLE (72)
#define GM_SHORT_GUIRO (73)
#define GM_LONG_GUIRO (74)
#define GM_CLAVES (75)
#define GM_HI_WOOD_BLOCK (76)
#define GM_LOW_WOOD_BLOCK (77)
#define GM_MUTE_CUICA (78)
#define GM_OPEN_CUICA (79)
#define GM_MUTE_TRIANGLE (80)
#define GM_OPEN_TRIANGLE (81)
typedef HumdrumLine* HLp;
class HumdrumLine : public std::string, public HumHash {
public:
HumdrumLine (void);
HumdrumLine (const std::string& aString);
HumdrumLine (const char* aString);
HumdrumLine (HumdrumLine& line);
HumdrumLine (HumdrumLine& line, void* owner);
~HumdrumLine ();
HumdrumLine& operator= (HumdrumLine& line);
bool isComment (void) const;
bool isCommentLocal (void) const;
bool isLocalComment (void) const { return isCommentLocal(); }
bool isCommentGlobal (void) const;
bool isReference (void) const;
bool isSignifier (void) const;
std::string getReferenceKey (void) const;
std::string getReferenceValue (void) const;
bool isGlobalComment (void) const { return isCommentGlobal(); }
bool isExclusive (void) const;
bool isExclusiveInterpretation (void) const { return isExclusive(); }
bool isTerminator (void) const;
bool isInterp (void) const;
bool isInterpretation (void) const { return isInterp(); }
bool isBarline (void) const;
bool isData (void) const;
bool isAllNull (void) const;
bool isAllRhythmicNull (void) const;
bool isEmpty (void) const;
bool isBlank (void) const { return isEmpty(); }
bool isManipulator (void) const;
bool hasSpines (void) const;
bool isGlobal (void) const;
HTp token (int index) const;
void getTokens (std::vector<HTp>& list);
int getTokenCount (void) const;
int getFieldCount (void) const { return getTokenCount(); }
std::string getTokenString (int index) const;
bool equalChar (int index, char ch) const;
char getChar (int index) const;
bool isKernBoundaryStart (void) const;
bool isKernBoundaryEnd (void) const;
std::ostream& printSpineInfo (std::ostream& out = std::cout);
std::ostream& printTrackInfo (std::ostream& out = std::cout);
std::ostream& printDataTypeInfo (std::ostream& out = std::cout);
std::ostream& printDurationInfo (std::ostream& out = std::cout);
std::ostream& printCsv (std::ostream& out = std::cout,
const std::string& separator = ",");
std::ostream& printXml (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlParameterInfo(std::ostream& out, int level,
const std::string& indent);
std::ostream& printGlobalXmlParameterInfo(std::ostream& out, int level,
const std::string& indent);
std::string getXmlId (const std::string& prefix = "") const;
std::string getXmlIdPrefix (void) const;
void createLineFromTokens (void);
int getLineIndex (void) const;
int getLineNumber (void) const;
HumdrumFile* getOwner (void);
void setText (const std::string& text);
std::string getText (void);
HumNum getDuration (void) const;
HumNum getDurationFromStart (void) const;
HumNum getDurationToEnd (void) const;
HumNum getDurationFromBarline (void) const;
HumNum getDurationToBarline (void) const;
HumNum getBarlineDuration (void) const;
HumNum getDuration (HumNum scale) const;
HumNum getDurationFromStart (HumNum scale) const;
HumNum getDurationToEnd (HumNum scale) const;
HumNum getDurationFromBarline (HumNum scale) const;
HumNum getDurationToBarline (HumNum scale) const;
HumNum getBarlineDuration (HumNum scale) const;
int getKernNoteAttacks (void);
int addLinkedParameter (HTp token);
HumNum getBeat (HumNum beatdur = "1") const;
HumNum getBeat (std::string beatrecip = "4") const;
HTp getTrackStart (int track) const;
void setLineFromCsv (const char* csv,
const std::string& separator = ",");
void setLineFromCsv (const std::string& csv,
const std::string& separator = ",");
// low-level editing functions (need to re-analyze structure after using)
void appendToken (HTp token);
void appendToken (const HumdrumToken& token);
void appendToken (const std::string& token);
void appendToken (const char* token);
void appendToken (int index, HTp token);
void appendToken (int index, const HumdrumToken& token);
void appendToken (int index, const std::string& token);
void appendToken (int index, const char* token);
void insertToken (int index, HTp token);
void insertToken (int index, const HumdrumToken& token);
void insertToken (int index, const std::string& token);
void insertToken (int index, const char* token);
void setDuration (HumNum aDur);
void setDurationFromStart (HumNum dur);
void setDurationFromBarline (HumNum dur);
void setDurationToBarline (HumNum dur);
protected:
bool analyzeTracks (std::string& err);
bool analyzeTokenDurations (std::string& err);
void setLineIndex (int index);
void clear (void);
void setOwner (void* hfile);
int createTokensFromLine (void);
void setLayoutParameters (void);
void setParameters (const std::string& pdata);
void storeGlobalLinkedParameters(void);
std::ostream& printXmlGlobalLinkedParameterInfo(std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlGlobalLinkedParameters(std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
private:
//
// State variables managed by the HumdrumLine class:
//
// m_lineindex: Used to store the index number of the HumdrumLine in
// the owning HumdrumFile object.
// This variable is filled by HumdrumFileStructure::analyzeLines().
int m_lineindex;
// m_tokens: Used to store the individual tab-separated token fields
// on a line. These are prepared automatically after reading in
// a full line of text (which is accessed throught the string parent
// class). If the full line is changed, the tokens are not updated
// automatically -- use createTokensFromLine(). Likewise the full
// text line is not updated if any tokens are changed -- use
// createLineFromTokens() in that case. The second case is more
// useful: you can read in a HumdrumFile, tweak the tokens, then
// reconstruct the full line and print out again.
// This variable is filled by HumdrumFile::read().
// The contents of this vector should be deleted when deconstructing
// a HumdrumLine object.
std::vector<HumdrumToken*> m_tokens;
// m_duration: This is the "duration" of a line. The duration is
// equal to the minimum time unit of all durational tokens on the
// line. This also includes null tokens when the duration of a
// previous note in a previous spine is ending on the line, so it is
// not just the minimum duration on the line.
// This variable is filled by HumdrumFileStructure::analyzeRhythm().
HumNum m_duration;
// m_durationFromStart: This is the cumulative duration of all lines
// prior to this one in the owning HumdrumFile object. For example,
// the first notes in a score start at time 0, If the duration of the
// first data line is 1 quarter note, then the durationFromStart for
// the second line will be 1 quarter note.
// This variable is filled by HumdrumFileStructure::analyzeRhythm().
HumNum m_durationFromStart;
// m_durationFromBarline: This is the cumulative duration from the
// last barline to the current data line.
// This variable is filled by HumdrumFileStructure::analyzeMeter().
HumNum m_durationFromBarline;
// m_durationToBarline: This is the duration from the start of the
// current line to the next barline in the owning HumdrumFile object.
// This variable is filled by HumdrumFileStructure::analyzeMeter().
HumNum m_durationToBarline;
// m_linkedParameters: List of Humdrum tokens which are parameters
// (mostly only layout parameters at the moment)
std::vector<HTp> m_linkedParameters;
// owner: This is the HumdrumFile which manages the given line.
void* m_owner;
friend class HumdrumFileBase;
friend class HumdrumFileStructure;
friend class HumdrumFileContent;
friend class HumdrumFile;
};
std::ostream& operator<< (std::ostream& out, HumdrumLine& line);
std::ostream& operator<< (std::ostream& out, HumdrumLine* line);
typedef HumdrumToken* HTp;
class HumdrumToken : public std::string, public HumHash {
public:
HumdrumToken (void);
HumdrumToken (const HumdrumToken& token);
HumdrumToken (HumdrumToken* token);
HumdrumToken (const HumdrumToken& token,
HumdrumLine* owner);
HumdrumToken (HumdrumToken* token,
HumdrumLine* owner);
HumdrumToken (const char* token);
HumdrumToken (const std::string& token);
~HumdrumToken ();
bool isNull (void) const;
bool isManipulator (void) const;
bool isExclusiveInterpretation (void) const;
bool isSplitInterpretation (void) const;
bool isMergeInterpretation (void) const;
bool isExchangeInterpretation (void) const;
bool isTerminateInterpretation (void) const;
bool isAddInterpretation (void) const;
// alises for the above
bool isExclusive (void) const
{ return isExclusiveInterpretation(); }
bool isExInterp (void) const
{ return isExclusiveInterpretation(); }
bool isSplit (void) const
{ return isSplitInterpretation(); }
bool isMerge (void) const
{ return isMergeInterpretation(); }
bool isExchange (void) const
{ return isExchangeInterpretation(); }
bool isTerminate (void) const
{ return isTerminateInterpretation(); }
bool isTerminator (void) const
{ return isTerminateInterpretation(); }
bool isAdd (void) const
{ return isSplitInterpretation(); }
bool isBarline (void) const;
bool isCommentLocal (void) const;
bool isCommentGlobal (void) const;
bool isComment (void) const;
bool isData (void) const;
bool isInterpretation (void) const;
bool isNonNullData (void) const;
bool isNullData (void) const;
bool isChord (const std::string& separator = " ");
bool isLabel (void) const;
bool hasRhythm (void) const;
bool hasBeam (void) const;
bool equalTo (const std::string& pattern);
// kern-specific functions:
bool isRest (void);
bool isNote (void);
bool isSecondaryTiedNote (void);
bool isSustainedNote (void);
bool isNoteAttack (void);
bool isInvisible (void);
bool isGrace (void);
bool isClef (void);
bool isKeySignature (void);
bool isKeyDesignation (void);
bool isTimeSignature (void);
bool isMensurationSymbol (void);
bool hasSlurStart (void);
bool hasSlurEnd (void);
int hasVisibleAccidental (int subtokenIndex) const;
int hasCautionaryAccidental (int subtokenIndex) const;
bool hasLigatureBegin (void);
bool hasRectaLigatureBegin (void);
bool hasObliquaLigatureBegin (void);
bool hasLigatureEnd (void);
bool hasRectaLigatureEnd (void);
bool hasObliquaLigatureEnd (void);
char hasStemDirection (void);
HumNum getDuration (void) const;
HumNum getDuration (HumNum scale) const;
HumNum getTiedDuration (void);
HumNum getTiedDuration (HumNum scale);
HumNum getDurationNoDots (void) const;
HumNum getDurationNoDots (HumNum scale) const;
int getDots (char separator = ' ') const;
HumNum getDurationFromStart (void) const;
HumNum getDurationFromStart (HumNum scale) const;
HumNum getDurationToEnd (void) const;
HumNum getDurationToEnd (HumNum scale) const;
HumNum getDurationFromBarline (void) const;
HumNum getDurationFromBarline (HumNum scale) const;
HumNum getDurationToBarline (void) const;
HumNum getDurationToBarline (HumNum scale) const;
HumNum getBarlineDuration (void) const;
HumNum getBarlineDuration (HumNum scale) const;
HumdrumLine* getOwner (void) const;
HumdrumLine* getLine (void) const { return getOwner(); }
bool equalChar (int index, char ch) const;
HTp resolveNull (void);
void setNullResolution (HTp resolution);
int getLineIndex (void) const;
int getLineNumber (void) const;
int getFieldIndex (void) const;
int getFieldNumber (void) const;
int getTokenIndex (void) const;
int getTokenNumber (void) const;
const std::string& getDataType (void) const;
bool isDataType (const std::string& dtype) const;
bool isKern (void) const;
bool isMens (void) const;
std::string getSpineInfo (void) const;
int getTrack (void) const;
int getSubtrack (void) const;
bool noteInLowerSubtrack (void);
std::string getTrackString (void) const;
int getSubtokenCount (const std::string& separator = " ") const;
std::string getSubtoken (int index,
const std::string& separator = " ") const;
std::vector<std::string> getSubtokens (const std::string& separator = " ") const;
void replaceSubtoken (int index, const std::string& newsubtok,
const std::string& separator = " ");
void setParameters (HTp ptok);
void setParameters (const std::string& pdata, HTp ptok = NULL);
int getStrandIndex (void) const;
int getSlurStartElisionLevel (int index = 0) const;
int getSlurEndElisionLevel (int index = 0) const;
HTp getSlurStartToken (int number = 0);
HTp getSlurEndToken (int number = 0);
void storeLinkedParameters (void);
bool linkedParameterIsGlobal (int index);
std::ostream& printCsv (std::ostream& out = std::cout);
std::ostream& printXml (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printGlobalXmlParameterInfo(std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::string getXmlId (const std::string& prefix = "") const;
std::string getXmlIdPrefix (void) const;
void setText (const std::string& text);
std::string getText (void) const;
int addLinkedParameter (HTp token);
int getLinkedParameterCount (void);
HumParamSet* getLinkedParameter (int index);
HumParamSet* getLinkedParameter (void);
std::string getSlurLayoutParameter (const std::string& keyname, int subtokenindex = -1);
std::string getLayoutParameter (const std::string& category, const std::string& keyname,
int subtokenindex = -1);
std::string getLayoutParameterChord(const std::string& category,
const std::string& keyname);
std::string getLayoutParameterNote (const std::string& category,
const std::string& keyname, int subtokenindex);
std::ostream& printXmlLinkedParameterInfo(std::ostream& out, int level, const std::string& indent);
// layout parameter accessors
std::string getVisualDuration (int subtokenindex = -1);
std::string getVisualDurationChord(void);
std::string getVisualDurationNote(int subtokenindex = -1);
HumdrumToken& operator= (HumdrumToken& aToken);
HumdrumToken& operator= (const std::string& aToken);
HumdrumToken& operator= (const char* aToken);
// next/previous token functions:
int getNextTokenCount (void) const;
int getPreviousTokenCount (void) const;
HTp getNextToken (int index = 0) const;
HTp getPreviousToken (int index = 0) const;
std::vector<HTp> getNextTokens (void) const;
std::vector<HTp> getPreviousTokens (void) const;
// next/previous token on line:
HTp getNextFieldToken (void) const;
HTp getPreviousFieldToken (void) const;
int getPreviousNonNullDataTokenCount(void);
int getPreviousNNDTCount (void)
{ return getPreviousNonNullDataTokenCount(); }
HTp getPreviousNonNullDataToken(int index = 0);
HTp getPreviousNNDT (int index = 0)
{ return getPreviousNonNullDataToken(index); }
int getNextNonNullDataTokenCount(void);
int getNextNNDTCount (void)
{ return getNextNonNullDataTokenCount(); }
HTp getNextNonNullDataToken (int index = 0);
HTp getNextNNDT (int index = 0)
{ return getNextNonNullDataToken(index); }
// slur-analysis based functions:
HumNum getSlurDuration (HumNum scale = 1);
void setTrack (int aTrack, int aSubtrack);
void setTrack (int aTrack);
protected:
void setLineIndex (int lineindex);
void setFieldIndex (int fieldlindex);
void setSpineInfo (const std::string& spineinfo);
void setSubtrack (int aSubtrack);
void setSubtrackCount (int count);
void setPreviousToken (HTp aToken);
void setNextToken (HTp aToken);
void addNextNonNullToken (HTp token);
void makeForwardLink (HumdrumToken& nextToken);
void makeBackwardLink (HumdrumToken& previousToken);
void setOwner (HumdrumLine* aLine);
int getState (void) const;
void incrementState (void);
void setDuration (const HumNum& dur);
void setStrandIndex (int index);
bool analyzeDuration (std::string& err);
std::ostream& printXmlBaseInfo (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlContentInfo (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlStructureInfo(std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlParameterInfo(std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlLinkedParameters (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
private:
// address: The address contains information about the location of
// the token on a HumdrumLine and in a HumdrumFile.
HumAddress m_address;
// duration: The duration of the token. Non-rhythmic data types
// will have a negative duration (which should be interpreted
// as a zero duration--See HumdrumToken::hasRhythm()).
// Grace note will have a zero duration, even if they have a duration
// list in the token for a graphical display duration.
HumNum m_duration;
// nextTokens: This is a list of all previous tokens in the spine which
// immediately precede this token. Typically there will be one
// following token, but there can be two tokens if the current
// token is *^, and there will be zero following tokens after a
// spine terminating token (*-).
std::vector<HTp> m_nextTokens; // link to next token(s) in spine
// previousTokens: Simiar to nextTokens, but for the immediately
// follow token(s) in the data. Typically there will be one
// preceding token, but there can be multiple tokens when the previous
// line has *v merge tokens for the spine. Exclusive interpretations
// have no tokens preceding them.
std::vector<HTp> m_previousTokens; // link to last token(s) in spine
// nextNonNullTokens: This is a list of non-tokens in the spine
// that follow this one.
std::vector<HTp> m_nextNonNullTokens;
// previousNonNullTokens: This is a list of non-tokens in the spine
// that preced this one.
std::vector<HTp> m_previousNonNullTokens;
// rhycheck: Used to perfrom HumdrumFileStructure::analyzeRhythm
// recursively.
int m_rhycheck;
// strand: Used to keep track of contiguous voice connections between
// secondary spines/tracks. This is the 1-D strand index number
// (not the 2-d one).
int m_strand;
// m_nullresolve: used to point to the token that a null token
// refers to.
HTp m_nullresolve;
// m_linkedParameters: List of Humdrum tokens which are parameters
// (mostly only layout parameters at the moment).
std::vector<HTp> m_linkedParameters;
// m_linkedParameter: A single parameter encoded in the text of the
// token.
HumParamSet* m_linkedParameter = NULL;
friend class HumdrumLine;
friend class HumdrumFileBase;
friend class HumdrumFileStructure;
friend class HumdrumFileContent;
friend class HumdrumFile;
};
std::ostream& operator<<(std::ostream& out, const HumdrumToken& token);
std::ostream& operator<<(std::ostream& out, HTp token);
std::ostream& printSequence(std::vector<std::vector<HTp> >& sequence, std::ostream& out=std::cout);
std::ostream& printSequence(std::vector<HTp>& sequence, std::ostream& out = std::cout);
// The following options are used for get[Primary]TrackTokens:
// * OPT_PRIMARY => only extract primary subspine/subtrack.
// * OPT_NOEMPTY => don't include null tokens in extracted list if all
// extracted subspines contains null tokens.
// Includes null interpretations and comments as well.
// * OPT_NONULL => don't include any null tokens in extracted list.
// * OPT_NOINTERP => don't include interprtation tokens.
// * OPT_NOMANIP => don't include spine manipulators (*^, *v, *x, *+,
// but still keep ** and *0).
// * OPT_NOCOMMENT => don't include comment tokens.
// * OPT_NOGLOBALS => don't include global records (global comments, reference
// records, and empty lines). In other words, only return
// a list of tokens from lines which hasSpines() it true.
// * OPT_NOREST => don't include **kern rests.
// * OPT_NOTIE => don't include **kern secondary tied notes.
//
// Compound options:
// * OPT_DATA (OPT_NOMANIP | OPT_NOCOMMENT | OPT_NOGLOBAL)
// Only data tokens (including barlines)
// * OPT_ATTACKS (OPT_DATA | OPT_NOREST | OPT_NOTIE | OPT_NONULL)
// Only note-attack tokens (when etracting **kern data)
//
#define OPT_PRIMARY 0x001
#define OPT_NOEMPTY 0x002
#define OPT_NONULL 0x004
#define OPT_NOINTERP 0x008
#define OPT_NOMANIP 0x010
#define OPT_NOCOMMENT 0x020
#define OPT_NOGLOBAL 0x040
#define OPT_NOREST 0x080
#define OPT_NOTIE 0x100
#define OPT_DATA (OPT_NOMANIP | OPT_NOCOMMENT | OPT_NOGLOBAL)
#define OPT_ATTACKS (OPT_DATA | OPT_NOREST | OPT_NOTIE | OPT_NONULL)
class TokenPair {
public:
TokenPair(void) { clear(); }
~TokenPair() { clear(); }
void clear(void) {
first = NULL;
last = NULL;
}
HTp first;
HTp last;
};
bool sortTokenPairsByLineIndex(const TokenPair& a, const TokenPair& b);
class HumdrumFileBase : public HumHash {
public:
HumdrumFileBase (void);
HumdrumFileBase (HumdrumFileBase& infile);
HumdrumFileBase (const std::string& contents);
HumdrumFileBase (std::istream& contents);
~HumdrumFileBase ();
HumdrumFileBase& operator= (HumdrumFileBase& infile);
bool read (std::istream& contents);
bool read (const char* filename);
bool read (const std::string& filename);
bool readCsv (std::istream& contents,
const std::string& separator=",");
bool readCsv (const char* contents,
const std::string& separator=",");
bool readCsv (const std::string& contents,
const std::string& separator=",");
bool readString (const char* contents);
bool readString (const std::string& contents);
bool readStringCsv (const char* contents,
const std::string& separator=",");
bool readStringCsv (const std::string& contents,
const std::string& separator=",");
bool isValid (void);
std::string getParseError (void) const;
bool isQuiet (void) const;
void setQuietParsing (void);
void setNoisyParsing (void);
void clear (void);
bool parse (std::istream& contents)
{ return read(contents); }
bool parse (const char* contents)
{ return readString(contents); }
bool parse (const std::string& contents)
{ return readString(contents); }
bool parseCsv (std::istream& contents,
const std::string& separator = ",")
{ return readCsv(contents); }
bool parseCsv (const char* contents,
const std::string& separator = ",")
{ return readStringCsv(contents); }
bool parseCsv (const std::string& contents,
const std::string& separator = ",")
{ return readStringCsv(contents); }
void setXmlIdPrefix (const std::string& value);
std::string getXmlIdPrefix (void);
void setFilename (const std::string& filename);
std::string getFilename (void);
void setSegmentLevel (int level = 0);
int getSegmentLevel (void);
std::ostream& printSegmentLabel (std::ostream& out);
std::ostream& printNonemptySegmentLabel(std::ostream& out);
HumdrumLine& operator[] (int index);
HumdrumLine* getLine (int index);
int getLineCount (void) const;
HTp token (int lineindex, int fieldindex);
std::string token (int lineindex, int fieldindex,
int subtokenindex,
const std::string& separator = " ");
int getMaxTrack (void) const;
int getTrackCount (void) const
{ return getMaxTrack(); }
int getSpineCount (void) const
{ return getMaxTrack(); }
int getMeasureNumber (int line);
std::ostream& printSpineInfo (std::ostream& out = std::cout);
std::ostream& printDataTypeInfo (std::ostream& out = std::cout);
std::ostream& printTrackInfo (std::ostream& out = std::cout);
std::ostream& printCsv (std::ostream& out = std::cout,
const std::string& separator = ",");
std::ostream& printFieldNumber (int fieldnum, std::ostream& out);
std::ostream& printFieldIndex (int fieldind, std::ostream& out);
void usage (const std::string& command);
void example (void);
HTp getTrackStart (int track) const;
void getSpineStopList (std::vector<HTp>& spinestops);
HTp getSpineStart (int spine) const
{ return getTrackStart(spine+1); }
void getSpineStartList (std::vector<HTp>& spinestarts);
void getSpineStartList (std::vector<HTp>& spinestarts,
const std::string& exinterp);
void getKernSpineStartList (std::vector<HTp>& spinestarts);
std::vector<HTp> getKernSpineStartList (void);
int getExinterpCount (const std::string& exinterp);
void getSpineStartList (std::vector<HTp>& spinestarts,
const std::vector<std::string>& exinterps);
void getTrackStartList (std::vector<HTp>& spinestarts)
{ return getSpineStartList(spinestarts); }
void getTrackStartList (std::vector<HTp>& spinestarts,
const std::string& exinterp)
{ return getSpineStartList(spinestarts, exinterp); }
void getTrackStartList (std::vector<HTp>& spinestarts,
const std::vector<std::string>& exinterps)
{ return getSpineStartList(spinestarts, exinterps); }
int getTrackEndCount (int track) const;
HTp getTrackEnd (int track, int subtrack) const;
void createLinesFromTokens (void);
void appendLine (const char* line);
void appendLine (const std::string& line);
void appendLine (HumdrumLine* line);
void push_back (const char* line)
{ appendLine(line); }
void push_back (const std::string& line)
{ appendLine(line); }
void push_back (HumdrumLine* line)
{ appendLine(line); }
void insertLine (int index, const char* line);
void insertLine (int index, const std::string& line);
void insertLine (int index, HumdrumLine* line);
void deleteLine (int index);
// void adjustMergeSpineLines (void);
HumdrumLine* back (void);
void makeBooleanTrackList (std::vector<bool>& spinelist,
const std::string& spinestring);
bool analyzeBaseFromLines (void);
bool analyzeBaseFromTokens (void);
std::vector<HumdrumLine*> getReferenceRecords(void);
// spine analysis functionality:
void getTrackSequence (std::vector<std::vector<HTp> >& sequence,
HTp starttoken, int options);
void getTrackSequence (std::vector<std::vector<HTp> >& sequence,
int track, int options);
void getPrimaryTrackSequence (std::vector<HTp>& sequence,
int track, int options);
void getSpineSequence (std::vector<std::vector<HTp> >& sequence,
HTp starttoken, int options);
void getSpineSequence (std::vector<std::vector<HTp> >& sequence,
int spine, int options);
void getPrimarySpineSequence (std::vector<HTp>& sequence,
int spine, int options);
void getTrackSeq (std::vector<std::vector<HTp> >& sequence,
HTp starttoken, int options)
{ getTrackSequence(sequence, starttoken, options); }
void getTrackSeq (std::vector<std::vector<HTp> >& sequence,
int track, int options)
{ getTrackSequence(sequence, track, options); }
void getPrimaryTrackSeq (std::vector<HTp>& sequence,
int track, int options)
{getPrimaryTrackSequence(sequence, track, options); }
// functions defined in HumdrumFileBase-net.cpp:
static std::string getUriToUrlMapping (const std::string& uri);
void readFromHumdrumUri (const std::string& humaddress);
void readFromJrpUri (const std::string& jrpaddress);
void readFromHttpUri (const std::string& webaddress);
static void readStringFromHttpUri (std::stringstream& inputdata,
const std::string& webaddress);
protected:
static int getChunk (int socket_id,
std::stringstream& inputdata,
char* buffer, int bufsize);
static int getFixedDataSize (int socket_id,
int datalength,
std::stringstream& inputdata,
char* buffer, int bufsize);
static void prepare_address (struct sockaddr_in *address,
const std::string& hostname,
unsigned short int port);
static int open_network_socket (const std::string& hostname,
unsigned short int port);
protected:
bool analyzeTokens (void);
bool analyzeSpines (void);
bool analyzeLinks (void);
bool analyzeTracks (void);
bool analyzeLines (void);
bool adjustSpines (HumdrumLine& line,
std::vector<std::string>& datatype,
std::vector<std::string>& sinfo);
std::string getMergedSpineInfo (std::vector<std::string>& info,
int starti, int extra);
bool stitchLinesTogether (HumdrumLine& previous,
HumdrumLine& next);
void addToTrackStarts (HTp token);
bool analyzeNonNullDataTokens (void);
void addUniqueTokens (std::vector<HTp>& target,
std::vector<HTp>& source);
bool processNonNullDataTokensForTrackForward(HTp starttoken,
std::vector<HTp> ptokens);
bool processNonNullDataTokensForTrackBackward(HTp starttoken,
std::vector<HTp> ptokens);
bool setParseError (std::stringstream& err);
bool setParseError (const std::string& err);
bool setParseError (const char* format, ...);
// void fixMerges (int linei);
protected:
// m_lines: an array representing lines from the input file.
// The contents of lines must be deallocated when deconstructing object.
std::vector<HumdrumLine*> m_lines;
// m_filename: name of the file which was loaded.
std::string m_filename;
// m_segementlevel: segment level (e.g., work/movement)
int m_segmentlevel;
// m_trackstarts: list of addresses of the exclusive interpreations
// in the file. The first element in the list is reserved, so the
// number of tracks (primary spines) is equal to one less than the
// size of this list.
std::vector<HTp> m_trackstarts;
// m_trackends: list of the addresses of the spine terminators in the
// file. It is possible that spines can split and their subspines do not
// merge before termination; therefore, the ends are stored in
// a 2d array. The first dimension is the track number, and the second
// dimension is the list of terminators.
std::vector<std::vector<HTp> > m_trackends;
// m_barlines: list of barlines in the data. If the first measures is
// a pickup measure, then the first entry will not point to the first
// starting exclusive interpretation line rather than to a barline.
std::vector<HumdrumLine*> m_barlines;
// Maybe also add "measures" which are complete metrical cycles.
// m_ticksperquarternote: this is the number of tick
int m_ticksperquarternote;
// m_idprefix: an XML id prefix used to avoid id collisions when
// includeing multiple HumdrumFile XML in a single group.
std::string m_idprefix;
// m_strands1d: one-dimensional list of spine strands.
std::vector<TokenPair> m_strand1d;
// m_strands2d: two-dimensional list of spine strands.
std::vector<std::vector<TokenPair> > m_strand2d;
// m_quietParse: Set to true if error messages should not be
// printed to the console when reading.
bool m_quietParse;
// m_parseError: Set to true if a read is successful.
std::string m_parseError;
// m_displayError: Used to print error message only once.
bool m_displayError;
// m_signifiers: Used to keep track of !!!RDF records.
HumSignifiers m_signifiers;
public:
// Dummy functions to allow the HumdrumFile class's inheritance
// to be shifted between HumdrumFileContent (the top-level default),
// HumdrumFileStructure (mid-level interface), or HumdrumFileBase
// (low-level interface).
//
// HumdrumFileStructure public functions:
//
bool readNoRhythm (std::istream& infile) { return read(infile); };
bool readNoRhythm (const char* filename) {return read(filename);};
bool readNoRhythm (const std::string& filename) {return read(filename);};
bool readStringNoRhythm(const char* contents) {return read(contents);};
bool readStringNoRhythm(const std::string& contents) {return read(contents);};
HumNum getScoreDuration (void) const { return 0; };
std::ostream& printDurationInfo (std::ostream& out=std::cout) {return out;};
int tpq (void) { return 0; }
int getBarlineCount (void) const { return 0; }
HumdrumLine* getBarline (int index) const { return NULL;};
HumNum getBarlineDuration (int index) const { return 0; };
HumNum getBarlineDurationFromStart(int index) const { return 0; };
HumNum getBarlineDurationToEnd (int index) const { return 0; };
// HumdrumFileContent public functions:
// to be added later
};
std::ostream& operator<<(std::ostream& out, HumdrumFileBase& infile);
class HumdrumFileStructure : public HumdrumFileBase {
public:
HumdrumFileStructure (void);
HumdrumFileStructure (const std::string& filename);
HumdrumFileStructure (std::istream& contents);
~HumdrumFileStructure ();
bool hasFilters (void);
// TSV reading functions:
bool read (std::istream& contents);
bool read (const char* filename);
bool read (const std::string& filename);
bool readString (const char* contents);
bool readString (const std::string& contents);
bool parse(std::istream& contents) { return read(contents); }
bool parse(const char* contents) { return readString(contents); }
bool parse(const std::string& contents) { return readString(contents); }
bool readNoRhythm (std::istream& contents);
bool readNoRhythm (const char* filename);
bool readNoRhythm (const std::string& filename);
bool readStringNoRhythm (const char* contents);
bool readStringNoRhythm (const std::string& contents);
// CSV reading functions:
bool readCsv (std::istream& contents,
const std::string& separator=",");
bool readCsv (const char* filename,
const std::string& separator=",");
bool readCsv (const std::string& filename,
const std::string& separator=",");
bool readStringCsv (const char* contents,
const std::string& separator=",");
bool readStringCsv (const std::string& contents,
const std::string& separator=",");
bool parseCsv(std::istream& contents, const std::string& separator = ",")
{ return readCsv(contents, separator); }
bool parseCsv(const char* contents, const std::string& separator = ",")
{ return readStringCsv(contents, separator); }
bool parseCsv(const std::string& contents, const std::string& separator = ",")
{ return readStringCsv(contents, separator); }
bool readNoRhythmCsv (std::istream& contents,
const std::string& separator = ",");
bool readNoRhythmCsv (const char* filename,
const std::string& separator = ",");
bool readNoRhythmCsv (const std::string& filename,
const std::string& separator = ",");
bool readStringNoRhythmCsv (const char* contents,
const std::string& separator = ",");
bool readStringNoRhythmCsv (const std::string& contents,
const std::string& separator = ",");
// rhythmic analysis related functionality:
HumNum getScoreDuration (void) const;
std::ostream& printDurationInfo (std::ostream& out = std::cout);
int tpq (void);
// strand functionality:
HTp getStrandStart (int index) const;
HTp getStrandEnd (int index) const;
HTp getStrandStart (int sindex, int index) const;
HTp getStrandEnd (int sindex, int index) const;
int getStrandCount (void) const;
int getStrandCount (int spineindex) const;
void resolveNullTokens (void);
HTp getStrand (int index) const
{ return getStrandStart(index); }
HTp getStrand (int sindex, int index) const
{ return getStrandStart(sindex, index); }
// barline/measure functionality:
int getBarlineCount (void) const;
HumdrumLine* getBarline (int index) const;
HumNum getBarlineDuration (int index) const;
HumNum getBarlineDurationFromStart (int index) const;
HumNum getBarlineDurationToEnd (int index) const;
bool analyzeStructure (void);
bool analyzeStrands (void);
// signifier access
std::string getKernLinkSignifier (void);
std::string getKernAboveSignifier (void);
std::string getKernBelowSignifier (void);
protected:
bool analyzeRhythm (void);
bool assignRhythmFromRecip (HTp spinestart);
bool analyzeMeter (void);
bool analyzeTokenDurations (void);
bool analyzeGlobalParameters (void);
bool analyzeLocalParameters (void);
bool analyzeDurationsOfNonRhythmicSpines(void);
HumNum getMinDur (std::vector<HumNum>& durs,
std::vector<HumNum>& durstate);
bool getTokenDurations (std::vector<HumNum>& durs,
int line);
bool cleanDurs (std::vector<HumNum>& durs,
int line);
bool decrementDurStates (std::vector<HumNum>& durs,
HumNum linedur, int line);
bool assignDurationsToTrack (HTp starttoken,
HumNum startdur);
bool prepareDurations (HTp token, int state,
HumNum startdur);
bool setLineDurationFromStart (HTp token, HumNum dursum);
bool analyzeRhythmOfFloatingSpine (HTp spinestart);
bool analyzeNullLineRhythms (void);
void fillInNegativeStartTimes (void);
void assignLineDurations (void);
void assignStrandsToTokens (void);
std::set<HumNum> getNonZeroLineDurations (void);
std::set<HumNum> getPositiveLineDurations (void);
void processLocalParametersForStrand(int index);
bool processLocalParametersForTrack (HTp starttok, HTp current);
void checkForLocalParameters (HTp token, HTp current);
bool assignDurationsToNonRhythmicTrack(HTp endtoken, HTp ptoken);
void analyzeSpineStrands (std::vector<TokenPair>& ends,
HTp starttok);
void analyzeSignifiers (void);
};
class HumdrumFileContent : public HumdrumFileStructure {
public:
HumdrumFileContent (void);
HumdrumFileContent (const std::string& filename);
HumdrumFileContent (std::istream& contents);
~HumdrumFileContent ();
bool analyzeSlurs (void);
bool analyzeMensSlurs (void);
bool analyzeKernSlurs (void);
bool analyzeKernTies (void);
bool analyzeKernAccidentals (void);
bool analyzeRScale (void);
// in HumdrumFileContent-rest.cpp
void analyzeRestPositions (void);
void assignImplicitVerticalRestPositions (HTp kernstart);
void checkForExplicitVerticalRestPositions (void);
// in HumdrumFileContent-stem.cpp
bool analyzeKernStemLengths (void);
// in HumdrumFileContent-metlev.cpp
void getMetricLevels (std::vector<double>& output, int track = 0,
double undefined = NAN);
// in HumdrumFileContent-timesig.cpp
void getTimeSigs (std::vector<std::pair<int, HumNum> >& output,
int track = 0);
template <class DATATYPE>
bool prependDataSpine (std::vector<DATATYPE> data,
const std::string& null = ".",
const std::string& exinterp = "**data",
bool recalcLine = true);
template <class DATATYPE>
bool appendDataSpine (std::vector<DATATYPE> data,
const std::string& null = ".",
const std::string& exinterp = "**data",
bool recalcLine = true);
template <class DATATYPE>
bool insertDataSpineBefore (int nexttrack,
std::vector<DATATYPE> data,
const std::string& null = ".",
const std::string& exinterp = "**data",
bool recalcLine = true);
template <class DATATYPE>
bool insertDataSpineAfter (int prevtrack,
std::vector<DATATYPE> data,
const std::string& null = ".",
const std::string& exinterp = "**data",
bool recalcLine = true);
// in HumdrumFileContent-ottava.cpp
void analyzeOttavas (void);
// in HumdrumFileContent-note.cpp
void analyzeCrossStaffStemDirections (void);
void analyzeCrossStaffStemDirections (HTp kernstart);
protected:
bool analyzeKernSlurs (HTp spinestart, std::vector<HTp>& slurstarts,
std::vector<HTp>& slurends,
std::vector<std::pair<HTp, HTp>>& labels,
std::vector<int>& endings,
const std::string& linksig = "");
bool analyzeKernTies (std::vector<std::pair<HTp, int>>& linkedtiestarts,
std::vector<std::pair<HTp, int>>& linkedtieends,
std::string& linkSignifier);
void fillKeySignature (std::vector<int>& states,
const std::string& keysig);
void resetDiatonicStatesWithKeySignature(std::vector<int>& states,
std::vector<int>& signature);
void linkSlurEndpoints (HTp slurstart, HTp slurend);
void linkTieEndpoints (HTp tiestart, int startindex,
HTp tieend, int endindex);
bool isLinkedSlurBegin (HTp token, int index, const std::string& pattern);
bool isLinkedSlurEnd (HTp token, int index, const std::string& pattern);
void createLinkedSlurs (std::vector<HTp>& linkstarts, std::vector<HTp>& linkends);
void assignVerticalRestPosition(HTp first, HTp second, int baseline);
int getRestPositionAboveNotes (HTp rest, std::vector<int>& vpos);
int getRestPositionBelowNotes (HTp rest, std::vector<int>& vpos);
void setRestOnCenterStaffLine (HTp rest, int baseline);
bool checkRestForVerticalPositioning(HTp rest, int baseline);
bool analyzeKernStemLengths (HTp stok, HTp etok, std::vector<std::vector<int>>& centerlines);
void getBaselines (std::vector<std::vector<int>>& centerlines);
void createLinkedTies (std::vector<std::pair<HTp, int>>& starts,
std::vector<std::pair<HTp, int>>& ends);
void checkCrossStaffStems (HTp token, std::string& above, std::string& below);
void checkDataForCrossStaffStems(HTp token, std::string& above, std::string& below);
void prepareStaffAboveNoteStems (HTp token);
void prepareStaffBelowNoteStems (HTp token);
};
//
// Templates:
//
//////////////////////////////
//
// HumdrumFileContent::prependDataSpine -- prepend a data spine
// to the file. Returns true if successful; false otherwise.
//
// data == numeric or string data to print
// null == if the data is converted to a string is equal to this
// string then set the data spine content to a null token, ".".
// default is ".".
// exinterp == the exterp string to use. Default is "**data".
// recalcLine == boolean for whether or not to recalculate line string.
// Default is true;
//
template <class DATATYPE>
bool HumdrumFileContent::prependDataSpine(std::vector<DATATYPE> data,
const std::string& null, const std::string& exinterp, bool recalcLine) {
if ((int)data.size() != getLineCount()) {
return false;
}
std::string ex;
if (exinterp.find("**") == 0) {
ex = exinterp;
} else if (exinterp.find("*") == 0) {
ex = "*" + exinterp;
} else {
ex = "**" + exinterp;
}
if (ex.size() <= 2) {
ex += "data";
}
std::stringstream ss;
HumdrumFileContent& infile = *this;
HumdrumLine* line;
for (int i=0; i<infile.getLineCount(); i++) {
line = infile.getLine(i);
if (!line->hasSpines()) {
continue;
}
if (line->isExclusive()) {
line->insertToken(0, ex);
} else if (line->isTerminator()) {
line->insertToken(0, "*-");
} else if (line->isInterpretation()) {
line->insertToken(0, "*");
} else if (line->isLocalComment()) {
line->insertToken(0, "!");
} else if (line->isBarline()) {
line->insertToken(0, (std::string)*infile.token(i, 0));
} else if (line->isData()) {
ss.str(std::string());
ss << data[i];
if (ss.str() == null) {
line->insertToken(0, ".");
} else if (ss.str() == "") {
line->insertToken(0, ".");
} else {
line->insertToken(0, ss.str());
}
} else{
std::cerr << "!!strange error for line " << i+1 << ":\t" << line << std::endl;
}
if (recalcLine) {
line->createLineFromTokens();
}
}
return true;
}
//////////////////////////////
//
// HumdrumFileContent::appendDataSpine -- prepend a data spine
// to the file. Returns true if successful; false otherwise.
//
// data == numeric or string data to print
// null == if the data is converted to a string is equal to this
// string then set the data spine content to a null token, ".".
// default is ".".
// exinterp == the exterp string to use. Default is "**data".
// recalcLine == boolean for whether or not to recalculate line string.
// Default is true;
//
template <class DATATYPE>
bool HumdrumFileContent::appendDataSpine(std::vector<DATATYPE> data,
const std::string& null, const std::string& exinterp, bool recalcLine) {
if ((int)data.size() != getLineCount()) {
std::cerr << "DATA SIZE DOES NOT MATCH GETLINECOUNT " << std::endl;
std::cerr << "DATA SIZE " << data.size() << "\tLINECOUNT ";
std::cerr << getLineCount() << std::endl;
return false;
}
std::string ex;
if (exinterp.find("**") == 0) {
ex = exinterp;
} else if (exinterp.find("*") == 0) {
ex = "*" + exinterp;
} else {
ex = "**" + exinterp;
}
if (ex.size() <= 2) {
ex += "data";
}
std::stringstream ss;
HumdrumFileContent& infile = *this;
HumdrumLine* line;
for (int i=0; i<infile.getLineCount(); i++) {
line = infile.getLine(i);
if (!line->hasSpines()) {
continue;
}
if (line->isExclusive()) {
line->appendToken(ex);
} else if (line->isTerminator()) {
line->appendToken("*-");
} else if (line->isInterpretation()) {
line->appendToken("*");
} else if (line->isLocalComment()) {
line->appendToken("!");
} else if (line->isBarline()) {
line->appendToken((std::string)*infile.token(i, 0));
} else if (line->isData()) {
ss.str(std::string());
ss << data[i];
if (ss.str() == null) {
line->appendToken(".");
} else if (ss.str() == "") {
line->appendToken(".");
} else {
line->appendToken(ss.str());
}
} else{
std::cerr << "!!strange error for line " << i+1 << ":\t" << line << std::endl;
}
if (recalcLine) {
line->createLineFromTokens();
}
}
return true;
}
//////////////////////////////
//
// HumdrumFileContent::insertDataSpineBefore -- prepend a data spine
// to the file before the given spine. Returns true if successful;
// false otherwise.
//
// nexttrack == track number to insert before.
// data == numeric or string data to print
// null == if the data is converted to a string is equal to this
// string then set the data spine content to a null token, ".".
// default is ".".
// exinterp == the exterp string to use. Default is "**data".
// recalcLine == boolean for whether or not to recalculate line string.
// Default is true;
//
template <class DATATYPE>
bool HumdrumFileContent::insertDataSpineBefore(int nexttrack,
std::vector<DATATYPE> data, const std::string& null, const std::string& exinterp,
bool recalcLine) {
if ((int)data.size() != getLineCount()) {
std::cerr << "DATA SIZE DOES NOT MATCH GETLINECOUNT " << std::endl;
std::cerr << "DATA SIZE " << data.size() << "\tLINECOUNT ";
std::cerr << getLineCount() << std::endl;
return false;
}
std::string ex;
if (exinterp.find("**") == 0) {
ex = exinterp;
} else if (exinterp.find("*") == 0) {
ex = "*" + exinterp;
} else {
ex = "**" + exinterp;
}
if (ex.size() <= 2) {
ex += "data";
}
std::stringstream ss;
HumdrumFileContent& infile = *this;
HumdrumLine* line;
int insertionField = -1;
int track;
for (int i=0; i<infile.getLineCount(); i++) {
line = infile.getLine(i);
if (!line->hasSpines()) {
continue;
}
insertionField = -1;
for (int j=0; j<line->getFieldCount(); j++) {
track = line->token(j)->getTrack();
if (track != nexttrack) {
continue;
}
insertionField = j;
break;
}
if (insertionField < 0) {
return false;
}
if (line->isExclusive()) {
line->insertToken(insertionField, ex);
} else if (line->isTerminator()) {
line->insertToken(insertionField, "*-");
} else if (line->isInterpretation()) {
line->insertToken(insertionField, "*");
} else if (line->isLocalComment()) {
line->insertToken(insertionField, "!");
} else if (line->isBarline()) {
line->insertToken(insertionField, (std::string)*infile.token(i, 0));
} else if (line->isData()) {
ss.str(std::string());
ss << data[i];
if (ss.str() == null) {
line->insertToken(insertionField, ".");
} else if (ss.str() == "") {
line->insertToken(insertionField, ".");
} else {
line->insertToken(insertionField, ss.str());
}
} else{
std::cerr << "!!strange error for line " << i+1 << ":\t" << line << std::endl;
}
if (recalcLine) {
line->createLineFromTokens();
}
}
return true;
}
//////////////////////////////
//
// HumdrumFileContent::insertDataSpineAfter -- appen a data spine
// to the file after the given spine. Returns true if successful;
// false otherwise.
//
// prevtrack == track number to insert after.
// data == numeric or string data to print
// null == if the data is converted to a string is equal to this
// string then set the data spine content to a null token, ".".
// default is ".".
// exinterp == the exterp string to use. Default is "**data".
// recalcLine == boolean for whether or not to recalculate line string.
// Default is true;
//
template <class DATATYPE>
bool HumdrumFileContent::insertDataSpineAfter(int prevtrack,
std::vector<DATATYPE> data, const std::string& null, const std::string& exinterp,
bool recalcLine) {
if ((int)data.size() != getLineCount()) {
std::cerr << "DATA SIZE DOES NOT MATCH GETLINECOUNT " << std::endl;
std::cerr << "DATA SIZE " << data.size() << "\tLINECOUNT ";
std::cerr << getLineCount() << std::endl;
return false;
}
std::string ex;
if (exinterp.find("**") == 0) {
ex = exinterp;
} else if (exinterp.find("*") == 0) {
ex = "*" + exinterp;
} else {
ex = "**" + exinterp;
}
if (ex.size() <= 2) {
ex += "data";
}
std::stringstream ss;
HumdrumFileContent& infile = *this;
HumdrumLine* line;
int insertionField = -1;
int track;
for (int i=0; i<infile.getLineCount(); i++) {
line = infile.getLine(i);
if (!line->hasSpines()) {
continue;
}
insertionField = -1;
for (int j = line->getFieldCount() - 1; j >= 0; j--) {
track = line->token(j)->getTrack();
if (track != prevtrack) {
continue;
}
insertionField = j;
break;
}
insertionField++;
if (insertionField < 0) {
return false;
}
if (line->isExclusive()) {
line->insertToken(insertionField, ex);
} else if (line->isTerminator()) {
line->insertToken(insertionField, "*-");
} else if (line->isInterpretation()) {
line->insertToken(insertionField, "*");
} else if (line->isLocalComment()) {
line->insertToken(insertionField, "!");
} else if (line->isBarline()) {
line->insertToken(insertionField, (std::string)*infile.token(i, 0));
} else if (line->isData()) {
ss.str(std::string());
ss << data[i];
if (ss.str() == null) {
line->insertToken(insertionField, ".");
} else if (ss.str() == "") {
line->insertToken(insertionField, ".");
} else {
line->insertToken(insertionField, ss.str());
}
} else{
std::cerr << "!!strange error for line " << i+1 << ":\t" << line << std::endl;
}
if (recalcLine) {
line->createLineFromTokens();
}
}
return true;
}
#ifndef HUMDRUMFILE_PARENT
#define HUMDRUMFILE_PARENT HumdrumFileContent
#endif
class HumdrumFile : public HUMDRUMFILE_PARENT {
public:
HumdrumFile (void);
HumdrumFile (const std::string& filename);
HumdrumFile (std::istream& filename);
~HumdrumFile ();
std::ostream& printXml (std::ostream& out = std::cout, int level = 0,
const std::string& indent = "\t");
std::ostream& printXmlParameterInfo(std::ostream& out, int level,
const std::string& indent);
};
#define GRIDREST NAN
class NoteGrid;
class NoteCell {
public:
NoteCell (NoteGrid* owner, HTp token);
~NoteCell (void) { clear(); }
double getSgnDiatonicPitch (void) { return m_b7; }
double getSgnMidiPitch (void) { return m_b12; }
double getSgnBase40Pitch (void) { return m_b40; }
double getSgnAccidental (void) { return m_accidental; }
double getSgnDiatonicPitchClass(void);
double getAbsDiatonicPitchClass(void);
double getSgnBase40PitchClass(void);
double getAbsBase40PitchClass(void);
double getAbsDiatonicPitch (void) { return fabs(m_b7); }
double getAbsMidiPitch (void) { return fabs(m_b12); }
double getAbsBase40Pitch (void) { return fabs(m_b40); }
double getAbsAccidental (void) { return fabs(m_accidental); }
HTp getToken (void) { return m_token; }
int getNextAttackIndex (void) { return m_nextAttackIndex; }
int getPrevAttackIndex (void) { return m_prevAttackIndex; }
int getCurrAttackIndex (void) { return m_currAttackIndex; }
int getSliceIndex (void) { return m_timeslice; }
int getVoiceIndex (void) { return m_voice; }
bool isAttack (void) { return m_b40>0? true:false; }
bool isRest (void);
bool isSustained (void);
std::string getAbsKernPitch (void);
std::string getSgnKernPitch (void);
double operator- (NoteCell& B);
double operator- (int B);
int getLineIndex (void);
int getFieldIndex (void);
std::ostream& printNoteInfo (std::ostream& out);
double getDiatonicIntervalToNextAttack (void);
double getDiatonicIntervalFromPreviousAttack(void);
double getMetricLevel (void);
HumNum getDurationFromStart (void);
HumNum getDuration (void);
void setMeter (int topval, HumNum botval);
int getMeterTop (void);
HumNum getMeterBottom (void);
std::vector<HTp> m_tiedtokens; // list of tied notes/rests after note attack
protected:
void clear (void);
void calculateNumericPitches(void);
void setVoiceIndex (int index) { m_voice = index; }
void setSliceIndex (int index) { m_timeslice = index; }
void setNextAttackIndex (int index) { m_nextAttackIndex = index; }
void setPrevAttackIndex (int index) { m_prevAttackIndex = index; }
void setCurrAttackIndex (int index) { m_currAttackIndex = index; }
private:
NoteGrid* m_owner; // the NoteGrid to which this cell belongs.
HTp m_token; // pointer to the note in the origina Humdrum file.
int m_voice; // index of the voice in the score the note belongs
// 0=bottom voice (HumdrumFile ordering of parts)
// column in NoteGrid.
int m_timeslice; // index for the row in NoteGrid.
double m_b7; // diatonic note number; NaN=rest; negative=sustain.
double m_b12; // MIDI note number; NaN=rest; negative=sustain.
double m_b40; // base-40 note number; NaN=rest; negative=sustain.
double m_accidental; // chromatic alteration of a diatonic pitch.
// NaN=no accidental.
int m_nextAttackIndex; // index to next note attack (or rest),
// -1 for undefined (interpred as rest).
int m_prevAttackIndex; // index to previous note attack.
int m_currAttackIndex; // index to current note attack (useful for
// finding the start of a sustained note.
int m_metertop = 0; // top number of prevailing meter signature
HumNum m_meterbot = 0; // bottom number of prevailing meter signature
friend NoteGrid;
};
class NoteGrid {
public:
NoteGrid (void) { }
NoteGrid (HumdrumFile& infile);
~NoteGrid ();
void clear (void);
bool load (HumdrumFile& infile);
NoteCell* cell (int voiceindex, int sliceindex);
int getVoiceCount (void);
int getSliceCount (void);
int getLineIndex (int sindex);
int getFieldIndex (int sindex);
void printDiatonicGrid (ostream& out);
void printMidiGrid (ostream& out);
void printBase40Grid (ostream& out);
void printRawGrid (ostream& out);
void printKernGrid (ostream& out);
double getSgnDiatonicPitch (int vindex, int sindex);
double getSgnMidiPitch (int vindex, int sindex);
double getSgnBase40Pitch (int vindex, int sindex);
string getSgnKernPitch (int vindex, int sindex);
double getAbsDiatonicPitch (int vindex, int sindex);
double getAbsMidiPitch (int vindex, int sindex);
double getAbsBase40Pitch (int vindex, int sindex);
string getAbsKernPitch (int vindex, int sindex);
bool isRest (int vindex, int sindex);
bool isSustained (int vindex, int sindex);
bool isAttack (int vindex, int sindex);
HTp getToken (int vindex, int sindex);
int getPrevAttackDiatonic (int vindex, int sindex);
int getNextAttackDiatonic (int vindex, int sindex);
void printGridInfo (ostream& out);
void printVoiceInfo (ostream& out, int vindex);
void getNoteAndRestAttacks (vector<NoteCell*>& attacks, int vindex);
double getMetricLevel (int sindex);
HumNum getNoteDuration (int vindex, int sindex);
protected:
void buildAttackIndexes (void);
void buildAttackIndex (int vindex);
private:
vector<vector<NoteCell*> > m_grid;
vector<HTp> m_kernspines;
vector<double> m_metriclevels;
HumdrumFile* m_infile;
};
class Convert {
public:
// Rhythm processing, defined in Convert-rhythm.cpp
static HumNum recipToDuration (const std::string& recip,
HumNum scale = 4,
const std::string& separator = " ");
static HumNum recipToDurationNoDots(const std::string& recip,
HumNum scale = 4,
const std::string& separator = " ");
static HumNum recipToDuration (std::string* recip,
HumNum scale = 4,
const std::string& separator = " ");
static HumNum recipToDurationNoDots(std::string* recip,
HumNum scale = 4,
const std::string& separator = " ");
static std::string durationToRecip (HumNum duration,
HumNum scale = HumNum(1,4));
static std::string durationFloatToRecip (double duration,
HumNum scale = HumNum(1,4));
// Pitch processing, defined in Convert-pitch.cpp
static std::string base40ToKern (int b40);
static int base40ToAccidental (int b40);
static int base40ToDiatonic (int b40);
static int base40ToMidiNoteNumber(int b40);
static std::string base40ToIntervalAbbr (int b40);
static int kernToOctaveNumber (const std::string& kerndata);
static int kernToOctaveNumber (HTp token)
{ return kernToOctaveNumber((std::string)*token); }
static int kernToAccidentalCount(const std::string& kerndata);
static int kernToAccidentalCount(HTp token)
{ return kernToAccidentalCount((std::string)*token); }
static int kernToDiatonicPC (const std::string& kerndata);
static int kernToDiatonicPC (HTp token)
{ return kernToDiatonicPC ((std::string)*token); }
static char kernToDiatonicUC (const std::string& kerndata);
static int kernToDiatonicUC (HTp token)
{ return kernToDiatonicUC ((std::string)*token); }
static char kernToDiatonicLC (const std::string& kerndata);
static int kernToDiatonicLC (HTp token)
{ return kernToDiatonicLC ((std::string)*token); }
static int kernToBase40PC (const std::string& kerndata);
static int kernToBase40PC (HTp token)
{ return kernToBase40PC ((std::string)*token); }
static int kernToBase12PC (const std::string& kerndata);
static int kernToBase12PC (HTp token)
{ return kernToBase12PC ((std::string)*token); }
static int kernToBase7PC (const std::string& kerndata) {
return kernToDiatonicPC(kerndata); }
static int kernToBase7PC (HTp token)
{ return kernToBase7PC ((std::string)*token); }
static int kernToBase40 (const std::string& kerndata);
static int kernToBase40 (HTp token)
{ return kernToBase40 ((std::string)*token); }
static int kernToBase12 (const std::string& kerndata);
static int kernToBase12 (HTp token)
{ return kernToBase12 ((std::string)*token); }
static int kernToBase7 (const std::string& kerndata);
static int kernToBase7 (HTp token)
{ return kernToBase7 ((std::string)*token); }
static int kernToMidiNoteNumber (const std::string& kerndata);
static int kernToMidiNoteNumber(HTp token)
{ return kernToMidiNoteNumber((std::string)*token); }
static std::string kernToScientificPitch(const std::string& kerndata,
std::string flat = "b",
std::string sharp = "#",
std::string separator = "");
static std::string kernToSciPitch (const std::string& kerndata,
std::string flat = "b",
std::string sharp = "#",
std::string separator = "")
{ return kernToScientificPitch(kerndata, flat, sharp, separator); }
static std::string kernToSP (const std::string& kerndata,
std::string flat = "b",
std::string sharp = "#",
std::string separator = "")
{ return kernToScientificPitch(kerndata, flat, sharp, separator); }
static int pitchToWbh (int dpc, int acc, int octave,
int maxacc);
static void wbhToPitch (int& dpc, int& acc, int& octave,
int maxacc, int wbh);
static int kernClefToBaseline (const std::string& input);
static int kernClefToBaseline (HTp input);
static std::string base40ToTrans (int base40);
static int transToBase40 (const std::string& input);
static int base40IntervalToLineOfFifths(int trans);
static std::string keyNumberToKern (int number);
static int base7ToBase40 (int base7);
static int base40IntervalToDiatonic(int base40interval);
// **mens, white mensual notation, defiend in Convert-mens.cpp
static bool isMensRest (const std::string& mensdata);
static bool isMensNote (const std::string& mensdata);
static bool hasLigatureBegin (const std::string& mensdata);
static bool hasRectaLigatureBegin(const std::string& mensdata);
static bool hasObliquaLigatureBegin(const std::string& mensdata);
static bool hasLigatureEnd (const std::string& mensdata);
static bool hasRectaLigatureEnd (const std::string& mensdata);
static bool hasObliquaLigatureEnd(const std::string& mensdata);
static bool getMensStemDirection (const std::string& mensdata);
static HumNum mensToDuration (const std::string& mensdata,
HumNum scale = 4,
const std::string& separator = " ");
static std::string mensToRecip (const std::string& mensdata,
HumNum scale = 4,
const std::string& separator = " ");
static HumNum mensToDurationNoDots(const std::string& mensdata,
HumNum scale = 4,
const std::string& separator = " ");
// Harmony processing, defined in Convert-harmony.cpp
static std::vector<int> minorHScaleBase40(void);
static std::vector<int> majorScaleBase40 (void);
static int keyToInversion (const std::string& harm);
static int keyToBase40 (const std::string& key);
static std::vector<int> harmToBase40 (HTp harm, const std::string& key) {
return harmToBase40(*harm, key); }
static std::vector<int> harmToBase40 (HTp harm, HTp key) {
return harmToBase40(*harm, *key); }
static std::vector<int> harmToBase40 (const std::string& harm, const std::string& key);
static std::vector<int> harmToBase40 (const std::string& harm, int keyroot, int keymode);
static void makeAdjustedKeyRootAndMode(const std::string& secondary,
int& keyroot, int& keymode);
static int chromaticAlteration(const std::string& content);
// data-type specific (other than pitch/rhythm),
// defined in Convert-kern.cpp
static bool isKernRest (const std::string& kerndata);
static bool isKernNote (const std::string& kerndata);
static bool isKernNoteAttack (const std::string& kerndata);
static bool hasKernSlurStart (const std::string& kerndata);
static bool hasKernSlurEnd (const std::string& kerndata);
static int getKernSlurStartElisionLevel(const std::string& kerndata, int index);
static int getKernSlurEndElisionLevel (const std::string& kerndata, int index);
static char hasKernStemDirection (const std::string& kerndata);
static bool isKernSecondaryTiedNote (const std::string& kerndata);
static std::string getKernPitchAttributes(const std::string& kerndata);
// String processing, defined in Convert-string.cpp
static std::vector<std::string> splitString (const std::string& data,
char separator = ' ');
static void replaceOccurrences (std::string& source,
const std::string& search,
const std::string& replace);
static std::string repeatString (const std::string& pattern, int count);
static std::string encodeXml (const std::string& input);
static std::string getHumNumAttributes (const HumNum& num);
static std::string trimWhiteSpace (const std::string& input);
static bool startsWith (const std::string& input,
const std::string& searchstring);
static bool contains(const std::string& input, const std::string& pattern);
static bool contains(const std::string& input, char pattern);
static bool contains(std::string* input, const std::string& pattern);
static bool contains(std::string* input, char pattern);
static void makeBooleanTrackList(std::vector<bool>& spinelist,
const std::string& spinestring,
int maxtrack);
// Mathematical processing, defined in Convert-math.cpp
static int getLcm (const std::vector<int>& numbers);
static int getGcd (int a, int b);
static void primeFactors (std::vector<int>& output, int n);
static double nearIntQuantize (double value,
double delta = 0.00001);
static double significantDigits (double value, int digits);
static bool isNaN (double value);
static double pearsonCorrelation (const std::vector<double> &x, const std::vector<double> &y);
static double standardDeviation (const std::vector<double>& x);
static int romanNumeralToInteger(const std::string& roman);
};
// SliceType is a list of various Humdrum line types. Groupings are
// segmented by categories which are prefixed with an underscore.
// For example Notes are in the _Duration group, since they have
// non-zero durations. Notes and Gracenotes are in the _Data group.
// The indentation shows the various types of groups.
//
enum class SliceType {
Notes = 1,
_Duration,
GraceNotes,
_Data,
Measures,
_Measure,
Clefs,
Transpositions,
KeyDesignations,
KeySigs,
TimeSigs,
MeterSigs,
Tempos,
Labels,
LabelAbbrs,
Ottavas,
_RegularInterpretation,
Exclusives,
Terminators,
Manipulators,
_Manipulator,
_Interpretation,
Layouts,
LocalComments,
_Spined,
GlobalComments,
GlobalLayouts,
ReferenceRecords,
_Other,
Invalid
};
// MeasureType is a list of the style types for a measure (ending type for now)
enum class MeasureStyle {
Plain,
RepeatBackward,
RepeatForward,
RepeatBoth,
Double,
Final
};
class MxmlMeasure;
class MxmlEvent;
class MxmlPart {
public:
MxmlPart (void);
~MxmlPart ();
void clear (void);
void enableStems (void);
bool readPart (const string& id, xml_node partdef,
xml_node part);
bool addMeasure (xml_node mel);
bool addMeasure (xpath_node mel);
int getMeasureCount (void) const;
MxmlMeasure* getMeasure (int index) const;
long getQTicks (void) const;
int setQTicks (long value);
MxmlMeasure* getPreviousMeasure (MxmlMeasure* measure) const;
HumNum getDuration (void) const;
void allocateSortedEvents (void);
void setPartNumber (int number);
int getPartNumber (void) const;
int getPartIndex (void) const;
int getStaffCount (void) const;
int getVerseCount (void) const;
int getVerseCount (int staffindex) const;
string getCaesura (void) const;
int getHarmonyCount (void) const;
void trackStaffVoices (int staffnum, int voicenum);
void printStaffVoiceInfo (void);
void prepareVoiceMapping (void);
int getVoiceIndex (int voicenum);
int getStaffIndex (int voicenum);
bool hasEditorialAccidental(void) const;
bool hasDynamics (void) const;
void parsePartInfo (xml_node partdeclaration);
string getPartName (void) const;
string getPartAbbr (void) const;
string cleanSpaces (const string& input);
bool hasOrnaments (void) const;
private:
void receiveStaffNumberFromChild (int staffnum, int voicenum);
void receiveVerseCount (int count);
void receiveVerseCount (int staffnum, int count);
void receiveHarmonyCount (int count);
void receiveEditorialAccidental (void);
void receiveDynamic (void);
void receiveCaesura (const string& letter);
void receiveOrnament (void);
protected:
vector<MxmlMeasure*> m_measures;
vector<long> m_qtick;
int m_partnum;
int m_maxstaff;
vector<int> m_verseCount;
int m_harmonyCount;
bool m_editorialAccidental;
bool m_stems = false;
bool m_has_dynamics = false;
string m_partname;
string m_partabbr;
string m_caesura;
bool m_hasOrnaments = false;
// m_staffvoicehist: counts of staff and voice numbers.
// staff=0 is used for items such as measures.
// voice=0 is used for nonduration items such as harmony.
vector<vector<int> > m_staffvoicehist;
vector<pair<int, int> > m_voicemapping; // voicenum -> (staff, voiceindex)
friend MxmlMeasure;
friend MxmlEvent;
};
class GridSide {
public:
GridSide(void);
~GridSide();
int getVerseCount (void);
HTp getVerse (int index);
void setVerse (int index, HTp token);
void setVerse (int index, const std::string& token);
int getHarmonyCount (void);
void setHarmony (HTp token);
void setHarmony (const std::string& token);
void detachHarmony (void);
HTp getHarmony (void);
int getDynamicsCount (void);
void setDynamics (HTp token);
void setDynamics (const std::string& token);
void detachDynamics (void);
HTp getDynamics (void);
private:
std::vector<HumdrumToken*> m_verses;
HumdrumToken* m_dynamics = NULL;
HumdrumToken* m_harmony = NULL;
};
std::ostream& operator<<(std::ostream& output, GridSide* side);
class GridStaff : public std::vector<GridVoice*>, public GridSide {
public:
GridStaff(void);
~GridStaff();
GridVoice* setTokenLayer (int layerindex, HTp token, HumNum duration);
void setNullTokenLayer (int layerindex, SliceType type, HumNum nextdur);
void appendTokenLayer (int layerindex, HTp token, HumNum duration,
const std::string& spacer = " ");
int getMaxVerseCount (void);
string getString (void);
};
std::ostream& operator<<(std::ostream& output, GridStaff* staff);
class GridPart : public std::vector<GridStaff*>, public GridSide {
public:
GridPart(void);
~GridPart();
};
std::ostream& operator<<(std::ostream& output, GridPart* part);
std::ostream& operator<<(std::ostream& output, GridPart& part);
class GridSlice;
class HumGrid;
class GridMeasure : public std::list<GridSlice*> {
public:
GridMeasure(HumGrid* owner);
~GridMeasure();
GridSlice* addTempoToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addTimeSigToken(const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addKeySigToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addClefToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addTransposeToken(const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addLabelToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxpart,
int maxstaff);
GridSlice* addLabelAbbrToken(const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxpart,
int maxstaff);
GridSlice* addDataToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff);
GridSlice* addGraceToken (const std::string& tok, HumNum timestamp,
int part, int staff, int voice, int maxstaff,
int gracenumber);
GridSlice* addGlobalLayout(const std::string& tok, HumNum timestamp);
GridSlice* addGlobalComment(const std::string& tok, HumNum timestamp);
GridSlice* appendGlobalLayout(const std::string& tok, HumNum timestamp);
bool transferTokens (HumdrumFile& outfile, bool recip,
bool addbar, int startbarnum = 0);
HumGrid* getOwner (void);
void setOwner (HumGrid* owner);
HumNum getDuration (void);
void setDuration (HumNum duration);
HumNum getTimestamp (void);
void setTimestamp (HumNum timestamp);
HumNum getTimeSigDur (void);
void setTimeSigDur (HumNum duration);
MeasureStyle getStyle (void) { return m_style; }
MeasureStyle getBarStyle (void) { return getStyle(); }
void setStyle (MeasureStyle style) { m_style = style; }
void setBarStyle (MeasureStyle style) { setStyle(style); }
void setFinalBarlineStyle(void) { setStyle(MeasureStyle::Final); }
void setRepeatEndStyle(void) { setStyle(MeasureStyle::RepeatBackward); }
void setRepeatBackwardStyle(void) { setStyle(MeasureStyle::RepeatBackward); }
bool isDouble(void)
{return m_style == MeasureStyle::Double;}
bool isFinal(void)
{return m_style == MeasureStyle::Final;}
bool isRepeatBackward(void)
{ return m_style == MeasureStyle::RepeatBackward; }
bool isRepeatForward(void)
{ return m_style == MeasureStyle::RepeatForward; }
bool isRepeatBoth(void)
{ return m_style == MeasureStyle::RepeatBoth; }
void addLayoutParameter(GridSlice* slice, int partindex, const std::string& locomment);
void addDynamicsLayoutParameters(GridSlice* slice, int partindex, const std::string& locomment);
bool isInvisible(void);
bool isSingleChordMeasure(void);
bool isMonophonicMeasure(void);
GridSlice* getLastSpinedSlice(void);
GridSlice* getFirstSpinedSlice(void);
protected:
void appendInitialBarline(HumdrumFile& infile, int startbarnum = 0);
private:
HumGrid* m_owner;
HumNum m_duration;
HumNum m_timestamp;
HumNum m_timesigdur;
MeasureStyle m_style;
};
std::ostream& operator<<(std::ostream& output, GridMeasure& measure);
std::ostream& operator<<(std::ostream& output, GridMeasure* measure);
class HumGrid;
class GridSlice : public std::vector<GridPart*> {
public:
GridSlice(GridMeasure* measure, HumNum timestamp, SliceType type,
int partcount = 0);
GridSlice(GridMeasure* measure, HumNum timestamp, SliceType type,
const GridSlice& slice);
GridSlice(GridMeasure* measure, HumNum timestamp, SliceType type,
GridSlice* slice);
~GridSlice();
bool isNoteSlice(void) { return m_type == SliceType::Notes; }
bool isGraceSlice(void) { return m_type == SliceType::GraceNotes; }
bool isMeasureSlice(void) { return m_type == SliceType::Measures; }
bool isClefSlice(void) { return m_type == SliceType::Clefs; }
bool isLabelSlice(void) { return m_type == SliceType::Labels; }
bool isLabelAbbrSlice(void) { return m_type == SliceType::LabelAbbrs; }
bool isTransposeSlice(void) { return m_type == SliceType::Transpositions; }
bool isKeySigSlice(void) { return m_type == SliceType::KeySigs; }
bool isKeyDesignationSlice(void){ return m_type == SliceType::KeyDesignations; }
bool isTimeSigSlice(void) { return m_type == SliceType::TimeSigs; }
bool isTempoSlice(void) { return m_type == SliceType::Tempos; }
bool isMeterSigSlice(void) { return m_type == SliceType::MeterSigs; }
bool isManipulatorSlice(void) { return m_type==SliceType::Manipulators; }
bool isLayoutSlice(void) { return m_type == SliceType::Layouts; }
bool isLocalLayoutSlice(void) { return m_type == SliceType::Layouts; }
bool isInvalidSlice(void) { return m_type == SliceType::Invalid; }
bool isGlobalComment(void) { return m_type == SliceType::GlobalComments; }
bool isGlobalLayout(void) { return m_type == SliceType::GlobalLayouts; }
bool isReferenceRecord(void) { return m_type == SliceType::ReferenceRecords; }
bool isOttavaRecord(void) { return m_type == SliceType::Ottavas; }
bool isInterpretationSlice(void);
bool isDataSlice(void);
bool hasSpines(void);
SliceType getType(void) { return m_type; }
void transferTokens (HumdrumFile& outfile, bool recip);
void initializePartStaves (std::vector<MxmlPart>& partdata);
void initializeBySlice (GridSlice* slice);
void initializeByStaffCount(int staffcount);
HumNum getDuration (void);
void setDuration (HumNum duration);
HumNum getTimestamp (void);
void setTimestamp (HumNum timestamp);
void setOwner (HumGrid* owner);
HumGrid* getOwner (void);
HumNum getMeasureDuration (void);
HumNum getMeasureTimestamp(void);
GridMeasure* getMeasure (void);
void invalidate (void);
void transferSides (HumdrumLine& line, GridStaff& sides,
const std::string& empty, int maxvcount,
int maxhcount);
void transferSides (HumdrumLine& line, GridPart& sides,
int partindex, const std::string& empty,
int maxvcount, int maxhcount,
int maxdcount);
int getVerseCount (int partindex, int staffindex);
int getHarmonyCount (int partindex, int staffindex = -1);
int getDynamicsCount (int partindex, int staffindex = -1);
void addToken (const std::string& tok, int parti, int staffi, int voicei);
protected:
HTp createRecipTokenFromDuration (HumNum duration);
private:
HumGrid* m_owner;
GridMeasure* m_measure;
HumNum m_timestamp;
HumNum m_duration;
SliceType m_type;
};
std::ostream& operator<<(std::ostream& output, GridSlice* slice);
class GridVoice {
public:
GridVoice(void);
GridVoice(HTp token, HumNum duration);
GridVoice(const char* token, HumNum duration);
GridVoice(const std::string& token, HumNum duration);
~GridVoice();
bool isTransfered (void);
HTp getToken (void) const;
void setToken (HTp token);
void setToken (const std::string& token);
void setToken (const char* token);
bool isNull (void) const;
void setDuration (HumNum duration);
HumNum getDuration (void) const;
HumNum getDurationToNext (void) const;
HumNum getDurationToPrev (void) const;
void setDurationToPrev (HumNum dur);
void incrementDuration (HumNum duration);
void forgetToken (void);
std::string getString (void);
protected:
void setTransfered (bool state);
private:
HTp m_token;
HumNum m_nextdur;
HumNum m_prevdur;
bool m_transfered;
friend class GridSlice;
};
std::ostream& operator<<(std::ostream& output, GridVoice* voice);
std::ostream& operator<<(std::ostream& output, GridVoice& voice);
class HumGrid : public std::vector<GridMeasure*> {
public:
HumGrid(void);
~HumGrid();
void enableRecipSpine (void);
bool transferTokens (HumdrumFile& outfile, int startbarnum = 0);
int getHarmonyCount (int partindex);
int getDynamicsCount (int partindex);
int getVerseCount (int partindex, int staffindex);
bool hasDynamics (int partindex);
void setDynamicsPresent (int partindex);
void setHarmonyPresent (int partindex);
void setVerseCount (int partindex, int staffindex, int count);
void setHarmonyCount (int partindex, int count);
void removeRedundantClefChanges (void);
void removeSibeliusIncipit (void);
bool hasPickup (void);
GridMeasure* addMeasureToBack (void);
int getPartCount (void);
int getStaffCount (int partindex);
void deleteMeasure (int index);
protected:
void calculateGridDurations (void);
void insertExclusiveInterpretationLine (HumdrumFile& outfile);
void insertDataTerminationLine (HumdrumFile& outfile);
void appendMeasureLine (HumdrumFile& outfile,
GridSlice& slice);
void insertPartIndications (HumdrumFile& outfile);
void insertStaffIndications (HumdrumFile& outfile);
void addNullTokens (void);
void addNullTokensForGraceNotes (void);
void addNullTokensForClefChanges (void);
void addNullTokensForLayoutComments(void);
void FillInNullTokensForGraceNotes(GridSlice* graceslice, GridSlice* lastnote,
GridSlice* nextnote);
void FillInNullTokensForLayoutComments(GridSlice* layoutslice, GridSlice* lastnote,
GridSlice* nextnote);
void FillInNullTokensForClefChanges (GridSlice* clefslice,
GridSlice* lastnote, GridSlice* nextnote);
void adjustClefChanges (void);
bool buildSingleList (void);
void extendDurationToken (int slicei, int parti,
int staffi, int voicei);
GridVoice* getGridVoice(int slicei, int parti, int staffi, int voicei);
void addMeasureLines (void);
void addLastMeasure (void);
bool manipulatorCheck (void);
GridSlice* manipulatorCheck (GridSlice* ice1, GridSlice* ice2);
void cleanupManipulators (void);
void cleanManipulator (std::vector<GridSlice*>& newslices,
GridSlice* curr);
GridSlice* checkManipulatorExpand (GridSlice* curr);
GridSlice* checkManipulatorContract(GridSlice* curr);
void transferMerges (GridStaff* oldstaff,
GridStaff* oldlaststaff,
GridStaff* newstaff,
GridStaff* newlaststaff, int pindex,
int sindex);
void transferOtherParts (GridSlice* oldline, GridSlice* newline, int maxpart);
void insertExInterpSides (HumdrumLine* line, int part,
int staff);
void insertSideTerminals (HumdrumLine* line, int part,
int staff);
void insertSidePartInfo (HumdrumLine* line, int part,
int staff);
void insertSideStaffInfo (HumdrumLine* line, int part,
int staff, int staffnum);
void getMetricBarNumbers (std::vector<int>& barnums);
string createBarToken (int m, int barnum,
GridMeasure* measure);
string getBarStyle (GridMeasure* measure);
void adjustExpansionsInStaff (GridSlice* newmanip, GridSlice* curr,
int p, int s);
void transferNonDataSlices (GridMeasure* output, GridMeasure* input);
string extractMelody (GridMeasure* measure);
void insertMelodyString (GridMeasure* measure, const string& melody);
GridVoice* createVoice (const string& tok, const string& post, HumNum duration, int pindex, int sindex);
HTp createHumdrumToken (const string& tok, int pindex, int sindex);
GridSlice* getNextSpinedLine (const GridMeasure::iterator& it, int measureindex);
void matchVoices (GridSlice* current, GridSlice* last);
void adjustVoices (GridSlice* curr, GridSlice* newmanip, int partsplit);
void createMatchedVoiceCount (GridStaff* snew, GridStaff* sold, int p, int s);
private:
std::vector<GridSlice*> m_allslices;
std::vector<std::vector<int>> m_verseCount;
std::vector<int> m_harmonyCount;
bool m_pickup;
std::vector<bool> m_dynamics;
std::vector<bool> m_harmony;
// options:
bool m_recip; // include **recip spine in output
bool m_musicxmlbarlines; // use measure numbers from <measure> element
};
ostream& operator<<(ostream& out, HumGrid& grid);
class MxmlMeasure;
class MxmlPart;
// Event types: These are all of the XML elements which can be children of
// the measure element in MusicXML.
enum measure_event_type {
mevent_unknown,
mevent_attributes,
mevent_backup,
mevent_barline,
mevent_bookmark,
mevent_direction,
mevent_figured_bass,
mevent_forward,
mevent_grouping,
mevent_harmony,
mevent_link,
mevent_note,
mevent_print,
mevent_sound,
mevent_float // category for GridSides not attached to note onsets
};
class MxmlEvent {
public:
MxmlEvent (MxmlMeasure* measure);
~MxmlEvent ();
void clear (void);
void enableStems (void);
bool parseEvent (xml_node el, xml_node nextel,
HumNum starttime);
bool parseEvent (xpath_node el, HumNum starttime);
void setTickStart (long value, long ticks);
void setTickDur (long value, long ticks);
void setStartTime (HumNum value);
void setDuration (HumNum value);
void setDurationByTicks (long value,
xml_node el = xml_node(NULL));
HumNum getStartTime (void) const;
HumNum getDuration (void) const;
void setOwner (MxmlMeasure* measure);
MxmlMeasure* getOwner (void) const;
const char* getName (void) const;
int setQTicks (long value);
long getQTicks (void) const;
long getIntValue (const char* query) const;
bool hasChild (const char* query) const;
void link (MxmlEvent* event);
bool isLinked (void) const;
bool isRest (void);
bool isGrace (void);
bool hasGraceSlash (void);
bool isFloating (void);
bool hasSlurStart (int& direction);
bool hasSlurStop (void);
void setLinked (void);
std::vector<MxmlEvent*> getLinkedNotes (void);
void attachToLastEvent (void);
bool isChord (void) const;
void printEvent (void);
int getSequenceNumber (void) const;
int getVoiceNumber (void) const;
void setVoiceNumber (int value);
int getStaffNumber (void) const;
int getStaffIndex (void) const;
int getVoiceIndex (int maxvoice = 4) const;
void setStaffNumber (int value);
measure_event_type getType (void) const;
int getPartNumber (void) const;
int getPartIndex (void) const;
std::string getRecip (void) const;
std::string getKernPitch (void);
std::string getPrefixNoteInfo (void) const;
std::string getPostfixNoteInfo (bool primarynote) const;
xml_node getNode (void);
xml_node getHNode (void);
HumNum getTimeSigDur (void);
std::string getElementName (void);
void addNotations (std::stringstream& ss,
xml_node notations) const;
void reportVerseCountToOwner (int count);
void reportVerseCountToOwner (int staffnum, int count);
void reportHarmonyCountToOwner (int count);
void reportMeasureStyleToOwner (MeasureStyle style);
void reportEditorialAccidentalToOwner(void);
void reportDynamicToOwner (void);
void reportCaesuraToOwner (const std::string& letter = "Z") const;
void reportOrnamentToOwner (void) const;
void makeDummyRest (MxmlMeasure* owner,
HumNum startime,
HumNum duration,
int staffindex = 0,
int voiceindex = 0);
void setVoiceIndex (int voiceindex);
void forceInvisible (void);
bool isInvisible (void);
void setBarlineStyle (xml_node node);
void setTexts (std::vector<std::pair<int, xml_node>>& nodes);
std::vector<std::pair<int, xml_node>>& getTexts (void);
void setDynamics (xml_node node);
xml_node getDynamics (void);
std::string getRestPitch (void) const;
protected:
HumNum m_starttime; // start time in quarter notes of event
HumNum m_duration; // duration in quarter notes of event
measure_event_type m_eventtype; // enumeration type of event
xml_node m_node; // pointer to event in XML structure
MxmlMeasure* m_owner; // measure that contains this event
std::vector<MxmlEvent*> m_links; // list of secondary chord notes
bool m_linked; // true if a secondary chord note
int m_sequence; // ordering of event in XML file
static int m_counter; // counter for sequence variable
short m_staff; // staff number in part for event
short m_voice; // voice number in part for event
int m_voiceindex; // voice index of item (remapping)
int m_maxstaff; // maximum staff number for measure
xml_node m_hnode; // harmony label starting at note event
bool m_invisible; // for forceInvisible();
bool m_stems; // for preserving stems
xml_node m_dynamics; // dynamics <direction> starting just before note
std::vector<std::pair<int, xml_node>> m_text; // text <direction> starting just before note
private:
void reportStaffNumberToOwner (int staffnum, int voicenum);
void reportTimeSigDurToOwner (HumNum duration);
int getDotCount (void) const;
public:
static HumNum getEmbeddedDuration (xml_node el = xml_node(NULL));
static HumNum getQuarterDurationFromType (const char* type);
static bool nodeType (xml_node node, const char* testname);
friend MxmlMeasure;
friend MxmlPart;
};
class MxmlEvent;
class MxmlPart;
class SimultaneousEvents {
public:
SimultaneousEvents(void) { }
~SimultaneousEvents() { }
HumNum starttime; // start time of events
HumNum duration; // duration to next non-zero duration
vector<MxmlEvent*> zerodur; // zero-duration elements at this time
vector<MxmlEvent*> nonzerodur; // non-zero dur elements at this time
};
class MxmlMeasure {
public:
MxmlMeasure (MxmlPart* part);
~MxmlMeasure (void);
void clear (void);
void enableStems (void);
bool parseMeasure (xml_node mel);
bool parseMeasure (xpath_node mel);
void setStartTimeOfMeasure (HumNum value);
void setStartTimeOfMeasure (void);
void setDuration (HumNum value);
HumNum getStartTime (void) const;
HumNum getTimestamp (void) const { return getStartTime(); }
HumNum getDuration (void) const;
void setOwner (MxmlPart* part);
MxmlPart* getOwner (void) const;
int getPartNumber (void) const;
int getPartIndex (void) const;
int setQTicks (long value);
long getQTicks (void) const;
void attachLastEventToPrevious (void);
void calculateDuration (void);
int getEventCount (void) const;
vector<SimultaneousEvents>* getSortedEvents(void);
MxmlEvent* getEvent (int index) const;
void setNextMeasure (MxmlMeasure* event);
MxmlMeasure* getNextMeasure (void) const;
MxmlMeasure* getPreviousMeasure (void) const;
void setPreviousMeasure (MxmlMeasure* event);
int getVoiceIndex (int voicenum);
int getStaffIndex (int voicenum);
void setTimeSigDur (HumNum duration);
HumNum getTimeSigDur (void);
void addDummyRest (void);
void addDummyRest (HumNum starttime, HumNum duration,
int staffindex, int voiceindex);
vector<MxmlEvent*>& getEventList (void);
void sortEvents (void);
void forceLastInvisible (void);
MeasureStyle getStyle (void);
MeasureStyle getBarStyle (void);
void setStyle (MeasureStyle style);
void setBarStyle (MeasureStyle style);
void makeFinalBarline(void) { m_style = MeasureStyle::Final; }
bool isFinal(void) { return m_style == MeasureStyle::Final; }
bool isDouble(void) { return m_style == MeasureStyle::Double; }
bool isRepeatBackward(void) { return m_style == MeasureStyle::RepeatBackward; }
bool isRepeatForward(void) { return m_style == MeasureStyle::RepeatForward; }
bool isRepeatBoth(void) { return m_style == MeasureStyle::RepeatBoth; }
private:
void receiveStaffNumberFromChild (int staffnum, int voicenum);
void receiveTimeSigDurFromChild (HumNum duration);
void receiveMeasureStyleFromChild (MeasureStyle style);
void receiveEditorialAccidentalFromChild (void);
void receiveOrnamentFromChild (void);
void reportStaffNumberToOwner (int staffnum, int voicenum);
void reportVerseCountToOwner (int count);
void reportVerseCountToOwner (int staffindex, int count);
void reportHarmonyCountToOwner (int count);
void reportEditorialAccidentalToOwner (void);
void reportDynamicToOwner (void);
void reportCaesuraToOwner (const string& letter);
void reportOrnamentToOwner (void);
protected:
HumNum m_starttime; // start time of measure in quarter notes
HumNum m_duration; // duration of measure in quarter notes
HumNum m_timesigdur; // duration of measure according to
// prevailing time signature.
MxmlPart* m_owner; // part which contains measure
MxmlMeasure* m_previous; // previous measure in part or null
MxmlMeasure* m_following; // following measure in part or null
vector<MxmlEvent*> m_events; // list of semi-ordered events in measure
vector<SimultaneousEvents> m_sortedevents; // list of time-sorted events
MeasureStyle m_style; // measure style type
bool m_stems = false;
friend MxmlEvent;
friend MxmlPart;
};
class Option_register {
public:
Option_register (void);
Option_register (const string& aDefinition, char aType,
const string& aDefaultOption);
Option_register (const string& aDefinition, char aType,
const string& aDefaultOption,
const string& aModifiedOption);
Option_register (const Option_register& reg);
~Option_register ();
Option_register& operator=(const Option_register& reg);
void clearModified (void);
string getDefinition (void);
string getDefault (void);
string getOption (void);
string getModified (void);
string getDescription (void);
bool isModified (void);
char getType (void);
void reset (void);
void setDefault (const string& aString);
void setDefinition (const string& aString);
void setDescription (const string& aString);
void setModified (const string& aString);
void setType (char aType);
ostream& print (ostream& out);
protected: