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 4 5 6 7 8 -9- 10 11 [ - Beitrag schreiben - ]

17.09.2006, 22:26 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:
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.

Ja, man sollte das printf() danach weglassen, das stimmt eigentlich. Und GetSysTime() vor ReadEClock einsetzen. Das Programm war, wie schon erwähnt, auf die Schnelle gestrickt.

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

Ich vermute letzteres. Übrigens kommt der Fall "weniger Zeit" weit seltener vor als "mehr Zeit".

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

Ja, das hätte ich etwas "geschickter" lösen sollen... andererseits reichts für erste Tests. Es ging ja mehr darum zu zeigen, daß das timer.device in gewissen Grenzen für solche Aufgaben brauchbar ist.

Zitat:
Ü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.


Aah... sorry, das ist ein Test-Überbleibsel (habe ich heute Nacht vergessen rauszunehmen). Ich hatte da mit zwei IORequests experimentiert.

Wird ersatzlos gestrichen :D

Grüße

--
---

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


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

[ - Antworten - Zitieren - Direktlink - ]

18.09.2006, 14:21 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
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?


Na auf Assembler/Maschinensprachebene gibt es natürlich die elegante Möglichkeit, einfach zu addieren und wenn das Overflow-Flag gesetzt ist, das Hi-word zu inkrementieren. Bzw. eine zweite Addition mittels ADDX, was man sowieso machen müsste, wenn beide Operanden 64Bit sind, in diesem speziellen Fall wäre das allerdings eine Addition mit 0.

Falls man nicht eh auf 64Bit-Befehle zurückgreifen kann.

In C ist die eleganteste Möglichkeit natürlich die, dass man gleich 64Bit-Integer benutzt. Da es aber in den Amiga-Includes keine Definition dafür gibt, bleibt nur der C99-Standard, wenn man will, dass die 64 Bit-Zahlen auch compiler-übergreifend funktionieren.

Mit vbcc funktionierts jedenfalls, damit habe ich mein Programm ja getestet.

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

[ - Antworten - Zitieren - Direktlink - ]

18.09.2006, 18:14 Uhr

MaikG
Posts: 5172
Nutzer
>Da es aber in den Amiga-Includes keine Definition dafür gibt,
>bleibt nur der C99-Standard, wenn man will, dass die 64 Bit-Zahlen
>auch compiler-übergreifend funktionieren.

64 Bit geht aber unter Maxonbasic bestimmt nicht?
Ich wollte das mit dem ReadEclock ja auch mal versuchen
aber da gehts ja auch wieder los mit irgendwelchen overflows
auf Minus testen etc.

[ - Antworten - Zitieren - Direktlink - ]

18.09.2006, 20:25 Uhr

whose
Posts: 2156
Nutzer
@MaikG:

Also, es würde mich wundern, wenn MB 64Bit-Integer kennen würde. Der Test in meinem Programm funktioniert aber auch damit und ist ziemlich simpel gehalten.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

18.09.2006, 23:10 Uhr

MaikG
Posts: 5172
Nutzer
>Also, es würde mich wundern, wenn MB 64Bit-Integer kennen würde.
>Der Test in meinem Programm funktioniert aber auch damit und ist
>ziemlich simpel gehalten.

Ja, den hab ich mir ausgedruckt. Aber im Kommentar steht was mit
Überläufe und man müsste auf Minus testen...
Wenn das so noch kein 100%iges Programm ist fang ich lieber
erst gar nicht an es in Basic umzusetzen...

[ - Antworten - Zitieren - Direktlink - ]

18.09.2006, 23:31 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
>Also, es würde mich wundern, wenn MB 64Bit-Integer kennen würde.
>Der Test in meinem Programm funktioniert aber auch damit und ist
>ziemlich simpel gehalten.

Ja, den hab ich mir ausgedruckt. Aber im Kommentar steht was mit
Überläufe und man müsste auf Minus testen...
Wenn das so noch kein 100%iges Programm ist fang ich lieber
erst gar nicht an es in Basic umzusetzen...


Du meinst wohl
C code:
if( ((eclockval.ev_lo) + diff) < eclockval.ev_lo)
        {
            eclockval.ev_hi++;
        }
        else
        {
            eclockval.ev_lo += diff;
        }

Das funktioniert so auch in Basic.

Das versagt erst <über den Daumen peil>ab ca. einer Stunde Wartezeit</über den Daumen peil>.

Allerdings fällt mir hier gerade ein Fehler auf. Das Ergebnis der Addition muss in jedem Fall in's Low-Word geschrieben werden...

Also korrekt eher so:
C code:
ULONG newLow = eclockval.ev_lo + diff;
if(newLow < eclockval.ev_lo)
{
  eclockval.ev_hi++;
}
eclockval.ev_lo = newLow;


mfg

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

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 00:03 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:

Das funktioniert so auch in Basic.

Das versagt erst <über den Daumen peil>ab ca. einer Stunde Wartezeit</über den Daumen peil>.

Allerdings fällt mir hier gerade ein Fehler auf. Das Ergebnis der Addition muss in jedem Fall in's Low-Word geschrieben werden...

Also korrekt eher so:
C code:
ULONG newLow = eclockval.ev_lo + diff;
if(newLow < eclockval.ev_lo)
{
  eclockval.ev_hi++;
}
eclockval.ev_lo = newLow;



Upps... ich habs irgendwie geahnt, daß ich da noch einen Bock drin habe... ich bin nur nicht drauf gekommen, was das sein könnte. Wald und Bäume und so...

Danke für die Korrektur.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 00:08 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
>Also, es würde mich wundern, wenn MB 64Bit-Integer kennen würde.
>Der Test in meinem Programm funktioniert aber auch damit und ist
>ziemlich simpel gehalten.

Ja, den hab ich mir ausgedruckt. Aber im Kommentar steht was mit
Überläufe und man müsste auf Minus testen...
Wenn das so noch kein 100%iges Programm ist fang ich lieber
erst gar nicht an es in Basic umzusetzen...


Ach was, halb so wild. Auf Minus müßte man streng betrachtet testen, weil die Methode, die ich da gewählt habe, nicht immer funktioniert, eben wegen dem Vorzeichen. Daher die "Warnung" mit dem Minus. Das habe ich bei dem "Trick" außer acht gelassen (weil in diesem sehr speziellen Fall nicht zwingend notwendig) und es funktioniert für Deine Zwecke.

Dem möglichen Überlauf mußt Du Rechnung tragen, weil das Programm sonst ab einer bestimmten Zeit (2^32 µs)nach Start des Rechners Unsinn liefern würde. Entweder, Du rennst im Laufe der Zeit da rein oder Du startest das Programm zufällig zur falschen Zeit, und da wärs ja doof, wenn das Programm dann Mist baut, weil wir den Überlauf von ev_lo nicht beachtet haben. Für ne Alarmanlage wärs ohne Überlauf-Test also nicht unbedingt brauchbar.

Du kannst es ruhig einsetzen, weil die entsprechenden Voraussetzungen mit 99%iger Wahrscheinlichkeit erfüllt sind. Ich nehme ja nicht an, daß Du versuchst, mit gebrochenen Frequenzen beim Samplen oder allgemein mit Zeiträumen von mehr als knapp ner Stunde für DTMF-Erkennung zu arbeiten. Oder das auf andere Plattformen als AmigaOS 68K zu portieren. Bei ganzen, positiven Zahlen für die Frequenz funktioniert das.

Sofern Du die von Holger korrigierte Form verwendest ;)

Grüße

--
---

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


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

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 09:54 Uhr

MaikG
Posts: 5172
Nutzer
>Ach was, halb so wild. Auf Minus müßte man streng betrachtet
>testen, weil die Methode, die ich da gewählt habe, nicht immer
>funktioniert, eben wegen dem Vorzeichen.

Na, bei der DTMF erkennung musste sie aber immer funktionieren.


>Dem möglichen Überlauf mußt Du Rechnung tragen, weil das Programm
>sonst ab einer bestimmten Zeit (2^32 µs)nach Start des Rechners
>Unsinn liefern würde. Entweder, Du rennst im Laufe der Zeit da
>rein oder Du startest das Programm zufällig zur falschen Zeit,
>und da wärs ja doof, wenn das Programm dann Mist baut, weil wir
>den Überlauf von ev_lo nicht beachtet haben. Für ne Alarmanlage
>wärs ohne Überlauf-Test also nicht unbedingt brauchbar.

Wie hoch geht die Zahl bis der Überlauf kommt?


>Ich nehme ja nicht an, daß Du versuchst, mit gebrochenen
>Frequenzen beim Samplen oder allgemein mit Zeiträumen von mehr
>als knapp ner Stunde für DTMF-Erkennung zu arbeiten.

Eigentlich nicht so lang.

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 12:51 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
>Ach was, halb so wild. Auf Minus müßte man streng betrachtet
>testen, weil die Methode, die ich da gewählt habe, nicht immer
>funktioniert, eben wegen dem Vorzeichen.

Na, bei der DTMF erkennung musste sie aber immer funktionieren.


Sagen wir: Bei der Bemessung des Zeitraums für das Sampling und der DTMF-Erkennung funktioniert es immer. Bei anderen Aufgaben (also was anderem, als Du vorhast) könnte es, je nach Größe der verwendeten Zahlen, Probleme geben.

Zitat:
>Dem möglichen Überlauf mußt Du Rechnung tragen, weil das Programm
>sonst ab einer bestimmten Zeit (2^32 µs)nach Start des Rechners
>Unsinn liefern würde. Entweder, Du rennst im Laufe der Zeit da
>rein oder Du startest das Programm zufällig zur falschen Zeit,
>und da wärs ja doof, wenn das Programm dann Mist baut, weil wir
>den Überlauf von ev_lo nicht beachtet haben. Für ne Alarmanlage
>wärs ohne Überlauf-Test also nicht unbedingt brauchbar.

Wie hoch geht die Zahl bis der Überlauf kommt?


2 hoch 32 = 4294967296

Je nach EClock-Rate des Rechners können da soundsoviel Minuten drin gespeichert werden. Kannst Du Dir ausrechnen, wenn Du Dir die "ticks" ausgeben läßt (Rückgabewert von ReadEClock()). Die "ticks" werden pro Sekunde angegeben. Angenommen, Dein Rechner arbeitet mit 709379 ticks/s, ergibt das 6054 Sekunden.

6054 Sekunden / 60 = 100 Minuten.

Nach 100 Minuten ab Start des Rechners käme es also zu einem Überlauf von ev_lo. Würden wir den nicht berücksichtigen und mit dem "alten" Wert von ev_hi weiter arbeiten, würde das Programm ab dann mit voller Rechnergeschwindigkeit weiterlaufen, statt 125µs zu warten (weil wir einen Zeitpunkt angeben, der bereits vorbei ist). Käme also Mist bei raus.

Da wir hier aber den Überlauf berücksichtigen und ev_hi brav um 1 erhöhen, passiert das nicht.

Zitat:
>Ich nehme ja nicht an, daß Du versuchst, mit gebrochenen
>Frequenzen beim Samplen oder allgemein mit Zeiträumen von mehr
>als knapp ner Stunde für DTMF-Erkennung zu arbeiten.

Eigentlich nicht so lang.


Meine ich doch. Mit dem Zeitraum ist auch der Zeitraum gemeint, der die Wartezeit ausmacht (also hier die 125µs, im Programm diff). Bei der Berechnung von diff könnte es bei zu großen Zeiträumen Schwierigkeiten geben, aber bei 125µs (oder, wie Holger schon sagte, Zeiträumen von weniger als über den Daumen gepeilt knapp einer Stunde) passiert das nicht.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 20:06 Uhr

MaikG
Posts: 5172
Nutzer
Stürzt nur ab:

code:
eclockval&=AllocMem&(EClockVal_sizeof%,MEMF_CLEAR&)

ticks&= ReadEClock&(eclockval&)
Intervall%=8000
diff&=ticks&/Intervall%

IF PEEKL(eclockval&+ev_lo%)+diff& < PEEKL(eclockval&+ev_lo%) THEN
 POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
 ELSE
 POKEL(eclockval&+ev_lo%),PEEKL(eclockval&+ev_lo%)+diff&
END IF 

POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
POKEL tr& + tr_time% + tv_secs%, PEEKL(eclockval&+ev_hi%)
POKEL tr& + tr_time% + tv_micro%, PEEKL(eclockval&+ev_lo%)
SendIO&(tr&)

t!=TIMER

      WHILE Repeat1%<Intervall%
 
       junk&=WaitPort&(timerport&)
       WHILE TimerMsg&=GetMsg&(timerport&)
       WEND
       newLow&=PEEKL(eclockval&+ev_lo%)+diff&
       IF newLow&<PEEKL(eclockval&+ev_lo%) THEN POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
       POKEL(eclockval&+ev_lo%),newLow&

       POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
       POKEL tr& + tr_time% + tv_secs%, PEEKL(eclockval&+ev_hi%)
       POKEL tr& + tr_time% + tv_micro%, PEEKL(eclockval&+ev_lo%)
       SendIO&(tr&)

       INCR repeat1%
       INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds% REM :move rpS&,20,25:Text rpS&, SADD(TIME$+CHR$(0)),8
       sa&=PEEKB(&hBFE101)<<8
       IF sa&>&H7FFF THEN sa&=sa& OR &HFFFF0000&
       bla%=goertzel%(sa&)
      WEND

      move rpS&,20,45:Text rpS&, SADD(STR$(TIMER-t!)+CHR$(0)),LEN(STR$(TIMER-t!))
      move rpS&,20,55:Text rpS&, SADD(STR$(myseconds%)+CHR$(0)),LEN(STR$(myseconds%))

AbortIO&(tr&)
junk&=WaitIO&(tr&)
FreeMem eclockval&,EClockVal_sizeof%


[ Dieser Beitrag wurde von MaikG am 19.09.2006 um 20:06 Uhr geändert. ]

[ Dieser Beitrag wurde von MaikG am 19.09.2006 um 20:07 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 22:05 Uhr

Ralf27
Posts: 2779
Nutzer
Ich hab jetzt nicht denn ganzen Thread gelesen, aber folgene Zeile hat mich eben etwas überrascht:

code:
eclockval&=AllocMem&(EClockVal_sizeof%,MEMF_CLEAR&)


Reicht es aus einfach MEMF_CLEAR& anzugeben, wenn man einen beliebigen Speicherbereich benötigt? Bzw. wird dann immer Fast bevorzugt? Oder muß man da doch noch angeben was man will?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 22:07 Uhr

Ralf27
Posts: 2779
Nutzer
Nochwas:

code:
move rpS&,20,45:Text rpS&, SADD(STR$(TIMER-t!)+CHR$(0)),LEN(STR$(TIMER-t!))
      move rpS&,20,55:Text rpS&, SADD(STR$(myseconds%)+CHR$(0)),LEN(STR$(myseconds%))


Hier wird das CHR$(0) nun wirklich nicht benötigt. Die länge wird ja hinter der Funktion angegeben.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

19.09.2006, 22:56 Uhr

MaikG
Posts: 5172
Nutzer
>Reicht es aus einfach MEMF_CLEAR& anzugeben, wenn man einen
>beliebigen Speicherbereich benötigt? Bzw. wird dann immer Fast
>bevorzugt? Oder muß man da doch noch angeben was man will?

Ja, warum nicht? Fast hat höhere Priorität, daher nehme ich das
an.


>Hier wird das CHR$(0) nun wirklich nicht benötigt. Die länge wird
>ja hinter der Funktion angegeben.

Mh, mag sein. Aber wir sind ja noch nicht bei der Optimierung
sondern bei der Grundfunktion :-)

[ - Antworten - Zitieren - Direktlink - ]

20.09.2006, 12:35 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von Ralf27:
code:
eclockval&=AllocMem&(EClockVal_sizeof%,MEMF_CLEAR&)

Reicht es aus einfach MEMF_CLEAR& anzugeben, wenn man einen beliebigen Speicherbereich benötigt? Bzw. wird dann immer Fast bevorzugt?

Ja.

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

[ - Antworten - Zitieren - Direktlink - ]

20.09.2006, 12:51 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
Stürzt nur ab:

code:
eclockval&=AllocMem&(EClockVal_sizeof%,MEMF_CLEAR&)

ticks&= ReadEClock&(eclockval&)
Intervall%=8000
diff&=ticks&/Intervall%

IF PEEKL(eclockval&+ev_lo%)+diff& < PEEKL(eclockval&+ev_lo%) THEN
 POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
 ELSE
 POKEL(eclockval&+ev_lo%),PEEKL(eclockval&+ev_lo%)+diff&
END IF 

POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
POKEL tr& + tr_time% + tv_secs%, PEEKL(eclockval&+ev_hi%)
POKEL tr& + tr_time% + tv_micro%, PEEKL(eclockval&+ev_lo%)
SendIO&(tr&)

t!=TIMER

      WHILE Repeat1%<Intervall%
 
       junk&=WaitPort&(timerport&)
       WHILE TimerMsg&=GetMsg&(timerport&)
       WEND
       newLow&=PEEKL(eclockval&+ev_lo%)+diff&
       IF newLow&<PEEKL(eclockval&+ev_lo%) THEN POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
       POKEL(eclockval&+ev_lo%),newLow&

       POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
       POKEL tr& + tr_time% + tv_secs%, PEEKL(eclockval&+ev_hi%)
       POKEL tr& + tr_time% + tv_micro%, PEEKL(eclockval&+ev_lo%)
       SendIO&(tr&)

       INCR repeat1%
       INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds% REM :move rpS&,20,25:Text rpS&, SADD(TIME$+CHR$(0)),8
       sa&=PEEKB(&hBFE101)<<8
       IF sa&>&H7FFF THEN sa&=sa& OR &HFFFF0000&
       bla%=goertzel%(sa&)
      WEND

      move rpS&,20,45:Text rpS&, SADD(STR$(TIMER-t!)+CHR$(0)),LEN(STR$(TIMER-t!))
      move rpS&,20,55:Text rpS&, SADD(STR$(myseconds%)+CHR$(0)),LEN(STR$(myseconds%))

AbortIO&(tr&)
junk&=WaitIO&(tr&)
FreeMem eclockval&,EClockVal_sizeof%



Prinzipiell siehts eigentlich gut aus, in der C-Variante funktioniert es so problemlos.

Ersetz doch mal
code:
junk&=WaitPort&(timerport&)
       WHILE TimerMsg&=GetMsg&(timerport&)
       WEND


gegen
code:
WaitIO(tr&)


und laß die WHILE-Schleife mit GetMsg() weg.

Sobald Du die Funktionalität hast, solltest Du das
code:
IF PEEKL(eclockval&+ev_lo%)+diff& < PEEKL(eclockval&+ev_lo%) THEN
 POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
 ELSE
 POKEL(eclockval&+ev_lo%),PEEKL(eclockval&+ev_lo%)+diff&
END IF


noch durch die (korrekte) Variante aus der Sample-Schleife ersetzen, also gegen das hier:
code:
newLow&=PEEKL(eclockval&+ev_lo%)+diff&
IF newLow&<PEEKL(eclockval&+ev_lo%) THEN POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
       POKEL(eclockval&+ev_lo%),newLow&

.

Ersteres war ein Fehler von mir, da hatte ich vergessen, ev_lo auf jeden Fall mit der Differenz zu addieren.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

20.09.2006, 13:35 Uhr

Holger
Posts: 8116
Nutzer
Also die vielen PEEKs und POKEs sind nicht gerade ein Gewinn für die Lesbarkeit des Programms. Da die EClockVal-Struktur nur ein einziges Mal am Anfang an ReadEClock&() übergeben wird, und im Rest des Programms ausschließlich für Basic-Zugriffe genutzt wird, liest sich das Programm mit Sicherheit besser, wenn man Basic-Variablen nutzt.

Also
Basic code:
DIM myEClockVal&(2)
ticks&=ReadEClock&(VARPTR(myEClockVal&(0)))
myEClockValHi&=myEClockVal&(0)
myEClockValLo&=myEClockVal&(1)

Und dann überall im Programm PEEKL(eclockval&+ev_lo%) durch myEClockValLo& und PEEKL(eclockval&+ev_hi%) durch myEClockValHi&, sowie POKEL eclockval&+ev_lo%, xxx durch myEClockValLo&=xxx und POKEL eclockval&+ev_hi%, xxx durch myEClockValHi&=xxx ersetzen.
Das erlaubt dann noch weitere Vereinfachungen, wie das Ersetzen von POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1 durch INCR myEClockValHi&.

Zitat:
Original von whose:
... noch durch die (korrekte) Variante aus der Sample-Schleife ersetzen, also gegen das hier:
code:
newLow&=PEEKL(eclockval&+ev_lo%)+diff&
IF newLow&<PEEKL(eclockval&+ev_lo%) THEN POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
       POKEL(eclockval&+ev_lo%),newLow&

.

Ersteres war ein Fehler von mir, da hatte ich vergessen, ev_lo auf jeden Fall mit der Differenz zu addieren.


Leider funktioniert das so auch nicht. Diese Art von Überlauftest funktioniert nur, wenn die Zahl als vorzeichenlos (ULONG) behandelt wird. Denn der Überlauf muss als solcher beim Übergang von 0xFFFFFFFF nach 0x00000000 erkannt werden. Da Basic aber diese Variablen immer als vorzeichenbehaftet betrachtet, wird der Vergleich beim Übergang von 0x7FFFFFFF nach 0x80000000 positiv.

Inkl. der oben vorgeschlagenen Lesbarkeitsverbesserung, müsste der korrekte Code so aussehen:
Basic code:
newLow&=myEClockValLo& + diff&
IF newLow& >= 0 AND myEClockValLo& < 0 THEN INCR myEClockValHi&
myEClockValLo&=newLow&


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

[ Dieser Beitrag wurde von Holger am 20.09.2006 um 13:37 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

20.09.2006, 16:19 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:

Zitat:
Original von whose:
... noch durch die (korrekte) Variante aus der Sample-Schleife ersetzen, also gegen das hier:
code:
newLow&=PEEKL(eclockval&+ev_lo%)+diff&
IF newLow&<PEEKL(eclockval&+ev_lo%) THEN POKEL(eclockval&+ev_hi%),PEEKL(eclockval&+ev_hi%)+1
       POKEL(eclockval&+ev_lo%),newLow&

.

Ersteres war ein Fehler von mir, da hatte ich vergessen, ev_lo auf jeden Fall mit der Differenz zu addieren.


Leider funktioniert das so auch nicht. Diese Art von Überlauftest funktioniert nur, wenn die Zahl als vorzeichenlos (ULONG) behandelt wird. Denn der Überlauf muss als solcher beim Übergang von 0xFFFFFFFF nach 0x00000000 erkannt werden. Da Basic aber diese Variablen immer als vorzeichenbehaftet betrachtet, wird der Vergleich beim Übergang von 0x7FFFFFFF nach 0x80000000 positiv.


Ah so, sorry, ich dachte, MB wäre da schon etwas weiter gewesen als AmigaBASIC. ACE z.B. kennt auch vorzeichenlose Integer-Variablen, daher dachte ich, das wäre bei MB auch so.

Wiederum danke für die Korrektur.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

20.09.2006, 23:07 Uhr

MaikG
Posts: 5172
Nutzer
Also so? Crasht trotzdem, kein Hit, aber Cyberguard meldet
8000000B.


code:
DIM myEClockVal&(2)
    ticks&=ReadEClock&(VARPTR(myEClockVal&(0)))
    myEClockValHi&=myEClockVal&(0)
    myEClockValLo&=myEClockVal&(1)

Intervall%=8000
diff&=ticks&/Intervall%

    newLow&=myEClockValLo& + diff&
    IF newLow& >= 0 AND myEClockValLo& < 0 THEN INCR myEClockValHi&
    myEClockValLo&=newLow&

POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
POKEL tr& + tr_time% + tv_secs%, myEClockValHi&
POKEL tr& + tr_time% + tv_micro%, myEClockValLo&
SendIO&(tr&)

t!=TIMER

      WHILE Repeat1%<Intervall%

       junk&=WaitIO&(tr&) REM neu

        newLow&=myEClockValLo& + diff&
        IF newLow& >= 0 AND myEClockValLo& < 0 THEN INCR myEClockValHi&
        myEClockValLo&=newLow&

       POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
       POKEL tr& + tr_time% + tv_secs%, myEClockValHi&
       POKEL tr& + tr_time% + tv_micro%, myEClockValLo&
       SendIO&(tr&)

       INCR repeat1%
       INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds%:move rpS&,20,25:Text rpS&, SADD(TIME$+CHR$(0)),8
       REM sa&=PEEKB(&hBFE101)<<8
       REM IF sa&>&H7FFF THEN sa&=sa& OR &HFFFF0000&
       REM bla%=goertzel%(sa&)
      WEND


[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 12:10 Uhr

whose
Posts: 2156
Nutzer
@MaikG:

Hm, da weiß ich im Moment auch nicht weiter, müßte jemand helfen, der sich mit den Eigenheiten von MB auskennt.

Prinzipiell sollte es laufen.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 13:04 Uhr

Holger
Posts: 8116
Nutzer
@MaikG:
Hilft ja nix, wenn wir den Rest des Programms nicht kennen.
Außerdem könntest Du einfach mal versuchen, die Zeile herauszufinden, bis zu der das Programm noch läuft.

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

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 13:06 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Ah so, sorry, ich dachte, MB wäre da schon etwas weiter gewesen als AmigaBASIC. ACE z.B. kennt auch vorzeichenlose Integer-Variablen, daher dachte ich, das wäre bei MB auch so.

Vielleicht kennt es ja sowas, aber wie soll man das ohne Handbuch herausfinden? Zumindest müsste man ja die gewünschte Vorzeichenlosigkeit irgendwie deklarieren.

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

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 14:53 Uhr

MaikG
Posts: 5172
Nutzer
>Hilft ja nix, wenn wir den Rest des Programms nicht kennen.

Gut, ist zwar schon ohne das neue so gelaufen aber steht unten.

>Außerdem könntest Du einfach mal versuchen, die Zeile
>herauszufinden, bis zu der das Programm noch läuft.

ich hab den Text mit reingenommen und dieser wird nicht mehr
ausgegeben, aber ich kann das noch genauer versuchen.


Wie man MaxonBasic dazu bewegen kann das vorzeichen nicht zu
benutzen weiss ich nicht. Evtl. direkt mit Peek und Poke arbeiten
aber für MaxonBasic selbst ist es immer vorzeichenbehaftet.

code:
REM $HEAPDYNAMIC=2048
    REM $KEEP=2048
    REM $MATHSTACK=8192
    REM $MINSTACK=16384
    REM $Nolibrary
    REM $Nolines
    REM $NoOverflow
    REM $NOEVENT
    REM $NoWindow
    REM $NoADDICON
    REM $NOARRAY
    REM $NOAUTODIM
    REM $NOERRORS
    REM $NOVARCHECKS

    DEFINT A-Z

    '$INCLUDE Exec.bh
    '$INCLUDE Timer.bh
    '$INCLUDE Graphics.bh
    '$INCLUDE Intuition.bh
    '$INCLUDE GadTools.bh

    LIBRARY OPEN "graphics.library", 37
    LIBRARY OPEN "intuition.library", 37
    LIBRARY OPEN "gadtools.library", 37
    LIBRARY OPEN "exec.library", 37
    DIM SHARED tl&(40), rpS&
    DIM SHARED junk&,dummy$

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

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


   SUB delete_timer(BYVAL tr&)
        STATIC tp&
        IF tr& <> NULL& THEN
            tp& = PEEKL(tr& + tr_node% + IORequestio_Message% + mn_ReplyPort%)
            IF tp& <> 0 THEN DeleteMsgPort tp&
            CloseDevice tr&
            DeleteIORequest tr&
        END IF
    END SUB

    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"

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

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

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

      '    /* 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 */

      REM IF r#(row%)>=4E5 AND r#(col%)>=4E5 THEN see_digit% = TRUE&
      IF r#(row%)<4E5 OR r#(col%)<4E5 THEN GOTO 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
REM 1*10^9
      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 move rpS&,20,50:Text rpS&, SADD(row_col_ascii_codes$(row%,col%-4)+CHR$(0)),1
2   END SUB

    ' *  goertzel
    FUNCTION goertzel%(BYVAL sample%)
     STATIC q0#, i%
     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%
     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%
      post_testing
      sample_count%=0
     END IF
    END FUNCTION


TAGLIST VARPTR(tl&(0)), _
    WA_Title&,  "DTMF erkennung", _
    WA_Width&, 600, _
    WA_InnerHeight&, 100, _
    WA_Top&, 16, _
     WA_Left&, 0, _
    WA_Activate&, TRUE&, _
    WA_DragBar&, TRUE&, _
    WA_DepthGadget&, TRUE&, _
    WA_CloseGadget&, TRUE&, _
    WA_SizeGadget&, TRUE&, _
    WA_SmartRefresh&, TRUE&, _
    WA_NoCareRefresh&, TRUE&, _
    WA_IDCMP&, IDCMP_CLOSEWINDOW&, _
    WA_MinWidth&, 631, _
    WA_MinHeight&, 100, _
    TAG_END&

 winS& = OpenWindowTagList&(NULL&, VARPTR(tl&(0)))

rpS&=PEEKL(winS&+rport%)


      POKEB &hBFE301,0
      REM tr&=create_timer&()

        timerport& = CreateMsgPort&()
        IF timerport& <> NULL& THEN
            tr& = CreateIORequest&(timerport&, timerequest_sizeof%)
            IF tr& <> NULL& THEN
                IF OpenDevice&(SADD("timer.device" + CHR$(0)), UNIT_WAITUNTIL&, tr&, 0)<> 0 THEN delete_timer tr&:GOTO 5
            ELSE
                DeleteMsgPort timerport&
            END IF
        END IF


REM eclockval&=AllocMem&(EClockVal_sizeof%,MEMF_CLEAR&)

REM ticks&=ReadEClock&(eclockval&)

    DIM myEClockVal&(2)
    ticks&=ReadEClock&(VARPTR(myEClockVal&(0)))
    myEClockValHi&=myEClockVal&(0)
    myEClockValLo&=myEClockVal&(1)

Intervall%=8000
diff&=ticks&/Intervall%

    newLow&=myEClockValLo& + diff&
    IF newLow& >= 0 AND myEClockValLo& < 0 THEN INCR myEClockValHi&
    myEClockValLo&=newLow&

POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
POKEL tr& + tr_time% + tv_secs%, myEClockValHi&
POKEL tr& + tr_time% + tv_micro%, myEClockValLo&
SendIO&(tr&)

t!=TIMER

      WHILE Repeat1%<Intervall%

       junk&=WaitIO&(tr&) REM neu

        newLow&=myEClockValLo& + diff&
        IF newLow& >= 0 AND myEClockValLo& < 0 THEN INCR myEClockValHi&
        myEClockValLo&=newLow&

       POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&
       POKEL tr& + tr_time% + tv_secs%, myEClockValHi&
       POKEL tr& + tr_time% + tv_micro%, myEClockValLo&
       SendIO&(tr&)

       INCR repeat1%
       INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds% rem :move rpS&,20,25:Text rpS&, SADD(TIME$+CHR$(0)),8
       REM sa&=PEEKB(&hBFE101)<<8
       REM IF sa&>&H7FFF THEN sa&=sa& OR &HFFFF0000&
       REM bla%=goertzel%(sa&)
      WEND

      move rpS&,20,45:Text rpS&, SADD(STR$(TIMER-t!)+CHR$(0)),LEN(STR$(TIMER-t!))
      move rpS&,20,55:Text rpS&, SADD(STR$(myseconds%)+CHR$(0)),LEN(STR$(myseconds%))

REM AbortIO&(tr&)
REM junk&=WaitIO&(tr&)
REM FreeMem eclockval&,EClockVal_sizeof%

terminatedS%=0
 WHILE terminatedS%=0
    junk&= xWait&(1& << PEEKB(PEEKL(winS&+UserPort%)+mp_SigBit%))

     DO
       imsgS& = GT_GetIMsg(PEEKL(winS&+UserPort%))
       IF imsgS&=0  THEN EXIT LOOP
        imsgClassS& =PEEKL(imsgS&+Class%)
        GT_ReplyIMsg imsgS&
  SELECT CASE imsgClassS&
            CASE IDCMP_CLOSEWINDOW&:
                terminatedS% = 1
            CASE IDCMP_REFRESHWINDOW&:
                GT_BeginRefresh winS&
                GT_EndRefresh winS&, TRUE&
  END SELECT
 LOOP UNTIL terminatedS%
 WEND

5 CloseWindow winS&
END


Nachtrag: Stürzt bei ReadEClock ab.

[ Dieser Beitrag wurde von MaikG am 21.09.2006 um 15:38 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 18:27 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Nachtrag: Stürzt bei ReadEClock ab.


ReadEClock ist ein Art Library-Funktion des timer.device. Um die aus MaxonBasic heraus aufzurufen, muss MaxonBasic die Basisadresse der Library kennen, man kann aber ein device nicht wie eine Library öffnen.

Wenn ich mein eigentlich nicht vorhandenes Wissen über MaxonBasic zusammenkratze, geht das so:

Nach dem erfolgreichen Öffnen des timer device (und nur dann), teilst Du MaxonBasic die Adresse via
code:
LIBRARY VARPTR "timer.device", PEEKL(tr& + IOStdReqio_Device%)

mit und bevor Du das device schließt, teilst Du MaxonBasic mit, dass diese Library nicht mehr zur Verfügung steht (damit MaxonBasic nicht etwa versucht, das device wie eine Library automatisch zu schließen).
code:
LIBRARY VARPTR "timer.device", NULL&

Kann das aber nicht testen, da das Programm den Rahmen der Demoversion sprengt.

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

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 21:41 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von MaikG:
Nachtrag: Stürzt bei ReadEClock ab.


ReadEClock ist ein Art Library-Funktion des timer.device. Um die aus MaxonBasic heraus aufzurufen, muss MaxonBasic die Basisadresse der Library kennen, man kann aber ein device nicht wie eine Library öffnen.


Ich seh schon, ich sollte mal die Antifalten-Gurkenscheiben von den Augen nehmen :D

Ich hab glatt übersehen, daß das fehlt.

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

21.09.2006, 22:58 Uhr

MaikG
Posts: 5172
Nutzer
>ReadEClock ist ein Art Library-Funktion des timer.device. Um die aus
>MaxonBasic heraus aufzurufen, muss MaxonBasic die Basisadresse der
>Library kennen, man kann aber ein device nicht wie eine Library
>öffnen.

Ah, dafür ist das mit Library VARPTR.


>Nach dem erfolgreichen Öffnen des timer device (und nur dann), teilst Du MaxonBasic die Adresse via
> code:
> LIBRARY VARPTR "timer.device", PEEKL(tr& + IOStdReqio_Device%)
>mit und bevor Du das device schließt, teilst Du MaxonBasic mit, dass diese Library nicht mehr zur Verfügung steht (damit MaxonBasic nicht etwa versucht, das device wie eine Library automatisch zu schließen).
> code:
> LIBRARY VARPTR "timer.device", NULL&


Klingt korrekt, das hab ich so mit was anderem schon gesehen.


[ - Antworten - Zitieren - Direktlink - ]

22.09.2006, 09:03 Uhr

MaikG
Posts: 5172
Nutzer
Stürzt nicht mehr ab, aber ich glaub auch nicht das es Funktioniert.

Bei einem Intervall von 8000 HZ läuft die Schleife
183.1758 sekunden -das kann ja nicht stimmen oder?

[ - Antworten - Zitieren - Direktlink - ]

22.09.2006, 12:27 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von MaikG:
Stürzt nicht mehr ab, aber ich glaub auch nicht das es Funktioniert.

Bei einem Intervall von 8000 HZ läuft die Schleife
183.1758 sekunden -das kann ja nicht stimmen oder?


Nein, kann es eigentlich nicht. Es sei denn, irgendwas in dem Programm läuft noch daneben oder es läuft schlicht zu langsam. Letzteres kann ich mir aber nicht so recht vorstellen.

Grüße

--
---

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


[ Dieser Beitrag wurde von whose am 22.09.2006 um 12:31 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

22.09.2006, 13:22 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von MaikG:
Stürzt nicht mehr ab, aber ich glaub auch nicht das es Funktioniert.

Bei einem Intervall von 8000 HZ läuft die Schleife
183.1758 sekunden -das kann ja nicht stimmen oder?


Du musst auch UNIT_WAITECLOCK beim Öffnen des device angeben, wenn Du UNIT_WAITECLOCK und nicht UNIT_WAITUNTIL verwenden willst.

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

[ - Antworten - Zitieren - Direktlink - ]

22.09.2006, 14:53 Uhr

MaikG
Posts: 5172
Nutzer
Oh, simmt nun sind es 1.648439 - mit goertzel also 1,0 müssten es sein.
Wie muss ich das machen wenn ich 20sekunden will?
Um der Schleife noch eine geht nicht.

[ - Antworten - Zitieren - Direktlink - ]


Erste 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.
.