-
Notifications
You must be signed in to change notification settings - Fork 3
/
motif.hpp
158 lines (124 loc) · 4.44 KB
/
motif.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
-----Motif Class Header-----
Auston Sterling
austonst@gmail.com
The header for the Motif class, representing a short sequence of notes in a piece.
This would be analogous to a single word.
*/
#ifndef _motif_h_
#define _motif_h_
#include "midi/midi.hpp"
#include <vector>
#include <random>
//Helper struct to store non-concrete note information
//Time units could be anything, should be specified when used
struct AbstractNoteTime
{
std::int8_t note;
std::uint32_t begin;
std::uint32_t duration;
};
//Helper struct for AbstractMotif generation
struct MotifGenSettings
{
//Default constructor, sets to minimum strictness
MotifGenSettings();
//Constructor to set up required fields and optionally strictness
//If no strictness specified, sets to minimum
MotifGenSettings(float inLength, std::mt19937* inGen, std::uint8_t strict = 1);
//Sets up values corresponding to a certain strictness
//Does not set length or gen!
void setStrictness(std::uint8_t strict);
//--- Strictness Independent Variables ---
//The length of the motif in whole notes
float length;
//A pointer to a random number generator to be used in generation
std::mt19937* gen;
//--- Strictness Dependent Variables ---
//If setStrictness used to generate this, this stores the given value
std::uint8_t strictness;
//A value of X here will make notes align their start time to a
//multiple of notelength/X. A value of 0 means to not try to align.
float noteAlign;
//Force the first note of the motif to be 0
bool forceFirstNote0;
};
//Helper struct for ConcreteMotif generation from an AbstractMotif
struct MotifConcreteSettings
{
//Default constructor, sets to minimum strictness
MotifConcreteSettings();
//Constructor to set up required fields and optionally strictness
//If no strictness specified, sets to minimum
MotifConcreteSettings(midi::Note inKey, std::uint8_t inType, std::uint32_t inMut,
midi::Instrument inInst, std::uint32_t inTPQ,
bool inForceStart, std::int8_t inStart, std::mt19937* inGen,
std::uint8_t strict = 1);
//Sets up values corresponding to a certain strictness
//Currently has no effect
void setStrictness(std::uint8_t strictness);
//--- Strictness Independent Variables ---
//The key of the concrete motif
midi::Note key;
//The type of key (0=major, 1=harmonic 2=natural minor)
std::uint8_t keyType;
//The points that can be spent on mutations
std::uint32_t mutations;
//The instrument that will play this motif
midi::Instrument instrument;
//The conversion between abstract and concrete time
std::uint32_t ticksPerQuarter;
//A note (in abstract format) to forcibly start the motif around
bool forceStartNote;
std::int8_t startNote;
//A pointer to a Mersenne Twister to be used in generation
std::mt19937* gen;
//--- Strictness Dependent Variables ---
//If setStrictness used to generate this, this stores the given value
std::uint8_t strictness;
};
//An abstract motif, which contains the main information about a motif but lacks
//some details
class AbstractMotif
{
public:
//Constructors
AbstractMotif() {length_=0;}
AbstractMotif(const MotifGenSettings& set);
//General use functions
void generate(const MotifGenSettings& set);
std::size_t numNotes() {return notes_.size();}
void addToNote(std::uint32_t note, std::int8_t change)
{
notes_[note].note += change;
}
//Accessors
AbstractNoteTime note(int n) const {return notes_[n];}
float length() const {return length_;}
std::size_t numNotes() const {return notes_.size();}
private:
//This is a collection of notes in an unspecified scale
//0 being the lowest note and 7 being the highest.
//Time units are in 32nd notes.
std::vector<AbstractNoteTime> notes_;
//The length of the motif in whole notes
float length_;
};
//A concrete motif, which is effectively an instance of an abstract motif and
//can be played directly
class ConcreteMotif
{
public:
//Constructors
ConcreteMotif(const AbstractMotif& abstr, const MotifConcreteSettings& set);
//General use functions
void generate(AbstractMotif abstr, MotifConcreteSettings set);
void addToTrack(midi::NoteTrack& nt, std::uint32_t begin);
std::uint32_t ticks() const;
private:
//A collection of notes, with time units being MIDI ticks
std::vector<midi::NoteTime> notes_;
//The settings, which need to be stored for ticks()
MotifConcreteSettings set_;
};
#endif