Schönen Guten Abend

one more thing
-----------------

Wenn ich so im Manual lese "liest" es sich sehr danach an als wäre das gerät besonders gut dafür kurze loops aufzunehmen und abzuspielen.
Was würde passieren wenn man laaaaaange loops bzw ganze stücke einspielt?

Bitte entschuldigt meine anfängerfragen. bin leider was sequencer angeht unerfahren.
Das ist schon wichtig - denn es ist eine Stärke - du kannst auch sehr lange Takte spielen und anpassen - der MT lässt dir nie das Gefühl, dass was nicht geht wegen Länge.
Daher hast du dann einfach die Länge die du dann einstellst.
 
Unter Umständen für den Ein oder Anderen ganz interessant, ein kleines Programm in C, welches euklidische Rhythmen generiert. Vorbild war hier der euclidian Mode im Analog Rytm. Zwei euklidisch erzeugte Pattern, die jeweils geshifted mit boolischen Operatoren verglichen werden. Die finale Sequenz kann bei Bedarf ebenfalls rotieren.

C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SEQSIZE 16 /*Pattern Length*/

char* init_Array(char* d, const char* s) {
    char* tmp = d;
    while (*s) {
        *d++ = *s++;
    }
    *d = '\0';
    return tmp;
}

char* append_Array(char* d, const char* s) {
    while (*d) {
        ++d;
    }
    while (*s) {
        *d++ = *s++;
    }
    *d = '\0';
    return d;
}

void euclid(int d[], const int size, const int value) {
    char** tmp = (char**)malloc(size * sizeof(char*));
    for (int i = 0; i < size; ++i) {
        tmp[i] = (char*)malloc((size + 1) * sizeof(char));
    }
    int z = size;
    int p = size;
    int t = size;
    int s = value;
    (p < s) ? (p = s, s = t) : 0;
    t = p - s;
    for (int i = 0; i < size; ++i) {
        (i < s) ? init_Array(tmp[i], "X") : init_Array(tmp[i], "-");
    }
    while (t > 1) {
        (z > 0) ? z-- : 0;
        if (t < s) {
            p = s;
            s = t;
        }
        else {
            p = t;
        }
        t = p - s;
        for (int i = 0; i < s; ++i) {
            append_Array(tmp[i], tmp[z - i]);
        }
        z = p;
    }
    int n = 0;
    for (int i = 0; i < z; ++i) {
        int j = 0;
        while (tmp[i][j] != '\0') {
            d[n++] = (tmp[i][j] == 'X') ? 1 : 0;
            ++j;
        }
    }
    for (int i = 0; i < size; ++i) {
        free(tmp[i]);
    }
    free(tmp);
}

void shift(int d[], const int size, int shift_Value) {
    if (!shift_Value) {
        return;
    }
    (shift_Value < 0) ? (shift_Value += size) : 0;
    int* tmp = (int*)malloc(size * sizeof(int));
    for (int i = 0; i < size; ++i) {
        tmp[(i + shift_Value) % size] = d[i];
    }
    for (int i = 0; i < size; ++i) {
        d[i] = tmp[i];
    }
    free(tmp);
}

void cmp(int d[], const int s[], const int size, const int bool_operator) {
    for (int i = 0; i < size; ++i) {
        switch (bool_operator) {
        case 0:
            d[i] &= s[i];
            d[i] = !d[i];
            break;
        case 1:
            d[i] &= s[i];
            break;
        case 2:
            d[i] |= s[i];
            break;
        case 3:
            d[i] ^= s[i];
            break;
        default:
            break;
        }
    }
}

void print_Seq(const int arr[], const int size) {
    for (int i = 0; i < size; ++i) {
        if (arr[i] == 1) {
            printf(" X ");
        }
        else {
            printf(" - ");
        }
    }
}

int main() {
    /*set random Values*/
    srand(time(NULL));
    int rnd_STEPS_A = rand() % (SEQSIZE - 1) + 1;
    int rnd_STEPS_B = rand() % (SEQSIZE - 1) + 1;
    int rnd_SHIFT_A = rand() % (2 * SEQSIZE - 2) - (SEQSIZE-1);
    int rnd_SHIFT_B = rand() % (2 * SEQSIZE - 2) - (SEQSIZE-1);
    int rnd_SHIFT_C = rand() % (2 * SEQSIZE - 2) - (SEQSIZE-1);
    int rnd_CMP_OPERATOR = rand() % 4;
  
    char op[4];
    if (rnd_CMP_OPERATOR == 0) init_Array(op,"NOT");
    else if (rnd_CMP_OPERATOR == 1) init_Array(op, "AND");
    else if (rnd_CMP_OPERATOR == 2) init_Array(op, "OR");
    else init_Array(op, "XOR");

    /*print Counter*/
    for (int i = 0; i < SEQSIZE; ++i) {
        printf("%02i|", i + 1);
    }
    printf(" | Counter\n");
    for (int i = 0; i < SEQSIZE; ++i) {
        printf("---");
    }
    printf("\n");

    /*init euclidian Sequence*/
    int a[SEQSIZE], b[SEQSIZE];
    euclid(a, SEQSIZE, rnd_STEPS_A);
    euclid(b, SEQSIZE, rnd_STEPS_B);

    /*print Seq_A*/
    print_Seq(a, SEQSIZE);
    printf(" | Seq_A -> %i von %i\n", rnd_STEPS_A, SEQSIZE);

    /*shift Seq_A*/
    shift(a, SEQSIZE, rnd_SHIFT_A);

    /*print shifted Seq_A*/
    print_Seq(a, SEQSIZE);
    printf(" | Seq_A shift -> %i\n", rnd_SHIFT_A);

    printf("\n");

    /*print Seq_B*/
    print_Seq(b, SEQSIZE);
    printf(" | Seq_B -> %i von %i\n", rnd_STEPS_B, SEQSIZE);

    /*shift Seq_B*/
    shift(b, SEQSIZE, rnd_SHIFT_B);

    /*print shifted Seq_B*/
    print_Seq(b, SEQSIZE);
    printf(" | Seq_B shift -> %i\n", rnd_SHIFT_B);
    printf("\n");

    /*print Seq_A / Seq_B*/
    print_Seq(a, SEQSIZE);
    printf(" | Seq_A\n");
    print_Seq(b, SEQSIZE);
    printf(" | Seq_B\n");

    /*compare Seq_A / Seq_B*/
    cmp(a, b, SEQSIZE, rnd_CMP_OPERATOR);

    /*print Result*/
    for (int i = 0; i < SEQSIZE; ++i) {
        printf("---");
    }
    printf("\n");

    print_Seq(a, SEQSIZE);
    printf(" | cmp Seq_A %s Seq_B\n\n",op);

    /*shift Result*/
    shift(a, SEQSIZE, rnd_SHIFT_C);

    /*print Pattern*/
    print_Seq(a, SEQSIZE);
    printf(" | Seq_C shift -> %i\n", rnd_SHIFT_C);
    for (int i = 0; i < SEQSIZE; ++i) {
        printf("===");
    }
    printf("\n");

    return 0;
}

Code:
01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16| | Counter
------------------------------------------------
 X  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  | Seq_A -> 1 von 16
 -  -  -  -  X  -  -  -  -  -  -  -  -  -  -  -  | Seq_A shift -> 4

 X  -  X  X  -  X  -  X  X  -  X  X  -  X  -  X  | Seq_B -> 10 von 16
 -  X  -  X  X  -  X  X  -  X  -  X  X  -  X  X  | Seq_B shift -> -12

 -  -  -  -  X  -  -  -  -  -  -  -  -  -  -  -  | Seq_A
 -  X  -  X  X  -  X  X  -  X  -  X  X  -  X  X  | Seq_B
------------------------------------------------
 -  X  -  X  -  -  X  X  -  X  -  X  X  -  X  X  | cmp Seq_A XOR Seq_B

 X  X  -  X  X  -  X  -  X  -  -  X  X  -  X  -  | Seq_C shift -> -11
================================================


** Process exited - Return Code: 0 **

Vorerst werden die euklidischen Rhythmen unter der Haube im Random Generator des MidiTraC's Anwendung finden, evtl. kommt auch noch ein UI für den User.

Kritik und Ideen im Hinblick auf Optimierung sind willkommen!
 
Zuletzt bearbeitet:
Firmware 1.97

v1.97
Improvement
- new Step Record Mode: allow different dividers & adjustment of Loop Length
- RND use euclidian Algorithm to generate Sequences
- poly to mono Funktion (lowest Note)
- Arpeggiator & Chord depends on Scale
- Scale show used Keys
- revised Manuals
Bugfix:
- transpose Record ends within select Keys
- faster encoder subroutine
- many small UI things...
 

Anhänge

  • MidiTraC_1_97.zip
    637 KB · Aufrufe: 3
Zuletzt bearbeitet:
Vielen Dank für das tolle Update!
Das Firmware Update lief bei mir übrigens unter Linux sehr gut. Den Befehl dafür habe ich aus der "update_MacOS.command" entnommen und das USB Serial Device direkt reingeschrieben. Das sah bei mir dann so aus:

Code:
esptool.py --chip esp32 --port /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 --baud 460800 --before default_reset --after hard_reset write_flash 0x0 ./MidiTraC.bin
 
Eine leicht schräge Demo, wo vor allem die neuen Features eingesetzt werden: livejam ->MidiTraC steuert Jupiter Xm & Microfreak...



ratchets lassen sich mit dem Step Sequencer nun extrem schnell realisieren. Da polyphon eingespielt werden kann, bin ich wesentlich schneller am Ziel als mit einem Lauflicht... Gate- und Steplänge können für jeden Step gewählt werden (kleinste Einheit 1/64 Triolen).

Die Spieluhr sequence ist Produkt des aus User Arpeggio Pattern, und Scaler. Im Chord Mode kann ebenfalls der Scaler aktiv sein. Das Ergebnis kommt bei den E-Pianos und dem Hauptthema zum Ausdruck. Chords die ich intuitiv so nicht auf der Klaviatur spielen bzw. finden würde.

Weitere Sequencen wurden mit dem Euklid Generator erzeugt. In der aktuellen Version werden die Parameter noch über ein Random Modul angesteuert. Um alle Parameter des Euclid Generator zugänglich zu machen, muss noch ein wenig am User Interface umgestrickt werden. Grundsätzlich habe ich mich an den Elektrons orientiert, wie oben bereits beschrieben. Der Euclid Generator liefert musikalisch sinnvollere Pattern als nur Random. Der Generator lässt sich schneller bedienen, gefällige Ergebnisse werden per Tastendruck im Gedächtnis behalten, während man sich weiter neue Ergebnisse anhört.
 
Firmware 1.98

Sequenzen lassen sich über einen euklidischen Algorithmus monophon und polyphon generieren. Dabei können nun alle Parameter selbst editiert werden. Eine schnelle Würfel Option ist ebenfalls wählbar.

Das Euklidische Muster kann bis zu 254 Steps umfassen. Erzeugt werden zwei Muster in Abhängigkeit vom Divider (1/128-1/1), die jeweils eigenständig rotieren und mit Vergleichsoperatoren bearbeitet werden können (siehe oben).

Tonhöhen werden schnell über eine große Range eingestellt. Skalen sind unabhängig von der globalen Skala anwendbar. Polyphone Pattern werden über interne Chord und Keying Algorithmen erweitert (bis zu vier Stimmen). Die Duration (Gate Time Range) ist ebenfalls einstellbar und wird wie Velocity zufällig generiert.

Code:
 ________________    ________________
|Ch: 12 Oct: 3+12|  |EuclidSteps: 032|
|RootScale: D-maj|  |SeqA: 012 S: 011|
|GTR:   1/16  1/4|  |SeqB: 004 S: -10|
|M/P: P Rytm: RND|  |A><B: XOR S: 000|
|////////////////|  |////////////////|


Die beiden Demo Pattern wurden nur mit Hilfe der neuen Dicer Funktionen erzeugt, nicht eingespielt. Die Drums sind in dem Fall monophon Schicht für Schicht generiert. Es lassen sich auch polyphone Rhythmus Strukturen direkt erstellen, was für Breaks und Fills durchaus brauchbar ist...

Anhang anzeigen dicer_demo2.mp3

Anhang anzeigen dicer_demo1.mp3
 

Anhänge

  • MidiTraC_1_98.zip
    630,2 KB · Aufrufe: 1
Bugfix:
If using Scaler in ARP-Mode and selected Root Note is different from C, Notes will hang on...
 

Anhänge

  • MidiTraC_1_98b.zip
    630,4 KB · Aufrufe: 4


Neueste Beiträge

News

Zurück
Oben