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 - ]

1 2 3 -4- 5 6 7 8 9 Letzte [ - Beitrag schreiben - ]

04.09.2006, 12:03 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:

Tja, aber wie auch immer auf meinem 060er mit 60 MHZ werden
8000 HZ alle 10 sekunden erreicht, alle 3 Sekunden ohne
das "Delay".


Was ist denn das für eine Aussage? 8000 Hz (oder 8kHz) bedeutet, daß Du etwas 8000 mal pro Sekunde machst - in dem Fall 8000 mal pro Sekunde den Wert vom Parallelport abfragen. Und das ist wirklich die unterste Grenze - bei CDs nimmt man normalerweise 44.1 kHz - also 44100 mal pro Sekunde (o.k. bei CDs nimmt man auch 16 Bit und nicht 8, aber egal). Selbst ein vergilbter Amiga 500 ohne Erweiterungen schaft es, den Parallelprot 44100 mal pro Sekunde auszulesen.

Wie Delay funktioniert, ist Dir klar? Die Funktion nimmt einen Wert der 50stel Sekunden bedeutet. Also z.B. Delay(50) = 1 Sekunde warten,
Delay (150) = 3 Sekunden warten, Delay(25) = 1/2 Sekunde warten usw.
Wenn Du auf die Idee kommst, Delay(125) hinzuschreiben, dann wartet Dein Task genau 2 1/2 Sekunden und nicht 0,000125 Sekunden !

Für Deine Aufgabe solltest Du aber besser das timer.device benutzen.
Dazu hatten wir erst eine ausführliche Debatte: http://www.amiganews.de/forum/thread.php?id=23045&BoardID=7

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

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 12:18 Uhr

DariusBrewka
Posts: 899
[Benutzer gesperrt]
Mit Delay() hat er sichel nicht das dos-delay gemeint.

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 14:26 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:

Wenn ich das mache:

1
warte x microsekunden
lese 1 Byte vom Parallelport
gehe zu DTMF auswertung
gehe zu 1


Warum machst Du das nicht so:

reserviere Speicher für n Werte (das Sample), z.B. Array

weise das timer.device an, Dir alle 125 Mikrosekunden ein Signal zu geben

Dann eine Schleife (Pseudocode):

WHILE NOT PROGRAMMENDE
{
FÜR n=0 BIS ARRAYGRÖße-1
{
Warte auf Signal vom timer.device
ARRAY[n] = Wert von Parallelport
n = n + 1
}

Werte das Sample aus dem Array aus
}

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

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

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 15:04 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von MaikG:
Mit ein paar Optimierungen und Compileroptionen komme ich
auf etwa 1x pro sekunde, allerdings ohne delay.

Es könnte helfen, wenn Du nicht für jeden Wartevorgang das timer.device erneut öffnen und wieder schließen würdest.
Zitat:
Selbst wenn ich die Samples in ein Array packen würde, würde
die Verarbeitung einiges an Zeit benötigen.

Die gleiche Zeit. Die Verarbeitung wird durch ein array ja nicht schneller.

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

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 15:09 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von MaikG:
Trotzdem Fantasieergebnisse.

Ich hab zwar geschrieben, dass der Algorithmus ziemlich robust ist, aber bei Deiner 8->16Bit Konvertierungsroutine ist er trotzdem hilflos.

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

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 17:29 Uhr

Holger
Posts: 8090
Nutzer
Hier ist das Programm, mal ein bißchen bereinigt.
Allerdings ist das Hauptproblem noch nicht beseitigt. Also, warum das Ding so lange braucht, versteh ich nicht. Es braucht ja selbst dann so lange, wenn man die Berechnung nicht aufruft. Also irgendwo steckt da wohl noch ein Bug.
Basic code:
REM aktualisiert 04.09.2006 - 16:00

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

DEFINT A-Z

'$INCLUDE Exec.bh
'$INCLUDE Timer.bh

LIBRARY OPEN "exec.library", LIBRARY_MINIMUM&

DIM SHARED junk&,dummy$

FUNCTION create_timer&()
    STATIC r&, timerport&, timerIO&
    create_timer& = NULL&
    timerport& = CreateMsgPort&()
    IF timerport& <> NULL& THEN
        timerIO& = CreateIORequest&(timerport&, timerequest_sizeof)
        IF timerIO& <> NULL& THEN
            r& = OpenDevice&(SADD("timer.device" + CHR$(0)), UNIT_MICROHZ&, timerIO&, 0)
            IF r& = 0 THEN
                create_timer& = timerIO&
            ELSE
                delete_timer timerIO&
            END IF
        ELSE
            DeleteMsgPort timerport&
        END IF
    END IF
END FUNCTION

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

FUNCTION finish_wait(BYVAL tr&)
    junk& = WaitIO&(tr&)
END FUNCTION

SUB init_wait(BYVAL tr&)
    POKEW tr& + IORequestio_Command, TR_ADDREQUEST&
    POKEL tr& + tr_time + tv_secs, 0
    POKEL tr& + tr_time + tv_micro, 125 REM 8000Hz
    SendIO&(tr&)
END SUB

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.

SUB post_testing
  STATIC row%, col%, see_digit%
  STATIC 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 */

  IF r#(row%)>=4E5 AND r#(col%)>=4E5 THEN 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%)>1*10^9 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 LOCATE 2,2:PRINT row_col_ascii_codes$(row%,col%-4)

END SUB

' *  goertzel
FUNCTION goertzel%(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

  POKEB &hBFE301,0
  tr&=create_timer&()
  IF tr&=NULL& THEN PRINT "timer open failed": GOTO 5
  WHILE INKEY$<>CHR$(27)
    init_wait(tr&)
    INCR mycount%:IF mycount%=8000 THEN LOCATE 1,1:PRINT TIME$:mycount%=0 
    sa%=( PEEKB(&hBFE101) - 127 )<<8
    bla%=goertzel%(sa%)
    junk = finish_wait(tr&)
  WEND

5 END

Ach, ja, nen Parallelport-Sampler hab ich eh nicht, kann ich also auch nicht testen...

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

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 18:08 Uhr

MaikG
Posts: 5172
Nutzer
>Hier ist das Programm, mal ein bißchen bereinigt.

Danke, probiere ich gleich aus.

>Allerdings ist das Hauptproblem noch nicht beseitigt. Also, warum
>das Ding so lange braucht, versteh ich nicht. Es braucht ja selbst
>dann so lange, wenn man die Berechnung nicht aufruft. Also irgendwo
>steckt da wohl noch ein Bug.

Hast du selbst MaxonBasic?
Vielleicht gefallen MB die double Variablen nicht sonderlich,
durch REM $Noevent ist das Programm schon doppelt so schnell
geworden. Der Compiler ist eigentlich für 040er geeignet, aber
einige (Interne) sachen laufen darauf nicht Optimal schnell.

[ - Antworten - Zitieren - Direktlink - ]

04.09.2006, 22:08 Uhr

MaikG
Posts: 5172
Nutzer
>Allerdings ist das Hauptproblem noch nicht beseitigt. Also, warum
>das Ding so lange braucht, versteh ich nicht. Es braucht ja selbst
>dann so lange, wenn man die Berechnung nicht aufruft.

Tatsächlich selbst ohne goertzel, das liegt wohl an den Timing
Routinen.
Nimmt man das Timing raus ist die Funktion leicht schneller
als 8000 HZ - Was trotzdem bescheiden ist.
Hab noch mehr Compiler Optionen Probiert, ich denke aber da
ist nichts mehr raus zu holen.

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 12:52 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:

Hab noch mehr Compiler Optionen Probiert, ich denke aber da
ist nichts mehr raus zu holen.


Probier's doch mal ohne die Textausgabe. Textausgaben sind erfahrungsgemäß ziemlich teuer...

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

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 13:03 Uhr

DariusBrewka
Posts: 899
[Benutzer gesperrt]
... warfum eigentlich 8000Hz, soweit ich das sehe ist die höchste Frequenz weit unterhalb 2000Hz, also müsste doch ca 4000Hz als Samplingfrequenz reichen oder ist Görzel da anders?

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 15:13 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von DariusBrewka:
... warfum eigentlich 8000Hz, soweit ich das sehe ist die höchste Frequenz weit unterhalb 2000Hz, also müsste doch ca 4000Hz als Samplingfrequenz reichen oder ist Görzel da anders?

Der Beispielcode enthielt hardcodierte Werte, weswegen das nicht so einfach geändert werden konnte. Allerdings hat zwischenzeitlich jemand den code auf wikipedia geändert (Maik's Port basiert schon auf der neueren Version), und man könnte es evtl. mit diesem Code auch mit anderen Sampling-Frequenzen versuchen. Habe ich bislang aber nicht getestet.

Trotzdem sollte 8000 Mal pro Sekunde selbst mit Basic kein Problem darstellen. Da steckt irgendwo noch Wurm drin...

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

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 16:52 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von MaikG:
Hast du selbst MaxonBasic?

Nur die Demoversion.
Zitat:
Vielleicht gefallen MB die double Variablen nicht sonderlich,
durch REM $Noevent ist das Programm schon doppelt so schnell
geworden. Der Compiler ist eigentlich für 040er geeignet, aber
einige (Interne) sachen laufen darauf nicht Optimal schnell.

Das wäre dann schon fine-tuning, das Problem ist aber grundlegender. Ich kann das hier mit ~2GHz testen, wo die Performance von Basic-Code kaum eine Rolle spielt. Der timer wartet aber offenbar eher zufällige intervalle. Du kannst ja mal mit unterschiedlichen micro-Werten experimentieren...

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

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 18:04 Uhr

MaikG
Posts: 5172
Nutzer
>Probier's doch mal ohne die Textausgabe. Textausgaben sind
>erfahrungsgemäß ziemlich teuer...

Hab ich schon Probiert, erst hab ich die Ausgabe beim Beenden
gemacht, dann das Programm so umgeschrieben das das Basic
Fenster/Ausgaben gar nicht genutzt werden sonder Intuition.
MaxonBasic ist damit sehr langsam auf Graka.


>Trotzdem sollte 8000 Mal pro Sekunde selbst mit Basic kein Problem
>darstellen. Da steckt irgendwo noch Wurm drin...

Selbst wenns mit 4000 HZ dann auf dem 060er@60MHZ ginge, auf
dem 030er@50MHZ(ohne FPU) dann trotzdem noch nicht.

>Das wäre dann schon fine-tuning, das Problem ist aber grundlegender.
>Ich kann das hier mit ~2GHz testen, wo die Performance von Basic-Code
>kaum eine Rolle spielt. Der timer wartet aber offenbar eher zufällige
>intervalle. Du kannst ja mal mit unterschiedlichen micro-Werten
>experimentieren...

Wenns mit 2GHZ auch so lahm ist, ist das schon eigenartig.
Hab micro schon auf 1 gesetzt, keine (sichtbare) änderung.
Aber wie gesagt selbst ohne Timing grade etwas schneller als
realtime mit 060@60MHZ

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 19:41 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von MaikG:
Aber wie gesagt selbst ohne Timing grade etwas schneller als
realtime mit 060@60MHZ

An dem Program lässt sich definitiv noch einiges optimieren. Aber wie gesagt, erst mal muss das Programm überhaupt funktionieren. Und da hakts eben. Ohne vernünftiges timing macht das Ganze nicht viel Sinn, wenn man a) davon ausgeht, dass es beim Optimieren auch deutlich schneller wird, bzw. b) so wie ich, auf einer deutlich schnelleren Maschine debuggen will.

Ohne timer kann ich auch 100000 Samples/s bearbeiten, aber das nutzt ja nichts.

Ok, ich kann Dir auch das C-Programm übersetzen und zum Testen geben, dann kannst Du die Performance ohne Basic-Handicap auf Deinem Zielsystem überprüfen. Wenn's damit dann nicht geht, brauchen wir an dem Basic-Programm nicht mehr rumschrauben.

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

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 21:03 Uhr

MaikG
Posts: 5172
Nutzer
>An dem Program lässt sich definitiv noch einiges optimieren.

Naja, vielleicht wenn man die Gleichung an sich versteht, ansonsten
sehe ich da nicht viel was sich optimieren liesse.

>Aber wie gesagt, erst mal muss das Programm überhaupt funktionieren.
>Und da hakts eben. Ohne vernünftiges timing macht das Ganze nicht
>viel Sinn,

Aber die Timing Routinen sind an sich korrekt, also wie man
die Betriebssystem Funktionen benutzt? Ich hab eine solche
Funktion nämlich noch nie benutzt. Hab das nur aus SimpleTimer.bas
kopiert, es könnte ja sein das die Funktionen gar nicht für solche
hohen Geschwindigkeiten gemacht sind.


>Ok, ich kann Dir auch das C-Programm übersetzen und zum Testen
>geben, dann kannst Du die Performance ohne Basic-Handicap auf
>Deinem Zielsystem überprüfen. Wenn's damit dann nicht geht,
>brauchen wir an dem Basic-Programm nicht mehr rumschrauben.

Das währe eine Idee. Aber du hast ja auch mal auf einem echten
Amiga Programmiert, besteht wirklich die möglichkeit das er zu
langsam für so eine relativ einfache sache ist? Immerhin macht
ein 020er schon Spracherkennung und das ist ja komplizierter.

[ - Antworten - Zitieren - Direktlink - ]

05.09.2006, 22:31 Uhr

MaikG
Posts: 5172
Nutzer
Hab die Timing Funktion jetzt "abgekürzt", die Poke's ausserhalb
der Schleife und auf die Sprünge zu den Unterprogrammen verzichtet.
Jetzt liefert diese ein korrektes 1s Intervall.
Mit der Funktion ist's trotzdem noch zu langsam.


code:
tr&=create_timer&()
      IF tr&=NULL& THEN GOTO 5

 POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&
 POKEL tr& + tr_time% + tv_secs%, 0&
 POKEL tr& + tr_time% + tv_micro%, 125& REM 125=8000Hz

      WHILE myseconds%<30
        SendIO&(tr&) REM init_wait(tr&)
        INCR mycount%:IF mycount%=8000 THEN mycount%=0:INCR myseconds%:move rpS&,20,25:Text rpS&, SADD(TIME$+CHR$(0)),8
        REM bla%=goertzel%((PEEKB(&hBFE101) - 127)<<8)
        junk& = WaitIO&(tr&) REM junk% = finish_wait(tr&)
      WEND


[ Dieser Beitrag wurde von MaikG am 05.09.2006 um 22:31 Uhr geändert. ]

[ Dieser Beitrag wurde von MaikG am 05.09.2006 um 22:32 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 09:47 Uhr

Mad_Dog
Posts: 1944
Nutzer
So. Ich hab gestern nacht noch schnell ein Programm geschrieben, welches das Auslesen der Werte macht. Dieses Programm benutzt ein Array als Puffer. Erst wenn der Puffer gefüllt ist, wird der Text auf der Konsole ausgegeben. Die Textausgabe ist das langsamste am ganzen Programm. Der Rest funktioniert wie vorgesehen: Wenn ich eine Samplingrate von 8kHz nehme und eine Sekunde Sampeln will, brauche ich 8000 Werte. Die Periode beträgt dann T=1/8000, also 0,000125 Sekunden oder 125 Mikrosekunden. Wenn ich dann 8000 Werte alle 0,000125 Sekunden auslese, dann dauert das - wie erwartet - genau eine Sekunde.

Die Low-Level Zugriffe sind die gleichen wie bei Eurem Basic-Programm.

Allerdings sind die Werte, die ich herausbekomme fraglich. Das ergibt nie und nimmer ein Audiosignal.

Ich frag mich sowieso, wie man das mit einem Stereo-Sampler machen soll, wenn man zu einem Zeitpunkt ja nur einen 8-Bit Wert bekommt und man 8 Bit pro Kanal haben möchte...

Auch ja: Ganz wichtig ist, daß man UNIT_MICROHZ als Timer verwendet - die anderen Timer können nicht so fein auflösen.
C code:
/*  HardHack.c
 *  LowLevel Zugriff auf CIA
 *  Autor: Norman Walter
 *  Datum: 5.9.2006
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <exec/types.h>
#include <exec/exec.h>
#include <exec/memory.h>
#include <exec/io.h>

#include <devices/timer.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>

// Samplingfrequenz (hier 8kHz)
#define SAMPLINGFREQ 8000

// Größe des Zeitfensters: Zeit in Sekunden
#define TIME 1

//  Wie groß soll das Zeitfenster sein, das wir betrachten?
#define FRAMESIZE SAMPLINGFREQ * TIME

// Puffer für das Sample
BYTE Buffer[FRAMESIZE];

// Ein Byte vom Parallelport lesen
BYTE ReadPar(void)
{
  BYTE x;

  memmove(&x,(void *)0xBFE101,1);

  return x;
}

int main(void)
{
   struct timerequest *TimerIO;
   struct MsgPort *TimerMP;

   int i;

   TimerMP = CreateMsgPort();
   if (TimerMP != NULL)
   {
     TimerIO = (struct timerequest *) CreateIORequest(TimerMP,sizeof(struct timerequest));
     if (TimerIO != NULL)
     {
        /*  Wichtig: Für diesen Zweck brauchen wir UNIT_MICROHZ.
         *  Die anderen Timer sind zu ungenau, weil wir tatsächlich
         *  0,000125 Sekunden messen wollen, also 125 Mikroherz.
         */
        if (OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)TimerIO,0L)==0)
        {
           /* Issue the command and wait for it to finish, then get the reply */
           TimerIO->tr_node.io_Command = TR_GETSYSTIME;
           SendIO((struct IORequest *) TimerIO);

           printf("Start\n");

           // Den Parallelport in den Lesemodus versetzen
           memset((void *)0xBFE301,0x0,1);

           /*  Zyklischen Alarm setzen:
            *  1/SAMPLINGFREQ entspricht dabei einer Periode.
            *  Nach der Formel T = 1/n
            *  wobei n unsere Samplingfrequenz ist.
            *  (siehe auch jede beliebige Physik-Formelsammlung)
            */
           TimerIO->tr_node.io_Command	= TR_ADDREQUEST;
           TimerIO->tr_time.tv_secs	= 0;
           TimerIO->tr_time.tv_micro = 1/SAMPLINGFREQ;

           /*  Hier werden die Werte gesammelt
            *  Bei einer Samplingfrequenz von 8kHz
            *  und 8000 Werten sollte das genau
            *  eine Sekunde dauern
            */
           for (i=0;i<FRAMESIZE;i++)
           {
              WaitPort(TimerMP);

	           if(1UL << TimerMP->mp_SigBit)
	           {
                 WaitIO((struct IORequest *)TimerIO);

                 // Wert vom Parallelport kopieren
                 Buffer[i]=ReadPar();
                 SendIO((struct IORequest *)TimerIO);
              }
           }

           printf("Auslesen beendet\n");

           /*  Ausgabe der Werte:
            *  Da Textausgaben sehr teuer sind,
            *  werden die Werte erst ausgegeben,
            *  wenn sie im Puffer liegen
            */
           for (i=0;i<FRAMESIZE;i++)
           {
              printf("%d ",Buffer[i]);
           }

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

           /* Close the timer device */
           CloseDevice((struct IORequest *) TimerIO);
        }
        else
        printf("\nError: Could not open timer device\n");

        /* Delete the I/O request structure */
        DeleteIORequest((struct IORequest *)TimerIO);
    }
    else
    printf("\nError: Could not create I/O structure\n");

    /* Delete the port */
    DeleteMsgPort(TimerMP);
  }
  else
  printf("\nError: Could not create port\n");

   printf("Ok\n");

   return 0;
}

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

[ Dieser Beitrag wurde von Mad_Dog am 06.09.2006 um 09:50 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 09:56 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von Holger:

code:
r& = OpenDevice&(SADD("timer.device" + CHR$(0)), UNIT_MICROHZ&, timerIO&, 0)



Bist Du sicher, daß das so richtig ist? Was bedeutet "&" in MaxonBasic? UNIT_MICROHZ ist eine Konstante.


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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:03 Uhr

MaikG
Posts: 5172
Nutzer
>Wenn ich dann 8000 Werte alle 0,000125 Sekunden auslese, dann dauert
>das - wie erwartet - genau eine Sekunde.

Naja, ohne den DTMF decoder schaffe ich das auch in Basic.

>Allerdings sind die Werte, die ich herausbekomme fraglich. Das
>ergibt nie und nimmer ein Audiosignal.

Welchen Sampler hast du? Ich hab Megalosound, wenn man das Signal
da grafisch darstellt siehts aus wie ein Sample.

127 ist 0, alles darunter Negativ, alles darüber Positiv.


>Ich frag mich sowieso, wie man das mit einem Stereo-Sampler machen
>soll, wenn man zu einem Zeitpunkt ja nur einen 8-Bit Wert bekommt
>und man 8 Bit pro Kanal haben möchte...

Die Modulieren bei bedarf das 2.Signal auf. Wie beim Radio-Sender.


[ Dieser Beitrag wurde von MaikG am 06.09.2006 um 10:03 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:29 Uhr

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

code:
r& = OpenDevice&(SADD("timer.device" + CHR$(0)), UNIT_MICROHZ&, timerIO&, 0)



Bist Du sicher, daß das so richtig ist? Was bedeutet "&" in MaxonBasic? UNIT_MICROHZ ist eine Konstante.


& bedeutet long, wenn ich mich nicht irre. Und die Includes sind für Basic etwas anders aufgebaut, einen Präprozessor scheints bei MaxonBasic nicht zu geben. Daher behilft man sich wohl mit long-Variablen, evtl. in Form von const UNIT_MICROHZ& = ...

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:30 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:
>Wenn ich dann 8000 Werte alle 0,000125 Sekunden auslese, dann dauert
>das - wie erwartet - genau eine Sekunde.

Naja, ohne den DTMF decoder schaffe ich das auch in Basic.


Ich dachte, es würde bei Euch schon am Auslesen der Daten hapern?
Mach's doch einfach so wie ich: Hole erst die Werte für ein Zeitfenster und schreibe sie in ein Array. Dann geb das Array mal testweise als Text aus. Dem C-Code von mir kannst Du folgen?
Also mein Code macht exakt das, was verlangt wird.

Zitat:
>Allerdings sind die Werte, die ich herausbekomme fraglich. Das
>ergibt nie und nimmer ein Audiosignal.

Welchen Sampler hast du? Ich hab Megalosound, wenn man das Signal
da grafisch darstellt siehts aus wie ein Sample.

127 ist 0, alles darunter Negativ, alles darüber Positiv.


Na wenn das so ist... woher nimmst Du die Information?
Mal sehen, vielleicht werd ich heut abend dazukommen, noch ein Oszi darumzubasteln...

Zitat:
>Ich frag mich sowieso, wie man das mit einem Stereo-Sampler machen
>soll, wenn man zu einem Zeitpunkt ja nur einen 8-Bit Wert bekommt
>und man 8 Bit pro Kanal haben möchte...

Die Modulieren bei bedarf das 2.Signal auf. Wie beim Radio-Sender.


Ich hab den "Stereo Master".

Aber ich denke, die meisten Parallelport Sampler sind mehr oder weniger kompatibel. Die erwähnten Programme von Infect funktionieren auch wunderbar, genauso wie diverse andere Software für Parallelport Sampler.

Was meinst Du mit "Aufmodulieren"? Ich bekomme zu dem Zeitpunkt, an dem ich hinschaue genau ein Byte. Wie bekomme ich daraus die Information für den linken/rechten Kanal? Hast Du da evtl. mehr Infos?

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:35 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von MaikG:

127 ist 0, alles darunter Negativ, alles darüber Positiv.


Kann doch nicht sein, oder? Der Wertebereich für ein Byte geht von -127 bis +128.


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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:40 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:
Zitat:
Original von Mad_Dog:
Zitat:
Original von Holger:

code:
r& = OpenDevice&(SADD("timer.device" + CHR$(0)), UNIT_MICROHZ&, timerIO&, 0)



Bist Du sicher, daß das so richtig ist? Was bedeutet "&" in MaxonBasic? UNIT_MICROHZ ist eine Konstante.


& bedeutet long, wenn ich mich nicht irre. Und die Includes sind für Basic etwas anders aufgebaut, einen Präprozessor scheints bei MaxonBasic nicht zu geben. Daher behilft man sich wohl mit long-Variablen, evtl. in Form von const UNIT_MICROHZ& = ...


Ich kenn mich mit MaxonBasic zwar nicht aus (hatte damals AMOS ;) ), aber mir sieht das mehr nach nem Zeiger aus. Womöglich funktioniert deshalb der Timer hier nicht. UNIT_MICROHZ ist (in C) nur eine symbolische Konstante für einen int-Wert. Was ich damit sagen will: Die Funktion OpenDevice() erwartet als 2. Argument einen Int-Wert (die Unit) und KEINEN Zeiger!

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

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 10:53 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Mad_Dog:
Ich kenn mich mit MaxonBasic zwar nicht aus (hatte damals AMOS ;) ), aber mir sieht das mehr nach nem Zeiger aus. Womöglich funktioniert deshalb der Timer hier nicht. UNIT_MICROHZ ist (in C) nur eine symbolische Konstante für einen int-Wert.


Ich kenne mich mit MB auch nicht so aus (AmigaBASIC bzw. ACE waren meine letzten BASIC-Erfahrungen auf dem Amiga) ;)

Es kann natürlich sein, daß UNIT_MICROHZ in den MB-Includes nicht korrekt definiert wurde. Ansonsten stellt es aber kein wirklich großes Problem dar, diesen (in C normalerweise als int-Konstante angegebenen) Wert in ein MB-Long zu packen. Die Prototypen in C zeigen für OpenDevice() jedenfalls ein ULONG für die Unit, insofern sollte das passen.

Zeiger kennt MB meines Wissens nach auch nicht (gibts außer Blitz eigentlich einen Dialekt, der Zeiger direkt unterstützt?), ich gehe daher davon aus, daß auch Zeigerwerte (sinnvollerweise) in einer long-Variablen landen. Technisch ist das ja kein Unterschied und wäre in C (mit Cast) genauso machbar, wenn auch sehr unschön :D

Grüße

--
---

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 11:15 Uhr

Mad_Dog
Posts: 1944
Nutzer
Zitat:
Original von whose:

Es kann natürlich sein, daß UNIT_MICROHZ in den MB-Includes nicht korrekt definiert wurde. Ansonsten stellt es aber kein wirklich großes Problem dar, diesen (in C normalerweise als int-Konstante angegebenen) Wert in ein MB-Long zu packen.


Falls x& in MaxonBasic "Adresse von x" bedeudet, dann wird statt dem gewünschten Wert die Adresse übergeben, wo der Wert im Speicher steht. Was dann dauskommen würde, wäre ein Zufallsergebnis.

Ich sitz jetzt nicht vor meim Amiga, weshalb ich nicht sagen kann, welche Unit UNIT_MICROHZ ist. War es vielleich 1? Setz einfach mal den passenden Zahlenwert statt UNIT_MICROHZ ein und schau, was passiert.


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

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 11:27 Uhr

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

Es kann natürlich sein, daß UNIT_MICROHZ in den MB-Includes nicht korrekt definiert wurde. Ansonsten stellt es aber kein wirklich großes Problem dar, diesen (in C normalerweise als int-Konstante angegebenen) Wert in ein MB-Long zu packen.


Falls x& in MaxonBasic "Adresse von x" bedeudet, dann wird statt dem gewünschten Wert die Adresse übergeben, wo der Wert im Speicher steht. Was dann dauskommen würde, wäre ein Zufallsergebnis.


Ja, falls. Wenn Du Dir den Rest des MB-Programms ansiehst, wird Dir & als Bezeichnerteil noch öfter begegnen. Daher vermute ich ganz stark, daß & einen long-Wert bezeichnet und MB keine Zeiger als Typ kennt.

Grüße

--
---

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


[ Dieser Beitrag wurde von whose am 06.09.2006 um 11:30 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 18:23 Uhr

Holger
Posts: 8090
Nutzer
Zitat:
Original von MaikG:
Das währe eine Idee. Aber du hast ja auch mal auf einem echten
Amiga Programmiert, besteht wirklich die möglichkeit das er zu
langsam für so eine relativ einfache sache ist? Immerhin macht
ein 020er schon Spracherkennung und das ist ja komplizierter.

Ich glaube, dass es keinerlei Performanceprobleme geben dürfte. Aber wenn es nunmal Probleme gibt, schließe ich lieber alle möglichen Ursachen aus.
Zitat:
Original von MaikG:
Hab die Timing Funktion jetzt "abgekürzt", die Poke's ausserhalb
der Schleife und auf die Sprünge zu den Unterprogrammen verzichtet.
Jetzt liefert diese ein korrektes 1s Intervall.

Erstaunlich, denn laut Dokumentation werden die Zeitangaben bei der Ausführung auf 0 gesetzt. Deshalb standen die Poke-Anweisungen ja innerhalb der der Funktion. POKE dürfte auch kaum Performance-relevant sein.
Zitat:
Original von Mad_Dog:
So. Ich hab gestern nacht noch schnell ein Programm geschrieben, welches das Auslesen der Werte macht.
C code:
...
TimerIO->tr_time.tv_micro = 1/SAMPLINGFREQ;
...



Wos? 1/8000 ist 0, bei int-Werten.
War wohl schon ziemlich spät, ...aber so funktioniert das Programm eher aus Versehen...
Zitat:
Bist Du sicher, daß das so richtig ist? Was bedeutet "&" in MaxonBasic? UNIT_MICROHZ ist eine Konstante.

Es bedeutet 32Bit-Zahl...
Zitat:
Aber ich denke, die meisten Parallelport Sampler sind mehr oder weniger kompatibel. Die erwähnten Programme von Infect funktionieren auch wunderbar, genauso wie diverse andere Software für Parallelport Sampler.
Sie sind kompatibel zueinander, solange Du kein Stereo verwendest...
Zitat:
Zitat:
127 ist 0, alles darunter Negativ, alles darüber Positiv.
Kann doch nicht sein, oder? Der Wertebereich für ein Byte geht von -127 bis +128.
Signed byte geht von -128 bis +127, unsigned byte geht von 0 bis 255.

Zitat:
Ich sitz jetzt nicht vor meim Amiga, weshalb ich nicht sagen kann, welche Unit UNIT_MICROHZ ist. War es vielleich 1? Setz einfach mal den passenden Zahlenwert statt UNIT_MICROHZ ein und schau, was passiert.
0, imho

mfg

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

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 18:50 Uhr

MaikG
Posts: 5172
Nutzer
>& bedeutet long, wenn ich mich nicht irre. Und die Includes sind für
>Basic etwas anders aufgebaut, einen Präprozessor scheints bei
>MaxonBasic nicht zu geben. Daher behilft man sich wohl mit
>long-Variablen, evtl. in Form von const UNIT_MICROHZ& = ...


CONST UNIT_MICROHZ& = 0&

Das ist schon richtig, ist im MaxonBasic Beispiel ja auch so.
Das wird von der timer.bc, welcher von der timer.bh geladen
wird bereitgestellt.

& ist Long, so direkte Zeiger gibts wohl nicht man kann aber
die Position einer Variable im Speicher mit VARPTR bestimmen.1

>Ich dachte, es würde bei Euch schon am Auslesen der Daten hapern?

Nein das geht, erst ging das Timing nicht, scheint jetzt okay.
Das Decoding ist zu lahm.

>Mach's doch einfach so wie ich: Hole erst die Werte für ein
>Zeitfenster und schreibe sie in ein Array. Dann geb das Array mal
>testweise als Text aus. Dem C-Code von mir kannst Du folgen?
>Also mein Code macht exakt das, was verlangt wird.

Damit ich die mögliche Sample geschwindigkeit erfahre?
Wie gesagt macht man die decodierung nicht "On the Fly" werden
ebend Tastenanschläge teils nicht erkannt.

Zitat:
>Allerdings sind die Werte, die ich herausbekomme fraglich. Das
>ergibt nie und nimmer ein Audiosignal.

Welchen Sampler hast du? Ich hab Megalosound, wenn man das Signal
da grafisch darstellt siehts aus wie ein Sample.

127 ist 0, alles darunter Negativ, alles darüber Positiv.

>Na wenn das so ist... woher nimmst Du die Information?

Per Print ausgeben, bzw. einen Punkt setzen und die X-Koordinate
erhöhen, dann sieht man das ja.


>Aber ich denke, die meisten Parallelport Sampler sind mehr oder
>weniger kompatibel.

Ja.

>Was meinst Du mit "Aufmodulieren"? Ich bekomme zu dem Zeitpunkt, an
>dem ich hinschaue genau ein Byte. Wie bekomme ich daraus die
>Information für den linken/rechten Kanal? Hast Du da evtl. mehr
>Infos?

Das wird wohl durch irgendeinen Pin umgeschalten. Aufmodulieren,
mh, wie soll ich das erklären. Beim Kabelfernsehn hast du auch
mehrere Sender, das das geht ist so weil die auf verschiedenen
Frequenzen liegen. Und beim Sampler ist das genauso der eine Kanal
ist ganz normal, der andere beginnt ab ca. 20kHz.

>Kann doch nicht sein, oder? Der Wertebereich für ein Byte geht
>von -127 bis +128.


Bei MB eingentlich von 0-255.


>Falls x& in MaxonBasic "Adresse von x" bedeudet, dann wird statt dem
>gewünschten Wert die Adresse übergeben, wo der Wert im Speicher
>steht. Was dann dauskommen würde, wäre ein Zufallsergebnis.

x& ist eine Long Variable, man kann darin aber eine Speicheradresse
hineinlegen.


>Erstaunlich, denn laut Dokumentation werden die Zeitangaben bei der
>Ausführung auf 0 gesetzt.

Mag sein.

>Deshalb standen die Poke-Anweisungen ja innerhalb der der Funktion.

Aber wenn ich ms auf 1 gesetzt habe wurde es auch nicht schneller.

>POKE dürfte auch kaum Performance-relevant sein.

Vielleicht nicht aber da sind jetzt 2 Sprünge in die Funktionen
etc. weniger.

[ - Antworten - Zitieren - Direktlink - ]

06.09.2006, 23:45 Uhr

MaikG
Posts: 5172
Nutzer
Verdammt, die Timing routinen funktionieren doch nicht korrekt.
Es sieht zwar erst so aus alswenn jede sekunde gezählt wird, macht
man jedoch eine korrekte Zeitmessung ist doch mehr Zeit vergangen.

[ - Antworten - Zitieren - Direktlink - ]

07.09.2006, 09:25 Uhr

MaikG
Posts: 5172
Nutzer
Ich hab einen Fehler gefunden:

POKEW tr& + IORequestio_Command%, TR_ADDREQUEST&

muss heissen:

POKEW tr& + tr_node% + IORequestio_Command%, TR_ADDREQUEST&

dadurch wird es trotzdem mit der unterfunktion nicht schneller.
Mit init_wait direkt im Programm erreicht es fast Echtzeit.

[ - Antworten - Zitieren - Direktlink - ]


1 2 3 -4- 5 6 7 8 9 Letzte [ - Beitrag schreiben - ]


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


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