Degenerator DIY Sampler/Synthesizer (Tubeohm)

Hi Mick. Das wüste ich auch gerne. Überall sind noch Baustellen. Aber ich bin "hartnäckich" und kämpfe mich halt durch. Hab jetzt zwei Wochen Urlaub und viel Zeit für meine Kiste.

Hier noch mehr "Cooler Scheiß" :geige: Gruß Rolf

 
Hallo und guten Morgen..

Ich habe ein kleines Sound Problem mit der "Quad Saw" im DE-GENERATOR. Im Vergleich mit dem
Shruthi Synthesizer klingt der Sound im DE-GENERATOR sehr statisch. Ich habe den Quellcode
aus dem Shruthi für den DE-GENERATOR etwas angepasst. Der Parameter-Wert steht auf beiden
Synthesizern auf 0. Ich habe ein kleines Video gedreht um es zu zeigen und zu hören.
Damit die QuadSaw funktioniert muss der "phase_spread" immer >0 sein.



Shruthi Quellcode
Code:
.
// ------- Quad saw or pwm (mit aliasing) ------------------------------------
void Oscillator::RenderQuad(uint8_t* buffer) {
  uint16_t phase_spread = (
      static_cast<uint32_t>(phase_increment_.integral) * parameter_) >> 13;
  ++phase_spread;
  uint16_t phase_increment = phase_increment_.integral;
  uint16_t increments[3];
  for (uint8_t i = 0; i < 3; ++i) {
    phase_increment += phase_spread;
    increments[i] = phase_increment;
  }
 
  if (shape_ == WAVEFORM_QUAD_SAW_PAD) {
    BEGIN_SAMPLE_LOOP
      UPDATE_PHASE
      data_.qs.phase[0] += increments[0];
      data_.qs.phase[1] += increments[1];
      data_.qs.phase[2] += increments[2];
      uint8_t value = (phase.integral >> 10);
      value += (data_.qs.phase[0] >> 10);
      value += (data_.qs.phase[1] >> 10);
      value += (data_.qs.phase[2] >> 10);
      *buffer++ = value;
    END_SAMPLE_LOOP
  }
  else { //WAVEFORM_QUAD_PWM
    uint16_t pwm_phase = static_cast<uint16_t>(127 + parameter_) << 8;
    BEGIN_SAMPLE_LOOP
      UPDATE_PHASE
      data_.qs.phase[0] += increments[0];
      data_.qs.phase[1] += increments[1];
      data_.qs.phase[2] += increments[2];
      uint8_t value = phase.integral < pwm_phase ? 0 : 63;
      value += data_.qs.phase[0] < pwm_phase ? 0 : 63;
      value += data_.qs.phase[1] < pwm_phase ? 0 : 63;
      value += data_.qs.phase[2] < pwm_phase ? 0 : 63;
      *buffer++ = value;
    END_SAMPLE_LOOP
  }
}

DE-GENERATOR Quellcode
Code:
.
//*************************************************************************
// OscRender: Quad saw or pwm (mit aliasing)
//*************************************************************************
void OscRender_PAD(uint8_t osc_nr)
{
   uint8_t block_size = 40;
   uint8_t shape = Osc.shape[osc_nr];
   uint8_t parameter = Osc.prm[osc_nr];
   uint8_t *buffer;   // pointer name
   uint8_t i = 0;
       
   if (osc_nr == 0)
   {
       if (Voice.buffer_nr == 0)
       {
           buffer = Voice.Buffer2a;
       }
       else {buffer = Voice.Buffer1a;}
   }
   else
   {
       if (Voice.buffer_nr == 0)
       {
           buffer = Voice.Buffer2b;
       }
       else {buffer = Voice.Buffer1b;}
   }
   
   uint16_t phase_increment_ = (Osc.phase_increment[osc_nr] >> 8);
   uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;
   ++phase_spread;
   
   uint16_t increments[3];
   for (uint8_t i = 0; i < 3; ++i) {
       phase_increment_ += phase_spread;
       increments[i] = phase_increment_;
   }

   //BEGIN_SAMPLE_LOOP ---------------------------------------------------
   if (shape == OSC_SAW_PAD) {
       do
       {
           // update Phase
           Osc.phase[osc_nr] += Osc.phase_increment[osc_nr];
           
           if (SREG & 0b00000001) // test overflow
           {
               Osc.phase[osc_nr] = 0;
           }
               
           uint16_t phase_intergral = Osc.phase[osc_nr] >> 8;
           uint8_t value = (phase_intergral >> 10);
           
           // Osc1
           if (osc_nr == 0)
           {
               Osc1.data_qs_phase[0] += increments[0];
               Osc1.data_qs_phase[1] += increments[1];
               Osc1.data_qs_phase[2] += increments[2];
               value += (Osc1.data_qs_phase[0] >> 10);
               value += (Osc1.data_qs_phase[1] >> 10);
               value += (Osc1.data_qs_phase[2] >> 10);
           }
           else // Osc2
           {
               Osc2.data_qs_phase[0] += increments[0];
               Osc2.data_qs_phase[1] += increments[1];
               Osc2.data_qs_phase[2] += increments[2];
               value += (Osc2.data_qs_phase[0] >> 10);
               value += (Osc2.data_qs_phase[1] >> 10);
               value += (Osc2.data_qs_phase[2] >> 10);
           }
           
           // write sample in sound-buffer
           buffer[i++] = ~value;
           
       } while (--block_size);
   }
}

Vielleicht hat jemand eine Idee, wie ich das im DE-GENERATOR verbessern kann.

Gruß Rolf
 
Zuletzt bearbeitet:
Hab nur kurz ins Video gesehen, da grad auf dem Sprung: Der zweite Sound klingt so, als ob da die Frequenzen näher beieinander lägen (also phase_spread und das daraus folgende Delta zwischen den increments deutlich kleiner ist).
 
Hi Cyclotron

Ich hab ein wenig experimentiert und einen kleinen Zufallswert zu dem phase_spread addiert. Klingt schon besser aber halt noch anders wie im Shruthi.

Mein Code
Code:
//*************************************************************************
// OscRender: Quad saw or pwm (mit aliasing)
//*************************************************************************
void OscRender_PAD(uint8_t osc_nr)
{
    uint8_t block_size = 40;
    uint8_t shape = Osc.shape[osc_nr];
    uint8_t parameter = Osc.prm[osc_nr];
    uint8_t *buffer;    // pointer name
    uint8_t i = 0;
       
    if (osc_nr == 0)
    {
        if (Voice.buffer_nr == 0)
        {
            buffer = Voice.Buffer2a;
        }
        else {buffer = Voice.Buffer1a;}
    }
    else
    {
        if (Voice.buffer_nr == 0)
        {
            buffer = Voice.Buffer2b;
        }
        else {buffer = Voice.Buffer1b;}
    }
   
    uint16_t phase_increment_ = (Osc.phase_increment[osc_nr] >> 8);
    uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;
   
    // Test phase_spread with/without random value
    if (Osc.Test_flag == 0)
    {
        ++phase_spread;
    }
    else {phase_spread += (Noise.sample >> 7);}
   
   
    uint16_t increments[3];
    for (uint8_t i = 0; i < 3; ++i) {
        phase_increment_ += phase_spread;
        increments[i] = phase_increment_;
    }

    //BEGIN_SAMPLE_LOOP ---------------------------------------------------
    if (shape == OSC_SAW_PAD) {
        do
        {
            // update Phase
            Osc.phase[osc_nr] += Osc.phase_increment[osc_nr];
           
            if (SREG & 0b00000001) // test overflow
            {
                Osc.phase[osc_nr] = 0;
            }
               
            uint16_t phase_intergral = Osc.phase[osc_nr] >> 8;
            uint8_t value = (phase_intergral >> 10);
           
            // Osc1
            if (osc_nr == 0)
            {
                Osc1.data_qs_phase[0] += increments[0];
                Osc1.data_qs_phase[1] += increments[1];
                Osc1.data_qs_phase[2] += increments[2];
                value += (Osc1.data_qs_phase[0] >> 10);
                value += (Osc1.data_qs_phase[1] >> 10);
                value += (Osc1.data_qs_phase[2] >> 10);
            }
            else // Osc2
            {
                Osc2.data_qs_phase[0] += increments[0];
                Osc2.data_qs_phase[1] += increments[1];
                Osc2.data_qs_phase[2] += increments[2];
                value += (Osc2.data_qs_phase[0] >> 10);
                value += (Osc2.data_qs_phase[1] >> 10);
                value += (Osc2.data_qs_phase[2] >> 10);
            }
           
            // write sample in sound-buffer
            buffer[i++] = ~value;
           
        } while (--block_size);
    }
}

Im Video schalte ich zwischen einer Addition mit random Wert und ohne um.



Gruß Rolf
 
Ich glaube den Fehler gefunden zu haben. Die Osc.phase_increment Werte in meiner DDS sind höher im Vergleich zum Shruthi. Deshalb gabs bei der Berechnung der increments einen Überlauf.
 
Silvester-1514736906-0-12.jpg
 
Hallöchen miteinander und allen ein schönes Neues Jahr

Hab den code jetzt wie im Shruthi Synth angepasst (Osc.phase_increment und buffer Größe). Aber leide keine Besserung. Beim erhöhen des parameter Wertes (0-127) klingt der Sound ab der 21.Sek (parameter Wert = 103) völlig anders im Vergleich zum Shruthi. Als ob da ein Wert überläuft ????

Hab alles geprüft. Ich seh da keinen Fehler. Der einzige Unterschied in den Codezeile ist der Cast im Shruthi:

Code:
uint16_t phase_spread = (
      static_cast<uint32_t>(phase_increment_.integral) * parameter_) >> 13;
  ++phase_spread;
  uint16_t phase_increment = phase_increment_.integral;
  uint16_t increments[3];

Soundtrack:



Code:
//*************************************************************************
// OscRender: Quad saw or pwm (mit aliasing)
//*************************************************************************
void OscRender_PAD(uint8_t osc_nr)
{
    if (osc_nr == 1)
    {
        return;
    }
 
    uint8_t block_size = 128;
    uint8_t shape = Osc.shape[osc_nr];
    uint8_t parameter = Osc.prm[osc_nr];
    uint8_t *buffer;    // pointer name
    uint16_t increments[3];
 
    // Double buffering
    if (Voice.buffer_nr == 0)
    {
        buffer = Voice.Buffer2a;
    }
    else {buffer = Voice.Buffer1a;}
 
    uint16_t phase_increment_ = (Osc.phase_increment[osc_nr] >> 8);
    uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;
    ++phase_spread;
 
    for (uint8_t i = 0; i < 3; ++i) {
        phase_increment_ += phase_spread;
        increments[i] = phase_increment_;
    }
 

    //BEGIN_SAMPLE_LOOP ---------------------------------------------------
    do
    {
        // update Phase
        Osc.phase[osc_nr] += Osc.phase_increment[osc_nr];
   
        if (SREG & 0b00000001) // test overflow
        {
            Osc.phase[osc_nr] = 0;
        }
   
        uint16_t phase_intergral = Osc.phase[osc_nr] >> 8;
        uint8_t value = (phase_intergral >> 10);
   
        Osc1.data_qs_phase[0] += increments[0];
        Osc1.data_qs_phase[1] += increments[1];
        Osc1.data_qs_phase[2] += increments[2];
        value += (Osc1.data_qs_phase[0] >> 10);
        value += (Osc1.data_qs_phase[1] >> 10);
        value += (Osc1.data_qs_phase[2] >> 10);
   
        // write sample in sound-buffer
        *buffer++ = ~value;
   
    } while (--block_size);
}
 
Zuletzt bearbeitet:
OK. Konnte den Überlauf Fehler jetzt beseitgt indem ich "phase_increment" auf 24Bit gesetzt habe. Aber der Sound im DE-GENERATOR klingt immer noch statisch:

QuadSaw from DE-GENERATOR
 
Wie gesagt, im Vergleich mit dem Shruti kommt es mir so vor, als ob die errechnete Spreizung bei Dir einen höheren Wert hat und die Schwebungen dadurch viel schneller laufen (d.h., falls das der problematische Effekt ist - habe hier grad nur mittelmäßige Boxen am Rechner und höre nur diesen Unterschied).

Was passiert denn, wenn du hier

Code:
uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;

mal testweise mit einem größeren Exponenten nach rechts shiftest?
 
Hat keine Auswirkung da der parameter immer 0 ist.

Der parameter ist bei allen Testsounds immer auf 0 eingestellt außer bei der letzten Demo.

Deshalb auch die Zeile ++phase_spread; die den phasen_spread bei parametereinstellung von 0 immer zu 1 macht.
 
Zuletzt bearbeitet:
Also das beste Soundergebnis habe ich jetzt mit einer Addition eines Zufallwertes (8Bit) zum phase_spread gemacht.

Beispiel:

Code:
__uint24 phase_increment_ = (Osc.phase_increment[osc_nr] >> 8);
    uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;
    //++phase_spread;
    phase_spread += (Noise.sample >> 7);
 
    for (uint8_t i = 0; i < 3; ++i) {
        phase_increment_ += phase_spread;
        increments[i] = phase_increment_;
    }

Sound: 1.DE-GENERATOR 2.Shruthi


Gruß Rolf
 
Zuletzt bearbeitet:
Bei Dir scheint aber selbst der minimale phase_spread von "1" einen viel größeren Detune - Effekt zur Folge zu haben. Hast Du bei Deiner Anpassung die Gewichtung von Integer / Fractional - Part im Gegensatz zum Shruti geändert?

Meine Überlegung: Wenn sich die Bitbreite des Integerparts verringert, hätte phase_spread = 1 auch eine höhere relative Wirkung. Damit gibt es mehr Detuning und die Schwebungen laufen schneller.

Gleiches würde auch passieren, wenn Du den Integerpart mit einem zu kleinen Exponenten (hier 8 ) extrahierst. Denn auf dessen Basis wird ja der Spread berechnet. Sowas könnte btw. auch zum dem Überlauf in phase_increment_ führen, so dass Du ab einem bestimmten Parameterwert plötzlich wieder einen sehr kleinen Spread hättest (oder eben auf 24 Bit gehen musst, bevor Du mit 13 shiftest).

Ich kann Deinen Code mangels Gerät leider nur im Kopf durchlaufen lassen. Sorry, wenn das alles nix bringt oder ich selber hier Denkfehler kultiviere. Will die Fehlersuche für andere nicht mit falschen Fährten zukleistern.

Aber: Die Variante mit Zufall klingt nicht schlecht. Finde ich besser als beim Shruti - Beispiel, weil sich die Frequenzen statt eines statischen Detunings immer ein wenig ändern.
 
Hi..

Erst einmal vielen Dank für deine Hilfe. Weis meinst du mit folgendem Satz genau:

"Hast Du bei Deiner Anpassung die Gewichtung von Integer / Fractional - Part im Gegensatz zum Shruti geändert?"

Versteh nicht ganz was du mit Integer / Fractional meinst.

Osc.phase_increment und Osc.phase sind jeweils 24Bit breit.
Die vorberechneten Phasen increments (16Bit Integer) lade ich aus einer Tabelle. Dazu werden noch Pitch und Modulationswerte addiert. Das Ergebnis steht als 24Bit Wert in Osc.phase_increment.
 
Zuletzt bearbeitet:
Besser gesagt: Integral / Fractional - also Fixed Point Math. Danach sieht es zumindest beim Shruti aus, wenn dort beispielsweise von phase_increment_.integral die rede ist (es müsste also auch ein phase_increment_.fractional geben - oder was soll das sein).

Wenn man das - wie in Deiner Variante - mit nur einer Variable macht, muss man halt rechts shiften, um den Integralteil zu erhalten (bzw. maskieren, um den fraktionalen Teil zu bekommen). Das ist hauptsächlich beim Table - Lookup relevant für die Adressierung (.integral) und die Interpolation (.fractional). Oder eben wie hier, wenn nur mit einem Teil (nämlich .integral) gerechnet werden soll.

Wenn man an der Integral / Fractional Aufteilung was ändert (weil man vielleicht andernorts die Größe einer Lookuptable verändert hat), ändert sich auch der Einfluss von phase_spread. Und es kommt dann genau zu diesem Effekt.

Und wenn man den Integralteil nicht korrekt isoliert (also mit zu kleinem Exponenten shifted und der resultierende Wert zu groß ist), kann es zu Überläufen kommen. Beide Probleme hatte ich mit meinem Synth auch schon mal und da lag es an der Änderung der Integral / Fractional Gewichtung. Weshalb ich alle "magic numbers" durch statische Konstanten ersetzt habe, die abhängig voneinander errechnet werden.

Wie gesagt, ich kenne das ganze Ding nicht und kann nur raten, was im Shruti was bedeuten soll. Die daraus resultierenden Folgerungen für dein Gerät mögen daher falsch sein.
 
OK. Vielen Dank für deine ausgiebige Erklärung.

Die Lookup Tabels sind nicht gleich, da ich mit 40.000 Hz abtaste. Im Shruthi sind es 39.215 Hz.
Ich werde mich jetzt noch einmal auf den Shruthi code stürzen.

Vielen Dank für deine Hilfe. Gruß Rolf
 
DE-GENERATOR Build 3.61
- Scope Darstellung: Auflösung wurde von 150 auf 64 Pixel reduziert. Dadurch wird die Systemlast verringert. Zeitbasis passt sich jetzt automatisch an Audiofrequenz an.
- Fehler in Ringmodulation auf der Oszillator Page beseitigt
- Vowel Sound implementiert (Shape: VOW)
- SoundBuffer Größe von 40 auf 128 erhöt. Menüdarstellung und Bedienung wird dadurch etwas schneller und flüssiger
- Für eine geringere Systemlast wurden einige Funktionen in der Soundengine verbessert.
- Berechnung der Notenfrequenz verbessert. Tabellenwerte jetzt 16Bit

DE-GENERATOR.JPG


Gruß Rolf
 
Wann ist das Release Date ?
Es wurde ja nun schon um mehr als 1 Jahr angekündigt.
Die Software kannst und wirst Du doch eh noch mehrfach anpassen, wichtiger ist doch das wir die Hardware haben bevor End of Life von diversen Bauteilen erreicht wird.

Es hilft Dir und Andre bestimmt weiter wenn Ihr mal Geld für eure Arbeit seht.
 
Hallo Rolf,

wir hatten schon vor langer Zeit bei einem Ditherproblem in Deinem Code das Vergnügen. Nun zeigst Du wieder ein bischen Code und ich frage mich, ob Du schon lange programmierst und ob Du die Entwicklungsumgebung von Arduino benutzt?

Bitte versteh das nicht als Klugscheissen, sondern als Tipp, um mit ganz einfachen Mitteln weniger Bugs zu erzielen.

Vielleicht würdest Du nämlich weniger Bugs übersehen, wenn Du den Sourcecode einmal automatisch reformatierst (und auf äquivalente Schreibweisen, die eine gute Entwicklungsumgebung wie Eclipse vorschlagen kann, eingehst)?

Dann würde folgendes Beispiel aus Deinem Code zur Zeile darunter:
Code:
if (Voice.buffer_nr == 0)
{
    buffer = Voice.Buffer2a;
}
else {buffer = Voice.Buffer1a;}
buffer = (Voice.buffer_nr == 0) ? Voice.Buffer2a : Voice.Buffer1a;

Oder die fehlende Einrückung würde verschwinden und klarer machen, dass die beiden Schleifen auch nur bedingt ausgeführt werden:
Code:
    if (!Osc.vw_update) {
        uint8_t offset_1 = U8ShiftRight4(parameter);
        offset_1 = U8U8Mul(offset_1, 7);
        uint8_t offset_2 = offset_1 + 7;
        uint8_t balance = parameter & 15;
 
    // Interpolate formant frequencies.
    for (uint8_t i = 0; i < 3; ++i) {
        Osc.vw_formant_increment = U8U4MixU12(
        pgm_read_byte (&(wav_res_vowel_data[offset_1 + i])),
        pgm_read_byte (&(wav_res_vowel_data[offset_2 + i])),balance);
        Osc.vw_formant_increment <<= 3;
    }
  
    // Interpolate formant amplitudes.
    for (uint8_t i = 0; i < 4; ++i) {
        uint8_t amplitude_a = pgm_read_byte (&(wav_res_vowel_data[offset_1 + 3 + i]));
        uint8_t amplitude_b = pgm_read_byte (&(wav_res_vowel_data[offset_2 + 3 + i]));
        Osc.vw_formant_amplitude = U8U4MixU8(amplitude_a,amplitude_b, balance);
    }
    }
 
Zuletzt bearbeitet:
Als ob da ein Wert überläuft ????

Hab alles geprüft. Ich seh da keinen Fehler. Der einzige Unterschied in den Codezeile ist der Cast im Shruthi:
Code:
uint16_t phase_spread = (static_cast<uint32_t>(phase_increment_.integral) * parameter_) >> 13;

De-Generator:
Code:
uint8_t parameter = ...;
uint16_t phase_increment_ = ...;
uint16_t phase_spread = (uint32_t)(phase_increment_ * parameter) >> 13;

Es gibt natürlich auch Fehler, die darauf basieren, dass die Cast-Regeln in C nicht verinnerlicht sind: Bei einer Multiplikation wird als Akkumulatorwortlänge immer die größere der Wortlängen der beiden Multiplikatoren genommen. Beim Shruthi wird vor der Multiplikation auf 32 Bit gecastet, damit der Akku 32 Bit hat und es nicht zu einem Überlauf kommt. Du dagegen castest erst hinterher, so dass Dein Akku immer nur die Wortlänge von phase_increment_ hat, also 16 Bit, so dass es zu Überläufen kommen kann. Dein Casten auf 32 Bit ist performancemäßig sogar kontraproduktiv, da der übergelaufene Wert dann auf 32 Bit erweitert wird, um dann aufwändig doch nur nach rechts geshiftet zu werden und sofort danach in 16 Bit gecastet zu werden.

Lösung:
Code:
uint16_t phase_spread = ( (uint32_t)phase_increment_ * parameter ) >> 13;
 
Zuletzt bearbeitet:
Gerne, ich kann ja mehr nicht dazu beitragen, dass Dein Projekt vorangeht. Was mir gerade noch einfällt: wenn Du einen 16 Bit-Wert um 13 Bit rechts shiftest, bleiben nur 3 Bit, also 7 Stufen von Deinen Parameter-Werten 0 bis 127 übrig. Und genau diese Sprünge bei der Zunahme der Spreizung habe ich (neben dem Überlauf) in Deinem Beispiel gehört:

Insofern ist das, was Cyclotron über "Integral / Fractional" geschrieben hat, äußerst wichtig für die Vergleichbarkeit mit Shruthi!
 
Der singende DE-GENERATOR


Parametereinstellungen
Osc1: Vowel
Osc2: Vowel -7 semitones
Env1: CUTOFF + Osc1+2 vowel parameter
Env2: VCA
LFO1: Osc1+2 fine tune
Portamento: 14
Delay: Time 114 / Feedback 79 / Volume 127
 
Zuletzt bearbeitet:
ich basel ja seit geraumer zeit auch an einem wavetable synth auf sample basis, aber der name "degenerator" schlägt alles was vor und nach ihm kommen wird :) der klingt jetzt schon wesentlich interessanter als ein schruti.
 
Keine Sorge. Ist alles noch erhältlich. Wir haben auch ein modulares Konzept entwickelt, das uns erlaubt, bestimmte Baugruppen wzB Filterboard, CPU-Board oder Panelboard auszustauschen. Für später ist zB ein neues CPU-Board mit ARM-Prozessor geplant um 4 stimmig und in 16Bit zu spielen (obwohl die 8Bit Auflösung im DEGENERATOR schon einen gewissen Reiz hat).

Gruß Rolf

DEGENERATOR Firmware/Buglist

Build 3.63f 03.03.2018
- Modulationsmatrix: geänderte Amount für Osc Pitch - 16 / + 16 Semitones
- Modulationsmatrix: geänderte Amount für Osc fine - 2 / + 2 Semitones
- Modulationsmatrix: Modwheel Amount Wert vergrößert (von 127 auf 255)
- Osc-Page: Osc-Sync für alles Wellenformen außer Samples

Build 3.63g 11.03.2018
- Init Sound: Osc1:SAW / Mod. ENV1~Cutoff +33 / Mod. ENV2~VCA +63 / Mod. PitchBend~Osc1+2 Pitch +8 / Mod. MWheel = LFO1~Osc1+2 fine +32
- Polling time für Midi buffer auf 250us verringert.
- Midi overflow symbol [!] in der Überschriftleiste integriert

Build 3.64 11.03.2018
- Modmatrix: Mit der Taste "MOD-MAT" kann jetzt von Slot 1-6 auf Slot 7-12 gewechselt werden
- Wird die Taste "CANCEL" länger als 3sec gedrückt, werden im DEGENERATOR alle Noten ausgeschaltet (Panic-Funktion)

Build 3.64a 22.03.2018
- Draw sample curve on osc-page if new sample recording
- Sample Editor: MUTE/CUT/LOOP/REV/SEC/SECL funktioniert jetzt
 


Zurück
Oben