Skip to content

Commit

Permalink
Implemented Brownian Motion Rhythm
Browse files Browse the repository at this point in the history
  • Loading branch information
RandyParedis committed Nov 22, 2018
1 parent 83ab799 commit 453c2cd
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,4 @@ compile `cmake` of this project with the flag `-DTRNG_LOC` set to your home dire
| 18-11-2018 | Added `rest-ratio` and `length` parameters to config file.
| 18-11-2018 | Added **1/f Noise** and **Centralized** as a pitch algorithm.
| 22-11-2018 | Fixed MidiPlayer playback with ties, added `bpm` and `time` signature to styles.
| 22-11-2018 | Added **Brownian Motion** as a rhythm algorithm.
5 changes: 4 additions & 1 deletion docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ The file contains of the following tree structure and fields:
the current stave, generate notes whose chance of being chosen corresponds with
its value on the gauss-curve.
- Anything else will generate completely random pitches within the entire music range.
- `rhythm`: The algoruthm to use for rhythms. Possible values are:
- `rhythm`: The algoruthm to use for rhythms. The `options.rhythm.smallest` and
`options.rhythm.largest` options allow the user to specify the minimal and maximal
duration of a note. This is respected by all algorithm.<br>Possible algorithms are:
- `random`: A random rhythm out of the possible range.
- `brownian-motion`: Implementation of the Brownian motion as a rhythmic algorithm.
- Anything else will create a constant tempo of `options.rhythm.duration` notes
(representations according to the MusicXML note types, or the corresponding fractions
when less than one). If this option cannot be found, `quarter` will be used instead.
Expand Down
1 change: 1 addition & 0 deletions docs/Future.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ This file describes all planned features to be added in the future
- _(Ability to randomize anything)_
- General Todo
- Simple Installation
- Automatic beaming for notes
10 changes: 8 additions & 2 deletions main/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
"generation": {
"pitch": "1/f-noise",
"rhythm": "random",
"options": {
"rhythm": {
"smallest": "16th",
"largest": "quarter"
}
},
"rest-ratio": 0.05
},
"export": {
"filename": "music.xml",
"filename": "good-rhythm.xml",
"title": "My Score",
"composer": "autoplay v@VERSION@",
"rights": "Copyright \u00A9 2018 autoplay v@VERSION@, created by Randy Paredis"
},
"style": {
"from": "F-major",
"bpm": 160
"bpm": 100
},
"parts": [
{
Expand Down
39 changes: 38 additions & 1 deletion main/util/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ namespace autoplay {

measure.setBPM(m_config.conf<int>("style.bpm", 80));

options.put("rhythm._divs", divisions);

std::shared_ptr<music::Part> part = std::make_shared<music::Part>(instruments);
part->setLines((uint8_t)pt_part.get<int>("lines", 5));

Expand Down Expand Up @@ -269,9 +271,18 @@ namespace autoplay {

if(algo == "random") {
return [](RNEngine& gen, music::Note* prev, std::vector<music::Note*>& conc, pt::ptree& pt) -> float {
auto rh = (float)std::pow(2.0f, Randomizer::pick_uniform(gen, 1, 10) - 8);
auto smallest =
(int)std::log2(music::Note::DURATION.at(pt.get<std::string>("rhythm.smallest", "256th")));
auto largest =
(int)std::log2(music::Note::DURATION.at(pt.get<std::string>("rhythm.largest", "long")));
smallest += 8;
largest += 8;
auto rh = (float)std::pow(2.0f, Randomizer::pick_uniform(gen, smallest, largest) - 8);
return rh;
};
} else if(algo == "brownian-motion") {
return [this](RNEngine& gen, music::Note* prev, std::vector<music::Note*>& conc,
pt::ptree& pt) -> float { return rhythmBrownianMotion(gen, prev, conc, pt); };
} else {
return [](RNEngine& gen, music::Note* prev, std::vector<music::Note*>& conc, pt::ptree& pt) -> float {
auto rh = pt.get<std::string>("rhythm.duration", "quarter");
Expand Down Expand Up @@ -433,5 +444,31 @@ namespace autoplay {

return pitches.at(sum);
}

float Generator::rhythmBrownianMotion(autoplay::util::RNEngine& gen, autoplay::music::Note* prev,
std::vector<autoplay::music::Note*>& conc, const pt::ptree& pt) const {
auto divisions = pt.get<unsigned int>("rhythm._divs");
auto smallest = (int)std::log2(music::Note::DURATION.at(pt.get<std::string>("rhythm.smallest", "256th")));
auto largest = (int)std::log2(music::Note::DURATION.at(pt.get<std::string>("rhythm.largest", "long")));
smallest += 8;
largest += 8;
if(prev) {
float prev_type = (float)prev->getDuration() / (4.0f * divisions);
auto prev_n = (int)(std::log2(prev_type) + 8);
auto min = pt.get<int>("rhythm.min", -3);
auto max = pt.get<int>("rhythm.max", 3);
if(prev_n + min < smallest) {
min = prev_n - smallest;
}
if(prev_n + max >= largest) {
max = largest - prev_n;
} else if(prev_n + max < smallest) {
max = prev_n - smallest;
}
return (float)std::pow(2.0f, Randomizer::pick_uniform(gen, prev_n + min, prev_n + max) - 8);
} else {
return (float)std::pow(2.0f, Randomizer::pick_uniform(gen, smallest, largest) - 8);
}
}
}
}
14 changes: 14 additions & 0 deletions main/util/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ namespace autoplay {
*/
uint8_t pitch1FNoise(RNEngine& gen, const pt::ptree& pt) const;

/**
* A rhythm generation algorithm, based upon the movements of small particles that are randomly bombarded by
* molecules of the surrounding medium.
* @param gen The generator object.
* @param prev The previous note that is played
* @param conc A vector of all concurrent notes that are being played
* @param pt A ptree with additional options. This algorithm expects rhythm.min and rhythm.max to be set
* in this ptree. When missing, -3 and 3 will be chosen respectively.
* index.
* @return A new rhythm.
*/
float rhythmBrownianMotion(RNEngine& gen, music::Note* prev, std::vector<music::Note*>& conc,
const pt::ptree& pt) const;

private:
Config m_config; ///< The Config of the system
RNEngine m_rnengine; ///< The Random Engine
Expand Down

0 comments on commit 453c2cd

Please sign in to comment.