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;
}