Jump to content

rolfdegen

Members
  • Posts

    457
  • Joined

  • Last visited

  • Days Won

    14

Posts posted by rolfdegen

  1. Hallo Thomasch

    Danke für dein Lob. So einen Synthesizer zu entwickeln ist schon eine große Herausforderung für mich. Ich habe mir das alles viel leichter vorgestellt. Aber jeden Tag gewinne ich neue Erkenntnisse und kann sie in das Projekt einfließen lassen und den AVR-Synthi dadurch verbessern. Die Menü-Seite mit der Einstellung für die Oszillatoren ist noch nicht perfekt gelöst, da werde ich mir noch was besseres Einfallen lassen. Diesbezüglich danke für den guter Tip von dir.

    Aber es sind noch viele Dinge im AVR-Synthi, an denen ich schrauben und programmieren muss. Auf jeden Fall danke ich die für deine Tips. Mal schaun was ich davon noch alles umsetzen kann.

    In Bezug auf deine Frage nach einer Polyphonie muss ich dich leider enttäuschen. Dafür reicht die Rechenleitung des Xmega-Prozessors nicht. Aber der AVR-Synthi besitzt zwei getrennte Audioausgänge und zwei Filterbausteine die unterschiedlich angesteuert bzw moduliert werden können. Dadurch ist so eine Art Pseudo-Stereo möglich.

    Gruß Rolf

  2. Hallo Nils

    Die Kunst ist es, einen Digitalen Synthi nicht zu steril klingen zu lassen. Ein wenig daneben klingt vielleicht besser.

    Nein.. kleiner Scherz :) Du hast natürlich Recht. Man könnte es vielleicht später mit einer größeren Tabelle genauer machen.

    Mal schaun ob dafür noch genug Platz im Flash-Speicher übrig ist. Die einzelnen Noten-Frequenzen sind aber schon sehr genau.

    Gruß Rolf

  3. Hallo nILS

    Danke für deinen Vorschlag. Ich hab das programmtechnisch etwas anders gelöst (siehe Code). Der Versuch mit direkten Ton-Frequenzen für jede Midi-Note zu rechnen, führte immer zu Ungenauigkeiten bei den Semitone-Werten. Die Tabelle besteht jetzt nur aus 14 PhasenDelta-Werten für die 1.Oktave und eine Halbton-Note oberhalb und unterhalb der 1.Oktave. Aus diesen Werten werden die restlichen Halbtöne abgeleitet und berechnet.

    inNote = Midi-Noten-Wert (Key-Nr.)

    inSemi = +-24 Semitones

    inFine = +-100 Cent

    
    //*********************************************
    
    //
    
    //   PhaccuDelta-Value from Midi Note-Nr. 0-11
    
    //
    
    //	 Phaccu_Delta = 411 * Midi-Note Frequenz
    
    //
    
    //*********************************************
    
    uint16_t phaccu_delta [14] = { 
    
    	3171,		// B-1
    
    	3360,		// C1	// Midi-Note 0-11
    
    	3560,
    
    	3771,
    
    	3996,
    
    	4233,
    
    	4485,
    
    	4752,
    
    	5034,
    
    	5334,
    
    	5651,
    
    	5987,
    
    	6343,
    
    	6720 	   // B+1					  
    
    };
    
    
    
    //***********************************************
    
    // Frequenz_Tune
    
    // Wiedergabefrequenz mit Tune-Werten berechnen
    
    //***********************************************
    
    void frequency_tune()
    
    {
    
    	 uint8_t fNote;
    
    	 uint8_t inNote = noten_nr;
    
    	 char inSemi = -12;
    
    	 char inFine = 0;
    
    	 uint8_t fFineByte;
    
    	 uint8_t fOctave;
    
    	 uint8_t fPitchIndex;
    
    	 uint16_t fPitch1;
    
    	 uint16_t fPitch2;
    
    	 int16_t fPitchDiff;
    
    	 __uint24 outPitch;
    
    
    	 //--------- Tune DCO1 -------------------
    
    	 fNote = inNote + inSemi;
    
    	 if(fNote & 0x80) fNote = 0;
    
    	 fOctave = fNote / 12;
    
    	 fPitchIndex = (fNote % 12);
    
    	 fPitch1 = phaccu_delta[fPitchIndex+1];
    
    	 if (inFine > 0)fPitchIndex+=2;
    
    	 fPitch2 = phaccu_delta[fPitchIndex];
    
    	 fPitchDiff = (int16_t) (fPitch2-fPitch1);
    
    	 fFineByte = ((uint8_t)(abs(inFine))) << 1;
    
    	 outPitch = (__uint24)(((((int32_t)fPitch1)<<8) + ((int32_t)fPitchDiff*(int32_t)fFineByte)) >> 8);
    
    	 outPitch <<=fOctave;
    
    	 schrittweite1 = outPitch; 
    
    

    Besten Dank an Maik aus dem mikrocontroller.net-Forum für die großartige Unterstützung.

    Gruß Rolf

  4. Hallo

    Ich habe Heute die Menü-Seite für die DCO-Einstellung fertig gestellt (siehe Bild).
    Jeder Oszillator kann in +-24 Semitone-Schritten (entspricht +- 2 Oktaven) verstellt
    werden. Zusätzlich kan man mit der Fine-Einstellung (Schrittweite +-100 Cent) den
    Oszillator zwischen zwei Halbtönen verstimmen. Mit den Tasten "+" und "-" ist außer-
    dem eine genauere Einstellung der Parameter möglich.


    Bild: DCO-Einstellung im AVR-Synthi

    DCO_Tune_01.jpg


    Gruß Rolf

  5. Hallo

    Ich komme einfach nicht weiter in Bezug auf die Tune-Funktion des

    Oszillators in meinem AVR-Synthi.

    Um die Midi-Note 1-127 in eine Tonfrequenz umzuwandeln greife ich auf

    eine 16Bit Tabelle mit 127 Frequenzwerten im Flash-Speicher des Xmegas

    zu. Wenn ich zB Oszillator2 eine Oktave tiefer stellen möchte, dann

    teile ich einfach den Frequenzwert der Midi-Note. Funktioniert auch

    problemlos und über alle Oktaven sehr genau. Aber wie kann ich den

    Oszillator um einen Halbton verstellen. Ich möchte später mit der

    Tune-Funktion den Oszillator um +-24 Halbtöne verstellen können. Alle

    meine Berechnungen liefern "Krumme Werte" so das eine genaue Einstellung

    nicht möglich ist.

    
    //***********************************************
    
    // Frequenz_Tune
    
    // Wiedergabefrequenz mit Tune-Werten berechnen
    
    // 
    
    // noten_nr = Midi-Key_Nr.
    
    //***********************************************
    
    void frequency_tune()
    
    {
    
         frequenz = pgm_read_word (&(midi_frequenz[noten_nr]));
    
         schrittweite1 = (__uint24) 411 * frequenz;  // Phasendelta für Oszillator1
    
    
         schrittweite2 = (__uint24) 411 * frequenz >> 1; Phasendelta für Oszillator2 (eine Oktave niedriger)
    
    
    

    Gruß Rolf

  6. Hallo amp

    Das Detune-Konzept ist vielleicht noch nicht ganz ausgereift. Die Detune-Funktion "Hard" und "Soft" funktionieren summierend. Das bedeutet, mit "Hard" stelle ich den Detune-Wert auf eine grobe Schwebung ein und kann dann mit "Soft" diese genauer justieren. Es wird eine zusätzliche Möglichkeit geben, beide Oszillatoren zu Oktavieren bzw in Halbton-Schritten zu verstellen. Ferne habe ich jetzt zu der Additiven Synthese und FM Synthese einen Ringmodulator integriert. Die Synchronisation werde ich allerdings noch einmal überarbeiten, so das sie richtig funktioniert.

    Gruß Rolf

  7. Hallo zusammen

    Ich war mal wieder fleißig und habe die letzten Wochen am AVR-Synthi gebastelt
    bzw programmiert. Herausgekommen ist eine neu gestaltete Menü-Seite für die
    DCO Einstellung. Was eigentlich sehr einfach klingt, hat mir doch etwas Kopf-
    zerbrechen gemacht. Die Einstellung der DCO's sollte Ãœbersichtlich und einfach
    zu bedienen sein.

    Bild 1: DCO-Menü

    Waveselect_01.jpg



    Herausgekommen ist eine Wellenform Auswahl-Matrix für beide DCO's um ver-
    schiedene Wellenformen zu kombinieren. Mit der internen Wellenform-Tabelle
    (ca. 22KByte) bestehend aus den Bandlimited Waves (Square, Saw, Triangle)
    und Synthezizer-Waves sind zur Zeit etwas mehr als 500 Wellenform Kombi-
    nationen möglich. Soundbeispiele wirds hier später geben.

    Ferne besteht die direkte Möglichkeit, mit dem Detune-Regler die DCO's gegen-
    einander zu verstimmen um einen Schwebungeffekt im Sound zu erreichen. Mit
    den Schaltern "Soft" und "Hard" kann man die Stärke des Reglers einstellen. Der
    "Sync"-Button synchronisiert beide DCO's wieder und stellt den Detune-Wert
    wieder auf null.

    Bild 2: Auswahl der Synthesizer-Waves

    Waveselect_02.jpg



    Eine etwas schwierige Aufgabe war die Wellenform Auswahl für die Synthesizer-
    Waves. Das habe ich durch ein Untermenü bewerkstelligt. Klickt man auf den
    "WAV"-Button öffnet sich eine neue Menüseite für die Auswahl der Waves und der
    grafischen Ansicht der Wellenform.


    Bild 3: Wellenform-Kombination einer Saw-Waveform und Synthesizer-Waveform

    Waveselect_03.jpg


    Gruß Rolf

  8. Hallo

    Bezüglich der Wave-Files habe von Humfrey aus dem CC2-Forum einen guten Vorschlag erhalten. Die Deklaration der Wave-Daten als Hexadezimal Werte in eine extra Quelltext-Datei schreiben und diese dann per #include in den normalen C-Quelltext mit einbinden. Funktioniert bestens.

    Gruß Rolf

  9. Hallo

    Ich habe mich dazu entschieden, fertige Bandbegrenzte Wavefiles zu benutzen und diese in den Flash-Speicher des Xmegas zu schreiben. Dadurch spar ich mir das ganze Rumrechnen mit Sinus und Cosinus und haste nicht gesehen zur Laufzeit. Die Bandbegrenzten Wavefiles liegen mir als bin.Datei vor und ich möchte diese als ext. Datei in meinen Quellcode mit einbinden. Leider weis ich nicht wie das in Atmel Studio funktioniert. Ich habe mir ersteinmal damit geholfen, das ich die Wave-Datei über einen Hexeditor als Hexadezimal-Tabelle exportiere und in meinen C-Quellcode kopiere. Das funktioniert problemlos. Dadurch wird aber der Quellcode sehr lang und unübersichtlich. Ein Tip wär nicht schlecht. Danke euch.

    Gruß Rolf

  10. Hallo

    Ich hab bei Oliver Gillert, dem Entwickler des genialen Shruthi Synth, mal nachgefragt, wie er das so mit der Sounderzeugung im Shruthi macht und eine Antwort erhalten die ich hier mit Hilfe von Google übersetzt habe.

    "Für die klassischer analoger Wellenformen auf dem Shruthi (Saw, Rechteck, Dreieck),
    verwende ich bandbegrenzten Wavetables .

    Die Wavetables werden durch integrierte bandbegrenzte Impulse (sinc-Funktionen) für verschiedene f0 / fs-Verhältnis
    Abstand mit 2 ** (16 / 12,0) Verhältnisse. Als Ergebnis gibt es ein
    Wavetable für jede Gruppe von 16 Noten. Um zu vermeiden, grobe Übergänge I
    Interpolieren zwischen jeder Wavetable. Für die höheren Töne, die Wellenform
    nähert sich einer sinusförmigen - von der erwartet wird, weil einer quadratischen
    Welle bei 8 kHz auf 44 kHz abgetastet ist in der Tat eine Sinuswelle (die dritte
    Oberwelle bei 24kHz oberhalb Nyquist-Frequenz).

    Hier ist eine Kurve der Wellenformen aus der Shruthi bei unterschiedlichen
    Frequenzen (50, 125, 320, 800, 2k, 5k, 12k):
    http://i.imgur.com/nZmMx.png

    Die quadratischen und Sägezahnwellen gefärbt sind - ich denke, diese Wellenformen
    sind viel interessanter als die "reinen" Sägezahn und "pure" eckig
    Welle.

    Die PWM-Wellenform wird durch Summieren von zwei bandbegrenzten Sägezahn erhalten
    mit einer Phasendifferenz - die Phasendifferenz steuert die PWM-Verhältnis.

    Ich habe versucht mit minBLEP und es verwendet, 70% der CPU. Auf der Shruthi-1 ist
    war keine Option, aber in Ihrem Projekt, das Sie mit einem XMega bei 32
    MHz, so dass es machbar sein, um minBLEP verwenden. Ich würde empfehlen, diese Option wählen,
    da es klingt sehr gut und kann tun hardsync! minBLEP nicht tun können
    Dreiecke, aber Sie können bandbegrenzte Wavetables für diese Verwendung.

    Die Shruthi-1-Code ist Open Source und finden Sie Antworten auf Ihre zu finden
    Fragen Sie sich den Code:
    https://github.com/pichenettes/shruthi-1/"



    Ich werde mich jetzt mal schlau machen, was das "minBLEP" ist. Vielleicht bekomme ich dadurch eine Idee um mein Sound-Problem zu lösen.



    Ich wollte mal wissen wie sich so ein Square-Sound mit Bandbegrenzung (eng. band-limited square)
    auf meinem Synthi so anhört und habe mir die Mühe gemacht zwei Hörbeispiele
    aufzunehmen. Die Aufnahmen wurden am LowPass-Filterausgang bei offenem
    Filter gemacht.
    Die 8Bit Square-Sounds werden aus einer 256 Byte großen Waveform-Tabelle mit 40KHz Sampling-Frequenz an den DAC Ausgang gesendet.


    Bild 1: 1KHz Square-Sound 8Bit (Rechteck) ohne Bandbegrenzung auf dem AVR-Synthi

    square_0.jpg

    Link soundcloud.com:Listen on Soundcloud.com


    Bild 2: 1KHz Square-Sound (aus dem Shruthi-Synth gestohlen ) mit Bandbegrenzung auf dem AVR-Synthi.

    bandlimited_square_0.jpg

    Link soundcloud.com:Listen on Soundcloud.com

    Wie man hört, ist der Square-Sound mit Bandbegrenzung viel sauberer und ohne Nebengeräusche.
    Mal schaun wie ich als "Nicht Studierter" so einen minBlep-Oszillator
    auf meinen Xmega implementieren kann.

    Gruß Rolf

  11. Hallo

    Hat leider nicht funktioniert. Der Phasen-Jitter bleibt unverändert.
    Aber vielleicht mach ich was falsch ???

    Meinen Programmcode habe ich wegen der Ãœbersicht etwas vereinfacht. Die
    markierte Zeile "ANDI phakku1,0b11111110" soll das Phasen-Jitter
    eliminieren indem sie das LSB im Low-Byte der Tabellenadresse löscht.
    Leider ohne Erfolg. Ich habe es auch mit kleineren Werten versucht, aber
    ohne Erfolg. Es ändert sich nur die Auflösung des Samples. Der Phasen-Jitter von +- 25µsec bleibt bestehen (siehe Pics).

     

    //**************************************************************
    // ATMEL Studio 6 Inline Assembler-Routine 
    // Soudausgabe auf DACA Chanal 0
    // TimeR1 Interruptroutine: alle 25usec = 40.0 KHz Samplerate
    //      
    //      (Laufzeit: ?,??? µsec = ??? Takte bei 32MHz)
    // 
    // 
    //           (c) 06.10.2012  Version 1.0 
    //**************************************************************
    
      #include "avr/io.h"
    
      .extern sound_out               // Name der Assembler-Funktion
      .global TCC1_OVF_vect           // Timer1 Interrupt-Vektor
    
     //---------------------------------------------------------------
    // Benutzte Prozessor-Register (Definition als Namen)
    //---------------------------------------------------------------
      dcoout0   = 16      ; R16  DCO-Out      Byte 0
      dcoout1   = 17      ; R17               Byte 1
    
      phakku0   = 18      ; R18  Phasen-Akku  Byte 0
      phakku1   = 19      ; R19               Byte 1
      phakku2   = 20      ; R20               Byte 2
    
      delta0    = 21      ; R21  Phasen-Delta Byte 0
      delta1    = 22      ; R22               Byte 1
      delta2    = 23      ; R23               Byte 2
    
      
    
    //---------------------------------------------------------------
    // Prozessor-Register inkl. Status-Register sichern
    // Interrupt-Routine Timer1-Overflow (40.000Hz)
    //---------------------------------------------------------------
    
    TCC1_OVF_vect:           
      PUSH  R0                       ; 2   R0  auf Stack schieben
      IN    R0, SREG                 ; 1   Status-Register über bereits gesichertes
      PUSH  R0                       ; 2     R0 auf Stack schieben
      PUSH  R1                       ; 2   R1  auf Stack schieben
      PUSH  R16                      ; 2   R16 auf Stack schieben 
      PUSH  R17                      ; 2   R17 auf Stack schieben
      PUSH  R18                      ; 2   R18 auf Stack schieben
      PUSH  R19                      ; 2   R19 auf Stack schieben
      PUSH  R20                      ; 2   R20 auf Stack schieben
      PUSH  R21                      ; 2   R21 auf Stack schieben
      PUSH  R22                      ; 2   R22 auf Stack schieben
      PUSH  R23                      ; 2   R23 auf Stack schieben
      PUSH  R30                      ; 2   R30 auf Stack schieben (ZL)
      PUSH  R31                      ; 2   R31 auf Stack schieben (ZH)
    
    
    //===============================================================
    // SUBTRAKTIVE KLANGSYSYNTHESE
    //===============================================================
    
    SubSynthese:
    
    //---------------------------------------------------------------
    // DCO-1 
    //   * 24-Bit Akku-Breite
    //   * 24-Bit Phasen-Delta (2,384185mHz/Unit)
    //   * 12-Bit Sample
    //---------------------------------------------------------------
    
      // Phasen-Akku 1 incrementieren
      // ----------------------------
    
      LDS   delta0, schrittweite1+0  ; 2   Phasen-Delta aus SRAM laden
      LDS   delta1, schrittweite1+1  ; 2
      LDS   delta2, schrittweite1+2  ; 2
    
      LDS   phakku0, phaccu1+0       ; 2   Phasen-Akku aus SRAM laden
      LDS   phakku1, phaccu1+1       ; 2
      LDS   phakku2, phaccu1+2       ; 2
    
      ADD   phakku0, delta0          ; 1   Phasen-Akku + Phasen-Delta
      ADC   phakku1, delta1          ; 1
      ADC   phakku2, delta2          ; 1
        
      STS   phaccu1+0, phakku0       ; 2   Phasen-Akku in SRAM zurückschreiben
      STS   phaccu1+1, phakku1       ; 2
      STS   phaccu1+2, phakku2       ; 2
     
      // Die oberen 12Bit des Phasen-Akkus extrahieren
      // ---------------------------------------------
      ANDI  phakku1, 0xF0            ; 1   Lower Nibble in Byte 0 abnullen
      LSR   phakku2                  ; 1   Division durch 8 (16-Bit)
      ROR   phakku1                  ; 1
      LSR   phakku2                  ; 1
      ROR   phakku1                  ; 1
      LSR   phakku2                  ; 1
      ROR   phakku1                  ; 1
        
      // SAW-Sample über aktive Phase aus Wavetable laden
      // -------------------------------------------------
      LDI   R30, 0xFC                ; 1   Basis-Adresse Saw-Tabelle (Low-Byte)
      LDI   R31, 0x03                ; 1                             (High-Byte)
      //********************************************************************************
      ANDI  phakku1,0b11111110     ;     Phasen-Jitter eliminieren 
      //********************************************************************************
      ADD   R30, phakku1             ; 1   Phasen-Pointer addieren
      ADC   R31, phakku2             ; 1
      LPM   dcoout0, Z+              ; 3   Sample aus Wavetable laden (12-Bit)
      LPM   dcoout1, Z               ; 3   
    
     // --------------------------------------------------------------
     // Ausgabe am DAC-Converter (DACA Chanal 0)
     // --------------------------------------------------------------
      STS   0x0318, dcoout0          ; 2   L-Byte to DAC-Register (CH0DATAL Adr. 0x0318)
      STS   0x0319, dcoout1          ; 2   H-Byte to DAC Register (CH0DATAH Adr. 0x0319)
        
    // --------------------------------------------------------------
    // Prozessor-Register inkl. Status-Register wiederherstellen
    // --------------------------------------------------------------
      
      POP   R31                      ; 2   R31 von Stack wiederherstellen (ZH)
      POP   R30                      ; 2   R30 von Stack wiederherstellen (ZL)
      POP   R23                      ; 2   R23 von Stack wiederherstellen
      POP   R22                      ; 2   R22 von Stack wiederherstellen
      POP   R21                      ; 2   R21 von Stack wiederherstellen
      POP   R20                      ; 2   R20 von Stack wiederherstellen
      POP   R19                      ; 2   R19 von Stack wiederherstellen
      POP   R18                      ; 2   R18 von Stack wiederherstellen
      POP   R17                      ; 2   R17 von Stack wiederherstellen
      POP   R16                      ; 2   R16 von Stack wiederherstellen
      POP   R1                       ; 2   R1  von Stack wiederherstellen
      POP   R0                       ; 2   Status-Register über R0 wieder
      OUT   SREG, R0                 ; 1     herstellen
      POP   R0                       ; 2   R0  von Stack wiederherstellen
      RETI                           ; 4   Return Interrupt und I-Flag quittieren
    
    // --------------------------------------------------------------
      .end
    //
    

     


    Bild 1: Saw Frequenz 1KHz mit voller 12Bit Auflösung
    ANDI phakku1,0b11111111
    ANDI phakku2,0b11111111

    Saw_12Bit.jpg




    Bild 2: Saw Frequenz 1KHz mit 5Bit Auflösung
    ANDI phakku1,0b10000000
    ANDI phakku2,0b11111111

    Saw_5Bit.jpg




    Bild 3: Saw Frequenz 1KHz mit 3Bit Auflösung
    ANDI phakku1,0b00000000
    ANDI phakku2,0b11111100

    Saw_3Bit.jpg



    Mein Fazit: Das Jitter von 25µsec (Taktzyklus für den Zähler des
    Phasenaccus) werde ich prinzipiell nicht los. Beim Sinus ist das auch
    kein großes Problem. Dieser wird sauber und störungsfrei wiedergegeben .
    Aber für die anderen Wellenformen wzB. Sägezahn, Puls oder Rechteck ist
    die Softwaregenerierte DDS-Synthese bei einer Taktrate von 25µsec nicht
    zu gebrauchen.

    Muss mir also was anderes überlegen. Gruß Rolf

  12. Hallo

    Ich habe einen guten Tip von Maik aus dem mikrocontroller.net Forum bekommen.

    Er meint: Den Jitter kann man vermeiden durch Reduzierung der Akkumulator-Breite

    (nicht beim Akkumulieren, sondern beim Ausgeben der Saw, bzw. beim

    Adressieren des Wavetables) ab bestimmten Frequenzen. Also im Prinzip

    kann man es so machen, dass man zB. ab 500Hz immer das LSB nullt, ab

    1000Hz nullt man dann das LSB und das nächst höhere, usw. Diese

    Grenz-Frequenzen kann man anhand des Phasen-Deltas setzen.

    Diese Methode ist im Prinzip immer ein Abrunden, was dazu führt, das der

    geringfügige Jitter wegbleibt, weil er weggerundet wird. Das hat aber

    auch Nachteile:

    1. Man verliert bei höheren Frequenzen die Auflösung

    2. Höhere Frequenzen werden leiser

    3. Man erzeugt automatisch ein DC-Offset, was man berücksichtigen

    sollte, oder besser noch, gleich im Oscillator kompensiert.

    Den Tip von Maik werde ich gleich Morgen versuchen umzusetzen. Werde dann hier berichten. Bin gespannt..

    Gruß Rolf

  13. Hallo

    Ich habe hier einmal den relevanten Programmteil der für die Erzeugung der Sinus und Saw-Wellenform verantwortlich ist dargestellt. Die gesammte Sound-Routine (hier nicht abgebildet) wird in einem Timer-Interrupt alle 25µsec im Main-Programm (C-Code) aufgerufen.

    Wellenformspeicher für Sinus (4096 Werte 12Bit)

    12Bit DAC-Wandlung im Xmega-Prozessor 1MHz-Wandlerate

    
    //===============================================================
    
    // SUBTRAKTIVE KLANGSYSYNTHESE
    
    //===============================================================
    
    
    SubSynthese:
    
    
    //---------------------------------------------------------------
    
    // DCO-1 
    
    //   * 24-Bit Akku-Breite
    
    //   * 24-Bit Phasen-Delta (2,384185mHz/Unit)
    
    //   * 12-Bit Sample
    
    // ( 38 Takte = 1,188 µsec)
    
    //---------------------------------------------------------------
    
    
      // Phasen-Akku 1 incrementieren
    
      // ----------------------------
    
    DCO1Calc:
    
      LDS   delta0, schrittweite1+0  ; 2   Phasen-Delta aus SRAM laden
    
      LDS   delta1, schrittweite1+1  ; 2
    
      LDS   delta2, schrittweite1+2  ; 2
    
    
      LDS   phakku0, phaccu1+0       ; 2   Phasen-Akku aus SRAM laden
    
      LDS   phakku1, phaccu1+1       ; 2
    
      LDS   phakku2, phaccu1+2       ; 2
    
    
      SUB   phakku0, delta0          ; 1   Phasen-Akku + Phasen-Delta
    
      SBC   phakku1, delta1          ; 1
    
      SBC   phakku2, delta2          ; 1
    
    
      STS   phaccu1+0, phakku0       ; 2   Phasen-Akku in SRAM zurückschreiben
    
      STS   phaccu1+1, phakku1       ; 2
    
      STS   phaccu1+2, phakku2       ; 2
    
    
      // Die oberen 12Bit des Phasen-Akkus extrahieren
    
      // ---------------------------------------------
    
      ANDI  phakku1, 0xF0            ; 1   Lower Nibble in Byte 0 abnullen
    
      LSR   phakku2                  ; 1   Division durch 8 (16-Bit)
    
      ROR   phakku1                  ; 1
    
      LSR   phakku2                  ; 1
    
      ROR   phakku1                  ; 1
    
      LSR   phakku2                  ; 1
    
      ROR   phakku1                  ; 1
    
    
      // Waveform-Selektion
    
      // ------------------
    
      LDS   dcowave, DcoWaveForm     ; 2   Wellenform-Selektion laden
    
      SBRS  dcowave, 0               ; 1/2 
    
      RJMP  DCO1Sine                 ; 2   Sinus bestimmen
    
    
      // Saw über 1:1 Phase ausgeben
    
      // ---------------------------
    
    DCO1Saw:
    
      LSR   phakku2                  ; 1   Phasen-Akku / 2
    
      ROR   phakku1                  ; 1
    
      MOV   dcomix0, phakku1         ; 1   Phase umladen
    
      MOV   dcomix1, phakku2         ; 1
    
      RJMP  DCO1End                  ; 2   Fertig
    
    
      // Sample über aktive Phase aus Wavetable laden
    
      // --------------------------------------------
    
    DCO1Sine:
    
      LDI   R30, 0xFC                ; 1   Basis-Adresse Sinus-Tabelle (Low-Byte)
    
      LDI   R31, 0x03                ; 1                               (High-Byte)
    
      ADD   R30, phakku1             ; 1   Phasen-Pointer addieren
    
      ADC   R31, phakku2             ; 1
    
      LPM   dcomix0, Z+              ; 3   Sample aus Wavetable laden (16-Bit)
    
      LPM   dcomix1, Z               ; 3   => in MixerSumme als Initialwert
    
    
    DCO1End:
    
    

    Gruß Rolf

  14. Hallo Imp

    Die Zwischentöne, die der Phasen-Jitter verursacht, kann man sehr deutlich ab einer Frequenz von 1KHz warnehmen. Hier ein Soundbeispiel mit einer SAW-Wellenform. Start 100Hz, Ende 5000Hz:

    In Bezug auf die Detune-Funktion werde ich im DCO-Menü einen Auswahl-Button "Low-Detune" und "High-Detune" für die Einstellung mit dem Bargraph integrieren.

    Gruß Rolf

  15. Hallo

    Stundenlagens Grübeln und die Notizen beim Schalfen unters Kopfkissen

    haben leider nicht geholfen

    Ich finde einfach keinen Lösungsansatz für mein Jitter-Problem. Würde

    man die Soundausgabe über einen Timer steuern, könnte man die

    DDS-Problematik vielleicht vergessen. Einen Lösungsweg wie es Olivier

    Gillet bei seinem Shruthi-Synth macht (Soundausgabe über PWM und ext.

    VCF+VCA) will ich nicht nachbauen. Ich möchte mein eigenes Hardware

    Konzept beibehalten.

    Link Shruthi Synth: http://mutable-instruments.net/shruthi1

  16. Hallo zusammen

    Ich habe Probleme mit Phasen-Jitter in meinem Synthi-Projekt. Der Phasen-Jitter entsteht, wenn der Wert des Phasenaccus mit dem Wert für die Schrittweite nicht gerade teilbar ist. In meinem Fall beträgt der Jitterwert max 25µsec = 40KHz und das ist genau die Sample-Frequenz für die Tonausgabe (siehe Bild 1+2). Wenn ich für die Schrittweite eine Wert nehme, mit dem der Phasenaccu (24Bit) gerade teilbar ist, sind keine Störungen warnehmbar und auf dem Oszilloskop ist eine saubere Saw-Wellenform zu sehen (Bild 3+4).

    Phasenaccu 24Bit
    Schrittweite 24Bit
    Samplerate 25usec (40KHz)
    Gemessen am LP-Filterausgang

    Bild 1: SAW-Wellenform ca. 2031Hz mit Phasen-Jitter (max. 25usec / Div. 100µsec)

    saw_with_jitter.jpg


    Bild 2: SAW-Wellenform ca. 2031Hz mit Phasen-Jitter (max. 25usec / Div. 2msec)

    saw_with_jitter_02.jpg




    Bild 3: Saw-Wellenform ca. 2038Hz ohne Phasen-Jitter (Div. 100µsec)

    saw_without_jitter.jpg


    Bild 4: Saw-Wellenform ca. 2038Hz ohne Phasen-Jitter (Div. 2msec)

    saw_without_jitter_02.jpg



    Das Problem lässt sich nach meiner Meinung nur durch ein Zurücksetzen des Phasenaccus auf 0 beheben, wenn die Wellenform neu beginnt . Dadurch wird der Phasenaccu mit der Wellenformerzeugung synchronisiert und es ensteht kein Jitter mehr. Allerdings ist dann keine genau Frequenzeinstellung mehr möglich. Versuche mit Erhöhung der Bitbreite des Phasenaccus waren nicht erfolgreich. Der Phasen-Jitter reduzierte sich dadurch nicht..

    Zur Information habe ich noch eine Infoseite gefunden, die das Phasen-Jitter Problem bei der DDS Synthese sehr anschaulich beschreibt: http://www.elektronik-labor.de/AVR/DDSGenerator.htm

    Gruß Rolf

  17. Hallo

    Es ist ein schöner sonniger Montag in Wuppertal und das hebt mal wieder die Laune und den Tatendrang in mir und für mein Projekt. Wie man auf den Bilder erkennen kann, arbeite ich gerade an den Menüfunktionen des AVR-Synthis. In der Tabreiterauswahl ist das "Main"-Menü hinzugekommen (Bild 1). Es vereinfacht die Navigation zu den vielen Menü-Seiten.

    Bild 1: Main-Menü

    avr_synth_menue_20.jpg


    Ferner gibt es auf jeder Menüseite einen sogenannten "Home"-Button (Bild 2: Kreis mit Kreuz Symbol unten Rechts), mit dem man schnell wieder ins Main-Menü gelangt. Die geänderten Parameter werden vor dem Schließen der Menüseite automatisch im EEPROM des ATxmegas abgespeichert.

    Bild 2: DCO1-Menü

    avr_synth_dco1_20.jpg


    Im DCO1-Menü gibt es zur Zeit die Auswahl der Wellenformen und die Möglichkeit, mit dem "Detune"-Fader die Frequenz des Oszilators1 zu Oszilator2 ein wenig nach oben zu verstimmen um Schwebungseffekte zu erzeugen. Eine Frage stellt sich jetzt noch in Bezug auf die max. Höhe der Detune-Werte. Da tappe ich als "Anti-Musikus" etwas im Dunklen. Um einen Schwebungseffekt zu erzielen, reicht ja schon eine minimale Frequenzabweichung von weniger als 0,01 Hz. Meine Frage ist nun, wie groß dieser Wert maximal sein sollte. In einem Youtube-Video habe ich das ganze mal veranschaulicht (siehe Video-Link). Die Grundfrequenz beider Oszilatoren liegt bei 200Hz.

    Youtube-Video: Detune-Funktion im AVR-Synthi

    Am Ende des Videos demonstriere ich die Filterfunktion mit den neuen SSM2044 Filterbausteinen.


    Gruß Rolf

  18. Hallo

    Habe Heute das Menü für den Audio-Filter im Synthesizer entwickelt (siehe Bild). Die Fader sind groß genug und lassen sich auch leicht mit einem Finger bedienen. Leichter und feinfühliger gehts natürlich auch mit einem Tabstift. Ich benutze zum Beispiel einen alten Kugelschreiber mit einer Kunststoffspitze. Funktioniert damit prima und hat nix gekostet.

    Bild: VCF1-Menü auf dem Touch Panel des AVR-Synthis

    VCF1_Menue.jpg


    Gruß Rolf


    Nachtrag: Durch die Anregung von Imp und Wolfgang aus dem CC2-Forum (alias Wiesolator), habe ich mich dazu entschieden, für die Parameter-Eingaben zusätzlich einen Drehencoder mit Rast- und Tasterfunktion zu verwenden. Damit werden die Parametereingaben noch leichter und komfortabler.

    • Like 1
  19. Hallo

    Ich habe jetzt das Bedienschema fuer das Touch Panal Display fertig gestellt. Die Systemeinstellungen fuer den Synthesizer werden ueber mehrere Menue-Seiten aufgerufen und koennen dort veraendert und abgespeichert werden. Das Aufrufen der einzelnen Menue-Seiten erfolgt ueber die Tabreiter (siehe Youtube-Video).

    Bild 1: Touch Panal Menue AVR-Synthi

    AVR_Synth_Menue.jpg



    Youtube Video


    Im Moment sind die Menue-Seiten noch leer. Ich werde mir jetzt Gedanken darueber machen muessen, wie ich die Synthesizer-Funktionen in den Menue-Seiten sinnvoll gestalte.


    MfG Rolf

  20. Hallo Nils

    Ich wollte keine "Tausend" Potis und Schalter verwenden. Aus diesem Grund habe ich ein "intelligentes" Display mit Touchpanal verwendet. Der Einsatz eines DOG-Display mit Touchpanal wäre mit einer höhere Prozessorlast verbunden und das ginge dann auf Kosten der Soundqualität und Soundeffekte. Alternativ ist später vielleicht ein schickes LCD- oder OLED-Display geplant. Kann man sich auch selber gestalten wie man möchte. Ich werde die Software später veröffentlichen. Der größte Teil der Software ist in C geschrieben, nur der Soundteil in Assembler.

    Gruß Rolf

  21. Hallo ilmenator

    Danke :) Es sind noch viele Dinge geplant wzB Midi-Out, SD-Card. Dank des großen Speichers (8MB SDRAM) auf dem Xplained Board sind später auch Wavetables möglich.

    Was mich selber an meinem Synthi-Projekt so erstaunt, das die 12Bit Soundausgabe dank der analogen Filterbausteine SSM2044 gar nicht mal so schlecht klingt.

    Für die Leute, die später an einem Nachbau interessiert sind: Die Filterbausteine SSM2044 kann man auch in größeren Stückzahlen im Online-Shop von www.darisusgmbh.de bestellen.

    Gruß Rolf

×
×
  • Create New...