Click Generator (for ‘Digital Click Fractals’) – Code
On this page you will find the C++ source code for generating the clicks for the piece “Digital Click Fractals”. For this I have developed a replacement system that consists of the following three rules:
- Rule 1: Every 0 is replaced by the number sequence [0, 1, 0].
- Rule 2: Every positive number is inverted
- Rule 3: Every negative number is inverted and doubled.
Example:
Generation 0 has by definition as its only value [0].
Generation 1 replaces this 0 by the number sequence [0, 1, 0] (rule 1).
Generation 2 replaces the 0 from generation 1 by [0, 1, 0], the 1 by -1 (rule 2) and the 0 again by [0, 1, 0].
and so on.
Here are the function definitions first:
/*
Click Generator
by Juergen Mayer
*/
#include <iostream>
#include <vector>
using namespace std;
//=============== functions ===============
// print vector
void printVec(const vector<double>& vec) {
for (int i = 0; i < vec.size(); i++) {
cout << vec.at(i) << " ";
}
cout << endl;
}
// detect maximum element
double maxElement(const vector<double>& vec) {
double maximum {vec.at(0)};
for (int i = 0; i < vec.size(); i++) {
if (maximum < vec.at(i)) {
maximum = vec.at(i);
}
}
return maximum;
}
// normalize Vector
vector<double> normalizeVec(const vector<double>& vec, double maxValue) {
vector<double> normVec = vec;
for (int i = 0; i < vec.size(); i++) {
normVec.at(i) = vec.at(i) / maxValue;
}
return normVec;
}
// map the amplitude to desired range for writing to file
// 16 Bit signed => max pos value = 32767
vector<double> mappedVec(const vector<double>& vec, double maxValue) {
vector<double> normVec = vec;
for (int i = 0; i < vec.size(); i++) {
normVec.at(i) = vec.at(i) / maxValue * 32767;
}
return normVec;
}
This is the main function:
//=============== main function ===============
int main()
{
// variables
int destinationGenerationNumber; // number of the last (highest) created generation
vector<double> currentGenerationVec {0}; // currently working vector
vector<double> assembleVec {0}; // assembling vector
vector<double> replacementVec; // replacement value or sequence
vector<double> destinationGenerationVec; // final generation vector
double maximum; // maximum element (peak element of the vector)
vector<double> normVec; // normalized Vector
// ask for the highest generation number?
do {
cout << "Create Sequence up to which Generation Number: ";
cin >> destinationGenerationNumber;
} while (destinationGenerationNumber <= 0);
// replacement system
for (size_t i = 0; i <= destinationGenerationNumber; i++) {
for (size_t j = 0; j < currentGenerationVec.size(); j++) {
if (i == 0) {
assembleVec = {0};
break;
}
else if (currentGenerationVec.at(j) == 0) {
replacementVec = { 0, 1, 0 };
}
else if (currentGenerationVec.at(j) > 0) {
replacementVec = { currentGenerationVec.at(j) * (-1) };
}
else if (currentGenerationVec.at(j) < 0) {
replacementVec = { currentGenerationVec.at(j) * (-2) };
}
else {
cout << "ERROR!";
break;
}
assembleVec.insert(assembleVec.begin(), replacementVec.begin(), replacementVec.end());
assembleVec.pop_back();
}
currentGenerationVec = assembleVec;
cout << "Size of Generation Nr. " << i << ":\t" << currentGenerationVec.size() << endl;
printVec(currentGenerationVec);
cout << endl;
}
destinationGenerationVec = currentGenerationVec;
cout << "Size of full sequence from Generation Nr. 0 up to Generation Nr. " << destinationGenerationNumber << ":\t" << destinationGenerationVec.size() << endl;
maximum = maxElement(destinationGenerationVec);
cout << "Maximum Element: " << maximum << endl;
normVec = mappedVec(destinationGenerationVec, maximum);
cout << "Normalized Vector: \n";
printVec(normVec);
//===============
long length = normVec.size();
short waveform[length];
cout << "vector size: " << length << endl;
cout << "array size: " << sizeof waveform / sizeof waveform[0] << endl;
for (int i = 0; i < length; i++) {
waveform[i] = normVec[i];
}
//===============
// at this point you just need to write the waveform[length] into a file ...
return 0;
}