Hallo Ihr Lieben..
Ich entwickel zur Zeit einen Synthesizer auf Basis eines ATxmega128A1
Prozessors. Falls euch mein Projekt interessiert schaut mal unter
http://www.cczwei-forum.de/cc2/thread.php?threadid=5878 vorbei. Da gibts
jede Menge an Informationen Rund um die Musikelektronik und auch
Programmier-Tips in C, um einen eigenen Synthesizer zu bauen.
Viel Spaß beim stöbern wünscht euch Rolf
Hallo Rolf,
erstmal möchte ich bekunden das du sehr schöne Erklärungen auf der CC2
Seite zu dem Thema gemacht hast. Die anderen Links sind auch sehr
schick. Find das immer wieder erstaunlich was man klangtechnisch aus nem
AVR holen kann. Dafür das das "nur" nen popeliger 8-bitter ist :-)
Werd deinen Beitrag weiterhin verfolgen und bin mal gespannt was du aus
dem Xmega rauskitzeln kannst. Ich selbst bin bei meinem Synthesizer
(schau mal hier im Forum unter Audio-DSP mit Spartan 3) einen anderen
weg gegangen. Da mache ich die Klangerzeugung/Bearbeitung/Filterung in
einem FPGA, und gesteuert wird das ganze von einem AVR. In dem Artikel
sind auch noch Links zu You-Tube Videos. Das ganze ist allerdings schon
was länger existent und liegt momentan auch was rum. Aber evtl
überarbeite ich den Synth mal mit einem neueren Spartan. Insgesamt hat
man mit der Platform (wenn sie mal fertig bzw dokumentiert wäre) recht
viele Möglichkeiten, da ich von vornherein auf der Verarbeitungsebene
modular bin.
Weiterhin viel Spaß beim Synth-DIYing :-)
Hallo Rene
Ich habe jetzt die ersten Sounds von meinem Synthi ins Netz gestellt.
Kann man sich auf SoundCload unter
http://soundcloud.com/rolfdegen/sets/testsounds-avr-synthesizer/
anhören. Die Sound sind zwar nix Besonderes, weil der Synthi zur Zeit
nur ein Oszillator und ein Hüllkurvengenerator besitzt. Aber ich bin
gerade dabei, das ganze auf drei Oszilatoren und 3 Hüllkurvengeneratoren
auszubauen.
In Bezug auf dein Audio-Projekt: Ich habe mir schon vor längerer Zeit
dein "Audio-DSP mit Spartan 3" hier auf mikrocontroller.net angesehen
bzw angehört und bin von der Soundqualität einfach begeistert. Ist schon
eine ganz andere Liga :)
Ich habe mir jetzt bei Watterott ein STM32F4 Discovery Board bestellt
und bin schon gespannt was das Bord im Audiobereich so alles kann. Die
Eckdaten sind vielversprechend zB. 168MHz CPU-Takt, 1 MB Flash, 192 KB
RAM, FPU und 24Bit DA-Wandler Chip onBoard. Werde das Board ausführlich
testen und vielleicht wird ja ein Wave-2 daraus werden. Schaun wir mal..
Gruß Rolf
Hallo Synthbastler :)
Ich habe mir auch schon einen Synth mit einem AVR gebastelt, allerdings
habe ich dann sehr bald aufgegeben weil mir der Sound nicht gefallen
hat. Ich bin halt besseres gewohnt, da ich aus der VST-DSP Ecke komme.
Habe mir dann mal ein paar Dev-Boards für schnellere Controller gesucht
(PIC32, dsPIC, AVR32...), allerdings bin ich da nicht sonderlich weit
gekommen. Der dsPIC ist recht simpel und billig, und man kommt schnell
zum DSP-Teil des Projekts, allerings ist er nicht sonderlich schnell.
AVR32 ist irgendwie sehr kompliziert, dafür ist er einigermaßen schnell.
Gleiches gilt für den PIC32.
Rene´s Projekt find ich recht interessant, und ich hatte schon lange vor
mal mit FPGAs zu arbeiten, weil damit geht man den Großteil der
Geschwindigkeits-Probleme aus dem Weg.
Jetzt habe ich wieder etwas mehr Zeit, und wollte das mal angehen. Habe
mich schon etwas informiert, und nach Dev-Boards umgesehen. Evtl. werde
ich mir ein CycloneII-Board holen, ist zwar nicht mehr der aktuellste,
aber das Board hat alles drauf was ich brauche, und eine
Synthesizer-Demo wird gleich mitgeliefert. Das einzige was mir da noch
etwas Sorgen macht ist: bei der freien Version von Quartus steht
"Windows 32bit only", und meine 32-bit Kisten habe ich alle ausgemustert
:)
@Rolf
Also die Sounds klingen schon recht witzig. Old-School-8-Bit-Style :-)
Bin mal gespannt auf weitere Demos. Wie willst das denn mit den Filtern
machen ? Analoge Filter die digital gesteuert werden ? Oder direkt
digitale Filter ?
Und danke noch für das Lob :-))
@Maik
was würde denn gegen Xilinx sprechen ?
Also den Spartan 6 zu routen war sehr angenehm. Mein (noch nicht
phsyisch vorhandenes, aber schon teilgeroutetes Test-Board) schaut schon
ganz gut aus und hat neben nem Codec, nem AVR noch 16MB SDRAM an dem
FPGA angeklebt bekommen. Aus dem Teil ne Platform zu machen ist
mittlerweile nen Klacks.
Würde das Audio-Projekt ja gerne nochmal reaktiveren (fürs Forum) aber
bei der "alten" Version war die Resonanz schon nicht so groß. Wobei das
Board als solches vllt noch für den einen oder anderen Interessant sein
könnte. Ist auch "relativ" einfach zu Löten (144'er QFP und 0603 SMD auf
ner doppelseitigen Platine). Na ja .. mal schauen. Vllt starte ich das
Projekt erneut.
Rene B. schrieb:> Also die Sounds klingen schon recht witzig. Old-School-8-Bit-Style :-)
Hallo Rene. Wenn schon.. denn schon. Es sind 12Bit Sounds :) Gerechnet
wird intern mit 16Bit und das Ergebnis wird dann für den Xmega-DAC auf
12Bit reduziert.
Eine Filtertechnik habe ich im Moment noch nicht integriert. Es läuft
aber mit Sicherheit auf analoge Filter-Bausteine hinaus, weil der Xmega
einfach zu wenig Rechengeschwindigkeit besitzt. Der ist schon voll mit
der Soundausgabe, Hüllkurve, Midi und Grafischen Touch-Display
beschäftigt, da bleibt keine Zeit mehr für eine Filterberechnungen.
Allerdings weis ich noch nicht, was ich für Filter-Chips nehmen soll.
Hatte Anfang der 90er Jahre mit dem Bau meines 1.Synthesizers von der
Firma Doepfer (http://www.doepfer.de/home_d.htm) begonnen und dafür ein
paar Curtis IC bestellt. Aber ich war "jung" und habe den Synthi nie
fertig gebaut. Und nach den vielen Umzügen sind die Bauteile einfach
verschwunden.
Hallo Maik. Ich habe mir die Beschreibung des Cyclone II Board mal
angesehen. Kann man sich hier herunterladen:
http://www.altera.com/products/devkits/altera/kit-cyc2-2C20N.html#note2
Das Board ist ja ganz schön groß und teuer im Verhältnis zum STM32F4
Discovery Board, hat aber alles was man so brauch für einen Synthi. Für
den Anfang bleibe ich erst einmal bei einem kleinen und preisgünstigen
Board um damit Erfahrungen zu sammeln. Später trau ich mich dann an die
größeren Boards wzB das EVK1104 evaluation Board von Atmel:
http://www.atmel.com/tools/EVK1104.aspx und als Entwicklungs-Tool AVR
Studio das ich jetzt schon für den Xmega benutze.
Gruß Rolf
@Rolf und Maik
was vllt auch noch als Platform sehr interessant wäre ist der Raspberry
PI. Der hat ja nen 700MHz ARM am werkeln. Das sollte für digitale
Synthies dicke reichen. Jedenfalls werd ich mich mit der Platform
auchmal auseinandersetzen, selbst wenns eben nichts zum nachbauen ist.
@Rolf
Die Curtis-Chips hätte ich gerne mal in den Fingern. Aber die sind so
schwer zu bekommen. Ich glaube da würd ich eher ein diskretes Design
(State-variable-Filter, oder den klassischen Moog-Filter) nehmen.
Hab damals auch mal nen "klassischen" Filter analog aufgebaut. Aber das
ganze ist dann irgendwann liegen geblieben.
Würde gerne aber bei meinem Audio-Projekt noch analoge Filter
integrieren und mit jeweils nem eigenen Codec versehen. Dann hätte ich
die Möglichkeit Signale zu mischen und beliebig zu routen (und eben auch
durch den Filter). Wäre für nen Mischpult mit Effektgerät ganz nützlich,
oder eben für nen Synthie (selbst wenn der dann nur max x-stimmig werden
kann wobei x dann die Anzahl analoger Filter ist).
Aber reizvoll sind analoge Synthies allemale. Egal ob mit oder ohne
digitale Komponenten.
Na und ?
Der hat doch USB-Schnittstellen. Und ne Soundkarte ist doch schnell da
dran gekorkt :-)
Wobei es mich mal interessieren würde wie schwer bzw unmöglich es ist
bzw wäre das Board ohne Linux zu betreiben. Also quasi die gesamte
Rechenleistung mit allem drum und dran für sich ganz alleine zu haben
:-)
Und ich denke von den Schnittstellen her ist es bestimmt möglich auch
nen guten Wandler noch dranzuflanschen. Notfalls per FPGA-Daughter Board
:-)
@Rolf: Ja das Board ist recht teuer im Vergleich zu den
Controller-Dev-Boards. Das relativiert sich aber in dem Moment, wo man
es mit anderen FPGA-Dev-Boards vergleicht. Auch kostet der FPGA auf dem
Board alleine schon mehr als 50 Euro :)
Ich habe das EVK1105, ansich ist das nicht schlecht, nur hat das einen
PCB-Fehler, was es extrem schwer macht das Teil zu programmieren. Und
DFU wird in Atmel Studio 6 nicht mehr unterstützt, deswegen benötigt man
ab da auch noch einen JTAG-Programmer.
@Rene: Ich habe mir ein paar Xilinx-Boards angeschaut, das günstigste
mit Codec was ich gefunden habe ist das Digilent Atlys, was aber schon
doppelt soviel kostet wie das CycloneII
Dein eigenes Layout ware natürlich optimal, weil das quasi das nötigste
enthält. Ich würde gern eins nehmen, allerdings benötige ich es fertig
aufgebaut. Da ich am Anfang meine "Lötfehler" als "mögliche
Fehlerquelle" ausschließen möchte.
Das Pi kommt für mich nicht in Frage. Mein Ziel ist es ein
Synthesizer/Effektgerät zu bauen, dh. später möchte ich eine eigene
Platine fertigen können.
Auf einem AVR ist schon einiges möglich - C, viele Kanäle und komplexe
Sounds passen da aber nicht mehr zusammen. Das größte Problem ist die
Rechenleistung für die vielen Kanäle. Wenn man 8 Kanäle realisieren
möchte hat man bei 44100 Hz @32Mhz
32Mhz : 44100 : 8 = 90 Takte pro Kanal Zeit.
In meinem Synthesizerprojekt konnte ich die Takte/Kanal auf ~15
reduzieren, dafür waren keine komplexen Sounds mehr möglich.
@Samuel
Hast du mal nen Link zu deinem Projekt ?
Würd mich mal interessieren. Im Prinzip ist mit den AVRs ja
soundtechnisch schon einiges machbar wenn man Kompromisse bei der
Samplingrate macht.
Aber Filter-Operationen sind halt bei der begrenzten Rechenleistung
schwierig. Oder sehr Tricky :-)
;Im Register ueber freqcnt2 liegt der Index zur richtigen Soundtabelle
7
movw ZL, freqcnt2
8
lpm temp, Z
9
10
;Lautstärke
11
mulsu temp, volsum1
12
13
;mischen
14
add sample, 0
15
adc sample2, 1
Ich habe die Hauptroutine nochmal herausgekramt:
Für einen Kanal sind es hier 11 Takte, allerdings kommt noch ein
bisschen dazu für Register laden etc.
Wenn man so viel optimiert wird irgendwann der Ram zum Flaschenhals mit
2 Zyklen pro Zugriff. Also werden alle Daten von bis zu drei Kanälen
geladen und die nächsten 64 Samples werden berechnet.
Hallo zusammen
Zufällig habe ich auf einer japanischen Website ein interessante FM
Sound Programm für das ST32F4 Discovery Board entdeckt. So wie es
verstanden habe (mein Japanisch ist nicht besonders gut :), ist das
Soundmodul 16stimmig polyphon, Samplingrate 48KHz und Midi fähig. Ich
habe die Firmware über ST-Link Utility direkt mal ins Discovery geflasht
. Nach dem Reset läuft sofort eine Sounddemo ab. Klingt nicht schlecht
wenn ihr mich fragt..
Link: http://d.hatena.ne.jp/pcm1723/20120418/1334746384
Download: http://www.geocities.jp/pcm1723/html2/download.htm
MfG Rolf
@Rolf
Hast du vllt mal das Sound-Demo als MP3 oder nen Link wo man sich dieses
Demo anhören kann ?
Ich hab leider keinen STM zur Hand um das mal ausprobieren zu können.
Würde mich aber dennoch mal interessieren wie das klingt. FM-Synthese
ist ja klanglich schon recht mächtig bzw bietet viele Möglichkeiten. Vor
allem wenn man FM-Synthese als Klangquelle nutzt und mit einem
nachgeschalteten analogen oder digitalen Filter "verfeinert" :-)
Das ist auch eins der Dinge die ich meinem Audio-Projekt gerne noch
beibringen würde. Aber bisher hab ich mich mit der FM noch nicht weiter
beschäftigt (also das ich das aufm PC mal "durchrechne" und einfach mal
was rumspielen kann). Von daher danke schonmal für die Links. Vllt kann
ich mir da was für aufn PC mal selbststricken.
Hallo Rene
Ich werde die Demo Heute in soundcloud.com bereitstellen und dich hier
informieren. Ferner versuch ich Heute einen Optokopler an das Discovery
Board "anzukleben", um die Demosounds anzuspielen. Mal schaun obs
funktioniert..
Hab noch eine interessante Projekt-Seite im INet gefunden. Nennt sich
"Jo-Midi-FM". Ist eine japanische Website. Mit Google-Translate in
Deutsch kann man es uebersetzen lassen.
Link: http://www.geocities.jp/pcm1723/
MfG Rolf
Hallo zusammen..
Ich habe an das Discovery-Board jetzt einen Midi-Anschluss gelötet,
damit ich die Demo Sound des FM Sound Generator über ein Midi-Keyboard
abspielen kann.
Schaltplan gibts hier:
http://www.cczwei-forum.de/cc2/thread.php?postid=76348#post76348
Gruß Rolf
Hallo Rene
Ich habe den Demo-Sound des STM32F4 Discovery Boards mal ins Netz
gestellt. Kann man sich als MP3 hier auf soundcloud.com anhören oder
downloaden: http://soundcloud.com/rolfdegen/st32mf4-demo-02
Gruß Rolf
Hallo Rolf,
erstmal danke für das Demo. Hört sich ja recht schnuckelig an. (Hatte
mir schon irgendwie gedacht das das so sanft und soft klingt, irgendwie
haben die Japaner glaub ich einen Faible dafür :-))
Aber klingt sehr sauber das ganze. Ich glaub ich werd mich auch mal mit
FM Synthese beschäftigen. Vllt bringe ich meinem FPGA sowas auch noch
bei :-)
Hallo Rene
Naja.. Im Vergleich zu den Demo-Sound von deinem Spartan3 Board klingen
die Sounds das Discovery sehr bescheiden.
Ich habe noch ein MP3-File mit einzelnen Klängen vom Discovery Board
erzeugt und auf soundcloud.com hochgeladen. Hier der Link:
http://soundcloud.com/rolfdegen/st32mf4-demo-03
Gruß Rolf
Ich werde jetzt erst einmal weiter an meinem 12Bit AVR-Synthi basteln
und ein GUI mit einem Tochdisplay integrieren. Die Programmierung mit
dem AVR ist auf jeden Fall leichter und unkomplizierter im Vergleich zum
Cortex M4 Prozessor.
Gruß Rolf
Na ja ... aber im Endeffekt ist es nur ne Frage der Software. Das was in
meinem Audio-Projekt abläuft lässt sich mit recht wenig aufwand
sicherlich auch auf nem Discovery Board laufen lassen.
Die Filter die ich verwende sind ganz normale IIR-Biquads. Und die
Berechnung der Koeffizienten erfolgt in einem AVR :-) Also alles im
Prinzip kein Hexenwerk. Daher fänd ich das ja so interessant die FM mal
so aufzuschnibbeln das ich das mit in meinem Synth reinbekäme :-)
Hab mir gerade mal die Sounds angehört. Sehr schöne Demos. Ideal als
Oszillator. Dahinter noch nen schönen Resonanzfilter mit Hüllkurve und
LFOs ... Yammy :-)
Der Hall bzw. die Echos in den Sounds kommen auch vom Discovery. Ich
habe die Sounds über den Line-Out vom Discovery übers Mischpult und ohne
Effekte aufgenommen.
Gruß Rolf
Ach ja ... der Hall in dem Demo. Wäre auch mal ein Interessanter
"Opcode" für mein Audio-Projekt. Hab dir übrigens ne PN geschickt.
Die Demos waren vom TGFM oder von dem Jo-MIDI FM ?
Hab jetzt mein Altera-Board, leider wurde da nur ein Ami-Netzteil
mitgeliefert, was mir hier natürlich nicht hilft. Hab es mal an mein
Labornetzteil gehangen, und es scheint zu gehen. Mehr kann ich da aber
nicht machen, weil ich in meiner Bastelecke keine Anschlussmöglichkeiten
habe.
Der Code der mitgeliefert wird, ist in Verilog, was ein herber
Rückschlag ist, da ich mich auf VHDL eingerichtet habe. Dennoch ist er
recht überschaubar, und ich begreif wenigstens wie sie zum Ziel kommen.
Es sind einige Audio-Demos dabei. Die Synthesizer-Demo nutzt
Wavetable-Synthese (vom FPGA Ram), was auch keine Überraschung ist, da
man damit schnell zum Ziel kommt.
Zum Thema FM: Ich habe nie verstanden, weshalb das immernoch so gefragt
ist. Mit den Sounds kann ich irgendwie nichts anfangen. Vom techn. her,
ist es auch nichts anderes als dass man den Ausgang eines Osc an den
Frequenzeingang eines anderen Osc hängt.
Beim Hall wird es schon interessanter, ab einer gewissen Dichte wird
dann auch einem M4 die Luft ausgehen. Bei meinem letzten Reverb den ich
gebaut habe, brauchte ich alleine 74 Filter:
1 Lowpass
1 Highpass
8 Allpass
64 Comb
@Maik
FM als alleiniger Sound ist auch recht langweilig. Aber FM als
Oszillator mit schönen "dicken" Resonanz-Filtern dahinter macht schon
was her.
Wenn ich mir den FM7 von NI z.b. anhöre. Ok, da ist die FM-Synthese ein
büüschen aufgebohrt, aber gerade das zeigt ja eigentlich das man mit ein
bissl Spielerei doch noch recht brauchbare Sounds rausholen kann.
Und es ist ja auch immer eine Frage wie komplex die Anordnung ist. Mit
zwei/drei Sinusoszillatoren gewinnt man auch keinen Blumentopf. Aber bei
6-8 Operatoren, entsprechenden Wellenformen, Filtern und Effekten klingt
das durchaus mehr als brauchbar.
Zum Thema selbstgebautes FPGA-Board. Falls ich mein Redesign für mein
Board mache und Interesse besteht kann ich dir (und auch dir Rolf) auch
gerne eins zusammenlöten und testen.
Rolf Degen schrieb:> Welches Altera-Board hast du genau ?
Der komplette Name lautet: DK-DE2-2C35N/UNIV
Es ist dieses:
http://www.altera.com/education/univ/materials/boards/de2/unv-de2-board.html
Im Prinzip tut es auch das DE1, aber ich wollte ein Board, wo ich ohne
zu basteln alles drauf habe (LCD fehlt beim DE1). Und der Vorteil bei
Dev-Boards ist ja, dass für alles was darauf ist, auch Demos vorhanden
sind, und ich lerne am funktionierenden Code einfach schneller :)
Rene B. schrieb:> Zum Thema selbstgebautes FPGA-Board. Falls ich mein Redesign für mein> Board mache und Interesse besteht kann ich dir (und auch dir Rolf) auch> gerne eins zusammenlöten und testen.
Ja, Interesse ist immernoch da. Ein simples FPGA-Audio Modul wäre eine
feine Sache, sowas findet man leider nirgends (--> Marktlücke :))
Dem kann ich nur zustimmen. Hätte auch Interesse an einem Sound-Board
von Rene. Zumal man dann auch ein Ansprechpartner bei Problemen und
Ideen hat.
Gruß Rolf
Na ja.
Ich hab damals schon nach "mitstreitern" gesucht und auch vereinzelt
gefunden. Aber das Problem ist eben immer der Preis. Der hängt eben
stark davon ab wieviele Leute sich finden. Zumal der "Löwenanteil" des
Preises in erster Linie durch die Platine bestimmt wird. Ein Einzelstück
(nur die Platine) kostet dann gerne 60-70 Euro. Bei 10 Leuten sinds dann
nur noch ca 15 Euro (oder so).
Die restlichen Bauteile liegen dann so im Bereich 50-60 Euro.
Also ich geb mal die Eckdaten was ich mir Vorstelle an Hardware bzw was
ich Schaltplan und Layoutmäßig schon fertig habe :
- Spartan 6 FPGA (LX9) nebst SPI-Flash
- 8/16/32MB SDRAM (je nach Beschaffbarkeit)
- Audio-Codec (TLV320AIC23B) mit Line In/Out, Kopfhöreranschluß,
Mikrofoneingang (aber nur der Kopfhörerausgang hat ne Klinkenbuchse)
- µSD-Karten-Slot
- AVR ATMega644P/1284P
- FTDI FT232 um mit dem AVR quatschen zu können und gleichzeitig die 5V
für die Platine
- 8 Analogeingänge (über einen Multiplexer)
- Stiftleisten für den FPGA
- Stfitleisten für den AVR
Was ich noch am überlegen bin da drauf zu flanschen ist :
- MIDI-Interface (je nach Platz)
- einfaches R-Netzwerk um VGA-Signale auf eine Stiftleiste zu geben
Ich schau mal das ich heute Abend den Schaltplan so wie er momentan ist
hier mal reinstelle.
Vllt schaffe ich es beim dritten Anlauf ja mal genug Leute für so ein
Projekt zusammenzutrommeln.
@Maik
Wenn das wirklich so ne Marktlücke ist würde ich diese gerne Ausfüllen.
Aber alleine bekomm ich das nicht hin (Vertrieb, Gewerbe, WEEE oder wie
das heißt usw). Tät mir gerne damit was dazuverdienen :-)
Ich helfe, soweit es mir möglich ist. Mit FPGAs fang ich "praktisch"
gerade erst an, "theoretisch" bin ich schon weiter.
Auf das Board würde ich nur das nötigste packen, alles das womit ein
einfacher µC-User bisher nichts zu tun hatte. Also im groben:
- das Board hat nur eine einzige Eingangsspannung (5V oder 3,3V)
- daraus folgt: alle Spannungsregler onboard
- FPGA + Config-Rom/Flash
- RAM
- Codec (ggf. mit Amp)
Mehr müsste da nicht drauf sein. Aber es gibt noch ein paar Dinge wo ich
mir nicht sicher bin. zB. man könnte die Klinkenbuchsen draufbauen, aber
was ist wenn man das Board nur als "Kern" einsetzt, und das Trägerboard
die eigentlichen externen Anschlüsse trägt?
Weiß nicht, wie es beim Programmieren vom Spartan ist, beim Cyclone
braucht man JTAG+AS und natürlich den passenden Programmieradapter
(Original: 200 Euro).
Den µC würde ich keinesfalls mit auf das Board nehmen, weil jeder
bevorzugt ja einen anderen. Auch kann man den zur Not auf ein Breadboard
setzen. Gleiches gilt für Midi. Man könnte den Midi-Anschluss ja an den
FPGA hängen oder halt an den µC. Das sollte dem User überlassen werden.
Ich werde das Soundmodul später in mein kleines Midi-Keyboard einbauen
und über ein Grafisches Display mit Touch-Panal-Funktion ansteuern. Ich
hab mal eine Fotomotage im Anhang gemacht. So solls später aussehen. Im
Midi-Keyboard ist Platz genug für zwei Eurokarten voll Elektronik.
@Rene. Hab auf der CC2-Website mal ein wenig Werbung für dein Projekt
gemacht. Vielleicht meldet sich ja noch der Eine oder Andere bei dir.
LG Rolf
@Maik
Die Platine wird mit 5V versorgt (über USB) und hat die LDOs für 3.3V
und 1.2V drauf.
Den uC möchte ich mir nur ungern "klemmen" da mich schon bei den
früheren Platinen genervt hat das ich immer nen uC separat drankorken
musste.
Und der AVR kann ja auch anfangs die Programmierung des SPI-Datenflashs
übernehmen. Ist ja nicht zwingend erforderlich das du den nutzt um den
FPGA zu "bespaßen" :-)
Und außerdem kann man ja über die Stiftleisten noch nen anderen uC an
den FPGA drankorken.
@Rolf
Vielen dank für die Werbung :-)
Und dein "Preview" zum AVR WAVE 1 im Keyboard sieht recht schnuckelig
aus :-)
Wollte das mit meiner Platform auch machen. Bin aber noch nicht dazu
gekommen.
Schaut recht kompakt aus. Wieviel Layer sind das?
Wie gesagt, würde ich das unnötige weglassen. Wenn das Board so klein
ist, könnte man das sogar als Arduino-Shield auslegen... damit hätte man
eine wesentlich größere Reichweite. In diesem Fall könnte man den
restlichen Platz für die 2 freien Audio-I/O nutzen und sogar Midi noch
mit draufbauen.
@Maik
Es sind genau 2 Layer :-)
Die Idee das Teil zu nem Arduino Shield umzubauen wäre evtl noch ne
Idee.
Nur sollte man dann die großen Arduino nehmen. Mit 32K kommt man u.u.
nicht so weit. Und es müssten noch einige Levelshifter platziert werden,
um die 5V Signale des Arduinos kompatibel mit den 3.3V Signalen des
FPGAs zu machen. Und man müsste sich überlegen wie man das macht wenn
das Board an einen 3.3V uC statt eines 5V uCs angekorkt wird (obwohl es
da u.u. reicht die Spgsversorgung für die Levelshifter Jumperbar zu
machen.
Hallo
Ich habe diese Tage ein wenig an der Soundquallität meines Synthis
gefeilt und die Auflösung von 8Bit auf 12Bit geändert. Zusätzlich habe
ich die 12Bit Sinustabelle von 256 Tabellenwerten auf 4096 Werte erhöht.
Die Soundausgabe klingt jetzt rauschärmer und erzeugt bei der Wiedergabe
von hohen Tönen weniger Verzerrungen.
Sinuston (12Bit und 8Bit) auf einem ATxmega128A1 mit internem 12Bit DAC
http://soundcloud.com/rolfdegen/sinus_12bit_8bit
Gruß Rolf
Hallo
Ich möchte die benötigte Zeit für die Soundaugabe von zwei
Sinus-Oszillatoren in meinem C-Code verringern (siehe Anhang), um einen
dritten Oszillator zu implementieren . Die Interrupt-Routine benötigt
für die Ausgabe von zwei Sinustönen auf einen DAC-Kanal schon über
17µsec. Für einen dritter Oszillator reicht die Zeit nicht mehr aus.
Hat jemand von euch vielleicht eine Idee, was ich an meinem Code
verbessern könnte ? Jeder Ratschlag ist willkommen. Ich dachte auch
schon daran, die DAC-Ausgabe in Assembler zu schreiben und in den C-Code
mit einzubinden. Aber ich habe keine Ahnung, wie ich das in Atmel Studio
6.0 machen könnte.
Ich bedanke mich schon im Voraus für eure Tips.
LG Rolf
schrittweite_temp kannst du weglassen, und direkt mit
schrittweite1/schrittweite2 rechnen. Spart Ram und mind. 4 Zyklen.
Die Accus kannst du Global auch als Register definieren, dann dürftest
du einiges an Zyklen sparen.
Kannst auch mal hier schauen:
http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung
Aber so etwas Zyklenkritisches würde ich eh komplett in Assembler
angehen. Dann hat man eine genaue Kontrolle.
Hallo Maik
Danke für deinen Tip. Das Ändern des Phasenaccus auf eine globale
Register-Variable mit "register32_t" hat leider nicht viel gebracht.
Ich habe testweise die Bit-Breite des Phasenaccus von 32Bit auf 16Bit
reduziert und komme jetzt auf eine Berechnungszeit von 2µsec pro
Oszillator. Ingesammt benötigt die Interrupt-Routine jetzt etwas weniger
als 9µsec (vorher 17µsec).
Durch die Änderung des Phasenaccus von 32Bit auf 16Bit reduziert leider
auch die Frequenzauflösung auf ca. 1,34 Hz pro Schritt. Als nächstes
werde ich versuchen, die Interrupt-Routine in Assembler zu schreiben und
in meinen C-Code mit einzubinden. Mal schaun obs funktioniert..
Gruß Rolf
Hallo Klaus
Ja gerne, ist kein Geheimnis. Die Routine läuft über einen
Timer-Interrupt und wird alle 1msec aufgerufen. Der berechnete
Hüllkurvenwert für den DAC hat eine Auflösung von 12Bit. Die Routine ist
alledings noch nicht ganz fertig, funktioniert aber in groben Zügen
schon.
Gruß Rolf
@Maik
Hallo
Ich konnte die Ausführungszeit meiner Sound-Routine nochmals von 9µsec
auf 6.5µsec reduzieren, indem ich die Compiler-Optimierung in Atmel
Studio 6 von "Os" auf "O2" geändert habe.
Mehr Infos zum Thema gibts hier:
http://www.cczwei-forum.de/cc2/thread.php?postid=76427#post76427
Gruß Rolf
Hallo ihr Musikbegeisterten,
habe selbst mit einem 80MHz-16Bit-DSP Musik in C erzeugt, dort geht
alles eleganter: z.B. 16x16-Mul in 25ns.
Finde es jedoch umso beachtlicher, dass es auch mit 8Bit und 20 MHz
akzeptabel klingt.
Wenn man den Asm-Code anschaut, merkt man, wo noch gespart werden kann:
Die häufigst verwendeten Variablen sollen in festen Registern stehen.
Ich weiß nicht aus dem Stegreif, wie man das dem GCC beibringt.
Die im oberen Link genannte Anote AVR200 ist völlig ungeeignet, da sie
für kleine AVRs ohne MUL-Befehl gedacht ist.
Auf jeden Fall lesenswert sind folgende Beiträge:
Beitrag "DDS normal ?"Beitrag "DDS Sinus erzeugung"Beitrag "Rechnen mit AVR"
Hallo an alle,
Wenn es von Ihrem Interesse ist, schauen Sie bitte auf
http://www.youtube.com/watch?v=4JkhzH57Je4
und geben Sie mir Ihre Meinung. Jeder Vorschlag wird zu schätzen wissen
!!
Hallo. My name is Rolf Degen from germany.
It is a very good project. I'm I also currently developing a synthesizer
on an AVR 8-bit processor basis.
My Link: http://www.cczwei-forum.de/cc2/thread.php?threadid=5878
I'm German and all information on this site is in german. Sorry
Greetings from germany
I can't writen a link on your youtube-site. Why ???
Greetings Rolf
Hello Rolf,
This is a YouTube restriction. I see that you have avoided the obstacle
!
I suggest you to open a parallel english page (for example on EmbDev.net
) to give more visibility at your project.
I also have developed some project in my native language, but due to the
poor quality of the various translator utility, I get only local
audience.
Best regards, Alessandro.
Hallo
Rolf Degen schrieb:> Ich versuch mich gerade mal mit Assembler. Ich möchte die komplette> Soundausgabe über eine Assembler-Routine in meinem C-Programm machen.
Zum Programm: Der Assembler-Code beinhaltet jetzt die komplette Timer1
Interrupt-Routine für die Soundausgabe der zwei DCO's inklusive der
Hüllkurve. Die Laufzeit beträgt insgesammt 5,53 µsec. Der Aufruf der
Interrupt Routine erfolgt alle 25 µsec durch die Interrupt-Freigabe im
Hauptprogramm (C-Code).
Mehr Info gibts hier:
http://www.cczwei-forum.de/cc2/thread.php?postid=76539#post76539
Gruß Rolf
Hallo zusammen
Dank großartiger Unterstützung von Wolfgang aus dem CC2-Forum
(http://www.cczwei-forum.de/cc2/), konnte ich die Assembler-Routine für
meinen AVR-Synthi noch etwas verbessern. Hinzugekommen ist die
Möglichkeit, außer einer Sinus-Wellenform auch eine Sägezahn-Wellenform
auszuwählen. Der Parameter dafür wird als 8Bit Volatile Variable aus dem
C-Programm (Main-Programm) übergeben.
Wolfgangs Website: http://www.wiesolator.de/
Gruß Rolf
Hallo
Ich bin gerade dabei, die Hüllkurvenansteuerung in meinem AVR-Synthi zu
verbessern. Problematisch war die Release-Phase, da sie nur einen
geraden Verlauf hatte. Aber was wäre ich ohne die Unterstützung von
Wolfgang (ein Genie wenn ihr mich fragt). Er hatte mich auf die Idee
gebracht, die Release-Phase mit Hilfe einer kleinen Umrechnung in eine
angeglichene e-Funktion umzusetzen (siehe Bild).
Hier die Berechnung für die Release-Phase:
ADSR_Hoehe = 65535
Release_Time = 2- 65535
if (ADSR_Hoehe > 0)
{
ADSR_Hoehe = ADSR_Hoehe - ((ADSR_Hoehe / Release_Time)+1);
}
Der Übergabewert für ADSR-Steuerung in meiner Assembler-Routine muss auf
12Bit reduziert werden: adsr_1 = ADSR_Hoehe >>4
Bild-Anhang: Neue Release-Phase im AVR-Synthi
Mehr zum Thema hier:
http://www.cczwei-forum.de/cc2/thread.php?postid=76736#post76736
Gruß Rolf
Ich würde mir überlegen, ob du das ganze wirklich so genau brauchst. In
meinem Synthesizer ist der Akkumulator 16bit groß (In meinem Quelltext
steht davon nichts, da ich beim Programmieren nicht mal DDS kannte,
sondern selbst überlegt habe wie ich verschiedene Frequenzen erzeuge).
Die Hüllkurve ist nur 8bit groß, zusätzlich gibt es eine
Lautstärkeregelung für jeden Kanal (8bit).
Ich würde in die Tonerzeugung nicht einfach mal so eine 16bit Division
reinhauen. Bei mir hat es quadratisch schon ziemlich gut funktioniert.
Pseudo-Code:
1
counter = 255;
2
...
3
if(counter < release_time)
4
Relase_volume = 0;
5
else
6
{
7
counter -= release_time;
8
Release_volume = counter * counter >> 8;
9
}
Das lässt sich in Assembler in wenigen Takten schreiben.
Eine Optimierung, die ich dir dringend empfehle ist einen Puffer
anzulegen, in den du die Samples berechnest. Das kannst du dann in der
Hauptschleife machen, während DMA die Daten ausgibt. Wichtig ist, dass
die Erzeugung immernoch in Assembler geschrieben wird. Allerdings werden
immer zuerst die Register mit den Werten geladen, dann z.B 64 Samples am
Stück berechnet und schließlich die Register zurückgeschrieben. Dadurch
fallen alle Schreibzugriffe auf das SRAM während der Tonerzeugung weg.
In meinem Synth werden alle Register während der Tonerzeugung genutzt:
Dadurch ist es möglich 3 Kanäle gleichzeitig zu berechnen und zu
mischen.
PS: Die Ideen zur Sounderzeugung in deinem Forum sind wirklich gut. Mein
Synthesizer spielt zurzeit zwischen um die 35 Kanäle gleichzeitig bei
25Mhz (44,1kHz). Allerdings sind die Sound relativ einfach, da sie nur
aus 512Byte-Tabellen geladen werden. Vielleicht werde ich versuchen auf
Kosten der Kanäle die Sounds zu verbessern.
Hallo Samuel
Erst einmal Danke für dein Interesse an meinem Synthi-Projekt. Die Idee
mit einem Sample-Buffer ist schon interessant. Ich frag mich nur, wie
ich andere Dinge wzB den Midi-Buffer, Touch-Panel und Grafik-Display
noch ansteuern bzw auswerten kann, wenn der Prozessor im Main-Programm
mit der Berechnung von Sample-Daten beschäftigt ist.
Meine Konstruktion sieht so aus, das ich die komplette Berechnung und
Ausgabe der 12Bit-Sounds in einer Timer Interrupt-Routine alle 25µsec
durchführe (Samplerate: 40Khz). Die Laufzeit der Interrupt-Routine
beträgt insgesamt je nach Syntheseart (SUB,FM) und Wellenform (Sinus,
Sägezahn) zwischen 5.4µsec und 5.9µsec für zwei Oszillatoren
gleichzeitig. Dadurch bleibt noch genügend Reserve übrig, um
Grafik-Display, Touch-Panel und Midi-Daten zu verarbeiten.
Später soll am DAC-Ausgang auch noch ein Analoger Filterbaustein wzB.
SSM2044 oder FM10 hinzu kommen. Dieser wird dann über die Hüllkuvendaten
in der Assembler-Routine gesteuert.
Gruß Rolf
Wenn ich das richtig verstanden habe macht die Blockweise berechnung nur
dann wirklich Sinn wenn man DMA nutzt.
Einzig der Overhead der durch das Wegspeichern und Wiederherstellen der
Prozessor-Register pro Sample ansteht wird minimiert. Die Berechnung
selbst wird ja nicht unbedingt kürzer. Ok, es hängt noch vom Algorithmus
ab, ob man beispielsweise vorher noch was "größeres" berechnen muss
bevor die eigentliche Audio-Verarbeitung losgeht. Aber im Prinzip spielt
das bei den "kleinen" Prozessoren keine Rolle. Gravierender wird das
wenn (wie beim PC) Cache ins Spiel kommt. Dann macht das u.u. erheblich
was aus einen Buffer vorzuberechnen, da dann der "Kontext-Wechel" nicht
bei jedem Sample neu gemacht werden muß, bzw benötigte Variablen nicht
erst mühsam bzw u.u. zeitaufwendig aus einem anderen Speicherbereich
geholt werden müssen.
Aber im Prinzip spricht nichts dagegen direkt Blockweise zu arbeiten.
Man muß sich nur je nach Blockgröße klarmachen das dadurch eben auch
eine Latenz entsteht (ok das Problem hat man eher auf einem PC), bzw bei
Blöcken die größer als 10ms sind die zeitliche Zuordnung der
MIDI-Signale auch nicht ganz unproblematisch ist. Aber wer berechnet
denn schon 480 Samples im voraus :-)
Ich hätte vllt auch noch einen Ansatz für die Hüllkurvengeschichte. Ist
aber auch was aufwendiger.
Ich habe die einzelnen Phasen anders definiert. Und zwar wird auf ein
Register immer der jeweilige Attack/Decay/Release Wert aufaddiert. Der
Akku ist quasi eine Skalierung für eine Tabelle (beispielsweise 0-255).
In dieser Tabelle steht dann linear/exponentiell/umgekehrt exponentiell
der Lautstärke Verlauf (von 0-1). Die nächste Phase beginnt dann wenn
der Akku überläuft. In der Sustain Phase wird der Akku immer genullt.
Man kann dann somit für jede steigende/fallende Phase unterschiedliche
Charakteristika definieren. Bei der Lautstärke macht sich das vllt nicht
so bemerkbar, aber wenn die Hüllkurve z.b. einen Filter langsam steuert
hört sich das dann schon unterschiedlich an. Außerdem kann man mit
dieser Phasen/Zeit-Unterteilung auch andere Hüllkurven leichter
realisieren. z.b. eine AHDSR, HADSHR oder die mehrphasigen Hüllkurven
von z.b. Roland Synthies recht einfach implementieren, ohne jedesmal den
Code umzuschreiben. Mal so als Anregung für deinen FM-Synthie :-)
Hallo Rene
Ich werde erst einmal bei meinem Konzept bleiben und langsam mein
Touch-Panel und Grafik-Display für Benutzereingaben programmieren.
Dadurch spare ich mir die ständige Neuprogrammierung des
Xmega-Prozessors für diverse Sound- und Hüllkurven-Test.
Deine Idee für die Hüllkurvensteuerung finde ich sehr interessant und
werde es Später mal ausprobieren.
Hab gerade mal nach dem Filter IC "SSM2044P" gegooglet. Bei
http://darisusgmbh.de/shop/index.php gibts das IC für nur 14,28 Euro.
Lieferzeit zwei Wochen.
Gruß Rolf
Der Puffer bringt schon ziemlich viel: Ich hab dein Asm-Programm mal
überflogen, da sind > 50 Ramzugriffe drin -> mehr als 100 Takte werden
für das Laden/Speichern/Sichern verbraucht.
Wenn man 64 Samples am Stück rechnet ist es nur noch 1/64 der Zeit.
Wenn du noch etwas optimieren willst, dann ist der Puffer wahrscheinlich
die beste Variante.
@Rene
Selbst ohne DMA macht es Sinn. Bei mir hat diese Optimierung das
Programm mehr als doppelt so schnell gemacht (Atmega328 hat leider kein
DMA).
Hallo zusammen
Ich habe die Hüllkurvensteuerung für den AVR-Synthi noch einmal
überarbeitet (siehe C-Code im Anhang). Die Parameter habe ich auf 16Bit
Breite belassen, weil dadurch auch außergewöhnlich lange Attack- und
Release-Phasen für spezielle Soundeffekte möglich sind. Im Anhang ein
Bild vom neuen Hüllkurvenverlauf im AVR-Synthi.
@Samuel
Ich werde auf jeden Fall deine Idee mit dem Sample-Buffer im Sinn
behalten und es Später versuchen umzusetzen. Zur Zeit arbeite ich noch
an vielen Baustellen im Synthi und die Optimierungen stehn da noch ganz
hinten an.
Gruß Rolf
Hallo Klaus
Im Anhang findes du meinen gepackten Quellcode. Es sind zwei Dateien.
Das Main-Programm in C und die Assembler-Routine, die per
Timer-Interrupt im Main-Programm aufgerufen wird. Ich arbeite unter
Atmel Studio 6 mit GCC 4.7.1.
LG Rolf
Hallo liebe Musikliebhaber auf mikrocontroller.net
Es gibt mal wieder was auf die Ohren von meinem Synthi. Aus purer Freude
an den Klängen aus meinem Synthi und weil es irren Spass macht, damit
rum zuspielen, habe ich im Synthi einen kleinen Live-Sequenzer
programmiert. Das Ergebnis könnt ihr euch auf SoundCloud anhören.
Allerdings hege ich keinen Anspruch auf kompositorische Fähigkeiten :-)
Link SoundCloud: http://soundcloud.com/rolfdegen
Aber Vorsicht, die Demo-Sequenzen sind von mir live gespielt und nur für
Ohren gedacht, die Elektronischen Musik wzB von Klaus Schulze,
Kraftwerk, Stockhausen und Co lieben :)
Wünsch euch viel Spass beim hören.
Gruß Rolf
Hallo zusammen
Ich habe die Attack-Phase in der Hüllkurvensteuerung meines AVR-Synthis
etwas verbessert. Die neue Hüllkurve kommt einem analogen Synthesizer
schon sehr nahe. Mehr Infos gibts hier:
http://www.cczwei-forum.de/cc2/thread.php?postid=76877#post76877
LG Rolf
Hallo liebe Synthi-Fans
Es gibt mal wieder was auf die Ohren. Dieses mal habe ich ein paar
Demo-Sounds durch den spannungsgesteuerten LowPass-Filter (CEM3320) im
AVR-Synthi gejagt. Die Filterfrequenz wird durch einen eigenen
ADSR-Generator gesteuert. Die Filterresonanz manuell über einen Regler
am Keyboard. Was leider noch fehlt, ist die Modulation durch einen LFO
(LowFrequenzOszillator).
AVR-Synthi Demo-Sounds mit LP-Filter:
http://soundcloud.com/rolfdegen/filter-wave-01
Die Steuerung der Filterfrequenz- und Resonaz erfolgt über zwei
PWM-Ausgänge am Xmega-Prozessor.
Gruß Rolf
Hallo zusammen
Ich habe einen Digitalen Noise-Generator (nach einer Idee von Wolfgang
aus dem CC2-Forum) in den AVR-Synthi implementiert (siehe
Klangbeispiel). Zusätzlich habe ich ein aktuelles Prinzipschaltbild mit
den Funktionsblöcken gezeichnet.
Klangbeispiel "Noise": http://soundcloud.com/rolfdegen/avr-synthi-noise
Im Anhang das Prinzipschaltbild und mein Programm. Das ganze ist leider
noch eine Baustelle und soll euch nur eine Stütze für eigene Ideen für
euer Projekt sein.
Gruß Rolf
Hallo Rolf,
ich möchte Deinen Thread nicht hijacken, aber gestatte eine kurze
OT-Frage:
Das scheint ein (Xplain?) Experimentierboard mit einem ATxmega128A1 +
S(D)RAM zu sein - genau das könnte ich für ein eigenes Projekt zur Zeit
gut gebrauchen...
Könntest Du mir sagen wie sich das Board nennt und ggf. woher man es
bekommen kann?
Grüße
Sascha
Sascha W. schrieb:
> Das scheint ein (Xplain?) Experimentierboard mit einem ATxmega128A1 +> S(D)RAM zu sein - genau das könnte ich für ein eigenes Projekt zur Zeit> gut gebrauchen...> Könntest Du mir sagen wie sich das Board nennt und ggf. woher man es> bekommen kann?http://www.cczwei-forum.de/cc2/thread.php?postid=72107#post72107
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: Touch Panal Menue AVR-Synthi
Youtube-Video:
http://www.youtube.com/watch?v=KFm-GHSx_5o&feature=youtu.be
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.
Gruß Rolf
Hallo
Habe Heute das 1.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
Durch die Anregung von verschiedenen Usern, habe ich mich dazu
entschieden, für die Parameter-Eingaben zusätzlich einen Drehencoder mit
Rast- und Tasterfunktion zu verwenden. Damit werden die Parametereingabe
noch leichter und komfortabler.
Gruß Rolf
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)
Bild 1: SAW-Wellenform ca. 2031Hz mit Phasen-Jitter (max. 25usec / Div.
100µsec)
Bild 2: SAW-Wellenform ca. 2031Hz mit Phasen-Jitter (max. 25usec / Div.
2msec)
Bild 3: Saw-Wellenform ca. 2038Hz ohne Phasen-Jitter (Div. 100µsec)
Bild 4: Saw-Wellenform ca. 2038Hz ohne Phasen-Jitter (Div. 2msec)
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
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
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
LPM dcomix0, Z+ ; 3 Sample aus Wavetable laden (16-Bit)
67
LPM dcomix1, Z ; 3 => in MixerSumme als Initialwert
68
69
DCO1End:
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:
http://soundcloud.com/rolfdegen/saw-sweeb
Gruß Rolf
Der KOMMENTAR ist falsch... extrahiert werden die 13Bit, wobei das
unterste Bit immer 0 ist.
Ich betone KOMMENTAR, weil der Code ansich richtig ist, aber auf den
ersten Blick schwer zu durchschauen, weil der Kommentar falsch ist. Du
brauchst sicher die 13Bit-Adressierung für den Sinus, wegen der 16Bit
Wortlänge im Programmspeicher.
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.
Software-Instrumente nutzen, um diese Problem generell zu umgehen
größere Wavetable, so hat man zB. für niedrigere Frequenzen ein besser
aufgelöste Wave als bei höheren. Im Schnitt teilt man diesen Wavetable
in 8 Frequenzbereiche. Für so einen kleinen µC ist das aber undenkbar.
Maik M. schrieb:> 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.
Hallo Maik,
das ist ein guter Tip. Werde ich Morgen gleich mal testen. Besten Dank.
In Bezug auf den Kommentar: Der Phasenaccu hat eine Auflösung von 24Bit
und ich benötige die oberen 12Bit für den Zugriff auf die 4KByte große
Sinus-Tabelle im Speicher des Xmegas.
Gruß Rolf
Hallo Maik
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 anderen Werten versucht, aber
ohne Erfolg. Der Phasen-Jitter bleibt.
Das bringt nichts, das unterste Bit ist bei deiner Addressierung immer
0, da du mit 13 Bit adressierst, nicht mit 12Bit. Jetzt bist du genau
auf den falschen Kommentar("Die oberen 12Bit des Phasen-Akkus
extrahieren") reingefallen, den ich dir mit dem letzen Post zeigen
wollte ;)
Diese Andrundungs-Maske ist etwas schwer zu bestimmen, aber evtl. gibt's
eine andere Lösung. Probier mal das:
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
Der Ansatz den Rolf meinte von wegen den Phasenakku zu nullen nach einem
Wellenformdurchgang ist doch im Prinzip richtig. Man darf den Akku an
sich aber nicht nullen. Man muß, sobald ein Neustart der Wellenform
erfolgt sich den aktuellen Phasenakku sichern und ihn als Offset zum
eigentlichen Phasenakku betrachten. Wenn der Phasenakku (gerade bei
höheren Frequenzen) eben nicht mit dem Index 0 auf den Wavetable bzw
Saw-Erzeugung liegt verschiebt man diesen für den Durchlauf der
Wellenform. Man hat dann aber dennoch das Problem das die Wellenform
eben nicht voll "ausgefahren" wird.
Die einzige Lösung die mir vllt einfallen würde wäre die Samplefrequenz
soweit zu erhöhen das der Jitter nicht mehr auftritt und dann per
Down-Sampling auf die Ausgabefrequenz zu shiften, aber das heißt dann
auch den Wavetable entsprechend aufzubohren.
Ich habe gerade nochmal gestöbert.
http://musicdsp.org/archive.php?classid=1#90
Vllt hilft das weiter. Ist zwar eher für Software-Synthies und DSP, aber
ich denke das ein oder andere könnte evtl nützlich sein.
Bei ihm ist's 40.000 / 4096, also ab ca. 10Hz wird der Jitter
auftauchen. Der ist zwar ab dieser Frequenz noch sehr gering, wird aber
größer, je höher die Frequenz ist. Das kann man aber umgehen, indem man
bei höheren Frequenzen einen kleinere Wavetable verwendet. Oder man
adressiert bei höheren Frequenzen einfach mit geringerer Auflösung
(nullen der niedrigen Bits).
Den Drift/Jitter kann man sich in etwa errechnen:
1
Drift in Prozent = (Wiedergabefrequenz*Wavetable_Länge)/(Samplerate*DAC_Auflösung)*100
Die Code-Änderungen hat leider nichts gebracht. Der Phasen-Jitter
bleibt.
Ich werde es wohl mit der Idee von Maik, bei höheren Frequenzen kleinere
Wavetables zu verwenden, versuchen.
Zum Hinweis von Rene "Bandlimited sawtooth synthesis":
Ich hab Gestern mit Oliver Gillert, dem Entwickler des genialen Shruthi
Synth (http://mutable-instruments.net/shruthi1) gemailt. Ich habe ih
gefragt, 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 .
(Anmerkung von mir: Wolfgang hat es oben in einen der letzten Beiträge
schon vorhergesagt hat).
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/"
Auf http://www.experimentalscene.com/articles/minbleps.php habe ich eine
kleine Anleitung (C++ Quellcode) für einen "minBLEP"-Oszilator gefunden.
Mal schaun wie ich das für einen Xmega nutzen kann.
Gruß Rolf
Hallo
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
Link soundcloud.com: http://soundcloud.com/rolfdegen/square-0
Bild 2: 1KHz Square-Sound (aus dem Shruthi-Synth gestohlen ) mit
Bandbegrenzung auf dem AVR-Synthi.
Link soundcloud.com:
http://soundcloud.com/rolfdegen/bandlimited-square-0
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
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
@Rolf
Ich hab gestern mal mit bandlimited waveforms auf dem PC
rumexperimentiert.
Ich habe dabei einen Oszillator programmiert der 64 einzelne Sinüsse
zusammenrechnet und deren Frequenz-Anteile (also 64 Koeffizienten)
vorgegeben werden können.
Den Sinus selbst hole ich über eine Tabelle. Ich habe mal deine
Erkenntnis darin verwurstet das der Sinus auch bei "ungenauen"
Frequenzen keine "Sprünge" macht und somit eine "ganz normale" DDS
genutzt. Also das Ergebnis klingt doch schon ganz gut, selbst wenn man
bei tiefen Frequenzen eine Art Tiefpass mit raushört, das aber eben
daran liegt das ich "nur" 64 Anteile berechne, die Wellenform aber noch
hörere Frequenzen beinhalten würde. (wenn meine Grundfrequenz
beispielsweise 100Hz ist, wäre der letzte Frequenzanteil bei 6,4kHz).
Das Ergebnis klingt aber recht brauchbar, und ich werd da auch mal was
weiter probieren. Das ganze ist somit quasi eine einfache Additive
Synthese.
Das was für mich son bissl den Reiz dabei ausmacht ist das ich die
Frequenzanteile zur Laufzeit ändern kann, und somit die
ausgangswellenform schon dynamisch gestalten kann (z.b. zwischen
Sägezahn und Rechteck "morphen") oder einer Wellenform einfach
Oberwellen hinzufügen kann, die z.b. von einer Hüllkurve gesteuert
werden.
Anbei mal die zusammengehackte Datei (ist noch viel Float drin, lässt
sich aber problemlos durch integer ersetzen), in der allerdings der
Sinus noch nicht drin ist (der ist bei mir in einer separaten Datei und
hat den Sinus-Kurvenzug von 0 bis pi/2).
@Maik
>if (rFrq > 23000.0f) { rFrq = 20000.0f; }
Da war noch ein Fehler drin. Hatte das ganze ursprünglich für 48kHz
ausgelegt, bis mir dann bei der Durchsicht eingefallen ist das meine
Soundkarte auf 44,1kHz läuft :-S
>if (ulPhi & 0x80000000) break;
Stimmt. Gute Idee. Vor allem hätte ich dann auch einen anhaltspunkt
wieviele Sinüsse ich bei hohen Frequenzen effektiv durchrechnen muß,
damit die 64. Oberwelle noch unterhalb meiner Nyquist Frequenz liegt.
>ist wohl nur ein Provisorium, oder? Besser wäre es, bei einer hohen>Basis-Frequenz, den Osc komplett zu umgehen.
Wie meinst das "komplett umgehen" ?
Hallo Rene
Hab ein einfaches Programm namens "WinFilter" für die Filterberechnung
gefunden. Vielleicht hilfts es dir :)
Bild: WinFilter
Download Link: http://www.winfilter.20m.com/
Gruß Rolf
@Rolf
Danke für den Link. Das Problem bei solchen Filter Tools ist das sie
zwar Koeffizienten ausspucken, aber den Weg wie man diese dann selbst
berechnen kann eben nicht. Und das wäre gerade für
Synthesizer/Mischpulte/Effektgeräte wo sich die Filter ja in
Frequenz/Güte/Typ/Charakteristik dynamisch ändern können interessant.
@Rolf
Die musicdsp-Seite hab ich vor einiger Zeit schon entdeckt. Daher kam
ich ja auf die bandlimited-Geschichte. Ich glaub das ich da auch die
Neuüberarbeitung meiner Filter-klamotten her hab (Koeffizientenseitig).
Ist schon recht lesenswert die Seite.
Daher dachte ich das dir das vllt bei deinem Problemchen evtl hilfreich
sein könnte.
Ich habe bei diesen Problemen wieder viel interessantes gelernt aber ich
bin nicht so der Mathetyp und mich schreckt der ganze Berechnungskram
eher ein wenig ab. Zumal der Xmega in meinem Projekt noch andere
Aufgaben nebenbei erledigen soll wz. Midi-Daten empfangen, Daten zum
Touch-Display senden und empfangen, Analoge Filter steuern uvm. Später
soll es auch eine Möglichkeit geben, die Soundbank von einer SD-Karte
in den 8MB SDRAM Speicher des Xplained Board zu laden.
Zur Zeit arbeite ich an der Soundbank für meinen Synthi. Ich habe im
Internet einige Bandlimited Wavetables gefunden, die ich in meine
Soundbank integriert habe. Somit bleibt meinem Xmega-Prozessor die
Berechnung wärend der Laufzeit erst einmal erspart.
Hier ein Code-Ausschnitt vom Shruthi Synth:
Viele Ideen kann man sich auch auf der Website des Shruthi Synth
abkucken. Olivier Gillert der Macher des Shruthi Synths hat seine
Entwicklungsarbeit für jederman frei zugänglich gemacht. Das Ding ist
einfach genial. Er arbeitet z.Zt. an einer mehrstimmigen Version des
Shruthis.
Link zur Shruthi Website: http://mutable-instruments.net/
Gruß Rolf
Rene B. schrieb:>>ist wohl nur ein Provisorium, oder? Besser wäre es, bei einer hohen>>Basis-Frequenz, den Osc komplett zu umgehen.>> Wie meinst das "komplett umgehen" ?
Das bezog sich auf diese Zeile:
1
if(rFrq>23000.0f){rFrq=20000.0f;}
Die ja soviel macht wie: Bei einer zu hohen Frequenz, generiere eine
völlig andere. Das ist ungünstig, weil der Osc. dann evtl. sinnlos eine
disharmonie spielt.
Mit "Osc. umgehen" meine ich, das man ihn bei einer zu hohen Frequenz
garnicht erst berechnet, sondern 0 (Stille) ausgibt.
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
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 Kopfzerbrechen bereitet. Die Einstellung der DCO's
sollte übersichtlich und einfach zu bedienen sein.
Bild 1: DCO-Menü
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
gegeneinander 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
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
Gruß Rolf
@Rolf
Sieht ja recht schick aus. Bin mal gespannt auf die Sound-Beispiele.
Aber ich hab mal ne Frage zum Sync. Heißt Sync nicht das ein Oszillator
beim Nulldurchgang den anderen Synchronisiert, also diesen dann
ebenfalls neustartet ? Das macht im Falle das beide Detune = 0 haben in
dem Sinne keinen Sinn, da beide dann ja exakt diesselbe Frequenz haben.
Aber interessant wird das meine ich dann sobald der zu Synchronisierende
Oszillator höher schwingt (egal ob mit einem Detune im Halbton bzw
Cent-Halbton) Hauptsache höher als der erste Oszillator, denn sonst
würde die Wellenform ja nicht voll ausschwingen können. Aber ich meine
das gerade das Synchronisieren den Sound was fetter bzw
charakteristischer macht. Was vllt auch noch ne schöne Variante für
deinen Oszillator wäre (wenn du ohnehin schon 2 davon hast ;-)) wäre
Ringmodulation. Also einfach die beiden Oszillator-Ausgänge miteinander
multiplizieren. Das würde die 500 möglichen Kombinationen noch ein bissl
aufstocken :-) Und wäre ne prima Klangquelle für nen analogen Filter.
Ich weiß ja nicht wie es in deine Programmierung passt. Aber mal so als
Vorschlag.
Ich hab gerade mal in meinen AVR-Synth code geschaut, wie ich das so
aufgebaut habe. Die Klangerzeugung lief bei mir über einen "morphable
wavetable". Der Wavetable selbst hatte 8 Wellenformen, wobei man immer
von einer Wellenform zur nächsten morphen kann. Das ging im Prinzip so:
Multiplikation war bei mir eine spezielle Funktion, die Word mit Byte
Multipliziert hat, und als Ergebnis kam Word raus (die untersten 8Bit
des 24Bit Ergebnisses werden ignoriert)
Ich habe auch mit einem Filter experimentiert, der so auschaute:
1
v0 = R*C*v0 + C*in - C*v1;
2
v1 = R*C*v1 + C*v0;
3
output = v1;
4
5
C = Cutoff (0..255)
6
R = Resonance(255..0)
Hierbei habe ich die Multiplikation R*C in einem nebenherlaufenden, sehr
langsamen Timer erledigt, weil es nicht so kritisch war. Soweit ich mich
erinnern kann, war der Filter sehr gut, und dank dem
Hardware-Multiplikator auch von den Zyklen her recht vertretbar.
Rene B. schrieb:> Heißt Sync nicht das ein Oszillator> beim Nulldurchgang den anderen Synchronisiert, also diesen dann> ebenfalls neustartet ?
Hallo Rene. Ja das ist richtig. Ich sollte meine Sync Funktion wohl
besser umbenennen, denn sie setzt lediglich beide Oszillator auf die
gleiche Frequenz und den gleichen Phasenwinkel zurueck. Ich bin mir
allerdings nicht im klaren darueber, ob das musikalisch gesehen
ueberhaupt sinnvoll ist.
Nemen wir mal an, das mit dem Einschalten des Synthis beide Oszillatoren
mit gleicher Frequenz und Phase starten. Nun verstelle ich im DCO Menue
den Detune Regler und dadurch schwingen beide Oszillatoren mit
unterschiedlicher Frequenz und als Ergebnis ensteht am Ausgang eine
gewollte Amplitdenmodulation. Mit dem alleinigen Zuruecksetzen des
Detune Reglers auf null, schwingen zwar beide Oszillatoren wieder mit
gleicher Frequenz aber nicht unbedingt synchron zueinander, was
ebenfalls zu einer Amplitudenmodulaton am Ausgang fuehrt. Aus diesem
Grund stelle ich mit dem Sync-Button auch die Phasen beider Oszillatoren
zurueck.
Danke fuer den Tip mit der Ringmodulation. Werde ich Morgen gleich
umsetzen :)
Hab die Preview von damals wiedergefunden und raufgeladen:
http://soundcloud.com/maikmenz/avr-8bit-filter
Der Reverb stammt nicht vom Synth, den hab ich nachträglich
draufgepackt. Der Filter in der Demo ist der den ich erwähnt habe. In
der Demo hört mach auch das Wavetable morphing von Sägezahn zu Rechteck
und zurück.
Der Sound klingt aber wie eine Ringmodulation. Ich wunder mich halt über
das Aussehen der Wellenform. Diese entspricht nicht der üblichen aus dem
Lehrbuch wie zB in Bild 2.
Mach ich was flasch in meiner Berechnung oder ist das so korrekt. Mir
scheint es so, als ob der Nullpunkt der Sinuskurve nach unten verschoben
ist. Die Frequenz von Oszillator 1 (dco1) beträgt 200Hz und von
Oszillator 2 (dco2) 6000Hz. Die beiden Sinuswerte stammen direkt aus
einer 8Bit Sinus-Tabelle im Flash des ATxmegas.
Gruß Rolf
du müsstest deinen Wavetable als Signed speichern, und von da an alle
Unsigned-Operationen durch Signed-Operationen ersetzen. Dann am Ende,
vor der Ausgabe konvertierst du dann erst wieder zurück auf Unsigned
Mach deine Wellenformen und die Multiplikation signed.
Wie Maik schon meinte : Nur unsigned (also positiv) ist eher schlecht,
selbst wenns sich nach dem gewünschten Ergebnis anhört.
Du wirst dann tlw Probleme bekommen mit nem DC-Offset. Dadurch das der
Nullpunkt dann ja eben irgendwo liegt, in Abhängigkeit von der
Beschaffenheit deines Ausgangssignals.
Die Tabellen kann ich nicht ändern. Besteht nicht die Möglichkeit den
ausgelesenen Tabellenwert als signed Byte zu konvertieren. Die Auflösung
würde dadurch auf 7Bit reduziert.
das kannst du machen, aber hast dann halt wieder einen Zyklus weniger.
Konvertieren von Signed nach Unsigned und umgekehrt geht relativ
einfach:
1
subi register,0x80
Allerdings musst du bei Signed-Operationen bedenken, dass das
höchstwertige Bit immer das Vorzeichen-Flag ist. Operationen wie lsl,
lsr, ror, rol, usw. darfst du auf das höchstwertige Byte eines Signed
nicht anwenden, weil sich sonst evtl. das Vorzeichen ändert. Für LSR
gibt es allerdings schon ersatz: ASR. Für LSL hingegen gibt es keinen,
aber da kannst du sowas machen:
1
bst reg,7
2
bld reg,6
3
lsl reg
Dabei bleibt das Vorzeichen erhalten. Auch musst du bei der
Multiplikation aufpassen, schau dir dazu die Operationen MULS und MULSU
an.
Das Ergebnis sieht jetzt richtig aus (Bild). Allerdings ist die
Ausgangsspannung nur noch halb so groß wie vorher. Eine Division durch
drei vor der DAC-Ausgabe funktioniert nicht. Dadurch entstehen wilde
Bit-Muster.
Gruß Rolf
Gruß Rolf
Das die Ausgangsspannug nur noch halb so groß ist, liegt daran das du 2
Vorzeichenbits hast. Da aber durch die Multiplikation ja nur noch 1
VZ-Bit übrigbleibt geht dir in der Dynamik ja ein Bit flöten. Du
müsstest quasi eienn Shift nach links machen um die Ausgangsspannung
wieder auf de vollen Bereich zu bringen.
Vorzeichenbehaftetes Multiplizieren ist etwas tricky, wie Rene schon
schrieb, verliert man 1 Bit. Genauer:
S XXX XXXX * S XXX XXXX = SS YY YYYY YYYY YYYY
Wobei S das Vorzeichenbit ist, X und Y sind Wertebits.
Probier mal folgendes (bisher ungetestet):
Der Compiler meckert immer bei "subi r1, 0x88"
Meldung: Error 1 register number above 15 required
Dieser Befehl funktioniert nur mit den oberen 16 Registern.
Ich hab es jetzt so geschrieben:
1
Ringmod:
2
subi dco1out0,0x80 ; make signed Wave
3
subi dco2out0,0x80
4
muls dco1out0, dco2out0 ; Multipl signed DCO1_out * DCO2_out
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.
Um die Rundungen bei der Berechnung der Schrittweite2 (Phasendelta) für
Oszillator2 so gering wie möglich zu halten, habe ich den Zahlenwert auf
32Bit erhöht.
Gruß Rolf
Du gehst die Sache sehr Ressourcenfressend an. Ich habe diesen Teil bei
meinem Synth auch in Assembler gemacht. Es ist nicht kompliziert, und
man kann mit der richtigen Technik auch sehr viel Ressourcen sparen. Bei
mir schaut das ungefähr so aus:
Ich habe 1 Table, der enthält 14 Akkumulatoren-Deltas, nennen wir ihn
mal "PitchTable". Der erste Wert ist das Delta für B-1, der 14. Wert ist
für das C+1, dazwischen sind endsprechend die anderen Noten-Werte.
Eingänge sind: inNote(0..127), inSemi(-24..24), inFine(-128..127)
Ausgang ist outPitch
1
fNote = inNote + inSemi;
2
if (fNote & 0x80)fNote = 0;// <-- Überschlag vermeiden
Das is Pseudocode. Aber die Voregehensweise ist im Groben: Oktave werden
geschiftet, Semi einfach ganz am Anfang auf die Notennummer addiert,
Fine wird linear zwischen zwei benachbarten Akkumulatoren-Werten
interpoliert.
Hallo Maik
Die Routine funktioniert leider nicht so wie sie soll. Als Ergebnis
erhalte ich immer Frequenzen im Bereich von 0-5Hz über die spielbaren
Oktaven.
Mein Code:
erhalte ich fast die richtige Frequenzen (A = 438.5 Hz).
Der Wert für die Oktavierung funktioniert leider auch nicht und hat
keine Auswirkungen auf die Wiedergabefrequenz.
Gruß Rolf
Das mit der Oktavierung war eine falsche Aussage von mir. Ich sehe
gerade das eine Oktavierung nur über den Semiton-Werte funktioniert.
Also Semiton-Wert zb "12" wäre eine Oktave höher und "-12" eine Oktave
niedriger.
Ich glaube C/C++ rechnet hier in 24bit, die Multiplikation aus 24bit mit
8bit ergibt allerdings 32bit und der Compiler convertiert das runter
indem er die höheren (wichtigeren) 8bit weglässt. Das müsste irgendwie
mit Typecasting lösbar sein, allerdings bin ich da nicht so Fit. Evtl.
geht es so:
@Maik,
aber das lineare Interpolieren zwischen zwei Halbton-Pitches müsste doch
eigentlich fehlerhaft sein da es ja eine Exponentialfunktion ist die die
Frequenzen zwischen den Oktaven und auch entsprechend den Halbtönen
bestimmt. Wie genau das Ohr diese unterschiede wahrnehmen kann weiß ich
nicht, aber ich denke das man bei ner abweichung von 50cent schon
hörbare Frequenzunterschiede wahrnehmen müsste zwischen tatsächlicher
Frequenz und interpolierter Frequenz.
Ansonsten ist das Verfahren ja richtig und auch recht platzsparend. Ich
wär bzw bin ganz bruteral mit ner Tabelle über 120 Halbtöne und 8/16/32
Abstufungen drangegangen, aber das ist im Prinzip ja quatsch, da sich
die Oktaven ja durch Shiften bilden lassen, und man dann von den
höchsten Inkrementen bzw Schrittweiten ausgeht und runtershiftet.
Rene B. schrieb:> @Maik,>> aber das lineare Interpolieren zwischen zwei Halbton-Pitches müsste doch> eigentlich fehlerhaft sein da es ja eine Exponentialfunktion ist die die> Frequenzen zwischen den Oktaven und auch entsprechend den Halbtönen> bestimmt.
Ja im Prinzip ist es falsch, aber man muss halt Kompromisse eingehen.
Zur Not könnte man einen Exponential-Tabelle nutzen, aber richtig
berechnen kann man das auf einem AVR nicht.
Rolf Degen schrieb:> Ja das wollte ich gerade machen.>> outPitch = (__uint24)fPitch1 << fOctave; = 440,1Hz> outPitch = (__uint24)fPitch2 << fOctave; = 261,6Hz
ja, dann hat es irgendwas mit der Typenkonvertierung in der Zeile zu
tun. Wie gesagt, das war nie mein Ding :)
Ohne Typkonvertierung könnte es so gehen:
outPitch = ( (fPitch1>>8) * (255-fFineByte) ) + ( (fPitch2>>8) *
(fFineByte) );
Allerdings produziert das massive Rundungsfehler
Ich habe das Programm etwas abgeändert und es kommen jetzt zumindest die
richtigen Frequenzen heraus. Allerdings funktioniert es mit
"inFine"-Werten noch nicht.
Dein Programm funktioniert soweit. Nur bei den inFine-Werten stimmt was
nicht. Ich bekomm bei positiven und negativen Werten immer eine niedrige
Frequenzen heraus.
Zum Beispiel:
inFine = 0 = 440Hz
inFine = 10 = 426Hz
inFine = -10 = 426Hz
Die Programmzeile hatte ich bereits wieder geändert. Ich habe mir den
fPitch2 Wert mal angesehen. Der Wert (3360) ist bei inFine = +10 bei
jeder Midi-Note gleich groß.
Also das die beiden fPitch's bei +10 und -10 cent diesselben sind kann
ja nicht sein. fPitch2 müsste ja ggü fPitch1 den Pitch für einen Halbton
unter fPitch1 liegen, oder ?
Ja es funktioniert jetzt. Prima :) Der Notenwerte liegen zwar jetzt
etwas höher A 440Hz = gemessen 440,5 aber das ist ok. Kann man mit dem
inFine-Wert -1 aber korregieren.
Danke für deine großartige Hilfe. Das Ganze bringt mich in meinem
Projekt wieder einen großen Schritt nach vorne.
Schönen Tag noch und lieben Gruß Rolf
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ßerdem eine
genauere Einstellung der Parameter möglich.
Nochmals besten Dank an Maik. Ohne seine großartige Unterstützung hätte
es nicht funktioniert.
Bild: DCO-Einstellung im AVR-Synthi
MfG Rolf
Hallöchen..
Damits hier nicht zu langweilig wird, gibts zur Abwechslung ein paar
Demo-Sound. Was in den Sounds noch fehlt, ist die Filter und
Amplituden-Modulation sowie FM und Synchronisation der Oszillatoren.
AVR-Synthi Demo-Sounds
Link: http://soundcloud.com/rolfdegen/avr-demo-31102012
Sehr schönes Demo.
Vor allem gefällt mir der Sound ab 11:30.
Aber ist der Filter wirklich noch nicht mir drin ? Tlw klingt es ja
schon so :-)
Aber echt sehr schön gemacht. Weiter so. Bin mal gespannt auf die
restlichen Features wie Ringmod/Sync/FM und eben alles noch mit Filtern
zusammen :-)
Meine AVR-Assembler sind zwar recht begrenzt, aber im Prinzip müsste es
so gehen. Sobald ein Überlauf im Phasenakku 1 festegestellt wird, wird
Phasenakku 2 genullt. Damit wird OSC2 durch OSC1 synchronisiert (was ja
auch angestrebt ist :-)).
Ja super. Dann werde ich das im Prinzip so und zusätzlich mit einer
Abfrage für die Sync-Funktion in meinem Programm implementieren.
Gruß Rolf und schönes Wochenende.
Hallo
Ich brauch mal wieder Hilfe. Ich möchte in Assembler auf einen 256 Byte
großen Ringbuffer in meinem Main-Programm (in C) zugreifen. So wie ich
es versuche funktioniert es leider nicht. Ein Rat wäre sehr hilfreich.
Schon mal Danke im Vorraus. LG Rolf
Ring-Buffer (FIFO) in C:
1
//******************************
2
// write data in to FIFO-Buffer
3
//******************************
4
buf_data=170;
5
test_buffer[wrbuf_pointer]=buf_data;// save data in to buffer
6
wrbuf_pointer++;// inc Buffer-Pointer
7
buf_data=0;
8
buf_status=1;
9
_delay_ms(10);
10
print_8bit_number(buf_data,120,70,2);
Lesen eines Bytes aus dem Ringbuffer in der Assembler-Routine und
anschließend zurückschreiben in buf_data. buf_dat wird im Main-Programm
ausgewertet.
habe zwar von dem gemixe von C und ASM nicht soviel Ahnung, aber die
Zeile
1
ldi r20, lo8(rdbuf_pointer) ; ein Datenbyte aus dem Buffer lesen
schaut schon merkwürdig aus. Wenn der Ringbuffer im SRAM liegt, müsste
die Adressierung 16Bit haben. Keine Ahnung was rdbuf_pointer überhaupt
ist, aber wäre es ein Pointer in den SRAM (Elementindex eingeschlossen
), dann würdest du mit ldi nur die Hälfte der Addresse bekommen.
Das ist jetzt nur wilde Spekulation, aber vielleicht geht es so:
Funktioniert leider nicht. Bekomme die Fehlermeldung :"Error 1 garbage
at end of line"
Die Dekleration der Buffer-Variablen sieht bei mir im Main-Programm so
aus:
// Test-Buffer (Lesezugriff erfolgt in ASM-Teil)
volatile uint8_t test_buffer[256]; // Receive Buffer for Wave-Data
uint8_t wrbuf_pointer = 0; // Write_Pointer
volatile uint8_t rdbuf_pointer = 0; // Read_Pointer
volatile uint8_t buf_data = 0; // Bufferdaten
uint8_t buf_status = 0; // buf_status = 1 wenn Daten im
Buffer
Die Buffer-Funktion soll später für die Soundausgabe in der ASM-Routine
genutz werden. Die Sounddaten werden alle im Main-Programm vorberechnet
und im Buffer gespeichert, wo sie dann im ASM-Teil ausgegeben werden.
rolf degen schrieb:> Ich programmiere unter atmel Studio 6 und der Assembler ist da etwas> eigen. Statt low/high muss lo8/Hi im Quellcode stehen.>> LG Rolf
Ich meine lo8 und hi8
Hallo
Ich habe die Soundausgabe des AVR-Synthis testweise über einen 256 Byte
großen Ring-Puffer geleitet (siehe Code). Der Puffer wird im
Main-Programm (siehe Code) ständig mit Sample-Daten aus einer 8Bit
Sinus-Tabelle befüllt und in der Interruptroutine für die Soundausgabe
geleert.
Soweit funktioniert das auch ganz nett. Aber sobald ich Eingaben und
andere Dinge auf dem Touch-Display mache, bekommt der Puffer nicht mehr
genug Daten und es treten Fehler in der Soundausgabe auf.
Viele Funktionen für das Touch-Display benötigen mehr Zeit als der
Puffer es erlaubt. Die maximale Pufferzeit beträgt 6.4 msec bis der
Puffer leer ist. In der Main-Schleife wird ständig der Füllstand geprüft
und nach Bedarf wieder gefüllt. Wenn der Prozessor aber z.Zt. mit
anderen Dingen wzB mit der Display-Ausgabe und Auswertung der
Touch-Eingaben beschäftigt ist, läuft der Puffer leer und kann nicht
rechtzeitig wieder befüllt werden.
Man müsste jetzt also hergehen und in den Display-Routinen eine
Füllstandsabfrage des Puffers integrieren. Sobald die Füllstandsanzeige
den "Beinahe"-Leerstand signalisiert, wird die Display-Routine
unterbrochen und der Puffer wieder befüllt. Mal schaun wie ich das
umsetze. Das Ganze müsste dann später genauso mit den Routinen für die
Soundberechnung gemacht werden. Da kommt Freude auf..
ASM-Code: Ring-Puffer für die Soundausgabe
@Rolf
Wie wäre es wenn du in der Main Loop das Funktionskonglomerat
"get_encoder, touch_panel, mididata_available, midi_play" immer nur pro
durchlauf einmal aufrufst.
Quasi eine Statemachine die erst get_encoder, dann touch_panel, dann
mididata_available und dann midi_play aufruft ?
also etwa so :
char state = 1;
while (1)
{
while (rd_pointer != wr_pointer)
{
...
}
switch (state)
{
case 1 : state = 2; get_encoder (); break;
case 2 : state = 3; touch_panel (); break;
case 3 : state = 4; mididata_available (); break;
case 4 : state = 1; midi_play (); break;
}
}
Ich weiß zwar nicht wie lange die einzelnen Funktionen brauchen, aber
vllt bietet es sich an längere Funktionen (vor allem wenn Verzögerungen
im Spiel sind) ebenfalls über eine Statemachine zu realisieren. Der
Vorteil ist das du dann nur dann was machen mußt, wenn auch wirklich was
zu tun ist, und du ersparst dir so Wartezeiten die den Prozi dann
komplett blockieren. Ein weiterer Nebeneffekt ist das solche
"Salami"-Funktionen eine gewisse Nebenläufigkeit mitbringen. Sprich : Es
wird quasi ein eigener "Task" daraus, der je nachdem wie er programmiert
ist eben keine anderen Aufgaben blockiert.
Hallo Rene
Ich hab das vorläufig etwas anders gelöst. Der Hinweis von Franz und
Wolfgang aus dem CC2-Forum war die Lösung. Ich habe in die Routine für
das Senden der Daten zum Display eine Abfrage für den Soundpuffer
integriert (siehe Code). Jetzt funktioniert die gleichzeitige
Display-Steuerung und Soundausgabe ohne Probleme. Verzögerungen bei der
Ansteuerung des Displays sind mir kaum aufgefallen.
Code: Routine zum Senden der Daten ans Display
else_delay_us(100);// wenn Soundpuffer nicht befüllt wird,
13
// dann warte 100µsec bis Display bereit für den Datenempfang
14
// (nur notwendig wenn SPI-Datentransfer schneller als 100KHz)
15
16
SPIC.DATA=data;// ein Byte zum Display senden
17
while(!(SPIC.STATUS&(1<<SPI_IF_bp))){}// wartet ca. 4µsec bis Byte gesendet wurde
18
}
Soundpuffer Routine
1
//---------------------------------------------
2
// Sound-Puffer füllen
3
//---------------------------------------------
4
voidsound_puffer()
5
{
6
uint8_ti;// Anzahl der Samples für die Befüllung
7
uint8_tsample;// Sample aus der Sinus-Tabelle
8
9
for(i=0;i<200;i++)
10
{
11
sample=pgm_read_byte(&(sinus_8Bit[sample_index]));// Sample aus Sinus-Tabelle laden
12
sample_puffer[wr_pointer]=sample;// Sample in Puffer schreiben
13
wr_pointer++;// Schreibzeiger des Soundpuffers +1
14
sample_index++;// Sample-Index für Datenposition in Sinustabelle inc
15
PORTA.OUT|=(1<<PIN0);// Für Testzweck: Portbit High
16
PORTA.OUT&=~(1<<PIN0);// Portbit Low
17
}
18
}
Bild 1:
Kanal 1 (Oben) Portbit signalisiert die Übertragung von 200 Bytes an den
Soundbuffer in ca. 230µsec
Kanal 2 (Unten) Sinus-Wave aus dem Soundpuffer
Gruß Rolf
Hallo
Ich verkaufe meinen beiden Original CEM3320 Filterbausteine. Geprüft und
kaum benutzt. Lagen bei mir in der Schublade auf einer Iso-Matte. Alter
ca. 10 Jahre. Da ich in meinem Synthi-Projekt die SSM2044 einsetze sind
die CEM3320 überflüssig. Preis ist Verhandlungssache.
Gruß Rolf
Achso.. hät ich beinahe vergessen. Zur Zeit teste ich die
Speicheranbindung des 8MByte großen SDRAM auf Xplained-Board das ich in
meinem AVR-Synthi als Wave-Speicher verwenden will. Die Transverleistung
des Speicherinterface im Xmega zum 8MByte SDRAM liegt bei beachtlichen
1.4Mbyte in der Sekunde. Für so einen 8Bitter eine stolze Leistung.
Falls alles nach meinen Vorstellungen funktioniert, soll der
XMega-Prozessor verschiedene 16Bit Waveforms nach dem Systemstart
vorrausberechnen und in dem 8MByte SDRAM zwischen speichern. Per
Timer-Interrupt werden die Wave-Daten aus dem Speicher gelesen und an
als 12Bit Wert an den DAC gesendet. Das ganze funktioniert per Direct
Digital Synthese und Waveform-Tabellenzugriff.
Gruß Rolf
Hallo
Ich will noch einmal auf das Thema Interpolation zu sprechen kommen.
Wolfgang aus dem CC2-Forum hatte ja bereits in seinem Beitrag
(http://www.cczwei-forum.de/cc2/thread.php?postid=79168#post79168) viel
erklärt und gute Tips für die Berechnung geliefert.
Da mir jetzt "Unbegrenzter" Speicherplatz in meinem Synthesizer zur
Verfügung steht (ganze 8 MegaByte wow..) habe ich einige Test mit der
Interpolation von Soundsamples gemacht (siehe Bild 1+2) . Die
Original-Samples hatten jeweils eine Auflösung von 7 Bit.
Bild 1: Links Original Waveform 7Bit, Rechts interpolierte Waveform
Bild 2: Links Original 7Bit Waveform, Mitte interpolierte Waveform
Das Ergebnis ist wirklich gut. Kein Rauschen kein nix. Die Original 7Bit
Soundsamples klangen im unteren Frequenzbereich (< 500Hz) sehr
verrauscht. Nach der Interpolation klingt das ganze schon super finde
ich.
Mein Code für die Interpolation