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

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

Erste 3 4 5 6 7 -8- 9 10 11 [ - Beitrag schreiben - ]

13.09.2006, 11:54 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:

Getsystime
sind 125 sekunden Vergangen?


Bleibt die Frage zu klären was in folgendem Fall passiert:

1. Hole die aktuelle Systemzeit - nennen wir diesen Zeitpunkt t_0
2. Berechne Zeitpunkt t_0 + gewünschte Wartezeit - nennen wir diesen Zeitpunkt t_1
3. Mach irgendwas (z.B. Parrallelport auslesen, Berechnungen anstellen...)
4. Warte bis zum Zeitpunkt t_1

Wenn in 4. der Zeitpunkt t_1 bereits überschritten ist, müsste AFAIK eine dieser "Warte Bis" Funktionen des timer.device das Warten trotzdem beenden, da dieser Zeitpunkt t_1 ja nie mehr erreicht werden kann, weil schon vorbei...



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

[ Dieser Beitrag wurde von Mad_Dog am 13.09.2006 um 11:55 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 11:58 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Und ausgerechnet Du mußt mit "...auf eine für Menschen verständliche Art und Weise" kommen, mit einem Testprogramm, das übelst zusammengehackt ist und vor allem auf Anhieb abstürzt auf einem normalen Amiga, noch dazu mit Deklarationen und Definitionen "wie es uns gefällt", irgendwo mitten im Text.

Eine Variable da zu deklarieren, wo sie gebraucht wird, statt irgendwo am Anfang von irgendetwas, ist das normalste von der Welt. So halten es C++, C99, Java und noch diverse andere Programmiersprachen, die nicht in den Denkmustern aus den 80ern, bzw. man müsste ja bei C eher 70ern stehengeblieben sind.
Zitat:
Lieber Holger, UNIT_WAITUNTIL ist sogar nur mit UNIT_VBLANK vergleichbar, was die Genauigkeit angeht.

Da wundert es nicht, wenn das bei 125µs aus dem Ruder läuft. Allerdings hättest Du als Kenner der Materie das eigentlich wissen müssen :D

Ja, ich hatte das Programm mehrfach umgestellt, von µHZ auf EClock, Wait... und zurück. Da habe ich wohl vor lauter "the same as" in den Autodocs die Falle übersehen. Ja ja, die Leute bei Commodore wussten halt, was Spass macht.
Zitat:
Original von Mad_Dog:
Dir ist aber schon bewußt, daß Du in Deinem Beispiel DoIO() genommen hast - was die Anfrage an das Device synchron versendet. D.h. nach DoIO geht's erst dann weiter, wenn der Request tatsächlich verarbeitet wurde. Im Gegesatz dazu arbeitet SendIO() asynchron, d.h. es geht sofort weiter, auch wenn das device den Request noch nicht ganz verdaut hat.

Vollkommen richtig, aber wenn man in der Schleife alles entfernt, was Overhead erzeugen könnte, rutschen SendIO und WaitIO sowieso direkt hintereinander, weil dazwischen ja nichts mehr passiert. Deshalb kann man es dann auch durch DoIO ersetzen.

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 11:59 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Mad_Dog:
Zitat:
Original von MaikG:

Getsystime
sind 125 sekunden Vergangen?


Bleibt die Frage zu klären was in folgendem Fall passiert:

1. Hole die aktuelle Systemzeit - nennen wir diesen Zeitpunkt t_0
2. Berechne Zeitpunkt t_0 + gewünschte Wartezeit - nennen wir diesen Zeitpunkt t_1
3. Mach irgendwas (z.B. Parrallelport auslesen, Berechnungen anstellen...)
4. Warte bis zum Zeitpunkt t_1

Wenn in 4. der Zeitpunkt t_1 bereits überschritten ist, müsste AFAIK eine dieser "Warte Bis" Funktionen des timer.device das Warten trotzdem beenden, da dieser Zeitpunkt t_1 ja nie mehr erreicht werden kann, weil schon vorbei...


Das tun sie auch. UNIT_WAITUNTIL gibt allerdings erst mit dem nächsten VBLANK Laut, was in den meisten Fällen viel zu spät sein dürfte. Daher kommt auch die Annahme, daß die Timer viel zu langsam laufen würden.

Maik arbeitet nun aber mit reinem Polling, wenn ich das recht verstanden habe, das ist naturgemäß etwas schwieriger zu handhaben.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 12:05 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:

Eine Variable da zu deklarieren, wo sie gebraucht wird, statt irgendwo am Anfang von irgendetwas, ist das normalste von der Welt. So halten es C++, C99, Java und noch diverse andere Programmiersprachen, die nicht in den Denkmustern aus den 80ern, bzw. man müsste ja bei C eher 70ern stehengeblieben sind.


Dann bleibe ich ehrlich gesagt lieber bei der Lesbarkeit der 70er, als mich da in die 90er zu begeben.

Zitat:
Zitat:
Lieber Holger, UNIT_WAITUNTIL ist sogar nur mit UNIT_VBLANK vergleichbar, was die Genauigkeit angeht.

Da wundert es nicht, wenn das bei 125µs aus dem Ruder läuft. Allerdings hättest Du als Kenner der Materie das eigentlich wissen müssen :D

Ja, ich hatte das Programm mehrfach umgestellt, von µHZ auf EClock, Wait... und zurück. Da habe ich wohl vor lauter "the same as" in den Autodocs die Falle übersehen. Ja ja, die Leute bei Commodore wussten halt, was Spass macht.

Komisch... ich habe das auf Anhieb gefunden und sofort gesehen, welche Unit mit welcher Granularität arbeitet. Steht direkt bei den Beschreibungen zu den Units im RKM. Auch in den Autodocs ist das recht klar ersichtlich, finde ich.

Nun ja, also bauen wir (bzw. ich) das Ganze mal für den Anfang mit UNIT_MICROHZ, später dann in einer Fassung mit UNIT_WAITECLOCK.

Und ich wette, daß das problemlos (mit Abweichungen +- 3-4µs) funktioniert.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 12:08 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Zitat:
Original von Mad_Dog:
Dir ist aber schon bewußt, daß Du in Deinem Beispiel DoIO() genommen hast - was die Anfrage an das Device synchron versendet. D.h. nach DoIO geht's erst dann weiter, wenn der Request tatsächlich verarbeitet wurde. Im Gegesatz dazu arbeitet SendIO() asynchron, d.h. es geht sofort weiter, auch wenn das device den Request noch nicht ganz verdaut hat.

Vollkommen richtig, aber wenn man in der Schleife alles entfernt, was Overhead erzeugen könnte, rutschen SendIO und WaitIO sowieso direkt hintereinander, weil dazwischen ja nichts mehr passiert. Deshalb kann man es dann auch durch DoIO ersetzen.

Wobei Du in Deinem Beispiel ja kein WaitIO(), Wait(), WaitPort() oder sonst was drin hast. Was dabei herauskommt könnte man eine "Denial of Service Attacke" auf das timer.device nennen. Du bombst das timer.device nur mit Anfragen zu, ohne zu warten... Ich weiß jetzt nicht auswendig, wo all diese Anfragen landen - möglicherweise in einer Queue. Und was passiert, wenn diese Queue voll ist?

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


[ Dieser Beitrag wurde von Mad_Dog am 13.09.2006 um 12:10 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 12:39 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Komisch... ich habe das auf Anhieb gefunden und sofort gesehen, welche Unit mit welcher Granularität arbeitet. Steht direkt bei den Beschreibungen zu den Units im RKM. Auch in den Autodocs ist das recht klar ersichtlich, finde ich.


Nein, hast Du nicht. Du hast zwei Tage lange Schwachsinn darüber, dass man das Programm "kalibrieren" müsste geredet, bevor Du den Fehler gefunden hast.

Dass das Programm von mir einen Fehler hatte, war bekannt, jedenfall bevor Du damit angefangen hast, dass das timer.device angeblich so funktionieren würde, dass wait until nicht mehr wait until, sondern wait something mystical bedeuten würde.

Hättest Du vor zwei Tagen diesen Fehler gefunden, wäre ich Dir dankbar gewesen. So hast Du zwei Tage lang meine Zeit verschwendet, wo das Ändern des Beispiels von WAIT_UNTIL auf WAIT_ECLOCK eine Sache von fünf Minuten gewesen wäre.

Aber Du wolltest lieber die Logik des Programms in Frage stellen, statt nach einem einfachen Fehler Suchen zu helfen.

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 12:42 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Mad_Dog:
Wobei Du in Deinem Beispiel ja kein WaitIO(), Wait(), WaitPort() oder sonst was drin hast. Was dabei herauskommt könnte man eine "Denial of Service Attacke" auf das timer.device nennen. Du bombst das timer.device nur mit Anfragen zu, ohne zu warten... Ich weiß jetzt nicht auswendig, wo all diese Anfragen landen - möglicherweise in einer Queue. Und was passiert, wenn diese Queue voll ist?


Wie kommst Du denn darauf?
DoIO() macht (fast) exakt das gleiche wie SendIO(), gefolgt von WaitIO(). Der einzige Unterschied ist, dass über das IOF_QUICK Flag dem device mitgeteilt wird, dass es diese Anfrage auch synchron ausführen könnte. Was aber in diesem speziellen Fall vom timer.device ignoriert wird.

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 13:09 Uhr

Holger
Posts: 8116
Nutzer
Klasse, jetzt sind eClock und Programm perfekt in Sync. Die reale Zeit ist es zwar nicht, aber das würde ich bei einem Emulator auch nicht zwingend erwarten.
C code:
#include <proto/dos.h>
#include <proto/exec.h>
#define __NOLIBBASE__
#define TimerBase (tr->tr_node.io_Device)
#include <proto/timer.h>
#include <devices/timer.h>
#include <stdint.h>

struct timerequest *open_timer(long unit)
{
  struct MsgPort *port;
  struct timerequest *req;

  if(port = CreateMsgPort())
  {
    if(req=(struct timerequest*)CreateIORequest(port,sizeof(struct timerequest)))
    {
      if(0 == OpenDevice("timer.device", unit, (struct IORequest*)req, 0))
        return req;
      DeleteIORequest((struct IORequest*)req);
    }
    DeleteMsgPort(port);
  }
  return NULL;
}
void close_timer(struct timerequest *req)
{
  struct MsgPort *port;

  CloseDevice((struct IORequest *)req);
  port = req->tr_node.io_Message.mn_ReplyPort;
  DeleteIORequest((struct IORequest *)req);
  DeleteMsgPort(port);
}

int main(int x, char**y)
{
  struct timerequest *tr=open_timer(UNIT_WAITECLOCK);
  ULONG ticksPerSecond=8000, eclockPerSec, eclockPerTick, sec, i;
  uint64_t target, startTime;

  if(!tr) { PrintFault(IoErr(), "Couldn't open timer.device"); return 10; }
  eclockPerTick=ReadEClock((struct EClockVal*)&startTime)/ticksPerSecond;
  target=startTime;
  tr->tr_node.io_Command = TR_ADDREQUEST;
  for(i=0; !(SetSignal(0L,0L)&SIGBREAKF_CTRL_C); i++)
  {
    target+=eclockPerTick;
    tr->tr_time=*(struct timeval*)&target;
    DoIO((struct IORequest *)tr);
  }
  eclockPerSec=ReadEClock((struct EClockVal*)&tr->tr_time);
  VPrintf("processed %ld requestsn", (ULONG*)&i);
  sec=(target-startTime)/eclockPerSec;
  VPrintf("elapsed target time %ld sn", &sec);
  sec=(*((uint64_t*)&tr->tr_time)-startTime)/eclockPerSec;
  VPrintf("elapsed sys time %ld sn", &sec);
  close_timer(tr);
  return 0;
}

Ich weiß, echte Männer programmieren sich ihre 64Bit-Arithmetik selbst, ich habe stattdessen auf den C99-Modus zurückgegriffen...

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 13:20 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Genauer geht es nicht, der DTMF Code gibt mir allerdings nach wie vor nichts aus. Selbst wenn, beim Ausgeben hätte der Code ja wieder mehr Zeit verbraucht als sonst und würde wieder abweichen.

Also mal ein Vorschlag.
Schreibe Dein Programm so um, dass es die Samples auf einer Datei liest. Erzeuge mit irgendeiner Sampling-Software eine Datei, in der definitiv ein paar Töne enthalten sind, und versuche diese zu analysieren.

So hab ich das auch zuerst gemacht, deshalb weiß ich ja, dass mein System genug Reserven zur Berechnung hat, natürlich auch, weil ich keinen Sampler habe.

Aber dann kannst Du sehen, ob ein realer Amiga das packt, und wie schnell er es schafft, wenn er nicht mit der Realzeit synchronisiert laufen muss.

Da Du eine andere Version des DTMF-Codes benutzt hast, kann es natürlich auch sein, dass diese fehlerhaft ist...

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 16:02 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Holger:
C code:
#include <proto/dos.h>
#include <proto/exec.h>
#define __NOLIBBASE__
#define TimerBase (tr->tr_node.io_Device)
#include <proto/timer.h>
#include <devices/timer.h>
#include <stdint.h>


IMHO sollten proto/ Header immer nach nach NDK-Headern kommen.
Zitat:
C code:
uint64_t target, startTime;
...
  eclockPerTick=ReadEClock((struct EClockVal*)&startTime)/ticksPerSecond;
...
    tr->tr_time=*(struct timeval*)&target;
    DoIO((struct IORequest *)tr);
...
  eclockPerSec=ReadEClock((struct EClockVal*)&tr->tr_time);
...
  sec=(*((uint64_t*)&tr->tr_time)-startTime)/eclockPerSec;

Ich weiß, echte Männer programmieren sich ihre 64Bit-Arithmetik selbst, ich habe stattdessen auf den C99-Modus zurückgegriffen...
Und Du meinst wirklich das all die Casts ganz harmlos sind? Der letzte ist besonders übel. Echte Männer können das wesentlich besser.
Zitat:
C code:
VPrintf("processed %ld requestsn", (ULONG*)&i);


Wofür ist der Cast bei &i gut?

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 18:12 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Hat vielleicht jemand der Mitlesenden einen über? Ein Billigheimer-Modell (von mir aus auch ein Mono-Sampler) würde es schon tun, für ernsthaftes Soundsampling habe ich eine Delfina bzw. Toccata bzw. µA1-onboard-Soundkarte.


Wenn man vom Teufel spricht: http://www.amiganews.de/forum/thread.php?id=24044&BoardID=14


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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 18:18 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von gni:
Und Du meinst wirklich das all die Casts ganz harmlos sind? Der letzte ist besonders übel. Echte Männer können das wesentlich besser.

Hey komm, der letzte hat mir eine Variable eingespart, immerhin ganze 8 bytes! :D

Um typecasts kommst Du an der Stelle trotzdem nicht drumrum, ReadEClock erwartet nunmal ein struct EClockVal und kein 64Bit-int, abgesehen davon, dass TimeRequest immer eine TimeVal-Struktur eingebettet hat, selbst dann, wenn man UNIT_ECLOCK oder UNIT_WAITECLOCK benutzt, also die Struktur eigentlich EClockVal sein müsste.
Zitat:
Wofür ist der Cast bei &i gut?
Ja, die Variable hatte ursprünglich einen anderen Typ. Kann man natürlich weglassen...

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

[ - Antworten - Zitieren - Direktlink - ]

13.09.2006, 18:26 Uhr

MaikG
Posts: 5172
Nutzer
>Wenn in 4. der Zeitpunkt t_1 bereits überschritten ist, müsste AFAIK
>eine dieser "Warte Bis" Funktionen des timer.device das Warten
>trotzdem beenden, da dieser Zeitpunkt t_1 ja nie mehr erreicht werden
>kann, weil schon vorbei...

Ja wenn new-old>124 wird rausgegangen.


>Das tun sie auch. UNIT_WAITUNTIL gibt allerdings erst mit dem
>nächsten VBLANK Laut, was in den meisten Fällen viel zu spät sein
>dürfte. Daher kommt auch die Annahme, daß die Timer viel zu langsam
>laufen würden.

Ich hab aber MicroHZ und nicht Waituntil verwendet.

>Maik arbeitet nun aber mit reinem Polling, wenn ich das recht
>verstanden habe, das ist naturgemäß etwas schwieriger zu handhaben.

Das ist nur eine von vielen Varianten die ich probiert habe,
welche halbwegs schneller als die anderen ist.


>Also mal ein Vorschlag.
>Schreibe Dein Programm so um, dass es die Samples auf einer Datei
>liest. Erzeuge mit irgendeiner Sampling-Software eine Datei, in der
>definitiv ein paar Töne enthalten sind, und versuche diese zu
>analysieren.

Ja, okay das könnte ich mal versuchen.


>Da Du eine andere Version des DTMF-Codes benutzt hast, kann es
>natürlich auch sein, dass diese fehlerhaft ist...

Hast du den Code nicht zuletzt noch überprüft und was geändert?

[ - Antworten - Zitieren - Direktlink - ]

14.09.2006, 13:23 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
>Da Du eine andere Version des DTMF-Codes benutzt hast, kann es
>natürlich auch sein, dass diese fehlerhaft ist...

Hast du den Code nicht zuletzt noch überprüft und was geändert?

Ich?!
Nein, ich habe lediglich hier den Link auf Wikipedia gepostet, dann den code runtergeladen und ein Amiga-Programm drumherum gestrickt, das ein Sample analysiert, um ihn auszuprobieren. Währenddessen hat jemand auf Wikipedia eine Änderung gemacht (nicht ich), die insgesamt sinnvoll erscheint, die ich bislang aber nicht ausprobiert habe. Und Du hast die geänderte Version als Ausgangsbasis verwendet.

Ich gehe zwar davon aus, dass normalerweise keiner ungetesten code auf Wikipedia legt, aber ich hab schon so manches erlebt, das ich nicht für normal gehalten hätte. Deshalb sag ich ja, probier Deinen code erst mal mit nem Sample. Evtl. hast Du ja auch beim Übersetzen in Basic noch Fehler eingebaut.

Wenn klar ist, dass die Analyse funktioniert, kann man immer noch die beiden anderen Fehlerquellen, Parallelport und Timer, hinzufügen.

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

[ - Antworten - Zitieren - Direktlink - ]

14.09.2006, 18:04 Uhr

MaikG
Posts: 5172
Nutzer
>Ich?!


Ja klick unten auf 4, 6.Post.


[ - Antworten - Zitieren - Direktlink - ]

14.09.2006, 18:48 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Ja klick unten auf 4, 6.Post.


Ach das meinst Du. Ja, da habe ich nur ein wenig aufgeräumt, ohne die Logik des Programms zu verändern. Und ich habe auch ein Auge darauf geworfen, dass es dem (aktuelleren) C-Programm entspricht. Aber zum einen kann ich dabei auch etwas übersehen haben, zum anderen habe ich es mangels Samplers und wegen des timing-Problems nicht getestet.

Hätte ich es schon zum Testen umgeschrieben, damit es mit Dateien klar kommt, hätte ich diese Version auch hier gepostet, statt Dir zu sagen, dass Du das mal machen sollst...

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

[ - Antworten - Zitieren - Direktlink - ]

14.09.2006, 22:21 Uhr

MaikG
Posts: 5172
Nutzer
>Ja, da habe ich nur ein wenig aufgeräumt, ohne die Logik des
>Programms zu verändern.

Naja, seitdem zeigt das Programm gar nichts mehr an, davor
immer irgendwelche sachen, manchmal traf das halt zu.

[ - Antworten - Zitieren - Direktlink - ]

15.09.2006, 16:36 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
>Ja, da habe ich nur ein wenig aufgeräumt, ohne die Logik des
>Programms zu verändern.

Naja, seitdem zeigt das Programm gar nichts mehr an, davor
immer irgendwelche sachen, manchmal traf das halt zu.


Manchmal zutreffen hilft Dir auch nicht weiter. Ich hab das jetzt soweit testen können, dass ich Dir sagen kann, dass Deine Umsetzung des Algorithmus funktioniert.

Das Problem lag in der Vorzeichenbehandlung, also da wo in meiner Fassung steht
code:
sa%=( PEEKB(&hBFE101) - 127 )<<8
bla%=goertzel%(sa%)

müsste man
code:
sa&=PEEKB(&hBFE101)<<8
IF sa&>&H7FFF THEN sa&=sa& OR &HFFFF0000&
bla%=goertzel%(sa&)

schreiben.

Hier mal das Programm, das 'ne Datei analysiert. Die Testdatei ist allerdings eine 16Bit 48kHz WAV-Datei, kein 8Bit 8kHz, den Teil bei der I/O müsste man abändern, wenn man andere Dateien testen will.
Basic code:
REM aktualisiert 04.09.2006 - 16:00

REM $Nolibrary
REM $Nolines
REM $NoOverflow
REM $NOEVENT

DEFINT A-Z

'$INCLUDE Exec.bh
'$INCLUDE Dos.bh

LIBRARY OPEN "exec.library", LIBRARY_MINIMUM&
LIBRARY OPEN "dos.library", LIBRARY_MINIMUM&

DIM SHARED junk&,dummy$

CONST SAMPLING_RATE%=8000
CONST MAX_BINS%=8
CONST GOERTZEL_N%=92

DIM SHARED q1#(MAX_BINS%) 'double      q1[ MAX_BINS ];
DIM SHARED q2#(MAX_BINS%) 'double      q2[ MAX_BINS ];
DIM SHARED r#(MAX_BINS%)  'double      r[ MAX_BINS ];
DIM SHARED freqs#(MAX_BINS%)
DIM SHARED sample_count% 'INT         sample_count;
DIM SHARED coefs#(MAX_BINS%)
DIM SHARED row_col_ascii_codes$(4,4)

freqs#(0)=697
freqs#(1)=770
freqs#(2)=852
freqs#(3)=941
freqs#(4)=1209
freqs#(5)=1336
freqs#(6)=1477
freqs#(7)=1633

row_col_ascii_codes$(0,0)="1"
row_col_ascii_codes$(0,1)="2"
row_col_ascii_codes$(0,2)="3"
row_col_ascii_codes$(0,3)="A"
row_col_ascii_codes$(1,0)="4"
row_col_ascii_codes$(1,1)="5"
row_col_ascii_codes$(1,2)="6"
row_col_ascii_codes$(1,3)="B"
row_col_ascii_codes$(2,0)="7"
row_col_ascii_codes$(2,1)="8"
row_col_ascii_codes$(2,2)="9"
row_col_ascii_codes$(2,3)="C"
row_col_ascii_codes$(3,0)="*"
row_col_ascii_codes$(3,1)="0"
row_col_ascii_codes$(3,2)="#"
row_col_ascii_codes$(3,3)="D"

REM SUB calc_coeffs
 FOR n%=0 TO 7 REM MAX_BINS%-1
   coefs#(n%)=2.0*COS(2.0*3.141592654 * freqs#(n%)/SAMPLING_RATE%)
 NEXT n%
REM END SUB

' post_testing
' This is where we look at the bins and decide if we have a valid signal.

FUNCTION post_testing$
  STATIC row%, col%, see_digit%
  STATIC peak_count%, max_index%, i%
  STATIC maxval#,t#

  post_testing$=""
  '    /* Find the largest in the row group. */
  row%=0
  maxval#=0.0
  FOR i%=0 TO 3
   IF r#(i%)>maxval# THEN maxval#=r#(i%):row%=i%
  NEXT i%

  '     /* Find the largest in the column group. */
  col%=4
  maxval#=0.0
  FOR i%=4 TO 7
   IF r#(i%)>maxval# THEN maxval#=r#(i%):col%=i%
  NEXT i%

'   /* Check FOR minimum energy */

  IF r#(row%)<4E5 OR r#(col%)<4E5 THEN 2
  see_digit%=TRUE&

  IF r#(col%)>r#(row%) THEN
    max_index%=col%
    IF r#(row%)<(r#(col%)*0.398) THEN see_digit% = FALSE& REM twist > 4dB, error
  ELSE
    max_index%=row%
    IF r#(col%)<(r#(row%)*0.158) THEN see_digit% = FALSE& REM twist > 8db, error
  END IF

  IF r#(max_index%)>1E9 THEN t#=r#(max_index%)*0.158 ELSE t#=r#(max_index%)*0.010

  peak_count%=0

  FOR i%=0 TO 7
    IF r#(i%)>t# THEN INCR peak_count%
  NEXT i%
  IF peak_count%>2 THEN see_digit%=FALSE&
  IF see_digit% THEN post_testing$=row_col_ascii_codes$(row%,col%-4)

2 END FUNCTION

' *  goertzel
FUNCTION goertzel$(sample%)
 STATIC q0#, i%
REM IF sample%<>0 THEN ? "sample: ";sample%;" ";
 IF sample_count%<GOERTZEL_N% THEN
  INCR sample_count%
  FOR i%=0 TO 7 REM MAX_BINS%-1
   q0#=coefs#(i%)*q1#(i%)-q2#(i%)+sample%
   q2#(i%)=q1#(i%)
   q1#(i%)=q0#
  NEXT i%
  goertzel$="." ' need more
 ELSE
  FOR i%=0 TO 7 REM MAX_BINS%-1
   r#(i%)=q1#(i%)*q1#(i%) + q2#(i%)*q2#(i%) - coefs#(i%)*q1#(i%)*q2#(i%)
   q1#(i%)=0.0
   q2#(i%)=0.0
  NEXT i%
  goertzel$=post_testing$
  sample_count%=0
 END IF
END FUNCTION

  file&=xOpen(SADD("work:code/dtmf/Dtmf_example.wav"+CHR$(0)), MODE_OLDFILE&)
  IF file&=NULL& THEN PRINT "opening file failed": GOTO 5
  REM skipping wave header
  dummy&=Seek&(file&, 48, OFFSET_CURRENT%)
  num&=0
  WHILE INKEY$<>CHR$(27)
    REM reading 16 Bit value
    a&=FGetC(file&):b&=FGetC(file&)
    IF (a& OR b&) == -1 THEN 4
    sample&=(b&<<8) OR c&
    IF b&>127 THEN sample&=sample& OR &hffff0000&
    INCR num&
    cur$=goertzel$(sample&)
    IF cur$<>"." AND cur$<>last$ THEN last$=cur$: ? last$;
    FOR i%=0 TO 4 ' Skipping 5 16Bit values to convert 48kHz to 8kHz
      c&=FGetC(file&):d&=FGetC(file&)
      IF (c& OR d&) == -1 THEN 4
    NEXT
  WEND
4 dummy&=xClose(file&)
  ?:?"proc";num&8000!;" sec"

5 END

Von der Performance her durchaus mit dem C-Program vergleichbar.

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

[ - Antworten - Zitieren - Direktlink - ]

15.09.2006, 17:56 Uhr

MaikG
Posts: 5172
Nutzer
>Manchmal zutreffen hilft Dir auch nicht weiter.

Stimmt.

>Ich hab das jetzt soweit testen können, dass ich Dir sagen kann,
>dass Deine Umsetzung des Algorithmus funktioniert.

Immerhin...

>Das Problem lag in der Vorzeichenbehandlung

Mh, dann werd ich die mal ändern und im ungenauen Timing testen.

>Hier mal das Programm, das 'ne Datei analysiert. Die Testdatei ist
>allerdings eine 16Bit 48kHz WAV-Datei, kein 8Bit 8kHz, den Teil bei
>der I/O müsste man abändern, wenn man andere Dateien testen will.

Macht nix hab ja eine Toccata, werd ich nachher mal Probieren.


>Von der Performance her durchaus mit dem C-Program vergleichbar.

Mein ich ja an MB liegt das nicht, es ist nur unter gewissen
umständen langsamer als C und die treffen hier nicht zu.


[ - Antworten - Zitieren - Direktlink - ]

15.09.2006, 19:51 Uhr

MaikG
Posts: 5172
Nutzer
Da gabs eine Zeile die hiess:

IF r#(row%)>=4E5 AND r#(col%)>=4E5 THEN see_digit% = TRUE&

jetzt:

IF r#(row%)<4E5 OR r#(col%)<4E5 THEN GOTO 2


Nun bekomme ich wieder meine Fantasiewerte, auch mit neuen
Sampler zugriff :-)
Das ist nur eine abweichung bei 20s hinter der Kommastelle
und das Prog liefert sonstwas.

Das Prg. was von der Datei liesst Funktioniert genau so wie es soll.
8 Sekunden sagt es. Ich hab mal 9876543210*# auf dem Handy getippt
und das kam auch raus, keine werte dazwischen, keine Falschen...

[ - Antworten - Zitieren - Direktlink - ]

16.09.2006, 19:06 Uhr

whose
Posts: 2156
Nutzer
@Holger:

(Bullshit bzgl. der Laufzeiten von GetMsg() entfernt).

Ich habe ein wenig experimentiert und auf meinem WinUAE-System geht es mittels WAITECLOCK-Unit problemlos.

Die Abweichungen, die man bei kleineren Frequenzen bekommt, stammen übrigens von GetSysTime, welches auch ein wenig braucht.

Also UNIT_WAITECLOCK benutzen.

Grüße


[ Dieser Beitrag wurde von whose am 16.09.2006 um 20:42 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

16.09.2006, 21:14 Uhr

whose
Posts: 2156
Nutzer
Und hier das dazugehörige Programm. Es ist "auf die Schnelle" zusammengestrickt,
während ich bei einem Kunden war.

Falls da ein dicker Patzer drin sein sollte, bitte ich im Voraus schon einmal
um größte Vergebung. Ich denke aber, daß das Ding soweit ok ist, logische
Fehler sollten keine drin sein.

Die Verzögerungen, die sich manchmal ergeben, scheinen tatsächlich von
GetSysTime() herzurühren. Hat jemand Informationen über die Granularität
dieser Funktion? Ich habe das Gefühl, daß die über den VBlank aktuell
gehalten wird.

Abgesehen davon: Kann es sein, daß da irgendwo noch ein Task-Switch dazwischenfunkt? Diese Merkwürdigen Zahlen, die sich da manchesmal ergeben, zwischen 20000 und 40000 µs zum Beispiel, kommen mir etwas "unheimlich" vor.
C code:
/* -----------------------------------------------------------------------------

  Testprogramm für die Funktion der UNIT_WAITECLOCK des timer.device
  
*/

#ifdef __amigaos4__
 #define __USE_INLINE__
#endif

#include <stdio.h>

#include <exec/exec.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <devices/timer.h>

#include <proto/dos.h>
#include <proto/exec.h>


struct timerequest *TimerIO;
struct MsgPort *TimerMP;
struct Message *TimerMsg;

struct Library *TimerBase;

int main(void)
{
    struct timeval ref1, ref2;
    struct EClockVal eclockval;
    unsigned long intervall, ticks;
    long diff;
    LONG error;

    unsigned int repeat = 0;

    TimerMP = (struct MsgPort *)CreatePort(NULL, 0);
    if(!TimerMP)
    {
        printf("Konnte Timer-Port nicht anlegen!n");
        exit(RETURN_FAIL);
    }

    TimerIO = (struct timerequest *)CreateExtIO(TimerMP, sizeof(struct timerequest));
    if(!TimerIO)
    {
        printf("Konnte Timer-IORequest nicht anlegen!n");
        exit(RETURN_FAIL);
    }

    error = OpenDevice(TIMERNAME, UNIT_WAITECLOCK, (struct IORequest *)TimerIO, 0L);
    if(error)
    {
        printf("Konnte timer.device nicht öffnen!n");
        exit(RETURN_FAIL);
    }
    
    TimerBase = (struct Library *)TimerIO->tr_node.io_Device;

    printf("Gewünschtes Intervall in Hz: ");
    scanf("%lu", &intervall);

    ticks = ReadEClock(&eclockval);
    diff = ticks / intervall; /* Normal müßte man auf - testen */

    printf("Hi: %lu Lo: %lun", eclockval.ev_hi, eclockval.ev_lo);

    /* sehr simpler Überlauf-Test */
    if( ((eclockval.ev_lo) + diff) < eclockval.ev_lo)
    {
        eclockval.ev_hi++;
    }
    else
    {
        eclockval.ev_lo += diff;
    }

    //printf("New Hi: %lu New Lo: %lun", eclockval.ev_hi, eclockval.ev_lo);

    TimerIO->tr_node.io_Command = TR_ADDREQUEST;
    TimerIO->tr_time.tv_secs = eclockval.ev_hi;
    TimerIO->tr_time.tv_micro = eclockval.ev_lo;

    SendIO((struct IORequest *)TimerIO);

    GetSysTime(&ref1);

    while(repeat < intervall)
    {
        TimerMsg = WaitPort(TimerMP);
        
        /* Vorsicht, wilde Überläufe ;) */
        if( ((eclockval.ev_lo) + diff) < eclockval.ev_lo)
        {
            eclockval.ev_hi++;
        }
        else
        {
            eclockval.ev_lo += diff;
        }
        TimerIO->tr_node.io_Command = TR_ADDREQUEST;
        TimerIO->tr_time.tv_secs = eclockval.ev_hi;
        TimerIO->tr_time.tv_micro = eclockval.ev_lo;
        SendIO((struct IORequest *)TimerIO);
        /* hier was sinnvolles tun, sofern vorhanden */
        
        repeat++;
    }    

    GetSysTime(&ref2);

    AbortIO((struct IORequest *)TimerIO);
    WaitIO((struct IORequest *)TimerIO);    

    CloseDevice((struct IORequest *)TimerIO);
    DeleteExtIO((struct IORequest *)TimerIO);
    DeletePort(TimerMP);

    printf("n");
    printf("Intervall(EClock-ticks): %ldn", ticks / intervall);
    printf("Referenz 1: %ld %ldn", ref1.tv_secs, ref1.tv_micro);
    printf("Referenz 2: %ld %ldn", ref2.tv_secs, ref2.tv_micro);
    SubTime(&ref2, &ref1);
    printf("Differenz:  %9ld %ldn", ref2.tv_secs, ref2.tv_micro);
    
    exit(RETURN_OK);
}


Grüße

--
---

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


[ Dieser Beitrag wurde von whose am 16.09.2006 um 21:16 Uhr geändert. ]


[ Dieser Beitrag wurde von whose am 17.09.2006 um 02:48 Uhr geändert. ]

[ Dieser Beitrag wurde von whose am 17.09.2006 um 22:28 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 13:08 Uhr

Holger
Posts: 8116
Nutzer
@whose:
Nur eine Frage, so beim Überfliegen:
Wieso hält sich eigentlich hartnäckig die Verwendung der AOS1.x Supportlib-Funktionen, wo es seit AOS2.0 die Funktionen CreateMsgPort() und CreateIORequest() gibt?
Ich mein, bei einem Programm, das mit #ifdef __amigaos4__ anfängt, erscheint mir das irgendwie unangemessen.

Ist zwar hier nicht wichtig, scheint aber irgendwie in die Gewohnheiten- Richtung zu gehen, mir fällt das irgendwie immer wieder hier auf.

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 13:18 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:
@whose:
Nur eine Frage, so beim Überfliegen:
Wieso hält sich eigentlich hartnäckig die Verwendung der AOS1.x Supportlib-Funktionen, wo es seit AOS2.0 die Funktionen CreateMsgPort() und CreateIORequest() gibt?
Ich mein, bei einem Programm, das mit #ifdef __amigaos4__ anfängt, erscheint mir das irgendwie unangemessen.

Ist zwar hier nicht wichtig, scheint aber irgendwie in die Gewohnheiten- Richtung zu gehen, mir fällt das irgendwie immer wieder hier auf.


Upps, ja da hast Du Recht. Ich sag ja, das war auf die Schnelle zusammengestrickt und CreateExtIO() ist tatsächlich eine blöde Angewohnheit. Das #ifdef __amigaos4__ stammt von Cubic und ich habs dringelassen, für den Fall, daß das jemand auf so einer Maschine mal testen mag.

Ich versuche, mir CreateExtIO() & Co. abzugewöhnen ;)

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 13:18 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Also UNIT_WAITECLOCK benutzen.

Die Schlussfolgerung hatte ich auch schon ;-)
Schließlich macht mein Programm oben (mit UNIT_WAITECLOCK) ja auch schon das richtige. Es weicht halt nur von der Echtzeit ab, messbar für das Programm nur in dem Fall, wenn der Emulator die Echtzeit-Uhr auch mitemuliert.
Ansonsten merkt das Programm selber davon nichts. Auf nem realen Amiga verhält es sich deshalb logischerweise etwas anders...
Jetzt werd ich mal Dein Programm ausprobieren.

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 13:38 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von whose:
Also UNIT_WAITECLOCK benutzen.

Die Schlussfolgerung hatte ich auch schon ;-)
Schließlich macht mein Programm oben (mit UNIT_WAITECLOCK) ja auch schon das richtige. Es weicht halt nur von der Echtzeit ab, messbar für das Programm nur in dem Fall, wenn der Emulator die Echtzeit-Uhr auch mitemuliert.
Ansonsten merkt das Programm selber davon nichts. Auf nem realen Amiga verhält es sich deshalb logischerweise etwas anders...
Jetzt werd ich mal Dein Programm ausprobieren.


Wie meinst Du das mit der Echtzeit-Uhr? GetSysTime() bzw. GETSYSTIME läuft ja im Grunde nur via EClock, die wird ja beim Start einmal auf den "aktuellen Stand" gebracht und läuft dann "allein" weiter, da tut sich zwischen Emulator und Amiga nicht viel (sofern der Emulator nicht an entscheidenden Stellen gebremst wird, was mir aber der Fall zu sein scheint. Manchmal weichen die Ergebnisse auf WinUAE wesentlich stärker ab als auf einem echten Amiga).

Abweichungen der GetSysTime()-Zeit wirst Du trotzdem bemerken, aber aufgrund der seltsam glatten Zahlen glaube ich, daß diese Abweichungen vom GetSysTime()-"Overhead" stammen (meine Vermutung geht eher da hin, daß GetSysTime() auf den nächste VBlank wartet, bevor der Zähler das nächste Mal ausgelesen wird).

Die Abweichungen treten übrigens stärker auf, je kleiner die Differenz wird (ich tippe auf zu hohe Last beim timer.device, so daß die GetSysTime()-Anfrage etwas zu spät "angenommen" wird). Es gibt aber einen Punkt, wo Du bei keinem Versuch mehr das "korrekte" Ergebnis bekommst, das ist der Punkt, wo die Systemzeit "abhaut" (bei mir inzwischen um die 12000Hz).

Ab und an scheint sich da auch noch was anderes bemerkbar zu machen, weil hin und wieder weniger Zeit angezeigt wird (im Rahmen bis -20000µs, ich tippe da auf einen Kontext-Switch zur unpassenden Zeit).

Bei geringeren Frequenzen überwiegt die Anzahl der "Treffer" bei weitem, aber auch dort kann man hin und wieder diese Abweichungen bei GetSysTime()beobachten.

Zu doof, daß ich keinen Sampler habe, sonst hätte ich das schon etwas genauer ausloten können, ob diese Abweichungen tatsächlich aus der Richtung stammen, wo ich sie vermute.

Man kann natürlich auch mal schauen, was die EClock dazu sagt (also die EClock-Unit als Referenz verwendet statt mit GetSysTime() zu messen).

Ach nochwas: Mein Überlauf-Test ist ja wirklich etwas sehr einfach... hast Du da evtl. was Passendes auf Lager, was man an der Stelle einsetzen könnte? Ich hatte nie viel mit 64Bit-Zahlen zu tun (wenn man mal von Fließkommazahlen absieht), daher keine großen Kenntnisse zu dem Thema.

Ein neckischer Trick, um auch mit vorzeichenbehafteten Zahlen korrekt umzugehen wäre etwas (auch wenn sowas in unserem Fall eher weniger von Verwendung ist, aber gebrauchen kann man sowas immer mal, denke ich) ;)

Grüße

--
---

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


[ Dieser Beitrag wurde von whose am 17.09.2006 um 13:52 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 21:33 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Wie meinst Du das mit der Echtzeit-Uhr? GetSysTime() bzw. GETSYSTIME läuft ja im Grunde nur via EClock, die wird ja beim Start einmal auf den "aktuellen Stand" gebracht und läuft dann "allein" weiter, da tut sich zwischen Emulator und Amiga nicht viel...

Nun, dass mein Programm mit der EClock synchron ist, habe ich ja schon geschrieben. Deshalb habe ich auch keinen weiteren Test durchgeführt, der auf der EClock basiert. Bringt ja nix.
Ich habe mit Date vor und nach dem Programm die reale Differenz gemessen, was man bei längeren Laufzeiten durchaus machen kann. Und da spielt's halt ne Rolle, ob man ne Echtzeituhr simuliert oder nicht, zumindest, solange die emulierte EClock von der Echtzeit erheblich abweicht.
Zitat:
Ab und an scheint sich da auch noch was anderes bemerkbar zu machen, weil hin und wieder weniger Zeit angezeigt wird (im Rahmen bis -20000µs, ich tippe da auf einen Kontext-Switch zur unpassenden Zeit).
Das habe ich bisher noch nicht bemerkt.
Zitat:
Man kann natürlich auch mal schauen, was die EClock dazu sagt (also die EClock-Unit als Referenz verwendet statt mit GetSysTime() zu messen).
Wozu?
ReadEClock() liefert doch schon die aktuelle EClock. So habe ich ja auch bei meinem Programm verifiziert, dass nach "WaitUntil x" die EClock auch "x + minimale Differenz" (aufgrund der nachträglichen Abfrage) enthält.
Also kann ich Dir schon mal sagen, dass die EClock den erwarteten Wert enthält. Aber Du kannst ja nach dem Programm einfach noch mal ReadEClock() aufrufen...
Zitat:
Ach nochwas: Mein Überlauf-Test ist ja wirklich etwas sehr einfach... hast Du da evtl. was Passendes auf Lager, was man an der Stelle einsetzen könnte?
Eigentlich habe ich in meinem Programm 64Bit-Arithmetik benutzt, um genau darüber nicht nachdenken zu müssen. ;)

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 21:59 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Ab und an scheint sich da auch noch was anderes bemerkbar zu machen, weil hin und wieder weniger Zeit angezeigt wird (im Rahmen bis -20000µs, ich tippe da auf einen Kontext-Switch zur unpassenden Zeit).

An sich kein Wunder, wenn man sich Dein Programm ansieht. Du holst Dir die EClock, welche die Basis für Dein Warten ist, dann machst Du diverse Dinge, wie Textausgabe, Berechnungen und ersten Request verschicken, und dann erst holst Du die Systemzeit, die den Beginn der Aktion markieren soll, Deine EClock, die Du als Basis für WAIT_ECLOCK benutzt, liegt aber schon deutlich früher.

Nur scheinen das Multitasking oder die Eigenheiten von GetSysTime() meistens noch größere Verfälschungen zu produzieren.

Die Abrundung der Wartezeit (diff = ticks / intervall;) fällt da kaum noch in's Gewicht (verkleinert aber auch...).

mfg

Übrigens ist die while((TimerMsg = GetMsg(TimerMP))) Schleife ("Für den Fall, das unser Programm zu langsam sein sollte") sinnlos. Du verschickst zwischen den WaitPort-Aufrufen nur genau einmal einen Request, und das ist auch gut so, denn Du hast ja auch nur den einen. Wenn mehr als eine Message an dem Port ankommen würde, wäre das ziemlich mystisch.

Ich versteh nicht, warum Du da nicht einfach WaitIO() benutzt.

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 22:06 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von whose:
Wie meinst Du das mit der Echtzeit-Uhr? GetSysTime() bzw. GETSYSTIME läuft ja im Grunde nur via EClock, die wird ja beim Start einmal auf den "aktuellen Stand" gebracht und läuft dann "allein" weiter, da tut sich zwischen Emulator und Amiga nicht viel...

Nun, dass mein Programm mit der EClock synchron ist, habe ich ja schon geschrieben. Deshalb habe ich auch keinen weiteren Test durchgeführt, der auf der EClock basiert. Bringt ja nix.
Ich habe mit Date vor und nach dem Programm die reale Differenz gemessen, was man bei längeren Laufzeiten durchaus machen kann. Und da spielt's halt ne Rolle, ob man ne Echtzeituhr simuliert oder nicht, zumindest, solange die emulierte EClock von der Echtzeit erheblich abweicht.


Ah, ok. Nu hab ichs :D

Zitat:
Zitat:
Ab und an scheint sich da auch noch was anderes bemerkbar zu machen, weil hin und wieder weniger Zeit angezeigt wird (im Rahmen bis -20000µs, ich tippe da auf einen Kontext-Switch zur unpassenden Zeit).
Das habe ich bisher noch nicht bemerkt.

Evtl. hängts auch mit dem UAE zusammen... auf dem 4000er hatte ich das auch noch nicht, auf dem µA1 aber schon (allerdings 68K per JIT).

Zitat:
Zitat:
Man kann natürlich auch mal schauen, was die EClock dazu sagt (also die EClock-Unit als Referenz verwendet statt mit GetSysTime() zu messen).
Wozu?
ReadEClock() liefert doch schon die aktuelle EClock. So habe ich ja auch bei meinem Programm verifiziert, dass nach "WaitUntil x" die EClock auch "x + minimale Differenz" (aufgrund der nachträglichen Abfrage) enthält.
Also kann ich Dir schon mal sagen, dass die EClock den erwarteten Wert enthält. Aber Du kannst ja nach dem Programm einfach noch mal ReadEClock() aufrufen...


Naja, wenn Du das schon gemacht hast, brauche ich das ja nicht mehr. Ich darf also davon ausgehen, daß das jetzt paßt mit dem Timer? ;)

Zitat:
Zitat:
Ach nochwas: Mein Überlauf-Test ist ja wirklich etwas sehr einfach... hast Du da evtl. was Passendes auf Lager, was man an der Stelle einsetzen könnte?
Eigentlich habe ich in meinem Programm 64Bit-Arithmetik benutzt, um genau darüber nicht nachdenken zu müssen. ;)

Och mööönsch ;)

Gibts da evtl. einen Link zu dem Thema, den Du posten könntest? Ich hab da mal nach gesucht, aber was wirklich brauchbares mit lesbarem Code habe ich dazu nicht gefunden. Alles mögliche, sogar 128Bit-Operationen, aber nichts über "simple" 64Bit-Operationen.

Ok, mit den "Hauruck"-Operationen in meinem Programm kann man sich wohl behelfen, aber ich könnte mir gut vorstellen, daß es da noch wesentlich elegantere Methoden gibt?

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

17.09.2006, 22:07 Uhr

NoImag
Posts: 1050
Nutzer
Zitat:
Original von Holger:
Wieso hält sich eigentlich hartnäckig die Verwendung der AOS1.x Supportlib-Funktionen, wo es seit AOS2.0 die Funktionen CreateMsgPort() und CreateIORequest() gibt?
...
Ist zwar hier nicht wichtig, scheint aber irgendwie in die Gewohnheiten- Richtung zu gehen, mir fällt das irgendwie immer wieder hier auf.


Es könnte auch daran liegen, dass die RKRM-Beipiele 1.x-kompatibel gehalten sind. Bei mir kann es deshalb vorkommen, dass ich vergesse das umzuschreiben, wenn ich mich dort bediene (was gerade bei Beispielen vorkommt).

Tschüß


[ - Antworten - Zitieren - Direktlink - ]


Erste 3 4 5 6 7 -8- 9 10 11 [ - Beitrag schreiben - ]


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


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