Ich möchte eine Melodie abspielen, aber ich verstehe nicht, wie ich die Töne genau erzeugen kann. Ich bin soweit dass ein Sinus mit dem schnellen PWM Modus von einem tiny45 @ 8MHz (als DAC) mit 64 Schritten erzeugt wird. Dann müssen die Sinuswerte mit dem 64fachen der Tonfrequenz in das PWM Register geladen werden. Wenn der Tonbereich von A3-A5 also 220-880Hz gehen soll, heisst das für den Interrupt 14080Hz (71.02µs) bis 56320Hz (17.75µs). In dem Bereich liegen 15 Noten mit einer Auflösung von 0.01Hz. Wenn der Timer mit 1MHz betrieben wird reicht es nicht (1µs), mit 8MHz läuft er bei 32µs über. Wie macht man das?
Es passt nicht genau zur Frage, aber hier gabs mal einen Thread zum Thema Noten in Halbtonschritten berechnen: Beitrag "Hochzahlen?"
Da steckt anscheinend genau drin, was ich brauche! Leider kann ich nicht richtig nachvollziehen, wie es gemacht wird, da ich praktisch keine Asm-Erfahrung habe. Anscheinend verwendet er einen 32kHz Interrupt, um die Frequenzen zu erzeugen . Aber wie kommt er bei 16MHz Takt und einem Compare-Wert von 62 auf 32kHz? Wie er die Töne erzeugt, verstehe ich leider auch nicht:
1 | ;--------------------------------------------------------------------; |
2 | ; Pitch number to angular speed conversion table |
3 | ;--------------------------------------------------------------------; |
4 | ;Since sustain area of wave table, a cycle of fundamental frequency, is sampled |
5 | ;in 128 points, the base frequency becomes 32000/128 = 250 Hz. The wave table |
6 | ;lookup pointer, 16.8 fraction, is increased every sample by these 8.8 fractional |
7 | ;angular speed values. |
8 | |
9 | tbl_pitch: ; A B H C Cis D Dis E F Fis G Gis |
10 | .dw 225, 239, 253, 268, 284, 301, 319, 338, 358, 379, 401, 425 ; 220Hz.. |
11 | .dw 451, 477, 506, 536, 568, 601, 637, 675, 715, 758, 803, 851 ; 440Hz.. |
12 | .dw 901, 955, 1011, 1072, 1135, 1203, 1274, 1350, 1430, 1515, 1606, 1701 ; 880Hz.. |
13 | .dw 1802, 1909, 2023, 2143, 2271, 2406, 2549, 2700, 2861, 3031, 3211, 3402 ; 1760Hz.. |
14 | .dw 3604, 3818, 4046, 4286, 4542, 4812, 5098, 5400 ; 3520Hz |
In meinem Fall bräuchte ich ja nur den Sustain-Table mit (hier: 128) Sinus-Werten. Aber wie macht er es - springt er durch die Tabelle (läßt Werte aus), oder spielt er sie unterschiedlich schnell ab? Ich vermute, da er mit 32kHz Sampling Frequenz auskommt, und anscheinend 3kHz erzeugen kann, muss er wohl Werte auslassen. Leidet da nicht das Signal drunter? Ich dachte, man spielt immer alle Werte ab, und das mit einer variablen Geschwindigkeit.. Kann mir das jemand erklären bitte?
Ich habe einen "Streit" zum Thema Interruptfrequenz vs. Schrittweite gefunden: Beitrag "erzeugen eines sinus mit variabler frequenz" Ich kann mir aber immer noch nicht vorstellen, wie beim Springen durch die Tabelle genaue Frequenzen erzeugt werden können, es sind ja keine halben Schritte möglich. Sollten dann die umliegenden Werte gemittelt werden? Speicherintensiv ist die Methode, für jeden Ton eine eigene Sinustabelle zu verwenden. Aber eigentlich brauche ich ja nur jemanden, der mit elm-chans prinzip kurz erläutert...
@jochen die ganze geschichte beruht auf dem dds. es wird einfach in regelmässigen abständen (samplerate) ein bestimmter wert auf eine variable addiert und der überlauf (also das kippen des höchstwertigen bits) gibt deine grundfrequenz an. durch abschneiden mehrerer Bits erhälst du eine "position" innerhalb der wellenform (sozusagen skaliert auf die anzahl der bits die du abgeschnitten hast). diese kannst du nun auf eine sius oder sonstwelche tabelle "mappen" und erhälst einen wert den man per pwm (sollte sinnigerweise in einem vielfachen der samplerate liegen) "analog" ausgibt. das eigentlich interessante an dds ist das der vorgegebene inkrement linear der freuenz entspricht (bis zur hälfte der wiedergabefrequenz bzw. samplerate). die tabelle ist jetzt (so wie ich es verstanden habe) nur der inkrement-wert (passend zur jeweiligen note). du selbst hüpfst nur noch in der tabelle herum um deine melodie zu erzeugen :-) gruß rene ps. hoffe ich habe die problematik richtig verstanden :-)
Vielen vielen Dank für die Erklärung, jetzt komme ich garantiert weiter! weitere Links: http://de.wikipedia.org/wiki/Direct_Digital_Synthesis "Re: Tonausgabe Attiny26?" Beitrag "Re: Tonausgabe Attiny26?" "direkte digitale Synthese" Beitrag "direkte digitale Synthese (DDS, NCO)" Unter "3.1.1. Funktionsberechnung" auf Seite 6 der Projektbeschreibung von http://www.mikrocontroller.net/wiki/Projekt_Digitaler_Funktionsgenerator wird man weiterhin fündig. "A Technical Tutorial on Digital Signal Synthesis" Analog Devices (PDF) http://www.analog.com/UploadedFiles/Tutorials/450968421DDS_Tutorial_rev12-2-99.pdf Precision Sine-Wave Tone Synthesis Using 8-Bit MCUs http://www.freescale.com/files/microcontrollers/doc/app_note/AN1771.pdf "AN1222: Arithmetic Waveform Synthesis with the HC05/08 MCUs" Freescale (PDF) http://www.freescale.com/files/microcontrollers/doc/app_note/AN1222.pdf
Ein paar Erkenntnisse zu ELM-CHANs Umsetzung: 16MHz PLL Clock Timer0 im CTC Mode, clk_IO/8 Comparewert von OCR0A, 62 -> 32258.0645 Hz 128 Werte für die Dauerton-Wellenform (sustain) > Der Clou ist: eine Sinus-Tabelle z.B. mit 256 Einträgen. > Der Zugriff auf diese Tabelle geschieht mit einem Pointer, der ein > Vorkomma- und ein Nachkomma-Byte hat. > Wir wollen z.B. 440 Hz erzeugen, die Samplefrequenz sei 10 kHz, also > habe ich 10000 / 440 = 22,7272 Samples für eine Sinusvollwelle. > also addiere ich in das Nachkommabyte jedesmal 256*0,7272=186,1632 -> > 186 und dann mit Carry die 22 in das Vorkommabyte, das dann als Index > in die Tabelle zeigt. > Die genaue Frequenz ist 10000/(22+186/256)=440,01375 Hz. Ich habe jetzt versucht, das mal umzusetzen: 8MHz / 8 OCR0A=31 440 Hz / 32.258kHz/128 = 1.74592 -> 1 0.74592 * 256 = 190.95 -> 191 Das entspricht etwa dem 16.8 Wert für A4 in tbl_pitch (mg.asm:267)
1 | ISR(TIM0_COMPA_vect) |
2 | {
|
3 | static uint8_t i,f; |
4 | |
5 | if(f+191 >=255) |
6 | {
|
7 | i++; |
8 | }
|
9 | f+=191; |
10 | |
11 | if ((i + 1) >= WTS) |
12 | {
|
13 | i = i + 1 - WTS; |
14 | }
|
15 | else
|
16 | {
|
17 | i = i + 1; |
18 | }
|
19 | |
20 | OCR1A = sine[i]; |
21 | |
22 | }
|
Mit der nur begrenzt vorhandenen Messtechnik stelle ich einen Fehler von 5% zu 440Hz fest, und es gibt leichte Schwankungen der Frequenz. Mit OSCCAL läßt sich der interne Oszillator etwas justieren, aber nur verhältnismässig grob. Also evtl. lieber einen Quarz benutzen. Um also Teilschritte in der Wellentabelle zu gehen, obwohl nur Integer-Werte möglich sind, wird stattdessen gelegentlich ein zusätzlicher Schritt eingefügt.
> Um also Teilschritte in der Wellentabelle zu gehen, obwohl nur > Integer-Werte möglich sind, wird stattdessen gelegentlich ein > zusätzlicher Schritt eingefügt. Korrektur: ... gelegentlich die Schrittweite vergrößert! Könnte mir jemand sagen, in welchem Format die Melodie gespeichert ist und wie das Abspiel-Timing funktioniert?
Nochmals ein interessantes, überschaubares und gut strukturiertes Projekt zum Thema Musik und Töne... http://www.microsyl.com/doorbell/doorbell.html
Stimmt, er benutzt ja auch DDS. Welche Rolle spielt bloß bei Chan der kontinuierlich erhöhte 2. Wert aus einem Datensatz der score-tabelle? Ich nehme an, dass der erste die Tondauer bestimmt.
Quatsch! -> Beitrag "Sequencer Prinzip ELM - Wavetable Melody Generator (ASM)" Microsyl verwendet anscheinend nur ganzzahlige Schrittweiten ohne Korrektur.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.