Closed gogins closed 6 years ago
Lo and behold, it works pretty much out of the box. To do:
Time is going to be an issue, but not I think insuperable.
We have for 2,000 notes:
KMeansMCRM::random_algorithm: 0.039 seconds.
KMeansMCRM::means_to_notes...
dkm::kmeans_lloyd...
dkm::kmeans_lloyd: 2710.647 seconds.
KMeansMCRM::means_to_notes: 2710.647 seconds.
KMeansMCRM::generate: 2710.686 seconds.
which is 45 minutes. Much longer than I normally tolerate, but still better than the old days.
With this:
mcrm.sample_count = 20000000;
mcrm.means_count = 200;
We do not get the best possible approximation to the fractal, as shown by opening the generated MIDI file in a piano roll editor. The heavier density in some places seems to "pull" means towards those places. This is a pretty big number of samples, but the notes along the base of the Sierpinski triangle differ by a semitone in places.
This obviously is not good enough.
It looks like the deterministic algorithm will be best after all, if it can be redone to take into account overlapping points and the need for numerical approximation. Right now I am just trying the KMeansMCRM using the deterministic algorithm to see if that behaves differently.
It does not, but the plain old MCRM works just fine.
This obviously works much better... I spent some time but I learned something.
For example, using https://github.com/genbattle/dkm or OpenCV.
There is also https://www.npmjs.com/package/ml-kmeans.
Given a run of N samples of either the random or discrete IFS algorithm, produce a score of K notes consisting of the centroids computed by the algorithm.
The samples could occupy 5 up to about GB of RAM on my notebook. The MCRM algorithm would operate on
std::array<float>
or<double>
. The dimensions would be {instrument, time, duration, key, velocity, pan} or 6 elements for a size of 24 or 48 bytes per sample, giving at least 104,166,666 samples. For a 2,000 note score, that would be 52,083 samples per note. The algorithm clearly is feasible regarding storage. About compute time, I don't know yet.This should be done both for score space (plain notes) and for fractal interpolation in chord spaces.
The
csound::Event
class will need a copy constructor forstd::array<>
.This approach should remove a good chunk of hackishness from my general approach.
Finally solved it!