188 lines
5.0 KiB
C++
188 lines
5.0 KiB
C++
/*
|
|
[generative]
|
|
knobs: ramdon low range note, ramdon high range note, number of notes to use(1 to 12 or 1 to 7 if harmonized), ramdomizer signatures
|
|
|
|
buttons: harmonizer scale-, harmonizer scale+, ramdomize it, shift left sequence, shift rigth sequence, play/stop
|
|
*/
|
|
|
|
uint8_t _lower_note = 36;
|
|
uint8_t _range_note = 34;
|
|
uint8_t _accent_probability = ACCENT_PROBABILITY_GENERATION;
|
|
uint8_t _glide_probability = GLIDE_PROBABILITY_GENERATION;
|
|
uint8_t _rest_probability = REST_PROBABILITY_GENERATION;
|
|
uint8_t _tie_probability = TIE_PROBABILITY_GENERATION;
|
|
uint8_t _number_of_tones = 3;
|
|
|
|
uint8_t _allowed_tones[12] = {0};
|
|
|
|
void shiftSequence(int8_t offset)
|
|
{
|
|
uint8_t shift = _sequencer[_selected_track].data.step_init_point+offset;
|
|
// clear stack note(also send any note on to off) before shift sequence init point
|
|
//clearStackNote(_selected_track);
|
|
ATOMIC(_sequencer[_selected_track].data.step_init_point = shift);
|
|
}
|
|
|
|
void processGenerativeButtons()
|
|
{
|
|
|
|
if ( released(GENERIC_BUTTON_1) ) {
|
|
// previous harmonic mode
|
|
if ( _selected_mode > 0 ) {
|
|
ATOMIC(--_selected_mode);
|
|
} else if ( _selected_mode == 0 ) {
|
|
ATOMIC(_harmonize = 0);
|
|
}
|
|
}
|
|
|
|
if ( released(GENERIC_BUTTON_2) ) {
|
|
// next harmonic mode
|
|
if ( _selected_mode < MODES_NUMBER-1 ) {
|
|
if ( _harmonize == 0 ) {
|
|
ATOMIC(_harmonize = 1);
|
|
} else {
|
|
ATOMIC(++_selected_mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pressed(GENERIC_BUTTON_3) ) {
|
|
// ramdomize it!
|
|
acidRandomize();
|
|
}
|
|
|
|
if ( pressed(GENERIC_BUTTON_4) ) {
|
|
shiftSequence(-1);
|
|
}
|
|
|
|
if ( pressed(GENERIC_BUTTON_5) ) {
|
|
shiftSequence(1);
|
|
}
|
|
|
|
}
|
|
|
|
void processGenerativeLeds()
|
|
{
|
|
|
|
if ( _harmonize == 1 ) {
|
|
if ( _selected_mode == MODES_NUMBER-1 ) {
|
|
digitalWrite(GENERIC_LED_1, LOW);
|
|
digitalWrite(GENERIC_LED_2, HIGH);
|
|
} else {
|
|
digitalWrite(GENERIC_LED_1, LOW);
|
|
digitalWrite(GENERIC_LED_2, LOW);
|
|
}
|
|
} else {
|
|
digitalWrite(GENERIC_LED_1, HIGH);
|
|
digitalWrite(GENERIC_LED_2, LOW);
|
|
}
|
|
|
|
digitalWrite(GENERIC_LED_3, LOW);
|
|
digitalWrite(GENERIC_LED_4, LOW);
|
|
digitalWrite(GENERIC_LED_5, LOW);
|
|
|
|
}
|
|
|
|
void processGenerativePots()
|
|
{
|
|
uint16_t value;
|
|
|
|
// GENERIC_POT_1: lower range note to be generated
|
|
value = getPotChanges(GENERIC_POT_1, 0, 127);
|
|
if ( value != -1 ) {
|
|
_lower_note = value;
|
|
}
|
|
|
|
// GENERIC_POT_2: high range note to be generated
|
|
value = getPotChanges(GENERIC_POT_2, 0, 127);
|
|
if ( value != -1 ) {
|
|
_range_note = value;
|
|
}
|
|
|
|
// GENERIC_POT_3: number of notes to use on sequence(1 to 12 or 1 to 7 if harmonized)
|
|
if ( _harmonize == 1 ) {
|
|
value = getPotChanges(GENERIC_POT_3, 1, 7);
|
|
} else if ( _harmonize == 0 ) {
|
|
value = getPotChanges(GENERIC_POT_3, 1, 12);
|
|
}
|
|
if ( value != -1 ) {
|
|
_number_of_tones = value;
|
|
uint8_t note = 0;
|
|
for ( uint8_t i=0; i < 12; i++ ) {
|
|
if ( i%(12/_number_of_tones) == 0 && i != 0 ) {
|
|
note += (12/_number_of_tones);
|
|
}
|
|
_allowed_tones[i] = note;
|
|
}
|
|
}
|
|
|
|
// GENERIC_POT_4: ramdomizer signatures
|
|
value = getPotChanges(GENERIC_POT_4, 0, 80);
|
|
if ( value != -1 ) {
|
|
//_accent_probability = value???;
|
|
//_glide_probability value???;
|
|
_rest_probability = 80-value;
|
|
}
|
|
|
|
}
|
|
|
|
uint8_t getNoteByMaxNumOfTones(uint8_t note)
|
|
{
|
|
uint8_t octave, relative_note;
|
|
|
|
octave = note/12;
|
|
relative_note = note%12;
|
|
return _allowed_tones[relative_note] + _lower_note + (octave*12);
|
|
}
|
|
|
|
void acidRandomize()
|
|
{
|
|
uint8_t note, high_note, accent, glide, tie, rest, last_step;
|
|
|
|
// random it all
|
|
ATOMIC(_sequencer[_selected_track].mute = true);
|
|
clearStackNote(_selected_track);
|
|
|
|
for ( uint16_t i = 0; i < STEP_MAX_SIZE; i++ ) {
|
|
|
|
// step on/off
|
|
_sequencer[_selected_track].data.step[i].rest = random(0, 100) < _rest_probability ? 0 : 1;
|
|
|
|
// random tie and reset accent and glide in case of a rest
|
|
if (_sequencer[_selected_track].data.step[i].rest) {
|
|
|
|
_sequencer[_selected_track].data.step[i].note = 36;
|
|
_sequencer[_selected_track].data.step[i].accent = 0;
|
|
_sequencer[_selected_track].data.step[i].glide = 0;
|
|
_sequencer[_selected_track].data.step[i].tie = 0;
|
|
|
|
if (i == 0) {
|
|
last_step = STEP_MAX_SIZE-1;
|
|
} else {
|
|
last_step = i-1;
|
|
}
|
|
|
|
// only tie probrablity when last step has a note or another tie event
|
|
if (_sequencer[_selected_track].data.step[last_step].rest == 0 || _sequencer[_selected_track].data.step[last_step].tie == 1)
|
|
_sequencer[_selected_track].data.step[i].tie = random(0, 100) < _tie_probability ? 1 : 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
high_note = _lower_note+_range_note;
|
|
if ( high_note > 127 ) {
|
|
high_note = 127;
|
|
}
|
|
note = getNoteByMaxNumOfTones(random(_lower_note, high_note));
|
|
|
|
accent = random(0, 100) < _accent_probability ? 1 : 0;
|
|
glide = random(0, 100) < _glide_probability ? 1 : 0;
|
|
|
|
_sequencer[_selected_track].data.step[i].note = note;
|
|
_sequencer[_selected_track].data.step[i].accent = accent;
|
|
_sequencer[_selected_track].data.step[i].glide = glide;
|
|
}
|
|
ATOMIC(_sequencer[_selected_track].mute = false);
|
|
}
|