Ist zeitgenaues programmieren mit GETTIMERALL() nicht möglich ?

Previous topic - Next topic

Trabant 500

Servus.

Ich sitze oft hinter meinem Schlagzeug und spiele einfach so vor mich hin. Dabei kommt es hin und wieder vor das mir ein Rhythmus gut gefällt und ich nichts zum Aufschreiben dabeihabe. Meinen WIZ habe ich allerdings immer einstecken und deswegen habe ich mir einen kleinen Drumcomputer programmiert.
Aus der aktuellen BPM-Zahl wird die Länge eines Ticks berechnet und wenn die vergangene Zeit gleich oder größer als diese Länge ist, wird einen Tick weitergezählt und die aktuellen Sounds ausgegeben.
Die vergangene Zeit wird mit GETTIMERALL() berechnet, aber irgendwie ist das zu ungenau. Wie man sich vorstellen kann muss sowas so exakt wir ein schweizer Uhrwerk laufen. Leider tut es das aber nicht, weil die vergangene Zeit immer größer ist als die benötigte. Dadurch holpert es manchmal und läuft auch absolut nicht im Metrum.
Hat jemand eine Idee wie man dieses Problem beheben und das Programm absolut exakt machen kann ?
IF was <> passt
   was = passt
ENDIF

Trabant 500

Also ich habe ein paar Testdurchläufe auf dem PC gemacht. Dabei habe ich den Drumcomputer eine Minute durchlaufen lassen und danach hat er mir die größte benötigte Zeit pro Tick ausgegeben. Ein Tick ist übrigens die Länge einer 16tel-Note (von einem 4/4-Takt ausgehend).

Hier die Ergebnisse dieser Testläufe:
QuoteBPM   Tickzeit   benötigte Zeit(gerundet)
  60   250         269
  80   187,5      216
100   150         179
120   125         146
150   100         127
200    75          113

Die Tickzeit ist also die berechnete Dauer die eine 16tel-Note eigentlich benötigen müsste (in ms). Wie man unschwer erkennen kann, weicht die benötigte Zeit erheblich von der errechneten ab. Ein wiederkehrendes Muster lässt sich dabei leider nicht feststellen. Es kommt anscheinend darauf an, was der PC nebenbei noch zu tun hat, denn ich bekam bei mehreren Durchläufen und der selben BPM-Einstellung trotzdem unterschiedliche Werte, die aber nur marginal voneinander abwichen. Jedoch machen sich selbst ein paar Millisekunden in der Masse sehr deutlich bemerkbar.

Diese Tests liefen im Leerlauf. Das Programm musste nur zählen und keine Sounds wiedergeben oder Eingaben entgegennehmen. Ich habe in Blitzbasic auch ein Testprogramm zum Ermitteln der Zeiten geschrieben und dort sah es ähnlich aus, denn auch da gab es große Unterschiede zwischen den verschiedenen Zeiten.

Meine Vergleiche zwischen meinem Korg-Metronom und Fruityloops ergaben aber keine Abweichungen. Das lief absolut exakt. Und Fruityloops muss ja auch noch sehr viele Aufgaben neben dem zählen erfüllen. Daran erkenne ich das es machbar ist, aber leider weiß ich nicht wie die das gemacht haben. Wo liegt also mein Denkfehler ?
IF was <> passt
   was = passt
ENDIF

Trabant 500

ÃÅ"ber das was Du schreibst habe ich mir auch schon Gedanken gemacht und das ist auch die ÃÅ"berzeugung zu der ich gekommen bin. Allerdings möchte ich nochmals auf das Fruityloops-Beispiel zurückkommen. Meine Tests mit Fruityloops liefen auf dem selben Rechner wie mein Programm und die selben Prozesse wurden gleichzeitig ausgeführt. Im Prinzip sind es also die gleichen Testbedingungen, aber trotzdem läuft Fruityloops absolut exakt. Selbst dann, wenn ich noch andere Anwendungen laufen habe. Also muss es ja irgendwie exakt funktionieren, selbst wenn man kein Echtzeitsystem hat. Die Frage ist nur: Wie ?
IF was <> passt
   was = passt
ENDIF

Trabant 500

Kann man denn die Windows-API in GLBasic einbinden ?
Die ausgegebenen Werte in meiner Tabelle sind, wie gesagt, gerundet. Ich habe nie wirklich gerade Ergebnisse bekommen, sondern immer mit Dezimalstellen hinter dem Komma. Und dennoch bekomme ich es nicht hin, daß mein Programm wirklich genau läuft.
Ich habe auch schon probiert die Zeitspanne, die das Programm für einen Durchlauf mehr als berechnet gebraucht hat, vom jeweils nächsten Durchlauf abzuziehen, aber da verschluckt er noch mehr. Das funktioniert also auch nicht.
IF was <> passt
   was = passt
ENDIF

Kitty Hello

Also.
Mit dem aktuellen Update verwende ich den genauesten Timer, den der Wiz anbietet.
Was macht Dein Code? Evtl. ist's ein Programmfehler?

Kann das Problem sein, dass es mit dem Screen-sync zu tun hat? LIMITFPS -1 schon mal versucht?

Schranz0r

Quote from: Trabant 500 on 2010-Feb-07
Kann man denn die Windows-API in GLBasic einbinden ?

sischa dat!

Ob dir das allerdings mehr hilft, wage ich zu bezweifeln...
Warten wir mal auf Gernots Kommentar!

EDIT:
Mist Gernot war schneller!
I <3 DGArray's :D

PC:
AMD Ryzen 7 3800X 16@4.5GHz, 16GB Corsair Vengeance LPX DDR4-3200 RAM, ASUS Dual GeForce RTX™ 3060 OC Edition 12GB GDDR6, Windows 11 Pro 64Bit, MSi Tomahawk B350 Mainboard

Trabant 500

Ja. LIMITFPS -1 war mein erster Gedanke, aber das hat leider keine Änderung gebracht.

Hier mal mein Testcode:
Code (glbasic) Select
GLOBAL OneTick#=125.0    //entspricht 120 BPM
GLOBAL MaxTick#
GLOBAL Ticktime#
GLOBAL ActTicktime#


LIMITFPS -1
Ticktime#=GETTIMERALL()


WHILE KEY(15)=0

ActTicktime=GETTIMERALL()-Ticktime

IF ActTicktime>=OneTick
IF ActTicktime>MaxTick THEN MaxTick=ActTicktime
Ticktime=GETTIMERALL()
ENDIF

PRINT "Berechnete Ticklänge = "+OneTick,0,0
PRINT "Maximale Ticklänge = "+MaxTick,0,20

SHOWSCREEN
WEND
END
IF was <> passt
   was = passt
ENDIF

Trabant 500

Wieso ? Wird denn das Win-API nicht auch kompiliert ?
IF was <> passt
   was = passt
ENDIF

Trabant 500

Na wenn es doch aber kompiliert wird, dann ist das doch am Ende alles ein (Maschinen)Code, den auch der WIZ versteht, oder !?  :blink:

Hat jemand mal das Beispielprogramm getestet und eventuell einen Denkfehler endeckt ?
IF was <> passt
   was = passt
ENDIF

Kitty Hello

geht unter win32
Code (glbasic) Select


AUTOPAUSE FALSE

GLOBAL OneTick#=125.0    //entspricht 120 BPM
GLOBAL MaxTick#
GLOBAL Ticktime#
GLOBAL ActTicktime#


LIMITFPS -1
Ticktime#=GETTIMERALL()


WHILE KEY(15)=0

LOCAL now = GETTIMERALL()
   ActTicktime= now -Ticktime

   IF ActTicktime>=OneTick
      IF ActTicktime>MaxTick THEN MaxTick=ActTicktime
      Ticktime=now
   ENDIF
   
   PRINT "Berechnete Ticklänge = "+OneTick,0,0
   PRINT "Maximale Ticklänge = "+MaxTick,0,20

SHOWSCREEN
WEND
END


Macht das bei Wiz Ärger?

Trabant 500

Bist Du Dir sicher ? Also bei mir zeigt das genauso Abweichungen.  :blink:
IF was <> passt
   was = passt
ENDIF

Kitty Hello


Trabant 500

IF was <> passt
   was = passt
ENDIF

Trabant 500

Das Problem ist, daß auch die geringste Abweichung nicht sein darf, denn auch Kleinvieh macht Mist. Und es sollte schon absolut genau sein.
IF was <> passt
   was = passt
ENDIF

Schranz0r

I <3 DGArray's :D

PC:
AMD Ryzen 7 3800X 16@4.5GHz, 16GB Corsair Vengeance LPX DDR4-3200 RAM, ASUS Dual GeForce RTX™ 3060 OC Edition 12GB GDDR6, Windows 11 Pro 64Bit, MSi Tomahawk B350 Mainboard