amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Timing nochmal [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- 2 [ - Beitrag schreiben - ]

14.09.2007, 18:15 Uhr

MaikG
Posts: 5172
Nutzer
Vor etwa einem Jahr hatten wir ja hier das Thema DTMF erkennung.
Also eingangssignal vom Sampler, dann durch den goertzel Alogarithmus.
So eine Simple warteschleife per timer.device und UNIT_MicroHZ
wollte ja gar nicht.
Hab das heute mal ohne berechnungen getestet und bekam Zufallswerte.

Ich glaube whose brachte dann ein Beispiel welches tatsächlich
ein Funktionierendes Timing lieferte(68060). Das teil ist aber
gegenüber dem Standard warten relativ komplex.

code:
FOR runs%=0 TO 50 REM 50 sekunden

 ticks&=ReadEClock&(VARPTR(myEClockVal&(0)))
 diff&=ticks&/Intervall%

 newLow&=myEClockVal&(1) + diff&
 IF newLow& >= 0 AND myEClockVal&(1) < 0 THEN INCR myEClockVal&(0)
 myEClockVal&(1)=newLow&

 POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
 POKEL tr& + tr_time%+tv_secs%, myEClockVal&(0)
 POKEL tr& + tr_time%+tv_micro%, myEClockVal&(1)
 SendIO&(tr&)


 WHILE repeat1%<10001 REM 8001 184 92 Samples
        newLow&=myEClockVal&(1) + diff&
        IF newLow& >= 0 AND myEClockVal&(1) < 0 THEN INCR myEClockVal&(0)
        myEClockVal&(1)=newLow&
        junk&=WaitIO&(tr&)
        POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
        POKEL tr& + tr_time% +tv_secs%,  myEClockVal&(0)
        POKEL tr& + tr_time% +tv_micro%, myEClockVal&(1)
        SendIO&(tr&)
        POKEB MySample&+repeat1%, PEEKB(&hBFE101)-128
        INCR repeat1%
 WEND

IF outst% THEN repeat1%=0:outst%=0:junk&= WaitIO(aio&(1)) ELSE repeat1%=0  REM überschreibt zwar währen spielen geht aber
PlaySample MySample&, 10000, 1, 63 REM 8000

NEXT runs%

IF outst% THEN junk&= WaitIO(aio&(1)):outst%=0



Jedenfalls wollte ich heute ein Prog schreiben welches
die Daten vom Sampler zum Amiga-Audio ausgang schreibt.
Gut, das prinzip klappt. Der durchlauf dauert wie immer geringfügig
länger als erwartet(z.B. 11s statt 10s).
Dabei leiert das ganze zwischendurch, alswenn eine Audio-Kassette
schleifft. Also der Ton wird zwischendurch langsamer.

Die CPU-Last liegt bei 50% @ 10000 HZ, daran liegts also nicht.
Das muss also irgendein Rechenfehler sein.
Andererseits verstehe ich immernoch nicht warum sowas nicht geht:

code:
POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
       POKEL tr& + tr_time% + tv_secs%, 0&
       POKEL tr& + tr_time% + tv_micro%, 43& REM 125=8000Hz  34=7.65 38=7.63 40/42=8.0 43=10.067 44=12.65

       SendIO&(tr&)
       INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds%
        
       junk& = WaitIO&(tr&)


das währe so wunderbar einfach.
Wie hinter dem REM steht sind aber die Ergebnisse bei gewünschten 10 Sekunden/8000HZ abweichend
und oft zufällig. Also 125 tv_micros sollten normalerweise 8000HZ sein.

[ - Antworten - Zitieren - Direktlink - ]

14.09.2007, 18:58 Uhr

whose
Posts: 2156
Nutzer
@MaikG:

Hm, hatte ich das damals nicht mehr erwähnt? Die "zufälligen" Ergebnisse kommen wohl dadurch zustande, daß Du in Deinem Programm nicht schnell genug auf die Message des timer.device reagierst (bzw. reagieren kannst).

Um da ein recht zuverlässiges Timing hinzubekommen (wenn Du es ganz genau haben wolltest, müßtest Du sogar mit Interrupts arbeiten), mußt Du quasi "sofort" den nächsten Request losschicken, wenn Du die Message bekommen hast, daß der vorige Request "erledigt" ist.

Wenn Du "zu viel" Zeit brauchst, kann Dir ein anderer Task "dazwischenpfuschen" und das Absenden des nächsten Requests verzögern. Diese Verzögerung ist (aus naheliegenden Gründen) natürlich nicht vorausberechenbar, der "bremsende" Task kann z.B. eine weit höhere Priorität als Deiner haben und gerade eine Menge CPU-Last verursachen, IO-Operationen in diesem Moment starten usw. usf.

Dazu kommt, daß auch das "Aufwachen", ausgelöst durch die Message vom timer.device, nicht immer in exakt der gleichen Zeit abläuft (aus den oben schon genannten Gründen, denn wenn Dein Programm noch nicht "an der Reihe ist", wirds auch nicht aufgeweckt sondern bekommt die Message etwas später bzw. wird etwas später aktiv. Dieses "etwas später" hängt natürlich auch wieder von vielen Faktoren ab, die man schlecht vorausberechnen kann). Eine gewisse (nicht feststehende) Latenzzeit ist also immer dabei.

Da ich Dich eigentlich als "och, das probieren wir einfach mal"-Entwickler kenne, dachte ich, daß Du schon mit Task-Prioritäten rumexperimentiert hättest. Spätestens da wäre es Dir aufgefallen, daß diese "zufällige" Timing-Geschichte u.A. mit der Taskpriorität Deines Programms zu tun hat.

Also, 100%-Timing wirst Du so nicht hinbekommen, aber recht nahe ans Ideal kommt man schon (für Audio in nicht allzu hoher Qualität reicht es).

Dazu solltest Du Dir Berechnungen jeder Art zwischen Empfang der Message und Senden des nächsten Requests sparen, die Priorität Deines Tasks erhöhen und vor allem möglichst wenig andere Sachen, die ordentlich CPU-Last erzeugen können, nebenbei laufen lassen.

Oder Dich in das Thema "Timer-Interrupts mit AmigaOS" einlesen.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

14.09.2007, 22:25 Uhr

MaikG
Posts: 5172
Nutzer
>Hm, hatte ich das damals nicht mehr erwähnt?

Weiss nicht mehr war 1 Jahr her...

>Die "zufälligen" Ergebnisse kommen wohl dadurch zustande, daß Du in
>Deinem Programm nicht schnell genug auf die Message des timer.device
>reagierst (bzw. reagieren kannst).

Nein, das währe der fall wenn das CPU Intensive goertzel dazwischen
laufen würde was jetzt nicht der fall ist.

Ausserdem läuft 10000 HZ unterbrechungsfrei und es leiert auch
bei 8000 HZ. Die CPU last ist bei 10khz auch nur 50%.


>Spätestens da wäre es Dir aufgefallen, daß diese "zufällige"
>Timing-Geschichte u.A. mit der Taskpriorität Deines Programms
>zu tun hat.


Kein unterschied von -50 0 +70.


>Also, 100%-Timing wirst Du so nicht hinbekommen, aber recht nahe
>ans Ideal kommt man schon (für Audio in nicht allzu hoher Qualität
>reicht es).

Vielleicht hab ich es falsch beschrieben. Etwa 70% von Ton ist okay.
Der rest ist zu langsam, also frauen klingen dann z.B. kurz wie männer.

Das ca. 1 Sekunde, also 10000 Requests! ab und zu zusammenhängend
verkehrt sind glaub ich nicht. Wenns 10 währen, immer mal wieder
aber so?

Alle Interrupt HW ist abgeschaltet, sonst nur OS3.9 am laufen.

Als "allzu hoch" würde ich das ergebniss beschreiben, eher als schlecht.


>Oder Dich in das Thema "Timer-Interrupts mit AmigaOS" einlesen.

Das muss man wieder kaufen und ist sehr kompliziert?

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 02:02 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Wenn Du "zu viel" Zeit brauchst, kann Dir ein anderer Task "dazwischenpfuschen" und das Absenden des nächsten Requests verzögern. Diese Verzögerung ist (aus naheliegenden Gründen) natürlich nicht vorausberechenbar, der "bremsende" Task kann z.B. eine weit höhere Priorität als Deiner haben und gerade eine Menge CPU-Last verursachen, IO-Operationen in diesem Moment starten usw. usf.


Wenn's nur darum gehen sollte, dann kann er ja für die Zeit des Einlesens eines Zeitfensters das Multitasking abschalten (forbit und permit, böse, böse ;) ). Dann ist sicher, dass Dir da kein anderer Task Dein Timing versaut.

Aber ich glaube, in dem Thread vor einem Jahr war das Problem, dass die Periodendauer der Abtastung nicht konstant war. So erklärt sich auch der "ausgelutschte-Musikkassetten-Effekt".

Nochmal für Mike: Du musst dafür sorgen, dass der zeitliche Abstand, in dem Du "hinschaust" (d.h. Dir den Wert vom Sampler holst), (bis auf vernachlässigbare Fluktuationen) konstant ist. Dann klappt das auch ohne "Leier-Effekt".

--
http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 06:08 Uhr

whose
Posts: 2156
Nutzer
@Mad_Dog:

Genau das meinte ich ja damit... wenn er die Abtasterei nicht innerhalb des "Zeitfensters" halten kann, kommt er in Schwulitäten. Der Leiereffekt kommt dadurch genauso zustande wie das scheinbar ungenaue Timing-Verhalten (das Problem in dem Thread damals, was wir dann ja zu einem großen Teil "beheben" konnten).

Das timer.device benutzt er ja, um in einem konstanten zeitlichen Abstand "hinzuschauen", aber er muß es flott "bedienen" und mögliche Störungen durch andere Tasks minimieren, damit das nicht aus dem Zeitfenster "rausrennt".

Stell Dir ein Zeitdiagramm mit senkrechten Flanken vor, die Plateaus geben an, wie viel Zeit ihm bleibt, um einen Wert ans audio.device weiterzureichen (das ist die Zeit, die bis zum Eintreffen der nächsten Message vergeht). Kann er diese Zeiten nicht halten (zum Beispiel weil er zu viel Zeit bei der Bearbeitung der gewonnenen Daten braucht, Stichwort Goertzel), gerät der Takt durcheinander. Er kommt quasi zu spät zum Wait().

Genauso, wenn die "Täler" nicht gehalten werden (welche die verfügbare Zeit zwischen Message-Empfang, Auslesen des aktuellen Wertes und Absenden des nächsten IORequests darstellen, und sie sind erheblich kürzer als die Plateaus. Streng genommen dürfte dort überhaupt gar keine Zeit "verbraten" werden, aber das geht nun mal nicht, Abtasten braucht Zeit).

Hilft halt nichts, wenn z.B. zwischen Message-Empfang und neuem Request auch noch "zufällige" Pausen eingefügt werden. Kommen z.B. zwei größere Pausen nacheinander geht ihm ein Abtastzeitpunkt flöten und er liest ein Datum weniger, als in die gewünschte Dauer hineingehört. Das passiert ein paar Mal und schon "leiert" es.

Es hat seinen Sinn, daß manche Steuerprogramme für Parallelport-Sampler das System für die Abtast-Dauer "einfrieren", 22,05KHz ist schon eine ziemlich frickelige Angelegenheit, was das Timing angeht ;)

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 09:45 Uhr

MaikG
Posts: 5172
Nutzer
>Der Leiereffekt kommt dadurch genauso zustande wie das scheinbar
>ungenaue Timing-Verhalten (das Problem in dem Thread damals, was
>wir dann ja zu einem großen Teil "beheben" konnten).

Da gings um zu große abweichungen beim Timing. Ein Prog was
halbwegs was erkennt lief nur auf den 68060. Das halbwegs
wird dann auch vom leiern sein.


>Stell Dir ein Zeitdiagramm mit senkrechten Flanken vor, die Plateaus
>geben an, wie viel Zeit ihm bleibt, um einen Wert ans audio.device
>weiterzureichen

Es leiert auch wenn ich eine Sekunde Sample, 1 Sekunde wiedergebe und
dann wieder Sample. Also keine Audiowiedergabe während des Samplen.


>Es hat seinen Sinn, daß manche Steuerprogramme für
>Parallelport-Sampler das System für die Abtast-Dauer "einfrieren",
>22,05KHz ist schon eine ziemlich frickelige Angelegenheit, was das
>Timing angeht ;)

22,05 Khz macht mein Sampler Problemlos in Stereo.
44 Khz in Mono.
Ich glaub das ging beim 68030er schon.

Über Interrupts hab ich nicht wirklich was gefunden, aber das
Programm Multimon(macht in etwa das selbe) setzt lt. Scout zumindest
kein Interrupt.

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 13:08 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Es hat seinen Sinn, daß manche Steuerprogramme für Parallelport-Sampler das System für die Abtast-Dauer "einfrieren", 22,05KHz ist schon eine ziemlich frickelige Angelegenheit, was das Timing angeht ;)


Also ich habe damals auch "ganz klein" mit einem nackten A1200 (68EC020@14Mhz, 2 MB Chip-Mem) angefangen. Gleich zu Beginn meiner "Amiga-Karriere" habe mir den Sampler "Stereo Master" geholt. Und soweit ich mich erinnern kann, waren 48khz Stereo problemlos in Echtzeit zu bewältigen - ohne irgendwelche Leier-Effekte oder sonstiges.

Das Problem hier ist vermutlich nicht fehlende Rechenpower.
--
http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 14:27 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
>Der Leiereffekt kommt dadurch genauso zustande wie das scheinbar
>ungenaue Timing-Verhalten (das Problem in dem Thread damals, was
>wir dann ja zu einem großen Teil "beheben" konnten).

Da gings um zu große abweichungen beim Timing. Ein Prog was
halbwegs was erkennt lief nur auf den 68060. Das halbwegs
wird dann auch vom leiern sein.


Das eine hängt aber auch mit dem anderen zusammen.

Zitat:
>Stell Dir ein Zeitdiagramm mit senkrechten Flanken vor, die Plateaus
>geben an, wie viel Zeit ihm bleibt, um einen Wert ans audio.device
>weiterzureichen

Es leiert auch wenn ich eine Sekunde Sample, 1 Sekunde wiedergebe und
dann wieder Sample. Also keine Audiowiedergabe während des Samplen.


Was darauf hinweist, daß Dein Timing (aus welchem Grund auch immer) unregelmäßig abläuft.

Zitat:
Über Interrupts hab ich nicht wirklich was gefunden, aber das
Programm Multimon(macht in etwa das selbe) setzt lt. Scout zumindest
kein Interrupt.


Gut, dann wissen wir noch mehr. Es geht also, auch ohne Tricksereien mit dem CIA. Da bleibt dann nicht mehr viel, MultiMon müßte demnach auch mit dem timer.device arbeiten und vor allem entweder mit der UNIT_ECLOCK oder UNIT_MICROHZ, den UNIT_VBLANK wäre für den Zweck nicht geeignet.

Am Sinn meiner Antwort ändert das jedenfalls nichts. Irgendwo hast Du eine Unregelmäßigkeit in Deinem Timing, die mußt Du finden.

Schau Dir doch nochmal den Thread von damals an, Mad_Dog hat, wenn ich mich recht erinnere, genau aus diesem Anlaß, ein kleines Sampler-Programm geschrieben. Das funktioniert recht gut und die Sourcen kannst Du Dir auch ansehen. Eventuell fällt Dir dann ein Unterschied zu Deinem Programm auf.

@Mad_Dog:

Ich habe nicht gesagt, daß das unmöglich wäre. Ich habe nur gesagt, daß es nicht trivial ist.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 15:44 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Schau Dir doch nochmal den Thread von damals an, Mad_Dog hat, wenn ich mich recht erinnere, genau aus diesem Anlaß, ein kleines Sampler-Programm geschrieben. Das funktioniert recht gut und die Sourcen kannst Du Dir auch ansehen.


Das war nur ein einfaches Oszilloskop. Ich hab das auch nur programmiert, damit ich den Sachverhalt hier praktisch nachvollziehen kann. Wie genau das Timing bei meinem Programm ist, kann ich nicht sagen - es gibt ja keinen Ton aus, sondern nur Grafik. Wer will, kann es ja so umbauen, dass der Ton zum Audio-Device umgeleitet wird - Source-Code ist ja dabei...

Hier nochmal das Programm von damals:
http://w3.norman-interactive.com/Monoscope_1_3.lha

Zitat:
@Mad_Dog:

Ich habe nicht gesagt, daß das unmöglich wäre. Ich habe nur gesagt, daß es nicht trivial ist.


Trivial ist es nicht, da gebe ich Dir recht. Das hier ist ein prima Beispiel zum Thema "Echtzeit-Systeme". Das verstehen manche Leute ja leider falsch... "Echtzeit-System" heisst, das ein System in einer bestimmten Zeit antworten muss. Das bedeutet nicht zwangsläufig, dass man da einen Supercomputer braucht. Manchmal tut's auch ein Microcontroller für ein paar Cent...

In unserem Fall heisst das, das eben sichergestellt werden muss, dass die Abtastfrequenz konstant bleibt. Wie man die Frequenz, die Periodendauer usw. berechnet, haben wir ja schon damals ausführlich durchgekaut.

Ich denke, das wichtigste bei diesem Problem ist, dass man erstmal die Physik versteht, die hinter "Audio-Digitalisierung" steht. Der Rest ergibt sich dann (hoffentlich) von selbst...


--
http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 18:07 Uhr

MaikG
Posts: 5172
Nutzer
>Was darauf hinweist, daß Dein Timing (aus welchem Grund auch immer) unregelmäßig abläuft.

Sagte ich doch. Ich möchte sagen der Code ist von dir.

Übrigens wird bei Multimon - 18000 HZ eine CPU Last von ganzen
5% angezeigt.

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 22:25 Uhr

DaxB
Posts: 1421
Nutzer
Habe jetzt nicht alles gelesen, aber was das Leiern betrifft, hängt das meiner Erfahrung nach, hauptsächlich mit der CPU last zusammen. Also die TST2 Software kann irgendwas bei 80kHz samplen. Hier auf 68040/40 keine probleme. Mit AHIRecord und noch IBrowse am werkeln (AGA), kommt ein rauschen/kratzen in die Aufnahme. Teilweise ist ein leiern zu hören. AHIRecord läuft ja im Multitasking. TST2 Software, Protracker, AudioMasterIV schalten das Multitasking ab.

[ - Antworten - Zitieren - Direktlink - ]

15.09.2007, 23:10 Uhr

MaikG
Posts: 5172
Nutzer
Multimon läuft auch im Multitasking und leiert nicht...

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 00:00 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
>Was darauf hinweist, daß Dein Timing (aus welchem Grund auch immer) unregelmäßig abläuft.

Sagte ich doch. Ich möchte sagen der Code ist von dir.


Ich möchte sagen, der Code ist keineswegs von mir, das ist Deiner. Nachdem ich mir den BASIC-Code nun etwas genauer angesehen habe, möchte ich sogar sagen: Der Code ist keinesfalls von mir, denn da passiert genau das, was ich schon die ganze Zeit bemängele.

Die äußere FOR-Schleife z.B.... da unterbrichst Du den Takt mit Sicherheit, denn da passiert viel zu viel anderes, bis der nächste Request auf den Weg geht. Der Zeitraum zwischen Empfang der Message und dem nächsten Request muß so kurz wie irgend möglich sein, damit das nicht zu schnell "wegläuft".

Normalerweise müßtest Du das Ganze vorher auch noch kalibrieren, damit es Langzeit-stabil läuft. Denn die Zeit, die zwischen Message und nächstem Request vergeht, müßtest Du streng genommen vom gewünschten Warte-Intervall abziehen.

Desweiteren ist es eigentlich großer Käse, ein bekanntes Intervall (dort: 50 Sekunden) nochmal in 1-Sekunden-Häppchen aufzuteilen. Warum machst Du das denn so?

Zitat:
Übrigens wird bei Multimon - 18000 HZ eine CPU Last von ganzen
5% angezeigt.


Wo kann man dieses ominöse Multimon eigentlich herbekommen? Ich habe gestern schon mal danach gesucht, aber finde nichts dergleichen, nur Zeugs für Multi-Monitor-Betrieb.

Ich persönlich glaube nämlich nicht daran, daß es ohne den Timer-Interrupt des CIAs arbeitet. Übrigens, man kann seine eigene Interrupt-Behandlung in eine sog. Interrupt-Server-Chain einhängen, das wird also nicht unbedingt als richtiger Interrupt angezeigt und inwieweit Scout das anzeigt weiß ich auch nicht.

Maik, ich kann Dir immer noch nur folgenden guten Rat geben: Untersuch Dein Programm genau, erkläre nicht alle, die Dir nicht auf Anhieb helfen können für inkompetent und vor allem setz die Ratschläge doch einfach mal so um, wie sie Dir gegeben werden.

Dein BASIC-Programm von oben läuft jedenfalls nicht so, wie man es Dir angeraten hat, im Gegenteil. Und es ist auch nicht das, was man Dir in dem DTMF-Thread als Hinweis gegeben hat.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 02:15 Uhr

Mad_Dog
Posts: 1944
Nutzer
Ich habe mir nochmal meinen Code von damals angeschaut.

Zur Erinnerung poste ich hier nochmal die Stelle, wo ich die Daten für ein Zeitfenster einlese:
C code:
// Ein Zeitfenster lesen.
void ReadFrame(struct Scope *sc)
{
   unsigned int t;

   /*  Hier werden die Werte gesammelt
    */
   for (t=0;t<sc->Size;t++)
   {
      sc->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
      sc->TimerIO->tr_time.tv_secs = 0;
      sc->TimerIO->tr_time.tv_micro = sc->Period;

      READ_PAR(sc->Data[t]);  // Wert vom Parallelport kopieren

      SendIO((struct IORequest *)sc->TimerIO);
      WaitIO((struct IORequest *)sc->TimerIO);

   }
}


Wie man sieht, hole ich den Wert vom Parallelport (ja, böse - ich lese direkt aus dem CIA-Register), sende dann ein Timer-Request und warte dann, bis ich eine Antwort erhalte. Optional hätte ich das Auslesen des Wertes auch zwischen dem SendIO und WaitIO machen können, wenn ich davon ausgehe, dass das fix genug geht. Mit der for-Schleife hole ich mir soviel Werte, wie ich für dieses Zeitfenster haben will. Dabei bleibt (hoffentlich) die Abtastfrequenz relativ konstant, weil ich ja immer brav auf die nächste Periode warte und sonst nichts tue.

Was andere Tasks in der Zwischenzeit machen, steht auf einem anderen Blatt. Wenn ich da auchnoch auf Nummer sicher gehen wollte, könnte ich vor der for-Schleife das Multitasking abschalten und danach wieder anschalten...

--
http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 02:31 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Mad_Dog:
Ich habe mir nochmal meinen Code von damals angeschaut.

Zur Erinnerung poste ich hier nochmal die Stelle, wo ich die Daten für ein Zeitfenster einlese:

...

Wie man sieht, hole ich den Wert vom Parallelport (ja, böse - ich lese direkt aus dem CIA-Register), sende dann ein Timer-Request und warte dann, bis ich eine Antwort erhalte. Optional hätte ich das Auslesen des Wertes auch zwischen dem SendIO und WaitIO machen können, wenn ich davon ausgehe, dass das fix genug geht.


So hätte ich das auch gemacht. Was ich mich allerdings bei den Samplern frage ist folgendes: Geht die Wandlung da immer mit "Fullspeed" oder wie wird das gehandhabt? Ich stelle mir das eigentlich immer als getakteten Vorgang vor und was passiert dann, wenn man mit dem Auslesen des Werts "außerhalb" des Wandlertakts liegt?

Was mir noch an Maiks Code aufgefallen ist: Er benutzt immer noch UNIT_ECLOCK, obwohl man ihm damals schon gesagt hat, daß UNIT_MIKROHZ praktikabler ist (und nicht ungenauer).

@MaikG

Benutz doch bitte mal UNIT_MIKROHZ, wie Mad_Dog es hier zeigt. Und bitte spiel das Sample erst nach dem kompletten Sample-Vorgang ab, um das zu überprüfen. Ich wette, da leiert es auf einmal nicht mehr.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 03:02 Uhr

Mad_Dog
Posts: 1944
Nutzer
Um eventuelle Unklarheiten zu beseitigen, zeige ich hier nochmal die Stelle, wo ich mein Scope-Struct initialisiere. Hier kann man auch sehen, wie die Periode aus der Frequenz berechnet wird usw.:
C code:
/*  Scope
 *
 *  Oszilloskop erzeugen:
 *
 *  Eingabeparameter: ULONG f  - Die Samplingfrequenz
 *                    double t - Dauer des Samples in Sekunden
 *                    LONG p   - Pen Nummer zum Zeichnen
 *                    LONG b   - Pen Nummer für Hintergrund
 *  Rückgabe:         struct Scope* - Zeiger auf Scope Struktur
 *
 */
struct Scope *CreateScope(ULONG f,double t,LONG p, LONG b)
{
   struct Scope *sc;

   sc = (struct Scope *) AllocMem(sizeof(struct Scope),MEMF_CLEAR);

   sc->SamplingFreq = f;
   sc->Time = t;
   sc->Period = (int)1E6/f;
   sc->Size = (ULONG)(f*t);
   sc->Data = (UBYTE *)AllocMem(sc->Size,MEMF_CLEAR);
   sc->Pen = p;
   sc->Background = b;
   sc->TimerMP = CreateMsgPort();
   sc->TimerIO = (struct timerequest *) CreateIORequest(sc->TimerMP,sizeof(struct timerequest));

   return sc; 
}


Bevor die Frage aufkommt, was ich in der Zeile sc->Period = (int)1E6/f; mache: Wie wir wissen, berechnet sich die Dauer der Periode aus dem Kehrwert der Frequenz. Da wir aber UNIT_MICROHZ als Timer nehmen, brauchen wir die Periode in Microsekunden. Deshalb steht hier 1E6/f statt 1/f.

Für alle Physik-Legasteniker: Die Periode bezeichnet die Zeit, die wir zwischen dem Auslesen der einzelnen Werte warten müssen. Bei 32kHz wären das 1/32000 = 0,000031 Sekunden oder 1000000/32000 = 31,25 Microsekunden.

Die explizite Typumwandlung auf Integer macht daraus den Wert 31.

--
http://www.norman-interactive.com


[ Dieser Beitrag wurde von Mad_Dog am 16.09.2007 um 03:14 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 03:29 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:
Was ich mich allerdings bei den Samplern frage ist folgendes: Geht die Wandlung da immer mit "Fullspeed" oder wie wird das gehandhabt? Ich stelle mir das eigentlich immer als getakteten Vorgang vor und was passiert dann, wenn man mit dem Auslesen des Werts "außerhalb" des Wandlertakts liegt?


Siehe http://de.wikipedia.org/wiki/Analog-Digital-Umsetzer und http://de.wikipedia.org/wiki/Abtastung.

--
http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 05:40 Uhr

whose
Posts: 2156
Nutzer
@Mad_Dog:

Danke für die Links. Das bestätigt nochmal, was ich mir bereits (trotz technischer Unwissenheit auf dem Gebiet) dachte. Man hat demnach (abhängig vom Typ des A/D-Wandlers) etwas Zeit, bevor der nächste Wert ansteht und der Wandel-Vorgang an sich läuft in einem bestimmten Takt ab.

Wenn man diesen Zeitrahmen überschreitet, der sich aus dem Wandlertakt ergibt, arbeitet man am Wandlertakt vorbei und verliert irgendwann zwangsläufig Werte bzw. liest Werte mehrfach. Ist das so korrekt gedacht?

Wenn ja, dann würde das bedeuten, daß man mit bestimmten Samplefrequenzen letzten Endes am "Leiern" gar nicht vorbeikommt, wenn der Samplevorgang zu lang angesetzt ist, da sich der Abtast-Takt und der Wandlertakt mit der Dauer des Samplevorgangs bei diesen Frequenzen auf jeden Fall gegeneinander verschieben und man im ungünstigen Fall mehrfach "alte" Werte liest oder mehrfach Werte "überspringt".

Eine Sample-Frequenz von z.B. 10000 wäre dann per se schon eine schlechte Idee, wenn der Wandler auf die "üblichen" Frequenzen von z.B. 22,05KHz getrimmt ist. Man kann dann nur geradzahlig gebrochene Frequenzen der maximalen Samplingfrequenz des Wandlers einigermaßen korrekt abtasten, also z.B. 11,02KHz oder 5,51. Die dazwischen liegenden Abtastfrequenzen wären dann nur "mehr oder weniger" brauchbar, je nach Verhältnis Samplefrequenz/Wandlerfrequenz und Dauer des Vorgangs.

Wenn ich hier jetzt falsch denken sollte, dann klärt das bitte auf. Wenn ich aber richtig denke, dürften wir dem "Fehler" schon um ein ganzes Stück nähergekommen sein.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 10:47 Uhr

MaikG
Posts: 5172
Nutzer
>Ich möchte sagen, der Code ist keineswegs von mir, das ist Deiner.

Nein, auf so eine idee würde ich nicht kommen.


>Die äußere FOR-Schleife z.B.... da unterbrichst Du den Takt mit
>Sicherheit, denn da passiert viel zu viel anderes, bis der nächste
>Request auf den Weg geht. Der Zeitraum zwischen Empfang der Message
>und dem nächsten Request muß so kurz wie irgend möglich sein,
>damit das nicht zu schnell "wegläuft".

Ich erinnere mich dunkel an "Zeit vorrausberchnen" wenn der Code
das oben tut, stimmt das.
Dann würde das leiern auch da sein, wenn man nach dem Samplen
abspielt und wieder Sampled.


>Desweiteren ist es eigentlich großer Käse, ein bekanntes Intervall
>(dort: 50 Sekunden) nochmal in 1-Sekunden-Häppchen aufzuteilen.
>Warum machst Du das denn so?

Weil ich einen Live-Ton will, aktuell ist er 1 sekunde verzögert
(Audio.device braucht glaube ich min 1 sek) - 50 sek währen viel
zu viel verzögerung.

>Wo kann man dieses ominöse Multimon eigentlich herbekommen?

Das ist beim Megalosound Sampler mit dabei.


>erkläre nicht alle, die Dir nicht
>auf Anhieb helfen können für inkompetent

Hey, das hab ich auch nie!

>und vor allem setz die Ratschläge doch einfach mal so um, wie sie
>Dir gegeben werden.

Wenn es für mich machbar ist, aber das ist es nicht.



>Und es ist auch nicht das, was man Dir in dem DTMF-Thread als
>Hinweis gegeben hat.


Es ist das einzige was überhaupt annährend an das "korrekte" Timing
rankommt. Ich hab damals alles probiert.




>Zur Erinnerung poste ich hier nochmal die Stelle, wo ich die Daten
>für ein Zeitfenster einlese:

Ja, wenn dieses Timing bei mir keine Zufallswerte liefern würde...
Wenn man SendIO+WaitIO hinternander schreibt ist da DOIO nicht besser?


So, habs nochmal getestet:
code:
WHILE myseconds%<10
        POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
        POKEL tr& + tr_time% + tv_secs%, 0&
        POKEL tr& + tr_time% + tv_micro%, 44& REM 125=8000Hz
        SendIO&(tr&)
        INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds% REM 11.39   
        junk& = WaitIO&(tr&)
        REM INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds%    rem 11.41   11.46 mit DOIO
      WEND


Also keine großen berechnungen, nur die sekundenzählung.
Bei 10sek mit 44 micros, entweder 11.39 sek oder 11.41(siehe Position).
Wie erwähnt, sind aber 44 keine 8000 HZ sondern wesentlich mehr.
Bei 125 komme ich auf etwa 18 sekunden.
In dem Minicode kann ja kaum ein Fehler sein.



[ Dieser Beitrag wurde von MaikG am 16.09.2007 um 12:55 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 13:44 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:

So, habs nochmal getestet:
code:
WHILE myseconds%<10
        POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
        POKEL tr& + tr_time% + tv_secs%, 0&
        POKEL tr& + tr_time% + tv_micro%, 44& REM 125=8000Hz
        SendIO&(tr&)
        INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds% REM 11.39   
        junk& = WaitIO&(tr&)
        REM INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds%    rem 11.41   11.46 mit DOIO
      WEND


Also keine großen berechnungen, nur die sekundenzählung.
Bei 10sek mit 44 micros, entweder 11.39 sek oder 11.41(siehe Position).
Wie erwähnt, sind aber 44 keine 8000 HZ sondern wesentlich mehr.
Bei 125 komme ich auf etwa 18 sekunden.
In dem Minicode kann ja kaum ein Fehler sein.


Naja, in dem Minicode an sich nicht. Ok, die 8000 ist etwas "daneben", weil man bei 44 auf irgendwas um die 22KHz kommen müßte.

Nur verstehe ich wirklich nicht, wieso das nur bei Dir wesentlich langsamer läuft. Der "Minicode" läuft bei mir (gemessen mit EClock) auf dein paar Mikrosekunden genau und man kann das Spielchen bequem bis zu einem Wert von 22 treiben (wahrscheinlich auch noch wesentlich weiter), ohne daß sich an der Genauigkeit etwas ändert.

Allerdings habe ich keine Ahnung, was MaxonBASIC (das verwendest Du doch?) daraus macht...

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 14:47 Uhr

Ralf27
Posts: 2779
Nutzer
MaxonBasic ist kein Geschwindigkeitswunder. Sowas in MBasic zu machen.. respekt.

Selbst ACE ist da schneller.

MaxonBasic kann man eigentlich für so eine Art von Programmen nicht verwenden. Und hier geht es ja um ein Timingproblem.

Ich vermute einfach mal, das MBasic da es vom Speed her nicht hinbekommt.
Ich bekomme es ja auch hin und wieder selbst mit, wie groß da die Unterschiede sein können. Vieles kann man kompensieren, anderes dagegen weniger...
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 14:52 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Danke für die Links. Das bestätigt nochmal, was ich mir bereits (trotz technischer Unwissenheit auf dem Gebiet) dachte. Man hat demnach (abhängig vom Typ des A/D-Wandlers) etwas Zeit, bevor der nächste Wert ansteht und der Wandel-Vorgang an sich läuft in einem bestimmten Takt ab.

Wenn man diesen Zeitrahmen überschreitet, der sich aus dem Wandlertakt ergibt, arbeitet man am Wandlertakt vorbei und verliert irgendwann zwangsläufig Werte bzw. liest Werte mehrfach. Ist das so korrekt gedacht?


Ehrlich gesagt: Genau habe ich mich mit der Funktionsweise von Parallelport-Samplern noch nicht beschäftigt. Deshalb kann ich hier auch nur Sachen annehmen. Da man die hardwaremässige Abtastfrequenz nicht vom Computer aus einstellen kann, nehme ich mal an, dass diese Sampler immer mit der maximalfrequenz des Wandlers arbeiten. Die softwaremäßige Abtastfrequenz ergibt sich demnach daraus, in welchen zeitlichen Abständen man sich die Werte vom Parallelport holt.

Demnach wäre man auf jeden Fall auf der sicheren Seite, wenn man die Werte mit der doppelten Frequenz der maximalen (festen) Abtastrate des Samplers vom Parallelport holt. Dann bräuchte man im Programm allerdings einen Puffer, in dem man für niedrigere Samplingraten einfach nur Werte in bestimmten Abständen rausnimmt (z.B. jeden 2. Wert für die halbe Samplingfrequenz). Das entspreche dann einer "Vergröberung" des Samples.

Ferner vermute ich, dass die Werte, die der AD-Wandler berechnet, auch noch in einem Register gepuffert werden. Genaues kann ich dazu aber auch nicht sagen. Vielleicht hat jemand, der hier mitliest schonmal beruflich was mit AD-Wandlern zu tun gehabt und kann mehr dazu erzählen?

--
http://www.norman-interactive.com

[ Dieser Beitrag wurde von Mad_Dog am 16.09.2007 um 14:53 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

16.09.2007, 16:03 Uhr

MaikG
Posts: 5172
Nutzer
>Naja, in dem Minicode an sich nicht. Ok, die 8000 ist etwas
>"daneben", weil man bei 44 auf irgendwas um die 22KHz kommen müßte.

Richtig, ist aber beabsichtigt da mit 125 keine 10sek erreicht werden,
welche ich ja benötige.

>Der "Minicode" läuft bei mir (gemessen mit EClock)
>auf dein paar Mikrosekunden genau und man kann das Spielchen bequem
>bis zu einem Wert von 22 treiben (wahrscheinlich auch noch
>wesentlich weiter), ohne daß sich an der Genauigkeit etwas ändert.

Kannst du den Code mal posten(mit timer öffnen), würde das unter C nochmal
machen.
Beim DTMF hatten wir ja eigentlich festgestellt das C nicht
schneller ist(inkl. goertzel) und selbst bei einer 060 optimierung.


>Ich vermute einfach mal, das MBasic da es vom Speed her nicht
>hinbekommt.

Eine Variable zu erhöhen? Um solche verzögerungen zu erreichen
brauchts schon viel mehr.


>Man hat demnach (abhängig vom Typ des A/D-Wandlers) etwas Zeit,
>bevor der nächste Wert ansteht und der Wandel-Vorgang an sich läuft
>in einem bestimmten Takt ab.

Okay, dann ein wort zu Hardware es ist ein AD Wandler, er arbeitet
immer mit Max. Geschwindigkeit. Es gibt keine Möglichkeit der
Syncronisation - weil weder der Amiga gibt dem Sampler einen Takt
noch umgekehrt.
Von daher wird direkt der wert gelesen wenn man ihn braucht.

Bei der Software kann man ja auch nicht nur 11khz, 22khz und 44khz
angeben sondern alles mögliche dazwischen.


>Ferner vermute ich, dass die Werte, die der AD-Wandler berechnet,
>auch noch in einem Register gepuffert werden.

Liegt direkt am Parport ohne weiter Pufferung.


Zu Multimon, es ist 9kB groß. Ergo vermutlich mit AMOS oder C
geschrieben - für Assembler zu groß.

Der Wert wird vom Parport gelesen AND 80 genommen, später
direkt ins Audio Register(Byteweise) geschrieben.
Mit dem Audio-Interrupt register wird auch gespielt.
Wo das Timing herkommt konnte ich nicht sehen, Assembler war
schon lange her ausserdem ists ja kein Quellcode.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 09:31 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Der Wert wird vom Parport gelesen AND 80 genommen, später
direkt ins Audio Register(Byteweise) geschrieben.

80 oder hexadezimal 80?
Richtig Sinn würde eine solche Operation in beiden Fällen nicht machen, weil bei AND Bits ausmaskiert werden und bei diesem Wert ja nichts verwertbares mehr übrig bleiben würde.

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 12:45 Uhr

MaikG
Posts: 5172
Nutzer
>80 oder hexadezimal 80?

0x80

>Richtig Sinn würde eine solche Operation in beiden Fällen nicht
>machen, weil bei AND Bits ausmaskiert werden und bei diesem Wert
>ja nichts verwertbares mehr übrig bleiben würde.

Kann auch was anderes sein, ich glaube ANDI oder so hiess der befehl.

Jedenfalls hats die aufgabe den Wert vom Sampler auf das Amiga
übliche Format(-127 bis +128) zu bringen. Also das vorzeichen
wird hinzugefügt.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 15:41 Uhr

tboeckel
Posts: 124
Nutzer
@MaikG:

Für das sinnvolle "Vorausberechnen" der Zeit sollte man dann aber nicht UNIT_MICROHZ oder UNIT_ECLOCK, sondern UNIT_WAITUNITL oder UNIT_WAITECLOCK nehmen, je nachdem welche Zeitbasis einem besser gefällt. Die beiden Units warten nicht eine bestimmte Zeitspanne, sondern bis zu einem bestimmten Zeitpunkt. Den muß man sich vorher ausrechnen. Auf jeden Fall kann zwischen zwei Zyklen (fast) beliebig viel passieren ohne daß der eigene Rhythmus durch andere äußere Einflüsse aus dem Takt gebracht wird. Wurde in einem Zyklus mehr Zeit verbraucht als in den vorherigen, so löst das timer.device trotzdem noch zum richtigen Zeitpunkt aus, weil die Endzeit absolut und nicht relativ berechnet wurde.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 16:21 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Kann auch was anderes sein, ich glaube ANDI oder so hiess der befehl.

ANDI ist ein AND, das I sagt nur aus, dass der Parameter eine im Befehl-Opcode mit enthaltene Konstante ist. Ist für die Logik unerheblich, kann man deshalb bei den meisten Assembler-Übersetzern auch weglassen.
Zitat:
Jedenfalls hats die aufgabe den Wert vom Sampler auf das Amiga
übliche Format(-127 bis +128) zu bringen. Also das vorzeichen
wird hinzugefügt.

Klingt aber nicht korrekt. Wenn man einen Wert in 0..255 zu -128..+127 transformieren will, muss man einfach 128 von der Zahl abziehen. Mit einer einzelnen AND Operation kann man da jedenfalls kein sinnvolles Ergebnis erzielen. Aber vielleicht handelt es sich ja auch um eine trickreiche "Optimierung", bei der statt der einfachen Subtraktion mehrere logische Verknüpfungen benutzt werden, und Du hast die anderen Befehle bisher nur übersehen?

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 16:26 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von tboeckel:
@MaikG:

Für das sinnvolle "Vorausberechnen" der Zeit sollte man dann aber nicht UNIT_MICROHZ oder UNIT_ECLOCK, sondern UNIT_WAITUNITL oder UNIT_WAITECLOCK nehmen, je nachdem welche Zeitbasis einem besser gefällt. Die beiden Units warten nicht eine bestimmte Zeitspanne, sondern bis zu einem bestimmten Zeitpunkt.


Das ist bekannt, und wenn Du Dir den Code aus dem ersten Posting ganz genau anschaust, kannst Du auch erkennen, dass es so gemacht wird. Das Öffnen des device mit der UNIT ist zwar nicht zu erkennen, aber an der Programmlogik wird es trotzdem ersichtlich, dass auf den Zeitpunkt «Programmstart (einmaliges ReadEClock am Anfang) plus n*vorausberechnetes Intervall» gewartet wird. Mit einer anderen Unit als WAITECLOCK kann dieses Codefragment da oben gar nicht funktionieren, also noch weniger als mit der geposteten Abweichung.

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 16:43 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Nur verstehe ich wirklich nicht, wieso das nur bei Dir wesentlich langsamer läuft. Der "Minicode" läuft bei mir (gemessen mit EClock) auf dein paar Mikrosekunden genau und man kann das Spielchen bequem bis zu einem Wert von 22 treiben (wahrscheinlich auch noch wesentlich weiter), ohne daß sich an der Genauigkeit etwas ändert.

Das liegt daran, dass er nicht mit EClock misst, sondern mit der Realzeit. Mit der Uhr zu messen, die falsch geht, macht ja auch wenig Sinn. Damit wirst Du immer darauf kommen, dass selbige Uhr "richtig" geht, also synchron zu sich selbst. Wenn Du es nachvollziehen willst, dann mach die Gesamtlaufzeit lang genug (wie z.B. die erwähnten zehn Sekunden) und nimm ne Stoppuhr. Oder schreib ein Testprogramm, dass die Echtzeituhr ausliest.

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

17.09.2007, 19:11 Uhr

MaikG
Posts: 5172
Nutzer
>Mit einer einzelnen AND Operation kann man da jedenfalls kein
>sinnvolles Ergebnis erzielen.

War auch ADDI.b also Anton Dora Dora Ida.

[ - Antworten - Zitieren - Direktlink - ]


-1- 2 [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Timing nochmal [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.